svapp  1.9
AudioCallbackPlaySource.cpp
Go to the documentation of this file.
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
00002 
00003 /*
00004     Sonic Visualiser
00005     An audio file viewer and annotation editor.
00006     Centre for Digital Music, Queen Mary, University of London.
00007     This file copyright 2006 Chris Cannam and QMUL.
00008     
00009     This program is free software; you can redistribute it and/or
00010     modify it under the terms of the GNU General Public License as
00011     published by the Free Software Foundation; either version 2 of the
00012     License, or (at your option) any later version.  See the file
00013     COPYING included with this distribution for more information.
00014 */
00015 
00016 #include "AudioCallbackPlaySource.h"
00017 
00018 #include "AudioGenerator.h"
00019 
00020 #include "data/model/Model.h"
00021 #include "base/ViewManagerBase.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 //#define DEBUG_AUDIO_PLAY_SOURCE 1
00038 //#define DEBUG_AUDIO_PLAY_SOURCE_PLAYING 1
00039 
00040 static const int DEFAULT_RING_BUFFER_SIZE = 131071;
00041 
00042 AudioCallbackPlaySource::AudioCallbackPlaySource(ViewManagerBase *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_trustworthyTimestamps(true),
00061     m_lastCurrentFrame(0),
00062     m_playing(false),
00063     m_exiting(false),
00064     m_lastModelEndFrame(0),
00065     m_ringBufferSize(DEFAULT_RING_BUFFER_SIZE),
00066     m_outputLeft(0.0),
00067     m_outputRight(0.0),
00068     m_auditioningPlugin(0),
00069     m_auditioningPluginBypassed(false),
00070     m_playStartFrame(0),
00071     m_playStartFramePassed(false),
00072     m_timeStretcher(0),
00073     m_monoStretcher(0),
00074     m_stretchRatio(1.0),
00075     m_stretchMono(false),
00076     m_stretcherInputCount(0),
00077     m_stretcherInputs(0),
00078     m_stretcherInputSizes(0),
00079     m_fillThread(0),
00080     m_converter(0),
00081     m_crapConverter(0),
00082     m_resampleQuality(Preferences::getInstance()->getResampleQuality())
00083 {
00084     m_viewManager->setAudioPlaySource(this);
00085 
00086     connect(m_viewManager, SIGNAL(selectionChanged()),
00087             this, SLOT(selectionChanged()));
00088     connect(m_viewManager, SIGNAL(playLoopModeChanged()),
00089             this, SLOT(playLoopModeChanged()));
00090     connect(m_viewManager, SIGNAL(playSelectionModeChanged()),
00091             this, SLOT(playSelectionModeChanged()));
00092 
00093     connect(this, SIGNAL(playStatusChanged(bool)),
00094             m_viewManager, SLOT(playStatusChanged(bool)));
00095 
00096     connect(PlayParameterRepository::getInstance(),
00097             SIGNAL(playParametersChanged(PlayParameters *)),
00098             this, SLOT(playParametersChanged(PlayParameters *)));
00099 
00100     connect(Preferences::getInstance(),
00101             SIGNAL(propertyChanged(PropertyContainer::PropertyName)),
00102             this, SLOT(preferenceChanged(PropertyContainer::PropertyName)));
00103 }
00104 
00105 AudioCallbackPlaySource::~AudioCallbackPlaySource()
00106 {
00107 #ifdef DEBUG_AUDIO_PLAY_SOURCE
00108     SVDEBUG << "AudioCallbackPlaySource::~AudioCallbackPlaySource entering" << endl;
00109 #endif
00110     m_exiting = true;
00111 
00112     if (m_fillThread) {
00113 #ifdef DEBUG_AUDIO_PLAY_SOURCE
00114     cout << "AudioCallbackPlaySource dtor: awakening thread" << endl;
00115 #endif
00116         m_condition.wakeAll();
00117         m_fillThread->wait();
00118         delete m_fillThread;
00119     }
00120 
00121     clearModels();
00122     
00123     if (m_readBuffers != m_writeBuffers) {
00124         delete m_readBuffers;
00125     }
00126 
00127     delete m_writeBuffers;
00128 
00129     delete m_audioGenerator;
00130 
00131     for (int i = 0; i < m_stretcherInputCount; ++i) {
00132         delete[] m_stretcherInputs[i];
00133     }
00134     delete[] m_stretcherInputSizes;
00135     delete[] m_stretcherInputs;
00136 
00137     delete m_timeStretcher;
00138     delete m_monoStretcher;
00139 
00140     m_bufferScavenger.scavenge(true);
00141     m_pluginScavenger.scavenge(true);
00142 #ifdef DEBUG_AUDIO_PLAY_SOURCE
00143     SVDEBUG << "AudioCallbackPlaySource::~AudioCallbackPlaySource finishing" << endl;
00144 #endif
00145 }
00146 
00147 void
00148 AudioCallbackPlaySource::addModel(Model *model)
00149 {
00150     if (m_models.find(model) != m_models.end()) return;
00151 
00152     bool canPlay = m_audioGenerator->addModel(model);
00153 
00154     m_mutex.lock();
00155 
00156     m_models.insert(model);
00157     if (model->getEndFrame() > m_lastModelEndFrame) {
00158         m_lastModelEndFrame = model->getEndFrame();
00159     }
00160 
00161     bool buffersChanged = false, srChanged = false;
00162 
00163     int modelChannels = 1;
00164     DenseTimeValueModel *dtvm = dynamic_cast<DenseTimeValueModel *>(model);
00165     if (dtvm) modelChannels = dtvm->getChannelCount();
00166     if (modelChannels > m_sourceChannelCount) {
00167         m_sourceChannelCount = modelChannels;
00168     }
00169 
00170 #ifdef DEBUG_AUDIO_PLAY_SOURCE
00171     cout << "AudioCallbackPlaySource: Adding model with " << modelChannels << " channels at rate " << model->getSampleRate() << endl;
00172 #endif
00173 
00174     if (m_sourceSampleRate == 0) {
00175 
00176         m_sourceSampleRate = model->getSampleRate();
00177         srChanged = true;
00178 
00179     } else if (model->getSampleRate() != m_sourceSampleRate) {
00180 
00181         // If this is a dense time-value model and we have no other, we
00182         // can just switch to this model's sample rate
00183 
00184         if (dtvm) {
00185 
00186             bool conflicting = false;
00187 
00188             for (std::set<Model *>::const_iterator i = m_models.begin();
00189                  i != m_models.end(); ++i) {
00190                 // Only wave file models can be considered conflicting --
00191                 // writable wave file models are derived and we shouldn't
00192                 // take their rates into account.  Also, don't give any
00193                 // particular weight to a file that's already playing at
00194                 // the wrong rate anyway
00195                 WaveFileModel *wfm = dynamic_cast<WaveFileModel *>(*i);
00196                 if (wfm && wfm != dtvm &&
00197                     wfm->getSampleRate() != model->getSampleRate() &&
00198                     wfm->getSampleRate() == m_sourceSampleRate) {
00199                     SVDEBUG << "AudioCallbackPlaySource::addModel: Conflicting wave file model " << *i << " found" << endl;
00200                     conflicting = true;
00201                     break;
00202                 }
00203             }
00204 
00205             if (conflicting) {
00206 
00207                 SVDEBUG << "AudioCallbackPlaySource::addModel: ERROR: "
00208                           << "New model sample rate does not match" << endl
00209                           << "existing model(s) (new " << model->getSampleRate()
00210                           << " vs " << m_sourceSampleRate
00211                           << "), playback will be wrong"
00212                           << endl;
00213                 
00214                 emit sampleRateMismatch(model->getSampleRate(),
00215                                         m_sourceSampleRate,
00216                                         false);
00217             } else {
00218                 m_sourceSampleRate = model->getSampleRate();
00219                 srChanged = true;
00220             }
00221         }
00222     }
00223 
00224     if (!m_writeBuffers || (int)m_writeBuffers->size() < getTargetChannelCount()) {
00225         clearRingBuffers(true, getTargetChannelCount());
00226         buffersChanged = true;
00227     } else {
00228         if (canPlay) clearRingBuffers(true);
00229     }
00230 
00231     if (buffersChanged || srChanged) {
00232         if (m_converter) {
00233             src_delete(m_converter);
00234             src_delete(m_crapConverter);
00235             m_converter = 0;
00236             m_crapConverter = 0;
00237         }
00238     }
00239 
00240     rebuildRangeLists();
00241 
00242     m_mutex.unlock();
00243 
00244     m_audioGenerator->setTargetChannelCount(getTargetChannelCount());
00245 
00246     if (!m_fillThread) {
00247         m_fillThread = new FillThread(*this);
00248         m_fillThread->start();
00249     }
00250 
00251 #ifdef DEBUG_AUDIO_PLAY_SOURCE
00252     cout << "AudioCallbackPlaySource::addModel: now have " << m_models.size() << " model(s) -- emitting modelReplaced" << endl;
00253 #endif
00254 
00255     if (buffersChanged || srChanged) {
00256         emit modelReplaced();
00257     }
00258 
00259     connect(model, SIGNAL(modelChangedWithin(int, int)),
00260             this, SLOT(modelChangedWithin(int, int)));
00261 
00262 #ifdef DEBUG_AUDIO_PLAY_SOURCE
00263     cout << "AudioCallbackPlaySource::addModel: awakening thread" << endl;
00264 #endif
00265 
00266     m_condition.wakeAll();
00267 }
00268 
00269 void
00270 AudioCallbackPlaySource::modelChangedWithin(int 
00271 #ifdef DEBUG_AUDIO_PLAY_SOURCE
00272                                             startFrame
00273 #endif
00274                                             , int endFrame)
00275 {
00276 #ifdef DEBUG_AUDIO_PLAY_SOURCE
00277     SVDEBUG << "AudioCallbackPlaySource::modelChangedWithin(" << startFrame << "," << endFrame << ")" << endl;
00278 #endif
00279     if (endFrame > m_lastModelEndFrame) {
00280         m_lastModelEndFrame = endFrame;
00281         rebuildRangeLists();
00282     }
00283 }
00284 
00285 void
00286 AudioCallbackPlaySource::removeModel(Model *model)
00287 {
00288     m_mutex.lock();
00289 
00290 #ifdef DEBUG_AUDIO_PLAY_SOURCE
00291     cout << "AudioCallbackPlaySource::removeModel(" << model << ")" << endl;
00292 #endif
00293 
00294     disconnect(model, SIGNAL(modelChangedWithin(int, int)),
00295                this, SLOT(modelChangedWithin(int, int)));
00296 
00297     m_models.erase(model);
00298 
00299     if (m_models.empty()) {
00300         if (m_converter) {
00301             src_delete(m_converter);
00302             src_delete(m_crapConverter);
00303             m_converter = 0;
00304             m_crapConverter = 0;
00305         }
00306         m_sourceSampleRate = 0;
00307     }
00308 
00309     int lastEnd = 0;
00310     for (std::set<Model *>::const_iterator i = m_models.begin();
00311          i != m_models.end(); ++i) {
00312 #ifdef DEBUG_AUDIO_PLAY_SOURCE
00313         cout << "AudioCallbackPlaySource::removeModel(" << model << "): checking end frame on model " << *i << endl;
00314 #endif
00315         if ((*i)->getEndFrame() > lastEnd) {
00316             lastEnd = (*i)->getEndFrame();
00317         }
00318 #ifdef DEBUG_AUDIO_PLAY_SOURCE
00319         cout << "(done, lastEnd now " << lastEnd << ")" << endl;
00320 #endif
00321     }
00322     m_lastModelEndFrame = lastEnd;
00323 
00324     m_audioGenerator->removeModel(model);
00325 
00326     m_mutex.unlock();
00327 
00328     clearRingBuffers();
00329 }
00330 
00331 void
00332 AudioCallbackPlaySource::clearModels()
00333 {
00334     m_mutex.lock();
00335 
00336 #ifdef DEBUG_AUDIO_PLAY_SOURCE
00337     cout << "AudioCallbackPlaySource::clearModels()" << endl;
00338 #endif
00339 
00340     m_models.clear();
00341 
00342     if (m_converter) {
00343         src_delete(m_converter);
00344         src_delete(m_crapConverter);
00345         m_converter = 0;
00346         m_crapConverter = 0;
00347     }
00348 
00349     m_lastModelEndFrame = 0;
00350 
00351     m_sourceSampleRate = 0;
00352 
00353     m_mutex.unlock();
00354 
00355     m_audioGenerator->clearModels();
00356 
00357     clearRingBuffers();
00358 }    
00359 
00360 void
00361 AudioCallbackPlaySource::clearRingBuffers(bool haveLock, int count)
00362 {
00363     if (!haveLock) m_mutex.lock();
00364 
00365     cerr << "clearRingBuffers" << endl;
00366 
00367     rebuildRangeLists();
00368 
00369     if (count == 0) {
00370         if (m_writeBuffers) count = m_writeBuffers->size();
00371     }
00372 
00373     cerr << "current playing frame = " << getCurrentPlayingFrame() << endl;
00374 
00375     cerr << "write buffer fill (before) = " << m_writeBufferFill << endl;
00376 
00377     m_writeBufferFill = getCurrentBufferedFrame();
00378 
00379     cerr << "current buffered frame = " << m_writeBufferFill << endl;
00380 
00381     if (m_readBuffers != m_writeBuffers) {
00382         delete m_writeBuffers;
00383     }
00384 
00385     m_writeBuffers = new RingBufferVector;
00386 
00387     for (int i = 0; i < count; ++i) {
00388         m_writeBuffers->push_back(new RingBuffer<float>(m_ringBufferSize));
00389     }
00390 
00391 //    cout << "AudioCallbackPlaySource::clearRingBuffers: Created "
00392 //            << count << " write buffers" << endl;
00393 
00394     if (!haveLock) {
00395         m_mutex.unlock();
00396     }
00397 }
00398 
00399 void
00400 AudioCallbackPlaySource::play(int startFrame)
00401 {
00402     if (!m_sourceSampleRate) {
00403         cerr << "AudioCallbackPlaySource::play: No source sample rate available, not playing" << endl;
00404         return;
00405     }
00406     
00407     if (m_viewManager->getPlaySelectionMode() &&
00408         !m_viewManager->getSelections().empty()) {
00409 
00410         SVDEBUG << "AudioCallbackPlaySource::play: constraining frame " << startFrame << " to selection = ";
00411 
00412         startFrame = m_viewManager->constrainFrameToSelection(startFrame);
00413 
00414         SVDEBUG << startFrame << endl;
00415 
00416     } else {
00417         if (startFrame >= m_lastModelEndFrame) {
00418             startFrame = 0;
00419         }
00420     }
00421 
00422 #ifdef DEBUG_AUDIO_PLAY_SOURCE
00423     cerr << "play(" << startFrame << ") -> playback model ";
00424 #endif
00425 
00426     startFrame = m_viewManager->alignReferenceToPlaybackFrame(startFrame);
00427 
00428 #ifdef DEBUG_AUDIO_PLAY_SOURCE
00429     cerr << startFrame << endl;
00430 #endif
00431 
00432     // The fill thread will automatically empty its buffers before
00433     // starting again if we have not so far been playing, but not if
00434     // we're just re-seeking.
00435     // NO -- we can end up playing some first -- always reset here
00436 
00437     m_mutex.lock();
00438 
00439     if (m_timeStretcher) {
00440         m_timeStretcher->reset();
00441     }
00442     if (m_monoStretcher) {
00443         m_monoStretcher->reset();
00444     }
00445 
00446     m_readBufferFill = m_writeBufferFill = startFrame;
00447     if (m_readBuffers) {
00448         for (int c = 0; c < getTargetChannelCount(); ++c) {
00449             RingBuffer<float> *rb = getReadRingBuffer(c);
00450 #ifdef DEBUG_AUDIO_PLAY_SOURCE
00451             cerr << "reset ring buffer for channel " << c << endl;
00452 #endif
00453             if (rb) rb->reset();
00454         }
00455     }
00456     if (m_converter) src_reset(m_converter);
00457     if (m_crapConverter) src_reset(m_crapConverter);
00458 
00459     m_mutex.unlock();
00460 
00461     m_audioGenerator->reset();
00462 
00463     m_playStartFrame = startFrame;
00464     m_playStartFramePassed = false;
00465     m_playStartedAt = RealTime::zeroTime;
00466     if (m_target) {
00467         m_playStartedAt = RealTime::fromSeconds(m_target->getCurrentTime());
00468     }
00469 
00470     bool changed = !m_playing;
00471     m_lastRetrievalTimestamp = 0;
00472     m_lastCurrentFrame = 0;
00473     m_playing = true;
00474 
00475 #ifdef DEBUG_AUDIO_PLAY_SOURCE
00476     cout << "AudioCallbackPlaySource::play: awakening thread" << endl;
00477 #endif
00478 
00479     m_condition.wakeAll();
00480     if (changed) {
00481         emit playStatusChanged(m_playing);
00482         emit activity(tr("Play from %1").arg
00483                       (RealTime::frame2RealTime
00484                        (m_playStartFrame, m_sourceSampleRate).toText().c_str()));
00485     }
00486 }
00487 
00488 void
00489 AudioCallbackPlaySource::stop()
00490 {
00491 #ifdef DEBUG_AUDIO_PLAY_SOURCE
00492     SVDEBUG << "AudioCallbackPlaySource::stop()" << endl;
00493 #endif
00494     bool changed = m_playing;
00495     m_playing = false;
00496 
00497 #ifdef DEBUG_AUDIO_PLAY_SOURCE
00498     cout << "AudioCallbackPlaySource::stop: awakening thread" << endl;
00499 #endif
00500 
00501     m_condition.wakeAll();
00502     m_lastRetrievalTimestamp = 0;
00503     if (changed) {
00504         emit playStatusChanged(m_playing);
00505         emit activity(tr("Stop at %1").arg
00506                       (RealTime::frame2RealTime
00507                        (m_lastCurrentFrame, m_sourceSampleRate).toText().c_str()));
00508     }
00509     m_lastCurrentFrame = 0;
00510 }
00511 
00512 void
00513 AudioCallbackPlaySource::selectionChanged()
00514 {
00515     if (m_viewManager->getPlaySelectionMode()) {
00516         clearRingBuffers();
00517     }
00518 }
00519 
00520 void
00521 AudioCallbackPlaySource::playLoopModeChanged()
00522 {
00523     clearRingBuffers();
00524 }
00525 
00526 void
00527 AudioCallbackPlaySource::playSelectionModeChanged()
00528 {
00529     if (!m_viewManager->getSelections().empty()) {
00530         clearRingBuffers();
00531     }
00532 }
00533 
00534 void
00535 AudioCallbackPlaySource::playParametersChanged(PlayParameters *)
00536 {
00537     clearRingBuffers();
00538 }
00539 
00540 void
00541 AudioCallbackPlaySource::preferenceChanged(PropertyContainer::PropertyName n)
00542 {
00543     if (n == "Resample Quality") {
00544         setResampleQuality(Preferences::getInstance()->getResampleQuality());
00545     }
00546 }
00547 
00548 void
00549 AudioCallbackPlaySource::audioProcessingOverload()
00550 {
00551     cerr << "Audio processing overload!" << endl;
00552 
00553     if (!m_playing) return;
00554 
00555     RealTimePluginInstance *ap = m_auditioningPlugin;
00556     if (ap && !m_auditioningPluginBypassed) {
00557         m_auditioningPluginBypassed = true;
00558         emit audioOverloadPluginDisabled();
00559         return;
00560     }
00561 
00562     if (m_timeStretcher &&
00563         m_timeStretcher->getTimeRatio() < 1.0 &&
00564         m_stretcherInputCount > 1 &&
00565         m_monoStretcher && !m_stretchMono) {
00566         m_stretchMono = true;
00567         emit audioTimeStretchMultiChannelDisabled();
00568         return;
00569     }
00570 }
00571 
00572 void
00573 AudioCallbackPlaySource::setTarget(AudioCallbackPlayTarget *target, int size)
00574 {
00575     m_target = target;
00576     cout << "AudioCallbackPlaySource::setTarget: Block size -> " << size << endl;
00577     if (size != 0) {
00578         m_blockSize = size;
00579     }
00580     if (size * 4 > m_ringBufferSize) {
00581         SVDEBUG << "AudioCallbackPlaySource::setTarget: Buffer size "
00582                   << size << " > a quarter of ring buffer size "
00583                   << m_ringBufferSize << ", calling for more ring buffer"
00584                   << endl;
00585         m_ringBufferSize = size * 4;
00586         if (m_writeBuffers && !m_writeBuffers->empty()) {
00587             clearRingBuffers();
00588         }
00589     }
00590 }
00591 
00592 int
00593 AudioCallbackPlaySource::getTargetBlockSize() const
00594 {
00595 //    cout << "AudioCallbackPlaySource::getTargetBlockSize() -> " << m_blockSize << endl;
00596     return m_blockSize;
00597 }
00598 
00599 void
00600 AudioCallbackPlaySource::setTargetPlayLatency(int latency)
00601 {
00602     m_playLatency = latency;
00603 }
00604 
00605 int
00606 AudioCallbackPlaySource::getTargetPlayLatency() const
00607 {
00608     return m_playLatency;
00609 }
00610 
00611 int
00612 AudioCallbackPlaySource::getCurrentPlayingFrame()
00613 {
00614     // This method attempts to estimate which audio sample frame is
00615     // "currently coming through the speakers".
00616 
00617     int targetRate = getTargetSampleRate();
00618     int latency = m_playLatency; // at target rate
00619     RealTime latency_t = RealTime::zeroTime;
00620 
00621     if (targetRate != 0) {
00622         latency_t = RealTime::frame2RealTime(latency, targetRate);
00623     }
00624 
00625     return getCurrentFrame(latency_t);
00626 }
00627 
00628 int
00629 AudioCallbackPlaySource::getCurrentBufferedFrame()
00630 {
00631     return getCurrentFrame(RealTime::zeroTime);
00632 }
00633 
00634 int
00635 AudioCallbackPlaySource::getCurrentFrame(RealTime latency_t)
00636 {
00637     // We resample when filling the ring buffer, and time-stretch when
00638     // draining it.  The buffer contains data at the "target rate" and
00639     // the latency provided by the target is also at the target rate.
00640     // Because of the multiple rates involved, we do the actual
00641     // calculation using RealTime instead.
00642 
00643     int sourceRate = getSourceSampleRate();
00644     int targetRate = getTargetSampleRate();
00645 
00646     if (sourceRate == 0 || targetRate == 0) return 0;
00647 
00648     int inbuffer = 0; // at target rate
00649 
00650     for (int c = 0; c < getTargetChannelCount(); ++c) {
00651         RingBuffer<float> *rb = getReadRingBuffer(c);
00652         if (rb) {
00653             int here = rb->getReadSpace();
00654             if (c == 0 || here < inbuffer) inbuffer = here;
00655         }
00656     }
00657 
00658     int readBufferFill = m_readBufferFill;
00659     int lastRetrievedBlockSize = m_lastRetrievedBlockSize;
00660     double lastRetrievalTimestamp = m_lastRetrievalTimestamp;
00661     double currentTime = 0.0;
00662     if (m_target) currentTime = m_target->getCurrentTime();
00663 
00664     bool looping = m_viewManager->getPlayLoopMode();
00665 
00666     RealTime inbuffer_t = RealTime::frame2RealTime(inbuffer, targetRate);
00667 
00668     int stretchlat = 0;
00669     double timeRatio = 1.0;
00670 
00671     if (m_timeStretcher) {
00672         stretchlat = m_timeStretcher->getLatency();
00673         timeRatio = m_timeStretcher->getTimeRatio();
00674     }
00675 
00676     RealTime stretchlat_t = RealTime::frame2RealTime(stretchlat, targetRate);
00677 
00678     // When the target has just requested a block from us, the last
00679     // sample it obtained was our buffer fill frame count minus the
00680     // amount of read space (converted back to source sample rate)
00681     // remaining now.  That sample is not expected to be played until
00682     // the target's play latency has elapsed.  By the time the
00683     // following block is requested, that sample will be at the
00684     // target's play latency minus the last requested block size away
00685     // from being played.
00686 
00687     RealTime sincerequest_t = RealTime::zeroTime;
00688     RealTime lastretrieved_t = RealTime::zeroTime;
00689 
00690     if (m_target &&
00691         m_trustworthyTimestamps &&
00692         lastRetrievalTimestamp != 0.0) {
00693 
00694         lastretrieved_t = RealTime::frame2RealTime
00695             (lastRetrievedBlockSize, targetRate);
00696 
00697         // calculate number of frames at target rate that have elapsed
00698         // since the end of the last call to getSourceSamples
00699 
00700         if (m_trustworthyTimestamps && !looping) {
00701 
00702             // this adjustment seems to cause more problems when looping
00703             double elapsed = currentTime - lastRetrievalTimestamp;
00704 
00705             if (elapsed > 0.0) {
00706                 sincerequest_t = RealTime::fromSeconds(elapsed);
00707             }
00708         }
00709 
00710     } else {
00711 
00712         lastretrieved_t = RealTime::frame2RealTime
00713             (getTargetBlockSize(), targetRate);
00714     }
00715 
00716     RealTime bufferedto_t = RealTime::frame2RealTime(readBufferFill, sourceRate);
00717 
00718     if (timeRatio != 1.0) {
00719         lastretrieved_t = lastretrieved_t / timeRatio;
00720         sincerequest_t = sincerequest_t / timeRatio;
00721         latency_t = latency_t / timeRatio;
00722     }
00723 
00724 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
00725     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 quantity: " << lastretrieved_t << endl;
00726 #endif
00727 
00728     // Normally the range lists should contain at least one item each
00729     // -- if playback is unconstrained, that item should report the
00730     // entire source audio duration.
00731 
00732     if (m_rangeStarts.empty()) {
00733         rebuildRangeLists();
00734     }
00735 
00736     if (m_rangeStarts.empty()) {
00737         // this code is only used in case of error in rebuildRangeLists
00738         RealTime playing_t = bufferedto_t
00739             - latency_t - stretchlat_t - lastretrieved_t - inbuffer_t
00740             + sincerequest_t;
00741         if (playing_t < RealTime::zeroTime) playing_t = RealTime::zeroTime;
00742         int frame = RealTime::realTime2Frame(playing_t, sourceRate);
00743         return m_viewManager->alignPlaybackFrameToReference(frame);
00744     }
00745 
00746     int inRange = 0;
00747     int index = 0;
00748 
00749     for (int i = 0; i < (int)m_rangeStarts.size(); ++i) {
00750         if (bufferedto_t >= m_rangeStarts[i]) {
00751             inRange = index;
00752         } else {
00753             break;
00754         }
00755         ++index;
00756     }
00757 
00758     if (inRange >= (int)m_rangeStarts.size()) inRange = m_rangeStarts.size()-1;
00759 
00760     RealTime playing_t = bufferedto_t;
00761 
00762     playing_t = playing_t
00763         - latency_t - stretchlat_t - lastretrieved_t - inbuffer_t
00764         + sincerequest_t;
00765 
00766     // This rather gross little hack is used to ensure that latency
00767     // compensation doesn't result in the playback pointer appearing
00768     // to start earlier than the actual playback does.  It doesn't
00769     // work properly (hence the bail-out in the middle) because if we
00770     // are playing a relatively short looped region, the playing time
00771     // estimated from the buffer fill frame may have wrapped around
00772     // the region boundary and end up being much smaller than the
00773     // theoretical play start frame, perhaps even for the entire
00774     // duration of playback!
00775 
00776     if (!m_playStartFramePassed) {
00777         RealTime playstart_t = RealTime::frame2RealTime(m_playStartFrame,
00778                                                         sourceRate);
00779         if (playing_t < playstart_t) {
00780 //            cerr << "playing_t " << playing_t << " < playstart_t " 
00781 //                      << playstart_t << endl;
00782             if (
00783                 m_playStartedAt + latency_t + stretchlat_t <
00784                 RealTime::fromSeconds(currentTime)) {
00785 //                cerr << "but we've been playing for long enough that I think we should disregard it (it probably results from loop wrapping)" << endl;
00786                 m_playStartFramePassed = true;
00787             } else {
00788                 playing_t = playstart_t;
00789             }
00790         } else {
00791             m_playStartFramePassed = true;
00792         }
00793     }
00794  
00795 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
00796     cerr << "playing_t " << playing_t;
00797 #endif
00798 
00799     playing_t = playing_t - m_rangeStarts[inRange];
00800  
00801 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
00802     cerr << " as offset into range " << inRange << " (start =" << m_rangeStarts[inRange] << " duration =" << m_rangeDurations[inRange] << ") = " << playing_t << endl;
00803 #endif
00804 
00805     while (playing_t < RealTime::zeroTime) {
00806 
00807         if (inRange == 0) {
00808             if (looping) {
00809                 inRange = m_rangeStarts.size() - 1;
00810             } else {
00811                 break;
00812             }
00813         } else {
00814             --inRange;
00815         }
00816 
00817         playing_t = playing_t + m_rangeDurations[inRange];
00818     }
00819 
00820     playing_t = playing_t + m_rangeStarts[inRange];
00821 
00822 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
00823     cerr << "  playing time: " << playing_t << endl;
00824 #endif
00825 
00826     if (!looping) {
00827         if (inRange == (int)m_rangeStarts.size()-1 &&
00828             playing_t >= m_rangeStarts[inRange] + m_rangeDurations[inRange]) {
00829 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" << endl;
00830             stop();
00831         }
00832     }
00833 
00834     if (playing_t < RealTime::zeroTime) playing_t = RealTime::zeroTime;
00835 
00836     int frame = RealTime::realTime2Frame(playing_t, sourceRate);
00837 
00838     if (m_lastCurrentFrame > 0 && !looping) {
00839         if (frame < m_lastCurrentFrame) {
00840             frame = m_lastCurrentFrame;
00841         }
00842     }
00843 
00844     m_lastCurrentFrame = frame;
00845 
00846     return m_viewManager->alignPlaybackFrameToReference(frame);
00847 }
00848 
00849 void
00850 AudioCallbackPlaySource::rebuildRangeLists()
00851 {
00852     bool constrained = (m_viewManager->getPlaySelectionMode());
00853 
00854     m_rangeStarts.clear();
00855     m_rangeDurations.clear();
00856 
00857     int sourceRate = getSourceSampleRate();
00858     if (sourceRate == 0) return;
00859 
00860     RealTime end = RealTime::frame2RealTime(m_lastModelEndFrame, sourceRate);
00861     if (end == RealTime::zeroTime) return;
00862 
00863     if (!constrained) {
00864         m_rangeStarts.push_back(RealTime::zeroTime);
00865         m_rangeDurations.push_back(end);
00866         return;
00867     }
00868 
00869     MultiSelection::SelectionList selections = m_viewManager->getSelections();
00870     MultiSelection::SelectionList::const_iterator i;
00871 
00872 #ifdef DEBUG_AUDIO_PLAY_SOURCE
00873     SVDEBUG << "AudioCallbackPlaySource::rebuildRangeLists" << endl;
00874 #endif
00875 
00876     if (!selections.empty()) {
00877 
00878         for (i = selections.begin(); i != selections.end(); ++i) {
00879             
00880             RealTime start =
00881                 (RealTime::frame2RealTime
00882                  (m_viewManager->alignReferenceToPlaybackFrame(i->getStartFrame()),
00883                   sourceRate));
00884             RealTime duration = 
00885                 (RealTime::frame2RealTime
00886                  (m_viewManager->alignReferenceToPlaybackFrame(i->getEndFrame()) -
00887                   m_viewManager->alignReferenceToPlaybackFrame(i->getStartFrame()),
00888                   sourceRate));
00889             
00890             m_rangeStarts.push_back(start);
00891             m_rangeDurations.push_back(duration);
00892         }
00893     } else {
00894         m_rangeStarts.push_back(RealTime::zeroTime);
00895         m_rangeDurations.push_back(end);
00896     }
00897 
00898 #ifdef DEBUG_AUDIO_PLAY_SOURCE
00899     cerr << "Now have " << m_rangeStarts.size() << " play ranges" << endl;
00900 #endif
00901 }
00902 
00903 void
00904 AudioCallbackPlaySource::setOutputLevels(float left, float right)
00905 {
00906     m_outputLeft = left;
00907     m_outputRight = right;
00908 }
00909 
00910 bool
00911 AudioCallbackPlaySource::getOutputLevels(float &left, float &right)
00912 {
00913     left = m_outputLeft;
00914     right = m_outputRight;
00915     return true;
00916 }
00917 
00918 void
00919 AudioCallbackPlaySource::setTargetSampleRate(int sr)
00920 {
00921     bool first = (m_targetSampleRate == 0);
00922 
00923     m_targetSampleRate = sr;
00924     initialiseConverter();
00925 
00926     if (first && (m_stretchRatio != 1.f)) {
00927         // couldn't create a stretcher before because we had no sample
00928         // rate: make one now
00929         setTimeStretch(m_stretchRatio);
00930     }
00931 }
00932 
00933 void
00934 AudioCallbackPlaySource::initialiseConverter()
00935 {
00936     m_mutex.lock();
00937 
00938     if (m_converter) {
00939         src_delete(m_converter);
00940         src_delete(m_crapConverter);
00941         m_converter = 0;
00942         m_crapConverter = 0;
00943     }
00944 
00945     if (getSourceSampleRate() != getTargetSampleRate()) {
00946 
00947         int err = 0;
00948 
00949         m_converter = src_new(m_resampleQuality == 2 ? SRC_SINC_BEST_QUALITY :
00950                               m_resampleQuality == 1 ? SRC_SINC_MEDIUM_QUALITY :
00951                               m_resampleQuality == 0 ? SRC_SINC_FASTEST :
00952                                                        SRC_SINC_MEDIUM_QUALITY,
00953                               getTargetChannelCount(), &err);
00954 
00955         if (m_converter) {
00956             m_crapConverter = src_new(SRC_LINEAR,
00957                                       getTargetChannelCount(),
00958                                       &err);
00959         }
00960 
00961         if (!m_converter || !m_crapConverter) {
00962             cerr
00963                 << "AudioCallbackPlaySource::setModel: ERROR in creating samplerate converter: "
00964                 << src_strerror(err) << endl;
00965 
00966             if (m_converter) {
00967                 src_delete(m_converter);
00968                 m_converter = 0;
00969             } 
00970 
00971             if (m_crapConverter) {
00972                 src_delete(m_crapConverter);
00973                 m_crapConverter = 0;
00974             }
00975 
00976             m_mutex.unlock();
00977 
00978             emit sampleRateMismatch(getSourceSampleRate(),
00979                                     getTargetSampleRate(),
00980                                     false);
00981         } else {
00982 
00983             m_mutex.unlock();
00984 
00985             emit sampleRateMismatch(getSourceSampleRate(),
00986                                     getTargetSampleRate(),
00987                                     true);
00988         }
00989     } else {
00990         m_mutex.unlock();
00991     }
00992 }
00993 
00994 void
00995 AudioCallbackPlaySource::setResampleQuality(int q)
00996 {
00997     if (q == m_resampleQuality) return;
00998     m_resampleQuality = q;
00999 
01000 #ifdef DEBUG_AUDIO_PLAY_SOURCE
01001     SVDEBUG << "AudioCallbackPlaySource::setResampleQuality: setting to "
01002               << m_resampleQuality << endl;
01003 #endif
01004 
01005     initialiseConverter();
01006 }
01007 
01008 void
01009 AudioCallbackPlaySource::setAuditioningEffect(Auditionable *a)
01010 {
01011     RealTimePluginInstance *plugin = dynamic_cast<RealTimePluginInstance *>(a);
01012     if (a && !plugin) {
01013         cerr << "WARNING: AudioCallbackPlaySource::setAuditioningEffect: auditionable object " << a << " is not a real-time plugin instance" << endl;
01014     }
01015 
01016     m_mutex.lock();
01017     m_auditioningPlugin = plugin;
01018     m_auditioningPluginBypassed = false;
01019     m_mutex.unlock();
01020 }
01021 
01022 void
01023 AudioCallbackPlaySource::setSoloModelSet(std::set<Model *> s)
01024 {
01025     m_audioGenerator->setSoloModelSet(s);
01026     clearRingBuffers();
01027 }
01028 
01029 void
01030 AudioCallbackPlaySource::clearSoloModelSet()
01031 {
01032     m_audioGenerator->clearSoloModelSet();
01033     clearRingBuffers();
01034 }
01035 
01036 int
01037 AudioCallbackPlaySource::getTargetSampleRate() const
01038 {
01039     if (m_targetSampleRate) return m_targetSampleRate;
01040     else return getSourceSampleRate();
01041 }
01042 
01043 int
01044 AudioCallbackPlaySource::getSourceChannelCount() const
01045 {
01046     return m_sourceChannelCount;
01047 }
01048 
01049 int
01050 AudioCallbackPlaySource::getTargetChannelCount() const
01051 {
01052     if (m_sourceChannelCount < 2) return 2;
01053     return m_sourceChannelCount;
01054 }
01055 
01056 int
01057 AudioCallbackPlaySource::getSourceSampleRate() const
01058 {
01059     return m_sourceSampleRate;
01060 }
01061 
01062 void
01063 AudioCallbackPlaySource::setTimeStretch(float factor)
01064 {
01065     m_stretchRatio = factor;
01066 
01067     if (!getTargetSampleRate()) return; // have to make our stretcher later
01068 
01069     if (m_timeStretcher || (factor == 1.f)) {
01070         // stretch ratio will be set in next process call if appropriate
01071     } else {
01072         m_stretcherInputCount = getTargetChannelCount();
01073         RubberBandStretcher *stretcher = new RubberBandStretcher
01074             (getTargetSampleRate(),
01075              m_stretcherInputCount,
01076              RubberBandStretcher::OptionProcessRealTime,
01077              factor);
01078         RubberBandStretcher *monoStretcher = new RubberBandStretcher
01079             (getTargetSampleRate(),
01080              1,
01081              RubberBandStretcher::OptionProcessRealTime,
01082              factor);
01083         m_stretcherInputs = new float *[m_stretcherInputCount];
01084         m_stretcherInputSizes = new int[m_stretcherInputCount];
01085         for (int c = 0; c < m_stretcherInputCount; ++c) {
01086             m_stretcherInputSizes[c] = 16384;
01087             m_stretcherInputs[c] = new float[m_stretcherInputSizes[c]];
01088         }
01089         m_monoStretcher = monoStretcher;
01090         m_timeStretcher = stretcher;
01091     }
01092 
01093     emit activity(tr("Change time-stretch factor to %1").arg(factor));
01094 }
01095 
01096 int
01097 AudioCallbackPlaySource::getSourceSamples(int ucount, float **buffer)
01098 {
01099     int count = ucount;
01100 
01101     if (!m_playing) {
01102 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
01103         SVDEBUG << "AudioCallbackPlaySource::getSourceSamples: Not playing" << endl;
01104 #endif
01105         for (int ch = 0; ch < getTargetChannelCount(); ++ch) {
01106             for (int i = 0; i < count; ++i) {
01107                 buffer[ch][i] = 0.0;
01108             }
01109         }
01110         return 0;
01111     }
01112 
01113 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
01114     SVDEBUG << "AudioCallbackPlaySource::getSourceSamples: Playing" << endl;
01115 #endif
01116 
01117     // Ensure that all buffers have at least the amount of data we
01118     // need -- else reduce the size of our requests correspondingly
01119 
01120     for (int ch = 0; ch < getTargetChannelCount(); ++ch) {
01121 
01122         RingBuffer<float> *rb = getReadRingBuffer(ch);
01123         
01124         if (!rb) {
01125             cerr << "WARNING: AudioCallbackPlaySource::getSourceSamples: "
01126                       << "No ring buffer available for channel " << ch
01127                       << ", returning no data here" << endl;
01128             count = 0;
01129             break;
01130         }
01131 
01132         int rs = rb->getReadSpace();
01133         if (rs < count) {
01134 #ifdef DEBUG_AUDIO_PLAY_SOURCE
01135             cerr << "WARNING: AudioCallbackPlaySource::getSourceSamples: "
01136                       << "Ring buffer for channel " << ch << " has only "
01137                       << rs << " (of " << count << ") samples available ("
01138                       << "ring buffer size is " << rb->getSize() << ", write "
01139                       << "space " << rb->getWriteSpace() << "), "
01140                       << "reducing request size" << endl;
01141 #endif
01142             count = rs;
01143         }
01144     }
01145 
01146     if (count == 0) return 0;
01147 
01148     RubberBandStretcher *ts = m_timeStretcher;
01149     RubberBandStretcher *ms = m_monoStretcher;
01150 
01151     float ratio = ts ? ts->getTimeRatio() : 1.f;
01152 
01153     if (ratio != m_stretchRatio) {
01154         if (!ts) {
01155             cerr << "WARNING: AudioCallbackPlaySource::getSourceSamples: Time ratio change to " << m_stretchRatio << " is pending, but no stretcher is set" << endl;
01156             m_stretchRatio = 1.f;
01157         } else {
01158             ts->setTimeRatio(m_stretchRatio);
01159             if (ms) ms->setTimeRatio(m_stretchRatio);
01160             if (m_stretchRatio >= 1.0) m_stretchMono = false;
01161         }
01162     }
01163 
01164     int stretchChannels = m_stretcherInputCount;
01165     if (m_stretchMono) {
01166         if (ms) {
01167             ts = ms;
01168             stretchChannels = 1;
01169         } else {
01170             m_stretchMono = false;
01171         }
01172     }
01173 
01174     if (m_target) {
01175         m_lastRetrievedBlockSize = count;
01176         m_lastRetrievalTimestamp = m_target->getCurrentTime();
01177     }
01178 
01179     if (!ts || ratio == 1.f) {
01180 
01181         int got = 0;
01182 
01183         for (int ch = 0; ch < getTargetChannelCount(); ++ch) {
01184 
01185             RingBuffer<float> *rb = getReadRingBuffer(ch);
01186 
01187             if (rb) {
01188 
01189                 // this is marginally more likely to leave our channels in
01190                 // sync after a processing failure than just passing "count":
01191                 int request = count;
01192                 if (ch > 0) request = got;
01193 
01194                 got = rb->read(buffer[ch], request);
01195             
01196 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
01197                 cout << "AudioCallbackPlaySource::getSamples: got " << got << " (of " << count << ") samples on channel " << ch << ", signalling for more (possibly)" << endl;
01198 #endif
01199             }
01200 
01201             for (int ch = 0; ch < getTargetChannelCount(); ++ch) {
01202                 for (int i = got; i < count; ++i) {
01203                     buffer[ch][i] = 0.0;
01204                 }
01205             }
01206         }
01207 
01208         applyAuditioningEffect(count, buffer);
01209 
01210 #ifdef DEBUG_AUDIO_PLAY_SOURCE
01211     cout << "AudioCallbackPlaySource::getSamples: awakening thread" << endl;
01212 #endif
01213 
01214         m_condition.wakeAll();
01215 
01216         return got;
01217     }
01218 
01219     int channels = getTargetChannelCount();
01220     int available;
01221     int warned = 0;
01222     int fedToStretcher = 0;
01223 
01224     // The input block for a given output is approx output / ratio,
01225     // but we can't predict it exactly, for an adaptive timestretcher.
01226 
01227     while ((available = ts->available()) < count) {
01228 
01229         int reqd = lrintf((count - available) / ratio);
01230         reqd = std::max(reqd, (int)ts->getSamplesRequired());
01231         if (reqd == 0) reqd = 1;
01232                 
01233         int got = reqd;
01234 
01235 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
01236         cerr << "reqd = " <<reqd << ", channels = " << channels << ", ic = " << m_stretcherInputCount << endl;
01237 #endif
01238 
01239         for (int c = 0; c < channels; ++c) {
01240             if (c >= m_stretcherInputCount) continue;
01241             if (reqd > m_stretcherInputSizes[c]) {
01242                 if (c == 0) {
01243                     cerr << "WARNING: resizing stretcher input buffer from " << m_stretcherInputSizes[c] << " to " << (reqd * 2) << endl;
01244                 }
01245                 delete[] m_stretcherInputs[c];
01246                 m_stretcherInputSizes[c] = reqd * 2;
01247                 m_stretcherInputs[c] = new float[m_stretcherInputSizes[c]];
01248             }
01249         }
01250 
01251         for (int c = 0; c < channels; ++c) {
01252             if (c >= m_stretcherInputCount) continue;
01253             RingBuffer<float> *rb = getReadRingBuffer(c);
01254             if (rb) {
01255                 int gotHere;
01256                 if (stretchChannels == 1 && c > 0) {
01257                     gotHere = rb->readAdding(m_stretcherInputs[0], got);
01258                 } else {
01259                     gotHere = rb->read(m_stretcherInputs[c], got);
01260                 }
01261                 if (gotHere < got) got = gotHere;
01262                 
01263 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
01264                 if (c == 0) {
01265                     SVDEBUG << "feeding stretcher: got " << gotHere
01266                               << ", " << rb->getReadSpace() << " remain" << endl;
01267                 }
01268 #endif
01269                 
01270             } else {
01271                 cerr << "WARNING: No ring buffer available for channel " << c << " in stretcher input block" << endl;
01272             }
01273         }
01274 
01275         if (got < reqd) {
01276             cerr << "WARNING: Read underrun in playback ("
01277                       << got << " < " << reqd << ")" << endl;
01278         }
01279 
01280         ts->process(m_stretcherInputs, got, false);
01281 
01282         fedToStretcher += got;
01283 
01284         if (got == 0) break;
01285 
01286         if (ts->available() == available) {
01287             cerr << "WARNING: AudioCallbackPlaySource::getSamples: Added " << got << " samples to time stretcher, created no new available output samples (warned = " << warned << ")" << endl;
01288             if (++warned == 5) break;
01289         }
01290     }
01291 
01292     ts->retrieve(buffer, count);
01293 
01294     for (int c = stretchChannels; c < getTargetChannelCount(); ++c) {
01295         for (int i = 0; i < count; ++i) {
01296             buffer[c][i] = buffer[0][i];
01297         }
01298     }
01299 
01300     applyAuditioningEffect(count, buffer);
01301 
01302 #ifdef DEBUG_AUDIO_PLAY_SOURCE
01303     cout << "AudioCallbackPlaySource::getSamples [stretched]: awakening thread" << endl;
01304 #endif
01305 
01306     m_condition.wakeAll();
01307 
01308     return count;
01309 }
01310 
01311 void
01312 AudioCallbackPlaySource::applyAuditioningEffect(int count, float **buffers)
01313 {
01314     if (m_auditioningPluginBypassed) return;
01315     RealTimePluginInstance *plugin = m_auditioningPlugin;
01316     if (!plugin) return;
01317     
01318     if ((int)plugin->getAudioInputCount() != getTargetChannelCount()) {
01319 //        cerr << "plugin input count " << plugin->getAudioInputCount() 
01320 //                  << " != our channel count " << getTargetChannelCount()
01321 //                  << endl;
01322         return;
01323     }
01324     if ((int)plugin->getAudioOutputCount() != getTargetChannelCount()) {
01325 //        cerr << "plugin output count " << plugin->getAudioOutputCount() 
01326 //                  << " != our channel count " << getTargetChannelCount()
01327 //                  << endl;
01328         return;
01329     }
01330     if ((int)plugin->getBufferSize() < count) {
01331 //        cerr << "plugin buffer size " << plugin->getBufferSize() 
01332 //                  << " < our block size " << count
01333 //                  << endl;
01334         return;
01335     }
01336 
01337     float **ib = plugin->getAudioInputBuffers();
01338     float **ob = plugin->getAudioOutputBuffers();
01339 
01340     for (int c = 0; c < getTargetChannelCount(); ++c) {
01341         for (int i = 0; i < count; ++i) {
01342             ib[c][i] = buffers[c][i];
01343         }
01344     }
01345 
01346     plugin->run(Vamp::RealTime::zeroTime, count);
01347     
01348     for (int c = 0; c < getTargetChannelCount(); ++c) {
01349         for (int i = 0; i < count; ++i) {
01350             buffers[c][i] = ob[c][i];
01351         }
01352     }
01353 }    
01354 
01355 // Called from fill thread, m_playing true, mutex held
01356 bool
01357 AudioCallbackPlaySource::fillBuffers()
01358 {
01359     static float *tmp = 0;
01360     static int tmpSize = 0;
01361 
01362     int space = 0;
01363     for (int c = 0; c < getTargetChannelCount(); ++c) {
01364         RingBuffer<float> *wb = getWriteRingBuffer(c);
01365         if (wb) {
01366             int spaceHere = wb->getWriteSpace();
01367             if (c == 0 || spaceHere < space) space = spaceHere;
01368         }
01369     }
01370     
01371     if (space == 0) {
01372 #ifdef DEBUG_AUDIO_PLAY_SOURCE
01373         cout << "AudioCallbackPlaySourceFillThread: no space to fill" << endl;
01374 #endif
01375         return false;
01376     }
01377 
01378     int f = m_writeBufferFill;
01379         
01380     bool readWriteEqual = (m_readBuffers == m_writeBuffers);
01381 
01382 #ifdef DEBUG_AUDIO_PLAY_SOURCE
01383     if (!readWriteEqual) {
01384         cout << "AudioCallbackPlaySourceFillThread: note read buffers != write buffers" << endl;
01385     }
01386     cout << "AudioCallbackPlaySourceFillThread: filling " << space << " frames" << endl;
01387 #endif
01388 
01389 #ifdef DEBUG_AUDIO_PLAY_SOURCE
01390     cout << "buffered to " << f << " already" << endl;
01391 #endif
01392 
01393     bool resample = (getSourceSampleRate() != getTargetSampleRate());
01394 
01395 #ifdef DEBUG_AUDIO_PLAY_SOURCE
01396     cout << (resample ? "" : "not ") << "resampling (source " << getSourceSampleRate() << ", target " << getTargetSampleRate() << ")" << endl;
01397 #endif
01398 
01399     int channels = getTargetChannelCount();
01400 
01401     int orig = space;
01402     int got = 0;
01403 
01404     static float **bufferPtrs = 0;
01405     static int bufferPtrCount = 0;
01406 
01407     if (bufferPtrCount < channels) {
01408         if (bufferPtrs) delete[] bufferPtrs;
01409         bufferPtrs = new float *[channels];
01410         bufferPtrCount = channels;
01411     }
01412 
01413     int generatorBlockSize = m_audioGenerator->getBlockSize();
01414 
01415     if (resample && !m_converter) {
01416         static bool warned = false;
01417         if (!warned) {
01418             cerr << "WARNING: sample rates differ, but no converter available!" << endl;
01419             warned = true;
01420         }
01421     }
01422 
01423     if (resample && m_converter) {
01424 
01425         double ratio =
01426             double(getTargetSampleRate()) / double(getSourceSampleRate());
01427         orig = int(orig / ratio + 0.1);
01428 
01429         // orig must be a multiple of generatorBlockSize
01430         orig = (orig / generatorBlockSize) * generatorBlockSize;
01431         if (orig == 0) return false;
01432 
01433         int work = std::max(orig, space);
01434 
01435         // We only allocate one buffer, but we use it in two halves.
01436         // We place the non-interleaved values in the second half of
01437         // the buffer (orig samples for channel 0, orig samples for
01438         // channel 1 etc), and then interleave them into the first
01439         // half of the buffer.  Then we resample back into the second
01440         // half (interleaved) and de-interleave the results back to
01441         // the start of the buffer for insertion into the ringbuffers.
01442         // What a faff -- especially as we've already de-interleaved
01443         // the audio data from the source file elsewhere before we
01444         // even reach this point.
01445         
01446         if (tmpSize < channels * work * 2) {
01447             delete[] tmp;
01448             tmp = new float[channels * work * 2];
01449             tmpSize = channels * work * 2;
01450         }
01451 
01452         float *nonintlv = tmp + channels * work;
01453         float *intlv = tmp;
01454         float *srcout = tmp + channels * work;
01455         
01456         for (int c = 0; c < channels; ++c) {
01457             for (int i = 0; i < orig; ++i) {
01458                 nonintlv[channels * i + c] = 0.0f;
01459             }
01460         }
01461 
01462         for (int c = 0; c < channels; ++c) {
01463             bufferPtrs[c] = nonintlv + c * orig;
01464         }
01465 
01466         got = mixModels(f, orig, bufferPtrs); // also modifies f
01467 
01468         // and interleave into first half
01469         for (int c = 0; c < channels; ++c) {
01470             for (int i = 0; i < got; ++i) {
01471                 float sample = nonintlv[c * got + i];
01472                 intlv[channels * i + c] = sample;
01473             }
01474         }
01475                 
01476         SRC_DATA data;
01477         data.data_in = intlv;
01478         data.data_out = srcout;
01479         data.input_frames = got;
01480         data.output_frames = work;
01481         data.src_ratio = ratio;
01482         data.end_of_input = 0;
01483         
01484         int err = 0;
01485 
01486         if (m_timeStretcher && m_timeStretcher->getTimeRatio() < 0.4) {
01487 #ifdef DEBUG_AUDIO_PLAY_SOURCE
01488             cout << "Using crappy converter" << endl;
01489 #endif
01490             err = src_process(m_crapConverter, &data);
01491         } else {
01492             err = src_process(m_converter, &data);
01493         }
01494 
01495         int toCopy = int(got * ratio + 0.1);
01496 
01497         if (err) {
01498             cerr
01499                 << "AudioCallbackPlaySourceFillThread: ERROR in samplerate conversion: "
01500                 << src_strerror(err) << endl;
01502         } else {
01503             got = data.input_frames_used;
01504             toCopy = data.output_frames_gen;
01505 #ifdef DEBUG_AUDIO_PLAY_SOURCE
01506             cout << "Resampled " << got << " frames to " << toCopy << " frames" << endl;
01507 #endif
01508         }
01509         
01510         for (int c = 0; c < channels; ++c) {
01511             for (int i = 0; i < toCopy; ++i) {
01512                 tmp[i] = srcout[channels * i + c];
01513             }
01514             RingBuffer<float> *wb = getWriteRingBuffer(c);
01515             if (wb) wb->write(tmp, toCopy);
01516         }
01517 
01518         m_writeBufferFill = f;
01519         if (readWriteEqual) m_readBufferFill = f;
01520 
01521     } else {
01522 
01523         // space must be a multiple of generatorBlockSize
01524         int reqSpace = space;
01525         space = (reqSpace / generatorBlockSize) * generatorBlockSize;
01526         if (space == 0) {
01527 #ifdef DEBUG_AUDIO_PLAY_SOURCE
01528             cout << "requested fill of " << reqSpace
01529                       << " is less than generator block size of "
01530                       << generatorBlockSize << ", leaving it" << endl;
01531 #endif
01532             return false;
01533         }
01534 
01535         if (tmpSize < channels * space) {
01536             delete[] tmp;
01537             tmp = new float[channels * space];
01538             tmpSize = channels * space;
01539         }
01540 
01541         for (int c = 0; c < channels; ++c) {
01542 
01543             bufferPtrs[c] = tmp + c * space;
01544             
01545             for (int i = 0; i < space; ++i) {
01546                 tmp[c * space + i] = 0.0f;
01547             }
01548         }
01549 
01550         int got = mixModels(f, space, bufferPtrs); // also modifies f
01551 
01552         for (int c = 0; c < channels; ++c) {
01553 
01554             RingBuffer<float> *wb = getWriteRingBuffer(c);
01555             if (wb) {
01556                 int actual = wb->write(bufferPtrs[c], got);
01557 #ifdef DEBUG_AUDIO_PLAY_SOURCE
01558                 cout << "Wrote " << actual << " samples for ch " << c << ", now "
01559                           << wb->getReadSpace() << " to read" 
01560                           << endl;
01561 #endif
01562                 if (actual < got) {
01563                     cerr << "WARNING: Buffer overrun in channel " << c
01564                               << ": wrote " << actual << " of " << got
01565                               << " samples" << endl;
01566                 }
01567             }
01568         }
01569 
01570         m_writeBufferFill = f;
01571         if (readWriteEqual) m_readBufferFill = f;
01572 
01573 #ifdef DEBUG_AUDIO_PLAY_SOURCE
01574         cout << "Read buffer fill is now " << m_readBufferFill << endl;
01575 #endif
01576 
01578     }
01579 
01580     return true;
01581 }    
01582 
01583 int
01584 AudioCallbackPlaySource::mixModels(int &frame, int count, float **buffers)
01585 {
01586     int processed = 0;
01587     int chunkStart = frame;
01588     int chunkSize = count;
01589     int selectionSize = 0;
01590     int nextChunkStart = chunkStart + chunkSize;
01591     
01592     bool looping = m_viewManager->getPlayLoopMode();
01593     bool constrained = (m_viewManager->getPlaySelectionMode() &&
01594                         !m_viewManager->getSelections().empty());
01595 
01596     static float **chunkBufferPtrs = 0;
01597     static int chunkBufferPtrCount = 0;
01598     int channels = getTargetChannelCount();
01599 
01600 #ifdef DEBUG_AUDIO_PLAY_SOURCE
01601     cout << "Selection playback: start " << frame << ", size " << count <<", channels " << channels << endl;
01602 #endif
01603 
01604     if (chunkBufferPtrCount < channels) {
01605         if (chunkBufferPtrs) delete[] chunkBufferPtrs;
01606         chunkBufferPtrs = new float *[channels];
01607         chunkBufferPtrCount = channels;
01608     }
01609 
01610     for (int c = 0; c < channels; ++c) {
01611         chunkBufferPtrs[c] = buffers[c];
01612     }
01613 
01614     while (processed < count) {
01615         
01616         chunkSize = count - processed;
01617         nextChunkStart = chunkStart + chunkSize;
01618         selectionSize = 0;
01619 
01620         int fadeIn = 0, fadeOut = 0;
01621 
01622         if (constrained) {
01623 
01624             int rChunkStart =
01625                 m_viewManager->alignPlaybackFrameToReference(chunkStart);
01626             
01627             Selection selection =
01628                 m_viewManager->getContainingSelection(rChunkStart, true);
01629             
01630             if (selection.isEmpty()) {
01631                 if (looping) {
01632                     selection = *m_viewManager->getSelections().begin();
01633                     chunkStart = m_viewManager->alignReferenceToPlaybackFrame
01634                         (selection.getStartFrame());
01635                     fadeIn = 50;
01636                 }
01637             }
01638 
01639             if (selection.isEmpty()) {
01640 
01641                 chunkSize = 0;
01642                 nextChunkStart = chunkStart;
01643 
01644             } else {
01645 
01646                 int sf = m_viewManager->alignReferenceToPlaybackFrame
01647                     (selection.getStartFrame());
01648                 int ef = m_viewManager->alignReferenceToPlaybackFrame
01649                     (selection.getEndFrame());
01650 
01651                 selectionSize = ef - sf;
01652 
01653                 if (chunkStart < sf) {
01654                     chunkStart = sf;
01655                     fadeIn = 50;
01656                 }
01657 
01658                 nextChunkStart = chunkStart + chunkSize;
01659 
01660                 if (nextChunkStart >= ef) {
01661                     nextChunkStart = ef;
01662                     fadeOut = 50;
01663                 }
01664 
01665                 chunkSize = nextChunkStart - chunkStart;
01666             }
01667         
01668         } else if (looping && m_lastModelEndFrame > 0) {
01669 
01670             if (chunkStart >= m_lastModelEndFrame) {
01671                 chunkStart = 0;
01672             }
01673             if (chunkSize > m_lastModelEndFrame - chunkStart) {
01674                 chunkSize = m_lastModelEndFrame - chunkStart;
01675             }
01676             nextChunkStart = chunkStart + chunkSize;
01677         }
01678         
01679 //      cout << "chunkStart " << chunkStart << ", chunkSize " << chunkSize << ", nextChunkStart " << nextChunkStart << ", frame " << frame << ", count " << count << ", processed " << processed << endl;
01680 
01681         if (!chunkSize) {
01682 #ifdef DEBUG_AUDIO_PLAY_SOURCE
01683             cout << "Ending selection playback at " << nextChunkStart << endl;
01684 #endif
01685             // We need to maintain full buffers so that the other
01686             // thread can tell where it's got to in the playback -- so
01687             // return the full amount here
01688             frame = frame + count;
01689             return count;
01690         }
01691 
01692 #ifdef DEBUG_AUDIO_PLAY_SOURCE
01693         cout << "Selection playback: chunk at " << chunkStart << " -> " << nextChunkStart << " (size " << chunkSize << ")" << endl;
01694 #endif
01695 
01696         if (selectionSize < 100) {
01697             fadeIn = 0;
01698             fadeOut = 0;
01699         } else if (selectionSize < 300) {
01700             if (fadeIn > 0) fadeIn = 10;
01701             if (fadeOut > 0) fadeOut = 10;
01702         }
01703 
01704         if (fadeIn > 0) {
01705             if (processed * 2 < fadeIn) {
01706                 fadeIn = processed * 2;
01707             }
01708         }
01709 
01710         if (fadeOut > 0) {
01711             if ((count - processed - chunkSize) * 2 < fadeOut) {
01712                 fadeOut = (count - processed - chunkSize) * 2;
01713             }
01714         }
01715 
01716         for (std::set<Model *>::iterator mi = m_models.begin();
01717              mi != m_models.end(); ++mi) {
01718             
01719             (void) m_audioGenerator->mixModel(*mi, chunkStart, 
01720                                               chunkSize, chunkBufferPtrs,
01721                                               fadeIn, fadeOut);
01722         }
01723 
01724         for (int c = 0; c < channels; ++c) {
01725             chunkBufferPtrs[c] += chunkSize;
01726         }
01727 
01728         processed += chunkSize;
01729         chunkStart = nextChunkStart;
01730     }
01731 
01732 #ifdef DEBUG_AUDIO_PLAY_SOURCE
01733     cout << "Returning selection playback " << processed << " frames to " << nextChunkStart << endl;
01734 #endif
01735 
01736     frame = nextChunkStart;
01737     return processed;
01738 }
01739 
01740 void
01741 AudioCallbackPlaySource::unifyRingBuffers()
01742 {
01743     if (m_readBuffers == m_writeBuffers) return;
01744 
01745     // only unify if there will be something to read
01746     for (int c = 0; c < getTargetChannelCount(); ++c) {
01747         RingBuffer<float> *wb = getWriteRingBuffer(c);
01748         if (wb) {
01749             if (wb->getReadSpace() < m_blockSize * 2) {
01750                 if ((m_writeBufferFill + m_blockSize * 2) < 
01751                     m_lastModelEndFrame) {
01752                     // OK, we don't have enough and there's more to
01753                     // read -- don't unify until we can do better
01754 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
01755                     SVDEBUG << "AudioCallbackPlaySource::unifyRingBuffers: Not unifying: write buffer has less (" << wb->getReadSpace() << ") than " << m_blockSize*2 << " to read and write buffer fill (" << m_writeBufferFill << ") is not close to end frame (" << m_lastModelEndFrame << ")" << endl;
01756 #endif
01757                     return;
01758                 }
01759             }
01760             break;
01761         }
01762     }
01763 
01764     int rf = m_readBufferFill;
01765     RingBuffer<float> *rb = getReadRingBuffer(0);
01766     if (rb) {
01767         int rs = rb->getReadSpace();
01769 //      cout << "rs = " << rs << endl;
01770         if (rs < rf) rf -= rs;
01771         else rf = 0;
01772     }
01773     
01774 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
01775     SVDEBUG << "AudioCallbackPlaySource::unifyRingBuffers: m_readBufferFill = " << m_readBufferFill << ", rf = " << rf << ", m_writeBufferFill = " << m_writeBufferFill << endl;
01776 #endif
01777 
01778     int wf = m_writeBufferFill;
01779     int skip = 0;
01780     for (int c = 0; c < getTargetChannelCount(); ++c) {
01781         RingBuffer<float> *wb = getWriteRingBuffer(c);
01782         if (wb) {
01783             if (c == 0) {
01784                 
01785                 int wrs = wb->getReadSpace();
01786 //              cout << "wrs = " << wrs << endl;
01787 
01788                 if (wrs < wf) wf -= wrs;
01789                 else wf = 0;
01790 //              cout << "wf = " << wf << endl;
01791                 
01792                 if (wf < rf) skip = rf - wf;
01793                 if (skip == 0) break;
01794             }
01795 
01796 //          cout << "skipping " << skip << endl;
01797             wb->skip(skip);
01798         }
01799     }
01800                     
01801     m_bufferScavenger.claim(m_readBuffers);
01802     m_readBuffers = m_writeBuffers;
01803     m_readBufferFill = m_writeBufferFill;
01804 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
01805     cerr << "unified" << endl;
01806 #endif
01807 }
01808 
01809 void
01810 AudioCallbackPlaySource::FillThread::run()
01811 {
01812     AudioCallbackPlaySource &s(m_source);
01813     
01814 #ifdef DEBUG_AUDIO_PLAY_SOURCE
01815     cout << "AudioCallbackPlaySourceFillThread starting" << endl;
01816 #endif
01817 
01818     s.m_mutex.lock();
01819 
01820     bool previouslyPlaying = s.m_playing;
01821     bool work = false;
01822 
01823     while (!s.m_exiting) {
01824 
01825         s.unifyRingBuffers();
01826         s.m_bufferScavenger.scavenge();
01827         s.m_pluginScavenger.scavenge();
01828 
01829         if (work && s.m_playing && s.getSourceSampleRate()) {
01830             
01831 #ifdef DEBUG_AUDIO_PLAY_SOURCE
01832             cout << "AudioCallbackPlaySourceFillThread: not waiting" << endl;
01833 #endif
01834 
01835             s.m_mutex.unlock();
01836             s.m_mutex.lock();
01837 
01838         } else {
01839             
01840             float ms = 100;
01841             if (s.getSourceSampleRate() > 0) {
01842                 ms = float(s.m_ringBufferSize) /
01843                     float(s.getSourceSampleRate()) * 1000.0;
01844             }
01845             
01846             if (s.m_playing) ms /= 10;
01847 
01848 #ifdef DEBUG_AUDIO_PLAY_SOURCE
01849             if (!s.m_playing) cout << endl;
01850             cout << "AudioCallbackPlaySourceFillThread: waiting for " << ms << "ms..." << endl;
01851 #endif
01852             
01853             s.m_condition.wait(&s.m_mutex, int(ms));
01854         }
01855 
01856 #ifdef DEBUG_AUDIO_PLAY_SOURCE
01857         cout << "AudioCallbackPlaySourceFillThread: awoken" << endl;
01858 #endif
01859 
01860         work = false;
01861 
01862         if (!s.getSourceSampleRate()) {
01863 #ifdef DEBUG_AUDIO_PLAY_SOURCE
01864             cout << "AudioCallbackPlaySourceFillThread: source sample rate is zero" << endl;
01865 #endif
01866             continue;
01867         }
01868 
01869         bool playing = s.m_playing;
01870 
01871         if (playing && !previouslyPlaying) {
01872 #ifdef DEBUG_AUDIO_PLAY_SOURCE
01873             cout << "AudioCallbackPlaySourceFillThread: playback state changed, resetting" << endl;
01874 #endif
01875             for (int c = 0; c < s.getTargetChannelCount(); ++c) {
01876                 RingBuffer<float> *rb = s.getReadRingBuffer(c);
01877                 if (rb) rb->reset();
01878             }
01879         }
01880         previouslyPlaying = playing;
01881 
01882         work = s.fillBuffers();
01883     }
01884 
01885     s.m_mutex.unlock();
01886 }
01887