00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "AudioCallbackPlaySource.h"
00017
00018 #include "AudioGenerator.h"
00019
00020 #include "data/model/Model.h"
00021 #include "view/ViewManager.h"
00022 #include "base/PlayParameterRepository.h"
00023 #include "base/Preferences.h"
00024 #include "data/model/DenseTimeValueModel.h"
00025 #include "data/model/WaveFileModel.h"
00026 #include "data/model/SparseOneDimensionalModel.h"
00027 #include "plugin/RealTimePluginInstance.h"
00028
00029 #include "AudioCallbackPlayTarget.h"
00030
00031 #include <rubberband/RubberBandStretcher.h>
00032 using namespace RubberBand;
00033
00034 #include <iostream>
00035 #include <cassert>
00036
00037
00038
00039
00040 const size_t AudioCallbackPlaySource::m_ringBufferSize = 131071;
00041
00042 AudioCallbackPlaySource::AudioCallbackPlaySource(ViewManager *manager,
00043 QString clientName) :
00044 m_viewManager(manager),
00045 m_audioGenerator(new AudioGenerator()),
00046 m_clientName(clientName),
00047 m_readBuffers(0),
00048 m_writeBuffers(0),
00049 m_readBufferFill(0),
00050 m_writeBufferFill(0),
00051 m_bufferScavenger(1),
00052 m_sourceChannelCount(0),
00053 m_blockSize(1024),
00054 m_sourceSampleRate(0),
00055 m_targetSampleRate(0),
00056 m_playLatency(0),
00057 m_target(0),
00058 m_lastRetrievalTimestamp(0.0),
00059 m_lastRetrievedBlockSize(0),
00060 m_playing(false),
00061 m_exiting(false),
00062 m_lastModelEndFrame(0),
00063 m_outputLeft(0.0),
00064 m_outputRight(0.0),
00065 m_auditioningPlugin(0),
00066 m_auditioningPluginBypassed(false),
00067 m_playStartFrame(0),
00068 m_playStartFramePassed(false),
00069 m_timeStretcher(0),
00070 m_stretchRatio(1.0),
00071 m_stretcherInputCount(0),
00072 m_stretcherInputs(0),
00073 m_stretcherInputSizes(0),
00074 m_fillThread(0),
00075 m_converter(0),
00076 m_crapConverter(0),
00077 m_resampleQuality(Preferences::getInstance()->getResampleQuality())
00078 {
00079 m_viewManager->setAudioPlaySource(this);
00080
00081 connect(m_viewManager, SIGNAL(selectionChanged()),
00082 this, SLOT(selectionChanged()));
00083 connect(m_viewManager, SIGNAL(playLoopModeChanged()),
00084 this, SLOT(playLoopModeChanged()));
00085 connect(m_viewManager, SIGNAL(playSelectionModeChanged()),
00086 this, SLOT(playSelectionModeChanged()));
00087
00088 connect(PlayParameterRepository::getInstance(),
00089 SIGNAL(playParametersChanged(PlayParameters *)),
00090 this, SLOT(playParametersChanged(PlayParameters *)));
00091
00092 connect(Preferences::getInstance(),
00093 SIGNAL(propertyChanged(PropertyContainer::PropertyName)),
00094 this, SLOT(preferenceChanged(PropertyContainer::PropertyName)));
00095 }
00096
00097 AudioCallbackPlaySource::~AudioCallbackPlaySource()
00098 {
00099 m_exiting = true;
00100
00101 if (m_fillThread) {
00102 m_condition.wakeAll();
00103 m_fillThread->wait();
00104 delete m_fillThread;
00105 }
00106
00107 clearModels();
00108
00109 if (m_readBuffers != m_writeBuffers) {
00110 delete m_readBuffers;
00111 }
00112
00113 delete m_writeBuffers;
00114
00115 delete m_audioGenerator;
00116
00117 for (size_t i = 0; i < m_stretcherInputCount; ++i) {
00118 delete[] m_stretcherInputs[i];
00119 }
00120 delete[] m_stretcherInputSizes;
00121 delete[] m_stretcherInputs;
00122
00123 m_bufferScavenger.scavenge(true);
00124 m_pluginScavenger.scavenge(true);
00125 }
00126
00127 void
00128 AudioCallbackPlaySource::addModel(Model *model)
00129 {
00130 if (m_models.find(model) != m_models.end()) return;
00131
00132 bool canPlay = m_audioGenerator->addModel(model);
00133
00134 m_mutex.lock();
00135
00136 m_models.insert(model);
00137 if (model->getEndFrame() > m_lastModelEndFrame) {
00138 m_lastModelEndFrame = model->getEndFrame();
00139 }
00140
00141 bool buffersChanged = false, srChanged = false;
00142
00143 size_t modelChannels = 1;
00144 DenseTimeValueModel *dtvm = dynamic_cast<DenseTimeValueModel *>(model);
00145 if (dtvm) modelChannels = dtvm->getChannelCount();
00146 if (modelChannels > m_sourceChannelCount) {
00147 m_sourceChannelCount = modelChannels;
00148 }
00149
00150 #ifdef DEBUG_AUDIO_PLAY_SOURCE
00151 std::cout << "Adding model with " << modelChannels << " channels " << std::endl;
00152 #endif
00153
00154 if (m_sourceSampleRate == 0) {
00155
00156 m_sourceSampleRate = model->getSampleRate();
00157 srChanged = true;
00158
00159 } else if (model->getSampleRate() != m_sourceSampleRate) {
00160
00161
00162
00163
00164 if (dtvm) {
00165
00166 bool conflicting = false;
00167
00168 for (std::set<Model *>::const_iterator i = m_models.begin();
00169 i != m_models.end(); ++i) {
00170
00171
00172
00173
00174
00175 WaveFileModel *wfm = dynamic_cast<WaveFileModel *>(*i);
00176 if (wfm && wfm != dtvm &&
00177 wfm->getSampleRate() != model->getSampleRate() &&
00178 wfm->getSampleRate() == m_sourceSampleRate) {
00179 std::cerr << "AudioCallbackPlaySource::addModel: Conflicting wave file model " << *i << " found" << std::endl;
00180 conflicting = true;
00181 break;
00182 }
00183 }
00184
00185 if (conflicting) {
00186
00187 std::cerr << "AudioCallbackPlaySource::addModel: ERROR: "
00188 << "New model sample rate does not match" << std::endl
00189 << "existing model(s) (new " << model->getSampleRate()
00190 << " vs " << m_sourceSampleRate
00191 << "), playback will be wrong"
00192 << std::endl;
00193
00194 emit sampleRateMismatch(model->getSampleRate(),
00195 m_sourceSampleRate,
00196 false);
00197 } else {
00198 m_sourceSampleRate = model->getSampleRate();
00199 srChanged = true;
00200 }
00201 }
00202 }
00203
00204 if (!m_writeBuffers || (m_writeBuffers->size() < getTargetChannelCount())) {
00205 clearRingBuffers(true, getTargetChannelCount());
00206 buffersChanged = true;
00207 } else {
00208 if (canPlay) clearRingBuffers(true);
00209 }
00210
00211 if (buffersChanged || srChanged) {
00212 if (m_converter) {
00213 src_delete(m_converter);
00214 src_delete(m_crapConverter);
00215 m_converter = 0;
00216 m_crapConverter = 0;
00217 }
00218 }
00219
00220 m_mutex.unlock();
00221
00222 m_audioGenerator->setTargetChannelCount(getTargetChannelCount());
00223
00224 if (!m_fillThread) {
00225 m_fillThread = new FillThread(*this);
00226 m_fillThread->start();
00227 }
00228
00229 #ifdef DEBUG_AUDIO_PLAY_SOURCE
00230 std::cout << "AudioCallbackPlaySource::addModel: now have " << m_models.size() << " model(s) -- emitting modelReplaced" << std::endl;
00231 #endif
00232
00233 if (buffersChanged || srChanged) {
00234 emit modelReplaced();
00235 }
00236
00237 connect(model, SIGNAL(modelChanged(size_t, size_t)),
00238 this, SLOT(modelChanged(size_t, size_t)));
00239
00240 m_condition.wakeAll();
00241 }
00242
00243 void
00244 AudioCallbackPlaySource::modelChanged(size_t startFrame, size_t endFrame)
00245 {
00246 #ifdef DEBUG_AUDIO_PLAY_SOURCE
00247 std::cerr << "AudioCallbackPlaySource::modelChanged(" << startFrame << "," << endFrame << ")" << std::endl;
00248 #endif
00249 if (endFrame > m_lastModelEndFrame) {
00250 m_lastModelEndFrame = endFrame;
00251 rebuildRangeLists();
00252 }
00253 }
00254
00255 void
00256 AudioCallbackPlaySource::removeModel(Model *model)
00257 {
00258 m_mutex.lock();
00259
00260 #ifdef DEBUG_AUDIO_PLAY_SOURCE
00261 std::cout << "AudioCallbackPlaySource::removeModel(" << model << ")" << std::endl;
00262 #endif
00263
00264 disconnect(model, SIGNAL(modelChanged(size_t, size_t)),
00265 this, SLOT(modelChanged(size_t, size_t)));
00266
00267 m_models.erase(model);
00268
00269 if (m_models.empty()) {
00270 if (m_converter) {
00271 src_delete(m_converter);
00272 src_delete(m_crapConverter);
00273 m_converter = 0;
00274 m_crapConverter = 0;
00275 }
00276 m_sourceSampleRate = 0;
00277 }
00278
00279 size_t lastEnd = 0;
00280 for (std::set<Model *>::const_iterator i = m_models.begin();
00281 i != m_models.end(); ++i) {
00282
00283 if ((*i)->getEndFrame() > lastEnd) lastEnd = (*i)->getEndFrame();
00284
00285 }
00286 m_lastModelEndFrame = lastEnd;
00287
00288 m_mutex.unlock();
00289
00290 m_audioGenerator->removeModel(model);
00291
00292 clearRingBuffers();
00293 }
00294
00295 void
00296 AudioCallbackPlaySource::clearModels()
00297 {
00298 m_mutex.lock();
00299
00300 #ifdef DEBUG_AUDIO_PLAY_SOURCE
00301 std::cout << "AudioCallbackPlaySource::clearModels()" << std::endl;
00302 #endif
00303
00304 m_models.clear();
00305
00306 if (m_converter) {
00307 src_delete(m_converter);
00308 src_delete(m_crapConverter);
00309 m_converter = 0;
00310 m_crapConverter = 0;
00311 }
00312
00313 m_lastModelEndFrame = 0;
00314
00315 m_sourceSampleRate = 0;
00316
00317 m_mutex.unlock();
00318
00319 m_audioGenerator->clearModels();
00320
00321 clearRingBuffers();
00322 }
00323
00324 void
00325 AudioCallbackPlaySource::clearRingBuffers(bool haveLock, size_t count)
00326 {
00327 if (!haveLock) m_mutex.lock();
00328
00329 rebuildRangeLists();
00330
00331 if (count == 0) {
00332 if (m_writeBuffers) count = m_writeBuffers->size();
00333 }
00334
00335 m_writeBufferFill = getCurrentBufferedFrame();
00336
00337 if (m_readBuffers != m_writeBuffers) {
00338 delete m_writeBuffers;
00339 }
00340
00341 m_writeBuffers = new RingBufferVector;
00342
00343 for (size_t i = 0; i < count; ++i) {
00344 m_writeBuffers->push_back(new RingBuffer<float>(m_ringBufferSize));
00345 }
00346
00347
00348
00349
00350 if (!haveLock) {
00351 m_mutex.unlock();
00352 }
00353 }
00354
00355 void
00356 AudioCallbackPlaySource::play(size_t startFrame)
00357 {
00358 if (m_viewManager->getPlaySelectionMode() &&
00359 !m_viewManager->getSelections().empty()) {
00360
00361 std::cerr << "AudioCallbackPlaySource::play: constraining frame " << startFrame << " to selection = ";
00362
00363 startFrame = m_viewManager->constrainFrameToSelection(startFrame);
00364
00365 std::cerr << startFrame << std::endl;
00366
00367 } else {
00368 if (startFrame >= m_lastModelEndFrame) {
00369 startFrame = 0;
00370 }
00371 }
00372
00373 std::cerr << "play(" << startFrame << ") -> playback model ";
00374
00375 startFrame = m_viewManager->alignReferenceToPlaybackFrame(startFrame);
00376
00377 std::cerr << startFrame << std::endl;
00378
00379
00380
00381
00382
00383 m_mutex.lock();
00384 if (m_timeStretcher) {
00385 m_timeStretcher->reset();
00386 }
00387 if (m_playing) {
00388 std::cerr << "playing already, resetting" << std::endl;
00389 m_readBufferFill = m_writeBufferFill = startFrame;
00390 if (m_readBuffers) {
00391 for (size_t c = 0; c < getTargetChannelCount(); ++c) {
00392 RingBuffer<float> *rb = getReadRingBuffer(c);
00393 std::cerr << "reset ring buffer for channel " << c << std::endl;
00394 if (rb) rb->reset();
00395 }
00396 }
00397 if (m_converter) src_reset(m_converter);
00398 if (m_crapConverter) src_reset(m_crapConverter);
00399 } else {
00400 if (m_converter) src_reset(m_converter);
00401 if (m_crapConverter) src_reset(m_crapConverter);
00402 m_readBufferFill = m_writeBufferFill = startFrame;
00403 }
00404 m_mutex.unlock();
00405
00406 m_audioGenerator->reset();
00407
00408 m_playStartFrame = startFrame;
00409 m_playStartFramePassed = false;
00410 m_playStartedAt = RealTime::zeroTime;
00411 if (m_target) {
00412 m_playStartedAt = RealTime::fromSeconds(m_target->getCurrentTime());
00413 }
00414
00415 bool changed = !m_playing;
00416 m_lastRetrievalTimestamp = 0;
00417 m_playing = true;
00418 m_condition.wakeAll();
00419 if (changed) emit playStatusChanged(m_playing);
00420 }
00421
00422 void
00423 AudioCallbackPlaySource::stop()
00424 {
00425 bool changed = m_playing;
00426 m_playing = false;
00427 m_condition.wakeAll();
00428 m_lastRetrievalTimestamp = 0;
00429 if (changed) emit playStatusChanged(m_playing);
00430 }
00431
00432 void
00433 AudioCallbackPlaySource::selectionChanged()
00434 {
00435 if (m_viewManager->getPlaySelectionMode()) {
00436 clearRingBuffers();
00437 }
00438 }
00439
00440 void
00441 AudioCallbackPlaySource::playLoopModeChanged()
00442 {
00443 clearRingBuffers();
00444 }
00445
00446 void
00447 AudioCallbackPlaySource::playSelectionModeChanged()
00448 {
00449 if (!m_viewManager->getSelections().empty()) {
00450 clearRingBuffers();
00451 }
00452 }
00453
00454 void
00455 AudioCallbackPlaySource::playParametersChanged(PlayParameters *)
00456 {
00457 clearRingBuffers();
00458 }
00459
00460 void
00461 AudioCallbackPlaySource::preferenceChanged(PropertyContainer::PropertyName n)
00462 {
00463 if (n == "Resample Quality") {
00464 setResampleQuality(Preferences::getInstance()->getResampleQuality());
00465 }
00466 }
00467
00468 void
00469 AudioCallbackPlaySource::audioProcessingOverload()
00470 {
00471 RealTimePluginInstance *ap = m_auditioningPlugin;
00472 if (ap && m_playing && !m_auditioningPluginBypassed) {
00473 m_auditioningPluginBypassed = true;
00474 emit audioOverloadPluginDisabled();
00475 }
00476 }
00477
00478 void
00479 AudioCallbackPlaySource::setTarget(AudioCallbackPlayTarget *target, size_t size)
00480 {
00481 m_target = target;
00482
00483 assert(size < m_ringBufferSize);
00484 m_blockSize = size;
00485 }
00486
00487 size_t
00488 AudioCallbackPlaySource::getTargetBlockSize() const
00489 {
00490
00491 return m_blockSize;
00492 }
00493
00494 void
00495 AudioCallbackPlaySource::setTargetPlayLatency(size_t latency)
00496 {
00497 m_playLatency = latency;
00498 }
00499
00500 size_t
00501 AudioCallbackPlaySource::getTargetPlayLatency() const
00502 {
00503 return m_playLatency;
00504 }
00505
00506 size_t
00507 AudioCallbackPlaySource::getCurrentPlayingFrame()
00508 {
00509
00510
00511
00512 size_t targetRate = getTargetSampleRate();
00513 size_t latency = m_playLatency;
00514 RealTime latency_t = RealTime::frame2RealTime(latency, targetRate);
00515
00516 return getCurrentFrame(latency_t);
00517 }
00518
00519 size_t
00520 AudioCallbackPlaySource::getCurrentBufferedFrame()
00521 {
00522 return getCurrentFrame(RealTime::zeroTime);
00523 }
00524
00525 size_t
00526 AudioCallbackPlaySource::getCurrentFrame(RealTime latency_t)
00527 {
00528 bool resample = false;
00529 double resampleRatio = 1.0;
00530
00531
00532
00533
00534
00535
00536
00537 size_t sourceRate = getSourceSampleRate();
00538 size_t targetRate = getTargetSampleRate();
00539
00540 if (sourceRate == 0 || targetRate == 0) return 0;
00541
00542 size_t inbuffer = 0;
00543
00544 for (size_t c = 0; c < getTargetChannelCount(); ++c) {
00545 RingBuffer<float> *rb = getReadRingBuffer(c);
00546 if (rb) {
00547 size_t here = rb->getReadSpace();
00548 if (c == 0 || here < inbuffer) inbuffer = here;
00549 }
00550 }
00551
00552 size_t readBufferFill = m_readBufferFill;
00553 size_t lastRetrievedBlockSize = m_lastRetrievedBlockSize;
00554 double lastRetrievalTimestamp = m_lastRetrievalTimestamp;
00555 double currentTime = 0.0;
00556 if (m_target) currentTime = m_target->getCurrentTime();
00557
00558 RealTime inbuffer_t = RealTime::frame2RealTime(inbuffer, targetRate);
00559
00560 size_t stretchlat = 0;
00561 double timeRatio = 1.0;
00562
00563 if (m_timeStretcher) {
00564 stretchlat = m_timeStretcher->getLatency();
00565 timeRatio = m_timeStretcher->getTimeRatio();
00566 }
00567
00568 RealTime stretchlat_t = RealTime::frame2RealTime(stretchlat, targetRate);
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579 RealTime sincerequest_t = RealTime::zeroTime;
00580 RealTime lastretrieved_t = RealTime::zeroTime;
00581
00582 if (m_target && lastRetrievalTimestamp != 0.0) {
00583
00584 lastretrieved_t = RealTime::frame2RealTime
00585 (lastRetrievedBlockSize, targetRate);
00586
00587
00588
00589
00590 double elapsed = currentTime - lastRetrievalTimestamp;
00591
00592 if (elapsed > 0.0) {
00593 sincerequest_t = RealTime::fromSeconds(elapsed);
00594 }
00595
00596 } else {
00597
00598 lastretrieved_t = RealTime::frame2RealTime
00599 (getTargetBlockSize(), targetRate);
00600 }
00601
00602 RealTime bufferedto_t = RealTime::frame2RealTime(readBufferFill, sourceRate);
00603
00604 if (timeRatio != 1.0) {
00605 lastretrieved_t = lastretrieved_t / timeRatio;
00606 sincerequest_t = sincerequest_t / timeRatio;
00607 }
00608
00609 bool looping = m_viewManager->getPlayLoopMode();
00610
00611 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
00612 std::cerr << "\nbuffered to: " << bufferedto_t << ", in buffer: " << inbuffer_t << ", time ratio " << timeRatio << "\n stretcher latency: " << stretchlat_t << ", device latency: " << latency_t << "\n since request: " << sincerequest_t << ", last retrieved: " << lastretrieved_t << std::endl;
00613 #endif
00614
00615 RealTime end = RealTime::frame2RealTime(m_lastModelEndFrame, sourceRate);
00616
00617
00618
00619
00620
00621 if (m_rangeStarts.empty()) {
00622 rebuildRangeLists();
00623 }
00624
00625 if (m_rangeStarts.empty()) {
00626
00627 RealTime playing_t = bufferedto_t
00628 - latency_t - stretchlat_t - lastretrieved_t - inbuffer_t
00629 + sincerequest_t;
00630 size_t frame = RealTime::realTime2Frame(playing_t, sourceRate);
00631 return m_viewManager->alignPlaybackFrameToReference(frame);
00632 }
00633
00634 int inRange = 0;
00635 int index = 0;
00636
00637 for (size_t i = 0; i < m_rangeStarts.size(); ++i) {
00638 if (bufferedto_t >= m_rangeStarts[i]) {
00639 inRange = index;
00640 } else {
00641 break;
00642 }
00643 ++index;
00644 }
00645
00646 if (inRange >= m_rangeStarts.size()) inRange = m_rangeStarts.size()-1;
00647
00648 RealTime playing_t = bufferedto_t;
00649
00650 playing_t = playing_t
00651 - latency_t - stretchlat_t - lastretrieved_t - inbuffer_t
00652 + sincerequest_t;
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664 if (!m_playStartFramePassed) {
00665 RealTime playstart_t = RealTime::frame2RealTime(m_playStartFrame,
00666 sourceRate);
00667 if (playing_t < playstart_t) {
00668
00669
00670 if (sincerequest_t > RealTime::zeroTime &&
00671 m_playStartedAt + latency_t + stretchlat_t <
00672 RealTime::fromSeconds(currentTime)) {
00673
00674 m_playStartFramePassed = true;
00675 } else {
00676 playing_t = playstart_t;
00677 }
00678 } else {
00679 m_playStartFramePassed = true;
00680 }
00681 }
00682
00683 playing_t = playing_t - m_rangeStarts[inRange];
00684
00685 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
00686 std::cerr << "playing_t as offset into range " << inRange << " (with start = " << m_rangeStarts[inRange] << ") = " << playing_t << std::endl;
00687 #endif
00688
00689 while (playing_t < RealTime::zeroTime) {
00690
00691 if (inRange == 0) {
00692 if (looping) {
00693 inRange = m_rangeStarts.size() - 1;
00694 } else {
00695 break;
00696 }
00697 } else {
00698 --inRange;
00699 }
00700
00701 playing_t = playing_t + m_rangeDurations[inRange];
00702 }
00703
00704 playing_t = playing_t + m_rangeStarts[inRange];
00705
00706 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
00707 std::cerr << " playing time: " << playing_t << std::endl;
00708 #endif
00709
00710 if (!looping) {
00711 if (inRange == m_rangeStarts.size()-1 &&
00712 playing_t >= m_rangeStarts[inRange] + m_rangeDurations[inRange]) {
00713 std::cerr << "Not looping, inRange " << inRange << " == rangeStarts.size()-1, playing_t " << playing_t << " >= m_rangeStarts[inRange] " << m_rangeStarts[inRange] << " + m_rangeDurations[inRange] " << m_rangeDurations[inRange] << " -- stopping" << std::endl;
00714 stop();
00715 }
00716 }
00717
00718 if (playing_t < RealTime::zeroTime) playing_t = RealTime::zeroTime;
00719
00720 size_t frame = RealTime::realTime2Frame(playing_t, sourceRate);
00721 return m_viewManager->alignPlaybackFrameToReference(frame);
00722 }
00723
00724 void
00725 AudioCallbackPlaySource::rebuildRangeLists()
00726 {
00727 bool constrained = (m_viewManager->getPlaySelectionMode());
00728
00729 m_rangeStarts.clear();
00730 m_rangeDurations.clear();
00731
00732 size_t sourceRate = getSourceSampleRate();
00733 if (sourceRate == 0) return;
00734
00735 RealTime end = RealTime::frame2RealTime(m_lastModelEndFrame, sourceRate);
00736 if (end == RealTime::zeroTime) return;
00737
00738 if (!constrained) {
00739 m_rangeStarts.push_back(RealTime::zeroTime);
00740 m_rangeDurations.push_back(end);
00741 return;
00742 }
00743
00744 MultiSelection::SelectionList selections = m_viewManager->getSelections();
00745 MultiSelection::SelectionList::const_iterator i;
00746
00747 #ifdef DEBUG_AUDIO_PLAY_SOURCE
00748 std::cerr << "AudioCallbackPlaySource::rebuildRangeLists" << std::endl;
00749 #endif
00750
00751 if (!selections.empty()) {
00752
00753 for (i = selections.begin(); i != selections.end(); ++i) {
00754
00755 RealTime start =
00756 (RealTime::frame2RealTime
00757 (m_viewManager->alignReferenceToPlaybackFrame(i->getStartFrame()),
00758 sourceRate));
00759 RealTime duration =
00760 (RealTime::frame2RealTime
00761 (m_viewManager->alignReferenceToPlaybackFrame(i->getEndFrame()) -
00762 m_viewManager->alignReferenceToPlaybackFrame(i->getStartFrame()),
00763 sourceRate));
00764
00765 m_rangeStarts.push_back(start);
00766 m_rangeDurations.push_back(duration);
00767 }
00768 } else {
00769 m_rangeStarts.push_back(RealTime::zeroTime);
00770 m_rangeDurations.push_back(end);
00771 }
00772
00773 #ifdef DEBUG_AUDIO_PLAY_SOURCE
00774 std::cerr << "Now have " << m_rangeStarts.size() << " play ranges" << std::endl;
00775 #endif
00776 }
00777
00778 void
00779 AudioCallbackPlaySource::setOutputLevels(float left, float right)
00780 {
00781 m_outputLeft = left;
00782 m_outputRight = right;
00783 }
00784
00785 bool
00786 AudioCallbackPlaySource::getOutputLevels(float &left, float &right)
00787 {
00788 left = m_outputLeft;
00789 right = m_outputRight;
00790 return true;
00791 }
00792
00793 void
00794 AudioCallbackPlaySource::setTargetSampleRate(size_t sr)
00795 {
00796 m_targetSampleRate = sr;
00797 initialiseConverter();
00798 }
00799
00800 void
00801 AudioCallbackPlaySource::initialiseConverter()
00802 {
00803 m_mutex.lock();
00804
00805 if (m_converter) {
00806 src_delete(m_converter);
00807 src_delete(m_crapConverter);
00808 m_converter = 0;
00809 m_crapConverter = 0;
00810 }
00811
00812 if (getSourceSampleRate() != getTargetSampleRate()) {
00813
00814 int err = 0;
00815
00816 m_converter = src_new(m_resampleQuality == 2 ? SRC_SINC_BEST_QUALITY :
00817 m_resampleQuality == 1 ? SRC_SINC_MEDIUM_QUALITY :
00818 m_resampleQuality == 0 ? SRC_SINC_FASTEST :
00819 SRC_SINC_MEDIUM_QUALITY,
00820 getTargetChannelCount(), &err);
00821
00822 if (m_converter) {
00823 m_crapConverter = src_new(SRC_LINEAR,
00824 getTargetChannelCount(),
00825 &err);
00826 }
00827
00828 if (!m_converter || !m_crapConverter) {
00829 std::cerr
00830 << "AudioCallbackPlaySource::setModel: ERROR in creating samplerate converter: "
00831 << src_strerror(err) << std::endl;
00832
00833 if (m_converter) {
00834 src_delete(m_converter);
00835 m_converter = 0;
00836 }
00837
00838 if (m_crapConverter) {
00839 src_delete(m_crapConverter);
00840 m_crapConverter = 0;
00841 }
00842
00843 m_mutex.unlock();
00844
00845 emit sampleRateMismatch(getSourceSampleRate(),
00846 getTargetSampleRate(),
00847 false);
00848 } else {
00849
00850 m_mutex.unlock();
00851
00852 emit sampleRateMismatch(getSourceSampleRate(),
00853 getTargetSampleRate(),
00854 true);
00855 }
00856 } else {
00857 m_mutex.unlock();
00858 }
00859 }
00860
00861 void
00862 AudioCallbackPlaySource::setResampleQuality(int q)
00863 {
00864 if (q == m_resampleQuality) return;
00865 m_resampleQuality = q;
00866
00867 #ifdef DEBUG_AUDIO_PLAY_SOURCE
00868 std::cerr << "AudioCallbackPlaySource::setResampleQuality: setting to "
00869 << m_resampleQuality << std::endl;
00870 #endif
00871
00872 initialiseConverter();
00873 }
00874
00875 void
00876 AudioCallbackPlaySource::setAuditioningPlugin(RealTimePluginInstance *plugin)
00877 {
00878 RealTimePluginInstance *formerPlugin = m_auditioningPlugin;
00879 m_auditioningPlugin = plugin;
00880 m_auditioningPluginBypassed = false;
00881 if (formerPlugin) m_pluginScavenger.claim(formerPlugin);
00882 }
00883
00884 void
00885 AudioCallbackPlaySource::setSoloModelSet(std::set<Model *> s)
00886 {
00887 m_audioGenerator->setSoloModelSet(s);
00888 clearRingBuffers();
00889 }
00890
00891 void
00892 AudioCallbackPlaySource::clearSoloModelSet()
00893 {
00894 m_audioGenerator->clearSoloModelSet();
00895 clearRingBuffers();
00896 }
00897
00898 size_t
00899 AudioCallbackPlaySource::getTargetSampleRate() const
00900 {
00901 if (m_targetSampleRate) return m_targetSampleRate;
00902 else return getSourceSampleRate();
00903 }
00904
00905 size_t
00906 AudioCallbackPlaySource::getSourceChannelCount() const
00907 {
00908 return m_sourceChannelCount;
00909 }
00910
00911 size_t
00912 AudioCallbackPlaySource::getTargetChannelCount() const
00913 {
00914 if (m_sourceChannelCount < 2) return 2;
00915 return m_sourceChannelCount;
00916 }
00917
00918 size_t
00919 AudioCallbackPlaySource::getSourceSampleRate() const
00920 {
00921 return m_sourceSampleRate;
00922 }
00923
00924 void
00925 AudioCallbackPlaySource::setTimeStretch(float factor)
00926 {
00927 m_stretchRatio = factor;
00928
00929 if (m_timeStretcher || (factor == 1.f)) {
00930
00931 return;
00932 } else {
00933 m_stretcherInputCount = getTargetChannelCount();
00934 RubberBandStretcher *stretcher = new RubberBandStretcher
00935 (getTargetSampleRate(),
00936 m_stretcherInputCount,
00937 RubberBandStretcher::OptionProcessRealTime,
00938 factor);
00939 m_stretcherInputs = new float *[m_stretcherInputCount];
00940 m_stretcherInputSizes = new size_t[m_stretcherInputCount];
00941 for (size_t c = 0; c < m_stretcherInputCount; ++c) {
00942 m_stretcherInputSizes[c] = 16384;
00943 m_stretcherInputs[c] = new float[m_stretcherInputSizes[c]];
00944 }
00945 m_timeStretcher = stretcher;
00946 return;
00947 }
00948 }
00949
00950 size_t
00951 AudioCallbackPlaySource::getSourceSamples(size_t count, float **buffer)
00952 {
00953 if (!m_playing) {
00954 for (size_t ch = 0; ch < getTargetChannelCount(); ++ch) {
00955 for (size_t i = 0; i < count; ++i) {
00956 buffer[ch][i] = 0.0;
00957 }
00958 }
00959 return 0;
00960 }
00961
00962
00963
00964
00965 for (size_t ch = 0; ch < getTargetChannelCount(); ++ch) {
00966
00967 RingBuffer<float> *rb = getReadRingBuffer(ch);
00968
00969 if (!rb) {
00970 std::cerr << "WARNING: AudioCallbackPlaySource::getSourceSamples: "
00971 << "No ring buffer available for channel " << ch
00972 << ", returning no data here" << std::endl;
00973 count = 0;
00974 break;
00975 }
00976
00977 size_t rs = rb->getReadSpace();
00978 if (rs < count) {
00979 #ifdef DEBUG_AUDIO_PLAY_SOURCE
00980 std::cerr << "WARNING: AudioCallbackPlaySource::getSourceSamples: "
00981 << "Ring buffer for channel " << ch << " has only "
00982 << rs << " (of " << count << ") samples available, "
00983 << "reducing request size" << std::endl;
00984 #endif
00985 count = rs;
00986 }
00987 }
00988
00989 if (count == 0) return 0;
00990
00991 RubberBandStretcher *ts = m_timeStretcher;
00992 float ratio = ts ? ts->getTimeRatio() : 1.f;
00993
00994 if (ratio != m_stretchRatio) {
00995 if (!ts) {
00996 std::cerr << "WARNING: AudioCallbackPlaySource::getSourceSamples: Time ratio change to " << m_stretchRatio << " is pending, but no stretcher is set" << std::endl;
00997 m_stretchRatio = 1.f;
00998 } else {
00999 ts->setTimeRatio(m_stretchRatio);
01000 }
01001 }
01002
01003 if (m_target) {
01004 m_lastRetrievedBlockSize = count;
01005 m_lastRetrievalTimestamp = m_target->getCurrentTime();
01006 }
01007
01008 if (!ts || ratio == 1.f) {
01009
01010 size_t got = 0;
01011
01012 for (size_t ch = 0; ch < getTargetChannelCount(); ++ch) {
01013
01014 RingBuffer<float> *rb = getReadRingBuffer(ch);
01015
01016 if (rb) {
01017
01018
01019
01020 size_t request = count;
01021 if (ch > 0) request = got;
01022
01023 got = rb->read(buffer[ch], request);
01024
01025 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
01026 std::cout << "AudioCallbackPlaySource::getSamples: got " << got << " (of " << count << ") samples on channel " << ch << ", signalling for more (possibly)" << std::endl;
01027 #endif
01028 }
01029
01030 for (size_t ch = 0; ch < getTargetChannelCount(); ++ch) {
01031 for (size_t i = got; i < count; ++i) {
01032 buffer[ch][i] = 0.0;
01033 }
01034 }
01035 }
01036
01037 applyAuditioningEffect(count, buffer);
01038
01039 m_condition.wakeAll();
01040
01041 return got;
01042 }
01043
01044 size_t channels = getTargetChannelCount();
01045 size_t available;
01046 int warned = 0;
01047 size_t fedToStretcher = 0;
01048
01049
01050
01051
01052 while ((available = ts->available()) < count) {
01053
01054 size_t reqd = lrintf((count - available) / ratio);
01055 reqd = std::max(reqd, ts->getSamplesRequired());
01056 if (reqd == 0) reqd = 1;
01057
01058 size_t got = reqd;
01059
01060 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
01061 std::cerr << "reqd = " <<reqd << ", channels = " << channels << ", ic = " << m_stretcherInputCount << std::endl;
01062 #endif
01063
01064 for (size_t c = 0; c < channels; ++c) {
01065 if (c >= m_stretcherInputCount) continue;
01066 if (reqd > m_stretcherInputSizes[c]) {
01067 if (c == 0) {
01068 std::cerr << "WARNING: resizing stretcher input buffer from " << m_stretcherInputSizes[c] << " to " << (reqd * 2) << std::endl;
01069 }
01070 delete[] m_stretcherInputs[c];
01071 m_stretcherInputSizes[c] = reqd * 2;
01072 m_stretcherInputs[c] = new float[m_stretcherInputSizes[c]];
01073 }
01074 }
01075
01076 for (size_t c = 0; c < channels; ++c) {
01077 if (c >= m_stretcherInputCount) continue;
01078 RingBuffer<float> *rb = getReadRingBuffer(c);
01079 if (rb) {
01080 size_t gotHere = rb->read(m_stretcherInputs[c], got);
01081 if (gotHere < got) got = gotHere;
01082
01083 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
01084 if (c == 0) {
01085 std::cerr << "feeding stretcher: got " << gotHere
01086 << ", " << rb->getReadSpace() << " remain" << std::endl;
01087 }
01088 #endif
01089
01090 } else {
01091 std::cerr << "WARNING: No ring buffer available for channel " << c << " in stretcher input block" << std::endl;
01092 }
01093 }
01094
01095 if (got < reqd) {
01096 std::cerr << "WARNING: Read underrun in playback ("
01097 << got << " < " << reqd << ")" << std::endl;
01098 }
01099
01100 ts->process(m_stretcherInputs, got, false);
01101
01102 fedToStretcher += got;
01103
01104 if (got == 0) break;
01105
01106 if (ts->available() == available) {
01107 std::cerr << "WARNING: AudioCallbackPlaySource::getSamples: Added " << got << " samples to time stretcher, created no new available output samples (warned = " << warned << ")" << std::endl;
01108 if (++warned == 5) break;
01109 }
01110 }
01111
01112 ts->retrieve(buffer, count);
01113
01114 applyAuditioningEffect(count, buffer);
01115
01116 m_condition.wakeAll();
01117
01118 return count;
01119 }
01120
01121 void
01122 AudioCallbackPlaySource::applyAuditioningEffect(size_t count, float **buffers)
01123 {
01124 if (m_auditioningPluginBypassed) return;
01125 RealTimePluginInstance *plugin = m_auditioningPlugin;
01126 if (!plugin) return;
01127
01128 if (plugin->getAudioInputCount() != getTargetChannelCount()) {
01129
01130
01131
01132 return;
01133 }
01134 if (plugin->getAudioOutputCount() != getTargetChannelCount()) {
01135
01136
01137
01138 return;
01139 }
01140 if (plugin->getBufferSize() != count) {
01141
01142
01143
01144 return;
01145 }
01146
01147 float **ib = plugin->getAudioInputBuffers();
01148 float **ob = plugin->getAudioOutputBuffers();
01149
01150 for (size_t c = 0; c < getTargetChannelCount(); ++c) {
01151 for (size_t i = 0; i < count; ++i) {
01152 ib[c][i] = buffers[c][i];
01153 }
01154 }
01155
01156 plugin->run(Vamp::RealTime::zeroTime);
01157
01158 for (size_t c = 0; c < getTargetChannelCount(); ++c) {
01159 for (size_t i = 0; i < count; ++i) {
01160 buffers[c][i] = ob[c][i];
01161 }
01162 }
01163 }
01164
01165
01166 bool
01167 AudioCallbackPlaySource::fillBuffers()
01168 {
01169 static float *tmp = 0;
01170 static size_t tmpSize = 0;
01171
01172 size_t space = 0;
01173 for (size_t c = 0; c < getTargetChannelCount(); ++c) {
01174 RingBuffer<float> *wb = getWriteRingBuffer(c);
01175 if (wb) {
01176 size_t spaceHere = wb->getWriteSpace();
01177 if (c == 0 || spaceHere < space) space = spaceHere;
01178 }
01179 }
01180
01181 if (space == 0) return false;
01182
01183 size_t f = m_writeBufferFill;
01184
01185 bool readWriteEqual = (m_readBuffers == m_writeBuffers);
01186
01187 #ifdef DEBUG_AUDIO_PLAY_SOURCE
01188 std::cout << "AudioCallbackPlaySourceFillThread: filling " << space << " frames" << std::endl;
01189 #endif
01190
01191 #ifdef DEBUG_AUDIO_PLAY_SOURCE
01192 std::cout << "buffered to " << f << " already" << std::endl;
01193 #endif
01194
01195 bool resample = (getSourceSampleRate() != getTargetSampleRate());
01196
01197 #ifdef DEBUG_AUDIO_PLAY_SOURCE
01198 std::cout << (resample ? "" : "not ") << "resampling (source " << getSourceSampleRate() << ", target " << getTargetSampleRate() << ")" << std::endl;
01199 #endif
01200
01201 size_t channels = getTargetChannelCount();
01202
01203 size_t orig = space;
01204 size_t got = 0;
01205
01206 static float **bufferPtrs = 0;
01207 static size_t bufferPtrCount = 0;
01208
01209 if (bufferPtrCount < channels) {
01210 if (bufferPtrs) delete[] bufferPtrs;
01211 bufferPtrs = new float *[channels];
01212 bufferPtrCount = channels;
01213 }
01214
01215 size_t generatorBlockSize = m_audioGenerator->getBlockSize();
01216
01217 if (resample && !m_converter) {
01218 static bool warned = false;
01219 if (!warned) {
01220 std::cerr << "WARNING: sample rates differ, but no converter available!" << std::endl;
01221 warned = true;
01222 }
01223 }
01224
01225 if (resample && m_converter) {
01226
01227 double ratio =
01228 double(getTargetSampleRate()) / double(getSourceSampleRate());
01229 orig = size_t(orig / ratio + 0.1);
01230
01231
01232 orig = (orig / generatorBlockSize) * generatorBlockSize;
01233 if (orig == 0) return false;
01234
01235 size_t work = std::max(orig, space);
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248 if (tmpSize < channels * work * 2) {
01249 delete[] tmp;
01250 tmp = new float[channels * work * 2];
01251 tmpSize = channels * work * 2;
01252 }
01253
01254 float *nonintlv = tmp + channels * work;
01255 float *intlv = tmp;
01256 float *srcout = tmp + channels * work;
01257
01258 for (size_t c = 0; c < channels; ++c) {
01259 for (size_t i = 0; i < orig; ++i) {
01260 nonintlv[channels * i + c] = 0.0f;
01261 }
01262 }
01263
01264 for (size_t c = 0; c < channels; ++c) {
01265 bufferPtrs[c] = nonintlv + c * orig;
01266 }
01267
01268 got = mixModels(f, orig, bufferPtrs);
01269
01270
01271 for (size_t c = 0; c < channels; ++c) {
01272 for (size_t i = 0; i < got; ++i) {
01273 float sample = nonintlv[c * got + i];
01274 intlv[channels * i + c] = sample;
01275 }
01276 }
01277
01278 SRC_DATA data;
01279 data.data_in = intlv;
01280 data.data_out = srcout;
01281 data.input_frames = got;
01282 data.output_frames = work;
01283 data.src_ratio = ratio;
01284 data.end_of_input = 0;
01285
01286 int err = 0;
01287
01288 if (m_timeStretcher && m_timeStretcher->getTimeRatio() < 0.4) {
01289 #ifdef DEBUG_AUDIO_PLAY_SOURCE
01290 std::cout << "Using crappy converter" << std::endl;
01291 #endif
01292 err = src_process(m_crapConverter, &data);
01293 } else {
01294 err = src_process(m_converter, &data);
01295 }
01296
01297 size_t toCopy = size_t(got * ratio + 0.1);
01298
01299 if (err) {
01300 std::cerr
01301 << "AudioCallbackPlaySourceFillThread: ERROR in samplerate conversion: "
01302 << src_strerror(err) << std::endl;
01304 } else {
01305 got = data.input_frames_used;
01306 toCopy = data.output_frames_gen;
01307 #ifdef DEBUG_AUDIO_PLAY_SOURCE
01308 std::cout << "Resampled " << got << " frames to " << toCopy << " frames" << std::endl;
01309 #endif
01310 }
01311
01312 for (size_t c = 0; c < channels; ++c) {
01313 for (size_t i = 0; i < toCopy; ++i) {
01314 tmp[i] = srcout[channels * i + c];
01315 }
01316 RingBuffer<float> *wb = getWriteRingBuffer(c);
01317 if (wb) wb->write(tmp, toCopy);
01318 }
01319
01320 m_writeBufferFill = f;
01321 if (readWriteEqual) m_readBufferFill = f;
01322
01323 } else {
01324
01325
01326 space = (space / generatorBlockSize) * generatorBlockSize;
01327 if (space == 0) {
01328 #ifdef DEBUG_AUDIO_PLAY_SOURCE
01329 std::cout << "requested fill is less than generator block size of "
01330 << generatorBlockSize << ", leaving it" << std::endl;
01331 #endif
01332 return false;
01333 }
01334
01335 if (tmpSize < channels * space) {
01336 delete[] tmp;
01337 tmp = new float[channels * space];
01338 tmpSize = channels * space;
01339 }
01340
01341 for (size_t c = 0; c < channels; ++c) {
01342
01343 bufferPtrs[c] = tmp + c * space;
01344
01345 for (size_t i = 0; i < space; ++i) {
01346 tmp[c * space + i] = 0.0f;
01347 }
01348 }
01349
01350 size_t got = mixModels(f, space, bufferPtrs);
01351
01352 for (size_t c = 0; c < channels; ++c) {
01353
01354 RingBuffer<float> *wb = getWriteRingBuffer(c);
01355 if (wb) {
01356 size_t actual = wb->write(bufferPtrs[c], got);
01357 #ifdef DEBUG_AUDIO_PLAY_SOURCE
01358 std::cout << "Wrote " << actual << " samples for ch " << c << ", now "
01359 << wb->getReadSpace() << " to read"
01360 << std::endl;
01361 #endif
01362 if (actual < got) {
01363 std::cerr << "WARNING: Buffer overrun in channel " << c
01364 << ": wrote " << actual << " of " << got
01365 << " samples" << std::endl;
01366 }
01367 }
01368 }
01369
01370 m_writeBufferFill = f;
01371 if (readWriteEqual) m_readBufferFill = f;
01372
01374 }
01375
01376 return true;
01377 }
01378
01379 size_t
01380 AudioCallbackPlaySource::mixModels(size_t &frame, size_t count, float **buffers)
01381 {
01382 size_t processed = 0;
01383 size_t chunkStart = frame;
01384 size_t chunkSize = count;
01385 size_t selectionSize = 0;
01386 size_t nextChunkStart = chunkStart + chunkSize;
01387
01388 bool looping = m_viewManager->getPlayLoopMode();
01389 bool constrained = (m_viewManager->getPlaySelectionMode() &&
01390 !m_viewManager->getSelections().empty());
01391
01392 static float **chunkBufferPtrs = 0;
01393 static size_t chunkBufferPtrCount = 0;
01394 size_t channels = getTargetChannelCount();
01395
01396 #ifdef DEBUG_AUDIO_PLAY_SOURCE
01397 std::cout << "Selection playback: start " << frame << ", size " << count <<", channels " << channels << std::endl;
01398 #endif
01399
01400 if (chunkBufferPtrCount < channels) {
01401 if (chunkBufferPtrs) delete[] chunkBufferPtrs;
01402 chunkBufferPtrs = new float *[channels];
01403 chunkBufferPtrCount = channels;
01404 }
01405
01406 for (size_t c = 0; c < channels; ++c) {
01407 chunkBufferPtrs[c] = buffers[c];
01408 }
01409
01410 while (processed < count) {
01411
01412 chunkSize = count - processed;
01413 nextChunkStart = chunkStart + chunkSize;
01414 selectionSize = 0;
01415
01416 size_t fadeIn = 0, fadeOut = 0;
01417
01418 if (constrained) {
01419
01420 size_t rChunkStart =
01421 m_viewManager->alignPlaybackFrameToReference(chunkStart);
01422
01423 Selection selection =
01424 m_viewManager->getContainingSelection(rChunkStart, true);
01425
01426 if (selection.isEmpty()) {
01427 if (looping) {
01428 selection = *m_viewManager->getSelections().begin();
01429 chunkStart = m_viewManager->alignReferenceToPlaybackFrame
01430 (selection.getStartFrame());
01431 fadeIn = 50;
01432 }
01433 }
01434
01435 if (selection.isEmpty()) {
01436
01437 chunkSize = 0;
01438 nextChunkStart = chunkStart;
01439
01440 } else {
01441
01442 size_t sf = m_viewManager->alignReferenceToPlaybackFrame
01443 (selection.getStartFrame());
01444 size_t ef = m_viewManager->alignReferenceToPlaybackFrame
01445 (selection.getEndFrame());
01446
01447 selectionSize = ef - sf;
01448
01449 if (chunkStart < sf) {
01450 chunkStart = sf;
01451 fadeIn = 50;
01452 }
01453
01454 nextChunkStart = chunkStart + chunkSize;
01455
01456 if (nextChunkStart >= ef) {
01457 nextChunkStart = ef;
01458 fadeOut = 50;
01459 }
01460
01461 chunkSize = nextChunkStart - chunkStart;
01462 }
01463
01464 } else if (looping && m_lastModelEndFrame > 0) {
01465
01466 if (chunkStart >= m_lastModelEndFrame) {
01467 chunkStart = 0;
01468 }
01469 if (chunkSize > m_lastModelEndFrame - chunkStart) {
01470 chunkSize = m_lastModelEndFrame - chunkStart;
01471 }
01472 nextChunkStart = chunkStart + chunkSize;
01473 }
01474
01475
01476
01477 if (!chunkSize) {
01478 #ifdef DEBUG_AUDIO_PLAY_SOURCE
01479 std::cout << "Ending selection playback at " << nextChunkStart << std::endl;
01480 #endif
01481
01482
01483
01484 frame = frame + count;
01485 return count;
01486 }
01487
01488 #ifdef DEBUG_AUDIO_PLAY_SOURCE
01489 std::cout << "Selection playback: chunk at " << chunkStart << " -> " << nextChunkStart << " (size " << chunkSize << ")" << std::endl;
01490 #endif
01491
01492 size_t got = 0;
01493
01494 if (selectionSize < 100) {
01495 fadeIn = 0;
01496 fadeOut = 0;
01497 } else if (selectionSize < 300) {
01498 if (fadeIn > 0) fadeIn = 10;
01499 if (fadeOut > 0) fadeOut = 10;
01500 }
01501
01502 if (fadeIn > 0) {
01503 if (processed * 2 < fadeIn) {
01504 fadeIn = processed * 2;
01505 }
01506 }
01507
01508 if (fadeOut > 0) {
01509 if ((count - processed - chunkSize) * 2 < fadeOut) {
01510 fadeOut = (count - processed - chunkSize) * 2;
01511 }
01512 }
01513
01514 for (std::set<Model *>::iterator mi = m_models.begin();
01515 mi != m_models.end(); ++mi) {
01516
01517 got = m_audioGenerator->mixModel(*mi, chunkStart,
01518 chunkSize, chunkBufferPtrs,
01519 fadeIn, fadeOut);
01520 }
01521
01522 for (size_t c = 0; c < channels; ++c) {
01523 chunkBufferPtrs[c] += chunkSize;
01524 }
01525
01526 processed += chunkSize;
01527 chunkStart = nextChunkStart;
01528 }
01529
01530 #ifdef DEBUG_AUDIO_PLAY_SOURCE
01531 std::cout << "Returning selection playback " << processed << " frames to " << nextChunkStart << std::endl;
01532 #endif
01533
01534 frame = nextChunkStart;
01535 return processed;
01536 }
01537
01538 void
01539 AudioCallbackPlaySource::unifyRingBuffers()
01540 {
01541 if (m_readBuffers == m_writeBuffers) return;
01542
01543
01544 for (size_t c = 0; c < getTargetChannelCount(); ++c) {
01545 RingBuffer<float> *wb = getWriteRingBuffer(c);
01546 if (wb) {
01547 if (wb->getReadSpace() < m_blockSize * 2) {
01548 if ((m_writeBufferFill + m_blockSize * 2) <
01549 m_lastModelEndFrame) {
01550
01551
01552 return;
01553 }
01554 }
01555 break;
01556 }
01557 }
01558
01559 size_t rf = m_readBufferFill;
01560 RingBuffer<float> *rb = getReadRingBuffer(0);
01561 if (rb) {
01562 size_t rs = rb->getReadSpace();
01564
01565 if (rs < rf) rf -= rs;
01566 else rf = 0;
01567 }
01568
01569
01570
01571 size_t wf = m_writeBufferFill;
01572 size_t skip = 0;
01573 for (size_t c = 0; c < getTargetChannelCount(); ++c) {
01574 RingBuffer<float> *wb = getWriteRingBuffer(c);
01575 if (wb) {
01576 if (c == 0) {
01577
01578 size_t wrs = wb->getReadSpace();
01579
01580
01581 if (wrs < wf) wf -= wrs;
01582 else wf = 0;
01583
01584
01585 if (wf < rf) skip = rf - wf;
01586 if (skip == 0) break;
01587 }
01588
01589
01590 wb->skip(skip);
01591 }
01592 }
01593
01594 m_bufferScavenger.claim(m_readBuffers);
01595 m_readBuffers = m_writeBuffers;
01596 m_readBufferFill = m_writeBufferFill;
01597
01598 }
01599
01600 void
01601 AudioCallbackPlaySource::FillThread::run()
01602 {
01603 AudioCallbackPlaySource &s(m_source);
01604
01605 #ifdef DEBUG_AUDIO_PLAY_SOURCE
01606 std::cout << "AudioCallbackPlaySourceFillThread starting" << std::endl;
01607 #endif
01608
01609 s.m_mutex.lock();
01610
01611 bool previouslyPlaying = s.m_playing;
01612 bool work = false;
01613
01614 while (!s.m_exiting) {
01615
01616 s.unifyRingBuffers();
01617 s.m_bufferScavenger.scavenge();
01618 s.m_pluginScavenger.scavenge();
01619
01620 if (work && s.m_playing && s.getSourceSampleRate()) {
01621
01622 #ifdef DEBUG_AUDIO_PLAY_SOURCE
01623 std::cout << "AudioCallbackPlaySourceFillThread: not waiting" << std::endl;
01624 #endif
01625
01626 s.m_mutex.unlock();
01627 s.m_mutex.lock();
01628
01629 } else {
01630
01631 float ms = 100;
01632 if (s.getSourceSampleRate() > 0) {
01633 ms = float(m_ringBufferSize) / float(s.getSourceSampleRate()) * 1000.0;
01634 }
01635
01636 if (s.m_playing) ms /= 10;
01637
01638 #ifdef DEBUG_AUDIO_PLAY_SOURCE
01639 if (!s.m_playing) std::cout << std::endl;
01640 std::cout << "AudioCallbackPlaySourceFillThread: waiting for " << ms << "ms..." << std::endl;
01641 #endif
01642
01643 s.m_condition.wait(&s.m_mutex, size_t(ms));
01644 }
01645
01646 #ifdef DEBUG_AUDIO_PLAY_SOURCE
01647 std::cout << "AudioCallbackPlaySourceFillThread: awoken" << std::endl;
01648 #endif
01649
01650 work = false;
01651
01652 if (!s.getSourceSampleRate()) continue;
01653
01654 bool playing = s.m_playing;
01655
01656 if (playing && !previouslyPlaying) {
01657 #ifdef DEBUG_AUDIO_PLAY_SOURCE
01658 std::cout << "AudioCallbackPlaySourceFillThread: playback state changed, resetting" << std::endl;
01659 #endif
01660 for (size_t c = 0; c < s.getTargetChannelCount(); ++c) {
01661 RingBuffer<float> *rb = s.getReadRingBuffer(c);
01662 if (rb) rb->reset();
01663 }
01664 }
01665 previouslyPlaying = playing;
01666
01667 work = s.fillBuffers();
01668 }
01669
01670 s.m_mutex.unlock();
01671 }
01672