svapp
1.9
|
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