1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2
3 /*
4 Sonic Visualiser
5 An audio file viewer and annotation editor.
6 Centre for Digital Music, Queen Mary, University of London.
7 This file copyright 2006 Chris Cannam and QMUL.
8
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License as
11 published by the Free Software Foundation; either version 2 of the
12 License, or (at your option) any later version. See the file
13 COPYING included with this distribution for more information.
14 */
15
16 #include "AudioCallbackPlaySource.h"
17
18 #include "AudioGenerator.h"
19
20 #include "data/model/Model.h"
21 #include "base/ViewManagerBase.h"
22 #include "base/PlayParameterRepository.h"
23 #include "base/Preferences.h"
24 #include "data/model/DenseTimeValueModel.h"
25 #include "data/model/WaveFileModel.h"
26 #include "data/model/ReadOnlyWaveFileModel.h"
27 #include "data/model/SparseOneDimensionalModel.h"
28 #include "plugin/RealTimePluginInstance.h"
29
30 #include "bqaudioio/SystemPlaybackTarget.h"
31 #include "bqaudioio/ResamplerWrapper.h"
32
33 #include "bqvec/VectorOps.h"
34
35 #include <rubberband/RubberBandStretcher.h>
36 using namespace RubberBand;
37
38 using breakfastquay::v_zero_channels;
39
40 #include <iostream>
41 #include <cassert>
42
43 //#define DEBUG_AUDIO_PLAY_SOURCE 1
44 //#define DEBUG_AUDIO_PLAY_SOURCE_PLAYING 1
45
46 static const int DEFAULT_RING_BUFFER_SIZE = 131071;
47
AudioCallbackPlaySource(ViewManagerBase * manager,QString clientName)48 AudioCallbackPlaySource::AudioCallbackPlaySource(ViewManagerBase *manager,
49 QString clientName) :
50 m_viewManager(manager),
51 m_audioGenerator(new AudioGenerator()),
52 m_clientName(clientName.toUtf8().data()),
53 m_readBuffers(nullptr),
54 m_writeBuffers(nullptr),
55 m_readBufferFill(0),
56 m_writeBufferFill(0),
57 m_bufferScavenger(1),
58 m_sourceChannelCount(0),
59 m_blockSize(1024),
60 m_sourceSampleRate(0),
61 m_deviceSampleRate(0),
62 m_deviceChannelCount(0),
63 m_playLatency(0),
64 m_target(nullptr),
65 m_lastRetrievalTimestamp(0.0),
66 m_lastRetrievedBlockSize(0),
67 m_trustworthyTimestamps(true),
68 m_lastCurrentFrame(0),
69 m_playing(false),
70 m_exiting(false),
71 m_lastModelEndFrame(0),
72 m_ringBufferSize(DEFAULT_RING_BUFFER_SIZE),
73 m_outputLeft(0.0),
74 m_outputRight(0.0),
75 m_levelsSet(false),
76 m_auditioningPlugin(nullptr),
77 m_auditioningPluginBypassed(false),
78 m_playStartFrame(0),
79 m_playStartFramePassed(false),
80 m_timeStretcher(nullptr),
81 m_monoStretcher(nullptr),
82 m_stretchRatio(1.0),
83 m_stretchMono(false),
84 m_stretcherInputCount(0),
85 m_stretcherInputs(nullptr),
86 m_stretcherInputSizes(nullptr),
87 m_fillThread(nullptr),
88 m_resamplerWrapper(nullptr)
89 {
90 m_viewManager->setAudioPlaySource(this);
91
92 connect(m_viewManager, SIGNAL(selectionChanged()),
93 this, SLOT(selectionChanged()));
94 connect(m_viewManager, SIGNAL(playLoopModeChanged()),
95 this, SLOT(playLoopModeChanged()));
96 connect(m_viewManager, SIGNAL(playSelectionModeChanged()),
97 this, SLOT(playSelectionModeChanged()));
98
99 connect(this, SIGNAL(playStatusChanged(bool)),
100 m_viewManager, SLOT(playStatusChanged(bool)));
101
102 connect(PlayParameterRepository::getInstance(),
103 SIGNAL(playParametersChanged(int)),
104 this, SLOT(playParametersChanged(int)));
105
106 connect(Preferences::getInstance(),
107 SIGNAL(propertyChanged(PropertyContainer::PropertyName)),
108 this, SLOT(preferenceChanged(PropertyContainer::PropertyName)));
109 }
110
~AudioCallbackPlaySource()111 AudioCallbackPlaySource::~AudioCallbackPlaySource()
112 {
113 #ifdef DEBUG_AUDIO_PLAY_SOURCE
114 SVDEBUG << "AudioCallbackPlaySource::~AudioCallbackPlaySource entering" << endl;
115 #endif
116 m_exiting = true;
117
118 if (m_fillThread) {
119 #ifdef DEBUG_AUDIO_PLAY_SOURCE
120 cout << "AudioCallbackPlaySource dtor: awakening thread" << endl;
121 #endif
122 m_condition.wakeAll();
123 m_fillThread->wait();
124 delete m_fillThread;
125 }
126
127 clearModels();
128
129 if (m_readBuffers != m_writeBuffers) {
130 delete m_readBuffers;
131 }
132
133 delete m_writeBuffers;
134
135 delete m_audioGenerator;
136
137 for (int i = 0; i < m_stretcherInputCount; ++i) {
138 delete[] m_stretcherInputs[i];
139 }
140 delete[] m_stretcherInputSizes;
141 delete[] m_stretcherInputs;
142
143 delete m_timeStretcher;
144 delete m_monoStretcher;
145
146 m_bufferScavenger.scavenge(true);
147 m_pluginScavenger.scavenge(true);
148 #ifdef DEBUG_AUDIO_PLAY_SOURCE
149 SVDEBUG << "AudioCallbackPlaySource::~AudioCallbackPlaySource finishing" << endl;
150 #endif
151 }
152
153 void
addModel(ModelId modelId)154 AudioCallbackPlaySource::addModel(ModelId modelId)
155 {
156 if (m_models.find(modelId) != m_models.end()) return;
157
158 bool willPlay = m_audioGenerator->addModel(modelId);
159
160 auto model = ModelById::get(modelId);
161 if (!model) return;
162
163 m_mutex.lock();
164
165 m_models.insert(modelId);
166
167 if (model->getEndFrame() > m_lastModelEndFrame) {
168 m_lastModelEndFrame = model->getEndFrame();
169 }
170
171 bool buffersIncreased = false, srChanged = false;
172
173 int modelChannels = 1;
174 auto rowfm = std::dynamic_pointer_cast<ReadOnlyWaveFileModel>(model);
175 if (rowfm) modelChannels = rowfm->getChannelCount();
176 if (modelChannels > m_sourceChannelCount) {
177 m_sourceChannelCount = modelChannels;
178 }
179
180 #ifdef DEBUG_AUDIO_PLAY_SOURCE
181 cout << "AudioCallbackPlaySource: Adding model with " << modelChannels << " channels at rate " << model->getSampleRate() << endl;
182 #endif
183
184 if (m_sourceSampleRate == 0) {
185
186 SVDEBUG << "AudioCallbackPlaySource::addModel: Source rate changing from 0 to "
187 << model->getSampleRate() << endl;
188
189 m_sourceSampleRate = model->getSampleRate();
190 srChanged = true;
191
192 } else if (model->getSampleRate() != m_sourceSampleRate) {
193
194 // If this is a read-only wave file model and we have no
195 // other, we can just switch to this model's sample rate
196
197 if (rowfm) {
198
199 bool conflicting = false;
200
201 for (ModelId otherId: m_models) {
202 // Only read-only wave file models should be
203 // considered conflicting -- writable wave file models
204 // are derived and we shouldn't take their rates into
205 // account. Also, don't give any particular weight to
206 // a file that's already playing at the wrong rate
207 // anyway
208 if (otherId == modelId) continue;
209 auto other = ModelById::getAs<ReadOnlyWaveFileModel>(otherId);
210 if (other &&
211 other->getSampleRate() != model->getSampleRate() &&
212 other->getSampleRate() == m_sourceSampleRate) {
213 SVDEBUG << "AudioCallbackPlaySource::addModel: Conflicting wave file model " << otherId << " found" << endl;
214 conflicting = true;
215 break;
216 }
217 }
218
219 if (conflicting) {
220
221 SVCERR << "AudioCallbackPlaySource::addModel: ERROR: "
222 << "New model sample rate does not match" << endl
223 << "existing model(s) (new " << model->getSampleRate()
224 << " vs " << m_sourceSampleRate
225 << "), playback will be wrong"
226 << endl;
227
228 emit sampleRateMismatch(model->getSampleRate(),
229 m_sourceSampleRate,
230 false);
231 } else {
232 SVDEBUG << "AudioCallbackPlaySource::addModel: Source rate changing from "
233 << m_sourceSampleRate << " to " << model->getSampleRate() << endl;
234
235 m_sourceSampleRate = model->getSampleRate();
236 srChanged = true;
237 }
238 }
239 }
240
241 if (!m_writeBuffers || (int)m_writeBuffers->size() < getTargetChannelCount()) {
242 cerr << "m_writeBuffers size = " << (m_writeBuffers ? m_writeBuffers->size() : 0) << endl;
243 cerr << "target channel count = " << (getTargetChannelCount()) << endl;
244 clearRingBuffers(true, getTargetChannelCount());
245 buffersIncreased = true;
246 } else {
247 if (willPlay) clearRingBuffers(true);
248 }
249
250 if (srChanged) {
251
252 SVCERR << "AudioCallbackPlaySource: Source rate changed" << endl;
253
254 if (m_resamplerWrapper) {
255 SVCERR << "AudioCallbackPlaySource: Source sample rate changed to "
256 << m_sourceSampleRate << ", updating resampler wrapper" << endl;
257 m_resamplerWrapper->changeApplicationSampleRate
258 (int(round(m_sourceSampleRate)));
259 m_resamplerWrapper->reset();
260 }
261
262 delete m_timeStretcher;
263 delete m_monoStretcher;
264 m_timeStretcher = nullptr;
265 m_monoStretcher = nullptr;
266
267 if (m_stretchRatio != 1.f) {
268 setTimeStretch(m_stretchRatio);
269 }
270 }
271
272 rebuildRangeLists();
273
274 m_mutex.unlock();
275
276 m_audioGenerator->setTargetChannelCount(getTargetChannelCount());
277
278 if (buffersIncreased) {
279 SVDEBUG << "AudioCallbackPlaySource::addModel: Number of buffers increased to " << getTargetChannelCount() << endl;
280 if (getTargetChannelCount() > getDeviceChannelCount()) {
281 SVDEBUG << "AudioCallbackPlaySource::addModel: This is more than the device channel count, signalling channelCountIncreased" << endl;
282 emit channelCountIncreased(getTargetChannelCount());
283 } else {
284 SVDEBUG << "AudioCallbackPlaySource::addModel: This is no more than the device channel count (" << getDeviceChannelCount() << "), so taking no action" << endl;
285 }
286 }
287
288 if (!m_fillThread) {
289 m_fillThread = new FillThread(*this);
290 m_fillThread->start();
291 }
292
293 #ifdef DEBUG_AUDIO_PLAY_SOURCE
294 SVDEBUG << "AudioCallbackPlaySource::addModel: now have " << m_models.size() << " model(s)" << endl;
295 #endif
296
297 connect(model.get(), SIGNAL(modelChangedWithin(ModelId, sv_frame_t, sv_frame_t)),
298 this, SLOT(modelChangedWithin(ModelId, sv_frame_t, sv_frame_t)));
299
300 #ifdef DEBUG_AUDIO_PLAY_SOURCE
301 cout << "AudioCallbackPlaySource::addModel: awakening thread" << endl;
302 #endif
303
304 m_condition.wakeAll();
305 }
306
307 void
modelChangedWithin(ModelId,sv_frame_t startFrame,sv_frame_t endFrame)308 AudioCallbackPlaySource::modelChangedWithin(ModelId, sv_frame_t
309 #ifdef DEBUG_AUDIO_PLAY_SOURCE
310 startFrame
311 #endif
312 , sv_frame_t endFrame)
313 {
314 #ifdef DEBUG_AUDIO_PLAY_SOURCE
315 SVDEBUG << "AudioCallbackPlaySource::modelChangedWithin(" << startFrame << "," << endFrame << ")" << endl;
316 #endif
317 if (endFrame > m_lastModelEndFrame) {
318 m_lastModelEndFrame = endFrame;
319 rebuildRangeLists();
320 }
321 }
322
323 void
removeModel(ModelId modelId)324 AudioCallbackPlaySource::removeModel(ModelId modelId)
325 {
326 auto model = ModelById::get(modelId);
327 if (!model) return;
328
329 m_mutex.lock();
330
331 #ifdef DEBUG_AUDIO_PLAY_SOURCE
332 cout << "AudioCallbackPlaySource::removeModel(" << modelId << ")" << endl;
333 #endif
334
335 disconnect(model.get(), SIGNAL(modelChangedWithin(ModelId, sv_frame_t, sv_frame_t)),
336 this, SLOT(modelChangedWithin(ModelId, sv_frame_t, sv_frame_t)));
337
338 m_models.erase(modelId);
339
340 sv_frame_t lastEnd = 0;
341 for (ModelId otherId: m_models) {
342 #ifdef DEBUG_AUDIO_PLAY_SOURCE
343 cout << "AudioCallbackPlaySource::removeModel(" << modelId << "): checking end frame on model " << otherId << endl;
344 #endif
345 if (auto other = ModelById::get(otherId)) {
346 if (other->getEndFrame() > lastEnd) {
347 lastEnd = other->getEndFrame();
348 }
349 }
350 #ifdef DEBUG_AUDIO_PLAY_SOURCE
351 cout << "(done, lastEnd now " << lastEnd << ")" << endl;
352 #endif
353 }
354 m_lastModelEndFrame = lastEnd;
355
356 m_audioGenerator->removeModel(modelId);
357
358 if (m_models.empty()) {
359 m_sourceSampleRate = 0;
360 }
361
362 m_mutex.unlock();
363
364 clearRingBuffers();
365 }
366
367 void
clearModels()368 AudioCallbackPlaySource::clearModels()
369 {
370 m_mutex.lock();
371
372 #ifdef DEBUG_AUDIO_PLAY_SOURCE
373 cout << "AudioCallbackPlaySource::clearModels()" << endl;
374 #endif
375
376 m_models.clear();
377
378 m_lastModelEndFrame = 0;
379
380 m_sourceSampleRate = 0;
381
382 m_mutex.unlock();
383
384 m_audioGenerator->clearModels();
385
386 clearRingBuffers();
387 }
388
389 void
clearRingBuffers(bool haveLock,int count)390 AudioCallbackPlaySource::clearRingBuffers(bool haveLock, int count)
391 {
392 if (!haveLock) m_mutex.lock();
393
394 #ifdef DEBUG_AUDIO_PLAY_SOURCE
395 cout << "clearRingBuffers" << endl;
396 #endif
397
398 rebuildRangeLists();
399
400 if (count == 0) {
401 if (m_writeBuffers) count = int(m_writeBuffers->size());
402 }
403
404 #ifdef DEBUG_AUDIO_PLAY_SOURCE
405 cout << "current playing frame = " << getCurrentPlayingFrame() << endl;
406
407 cout << "write buffer fill (before) = " << m_writeBufferFill << endl;
408 #endif
409
410 m_writeBufferFill = getCurrentBufferedFrame();
411
412 #ifdef DEBUG_AUDIO_PLAY_SOURCE
413 cout << "current buffered frame = " << m_writeBufferFill << endl;
414 #endif
415
416 if (m_readBuffers != m_writeBuffers) {
417 delete m_writeBuffers;
418 }
419
420 m_writeBuffers = new RingBufferVector;
421
422 for (int i = 0; i < count; ++i) {
423 m_writeBuffers->push_back(new RingBuffer<float>(m_ringBufferSize));
424 }
425
426 m_audioGenerator->reset();
427
428 // cout << "AudioCallbackPlaySource::clearRingBuffers: Created "
429 // << count << " write buffers" << endl;
430
431 if (!haveLock) {
432 m_mutex.unlock();
433 }
434 }
435
436 void
play(sv_frame_t startFrame)437 AudioCallbackPlaySource::play(sv_frame_t startFrame)
438 {
439 if (!m_target) return;
440
441 if (!m_sourceSampleRate) {
442 SVCERR << "AudioCallbackPlaySource::play: No source sample rate available, not playing" << endl;
443 return;
444 }
445
446 if (m_viewManager->getPlaySelectionMode() &&
447 !m_viewManager->getSelections().empty()) {
448
449 #ifdef DEBUG_AUDIO_PLAY_SOURCE
450 cout << "AudioCallbackPlaySource::play: constraining frame " << startFrame << " to selection = ";
451 #endif
452
453 startFrame = m_viewManager->constrainFrameToSelection(startFrame);
454
455 #ifdef DEBUG_AUDIO_PLAY_SOURCE
456 cout << startFrame << endl;
457 #endif
458
459 } else {
460 if (startFrame < 0) {
461 startFrame = 0;
462 }
463 if (startFrame >= m_lastModelEndFrame) {
464 startFrame = 0;
465 }
466 }
467
468 #ifdef DEBUG_AUDIO_PLAY_SOURCE
469 cout << "play(" << startFrame << ") -> aligned playback model ";
470 #endif
471
472 startFrame = m_viewManager->alignReferenceToPlaybackFrame(startFrame);
473
474 #ifdef DEBUG_AUDIO_PLAY_SOURCE
475 cout << startFrame << endl;
476 #endif
477
478 // The fill thread will automatically empty its buffers before
479 // starting again if we have not so far been playing, but not if
480 // we're just re-seeking.
481 // NO -- we can end up playing some first -- always reset here
482
483 m_mutex.lock();
484
485 if (m_timeStretcher) {
486 m_timeStretcher->reset();
487 }
488 if (m_monoStretcher) {
489 m_monoStretcher->reset();
490 }
491
492 m_readBufferFill = m_writeBufferFill = startFrame;
493 if (m_readBuffers) {
494 for (int c = 0; c < getTargetChannelCount(); ++c) {
495 RingBuffer<float> *rb = getReadRingBuffer(c);
496 #ifdef DEBUG_AUDIO_PLAY_SOURCE
497 cout << "reset ring buffer for channel " << c << endl;
498 #endif
499 if (rb) rb->reset();
500 }
501 }
502
503 m_mutex.unlock();
504
505 m_audioGenerator->reset();
506
507 m_playStartFrame = startFrame;
508 m_playStartFramePassed = false;
509 m_playStartedAt = RealTime::zeroTime;
510 if (m_target) {
511 m_playStartedAt = RealTime::fromSeconds(m_target->getCurrentTime());
512 }
513
514 bool changed = !m_playing;
515 m_lastRetrievalTimestamp = 0;
516 m_lastCurrentFrame = 0;
517 m_playing = true;
518
519 #ifdef DEBUG_AUDIO_PLAY_SOURCE
520 cout << "AudioCallbackPlaySource::play: awakening thread" << endl;
521 #endif
522
523 m_condition.wakeAll();
524 if (changed) {
525 emit playStatusChanged(m_playing);
526 emit activity(tr("Play from %1").arg
527 (RealTime::frame2RealTime
528 (m_playStartFrame, m_sourceSampleRate).toText().c_str()));
529 }
530 }
531
532 void
stop()533 AudioCallbackPlaySource::stop()
534 {
535 #ifdef DEBUG_AUDIO_PLAY_SOURCE
536 SVDEBUG << "AudioCallbackPlaySource::stop()" << endl;
537 #endif
538 bool changed = m_playing;
539 m_playing = false;
540
541 #ifdef DEBUG_AUDIO_PLAY_SOURCE
542 cout << "AudioCallbackPlaySource::stop: awakening thread" << endl;
543 #endif
544
545 m_condition.wakeAll();
546 m_lastRetrievalTimestamp = 0;
547 if (changed) {
548 emit playStatusChanged(m_playing);
549 if (m_sourceSampleRate) {
550 emit activity(tr("Stop at %1").arg
551 (RealTime::frame2RealTime
552 (m_lastCurrentFrame, m_sourceSampleRate)
553 .toText().c_str()));
554 } else {
555 emit activity(tr("Stop"));
556 }
557 }
558 m_lastCurrentFrame = 0;
559 }
560
561 void
selectionChanged()562 AudioCallbackPlaySource::selectionChanged()
563 {
564 if (m_viewManager->getPlaySelectionMode()) {
565 clearRingBuffers();
566 }
567 }
568
569 void
playLoopModeChanged()570 AudioCallbackPlaySource::playLoopModeChanged()
571 {
572 clearRingBuffers();
573 }
574
575 void
playSelectionModeChanged()576 AudioCallbackPlaySource::playSelectionModeChanged()
577 {
578 if (!m_viewManager->getSelections().empty()) {
579 clearRingBuffers();
580 }
581 }
582
583 void
playParametersChanged(int)584 AudioCallbackPlaySource::playParametersChanged(int)
585 {
586 clearRingBuffers();
587 }
588
589 void
preferenceChanged(PropertyContainer::PropertyName)590 AudioCallbackPlaySource::preferenceChanged(PropertyContainer::PropertyName)
591 {
592 }
593
594 void
audioProcessingOverload()595 AudioCallbackPlaySource::audioProcessingOverload()
596 {
597 SVCERR << "Audio processing overload!" << endl;
598
599 if (!m_playing) return;
600
601 RealTimePluginInstance *ap = m_auditioningPlugin;
602 if (ap && !m_auditioningPluginBypassed) {
603 m_auditioningPluginBypassed = true;
604 emit audioOverloadPluginDisabled();
605 return;
606 }
607
608 if (m_timeStretcher &&
609 m_timeStretcher->getTimeRatio() < 1.0 &&
610 m_stretcherInputCount > 1 &&
611 m_monoStretcher && !m_stretchMono) {
612 m_stretchMono = true;
613 emit audioTimeStretchMultiChannelDisabled();
614 return;
615 }
616 }
617
618 void
setSystemPlaybackTarget(breakfastquay::SystemPlaybackTarget * target)619 AudioCallbackPlaySource::setSystemPlaybackTarget(breakfastquay::SystemPlaybackTarget *target)
620 {
621 if (target == nullptr) {
622 // reset target-related facts and figures
623 m_deviceSampleRate = 0;
624 m_deviceChannelCount = 0;
625 }
626 m_target = target;
627 }
628
629 void
setResamplerWrapper(breakfastquay::ResamplerWrapper * w)630 AudioCallbackPlaySource::setResamplerWrapper(breakfastquay::ResamplerWrapper *w)
631 {
632 m_resamplerWrapper = w;
633 if (m_resamplerWrapper && m_sourceSampleRate != 0) {
634 m_resamplerWrapper->changeApplicationSampleRate
635 (int(round(m_sourceSampleRate)));
636 }
637 }
638
639 void
setSystemPlaybackBlockSize(int size)640 AudioCallbackPlaySource::setSystemPlaybackBlockSize(int size)
641 {
642 cout << "AudioCallbackPlaySource::setTarget: Block size -> " << size << endl;
643 if (size != 0) {
644 m_blockSize = size;
645 }
646 if (size * 4 > m_ringBufferSize) {
647 #ifdef DEBUG_AUDIO_PLAY_SOURCE
648 cout << "AudioCallbackPlaySource::setTarget: Buffer size "
649 << size << " > a quarter of ring buffer size "
650 << m_ringBufferSize << ", calling for more ring buffer"
651 << endl;
652 #endif
653 m_ringBufferSize = size * 4;
654 if (m_writeBuffers && !m_writeBuffers->empty()) {
655 clearRingBuffers();
656 }
657 }
658 }
659
660 int
getTargetBlockSize() const661 AudioCallbackPlaySource::getTargetBlockSize() const
662 {
663 // cout << "AudioCallbackPlaySource::getTargetBlockSize() -> " << m_blockSize << endl;
664 return int(m_blockSize);
665 }
666
667 void
setSystemPlaybackLatency(int latency)668 AudioCallbackPlaySource::setSystemPlaybackLatency(int latency)
669 {
670 m_playLatency = latency;
671 }
672
673 sv_frame_t
getTargetPlayLatency() const674 AudioCallbackPlaySource::getTargetPlayLatency() const
675 {
676 return m_playLatency;
677 }
678
679 sv_frame_t
getCurrentPlayingFrame()680 AudioCallbackPlaySource::getCurrentPlayingFrame()
681 {
682 // This method attempts to estimate which audio sample frame is
683 // "currently coming through the speakers".
684
685 sv_samplerate_t deviceRate = getDeviceSampleRate();
686 sv_frame_t latency = m_playLatency; // at target rate
687 RealTime latency_t = RealTime::zeroTime;
688
689 if (deviceRate != 0) {
690 latency_t = RealTime::frame2RealTime(latency, deviceRate);
691 }
692
693 return getCurrentFrame(latency_t);
694 }
695
696 sv_frame_t
getCurrentBufferedFrame()697 AudioCallbackPlaySource::getCurrentBufferedFrame()
698 {
699 return getCurrentFrame(RealTime::zeroTime);
700 }
701
702 sv_frame_t
getCurrentFrame(RealTime latency_t)703 AudioCallbackPlaySource::getCurrentFrame(RealTime latency_t)
704 {
705 // The ring buffers contain data at the source sample rate and all
706 // processing (including time stretching) happens at this
707 // rate. Resampling only happens after the audio data leaves this
708 // class.
709
710 // (But because historically more than one sample rate could have
711 // been involved here, we do latency calculations using RealTime
712 // values instead of samples.)
713
714 sv_samplerate_t rate = getSourceSampleRate();
715
716 if (rate == 0) return 0;
717
718 int inbuffer = 0; // at target rate
719
720 for (int c = 0; c < getTargetChannelCount(); ++c) {
721 RingBuffer<float> *rb = getReadRingBuffer(c);
722 if (rb) {
723 int here = rb->getReadSpace();
724 if (c == 0 || here < inbuffer) inbuffer = here;
725 }
726 }
727
728 sv_frame_t readBufferFill = m_readBufferFill;
729 sv_frame_t lastRetrievedBlockSize = m_lastRetrievedBlockSize;
730 double lastRetrievalTimestamp = m_lastRetrievalTimestamp;
731 double currentTime = 0.0;
732 if (m_target) currentTime = m_target->getCurrentTime();
733
734 bool looping = m_viewManager->getPlayLoopMode();
735
736 RealTime inbuffer_t = RealTime::frame2RealTime(inbuffer, rate);
737
738 sv_frame_t stretchlat = 0;
739 double timeRatio = 1.0;
740
741 if (m_timeStretcher) {
742 stretchlat = m_timeStretcher->getLatency();
743 timeRatio = m_timeStretcher->getTimeRatio();
744 }
745
746 RealTime stretchlat_t = RealTime::frame2RealTime(stretchlat, rate);
747
748 // When the target has just requested a block from us, the last
749 // sample it obtained was our buffer fill frame count minus the
750 // amount of read space (converted back to source sample rate)
751 // remaining now. That sample is not expected to be played until
752 // the target's play latency has elapsed. By the time the
753 // following block is requested, that sample will be at the
754 // target's play latency minus the last requested block size away
755 // from being played.
756
757 RealTime sincerequest_t = RealTime::zeroTime;
758 RealTime lastretrieved_t = RealTime::zeroTime;
759
760 if (m_target &&
761 m_trustworthyTimestamps &&
762 lastRetrievalTimestamp != 0.0) {
763
764 lastretrieved_t = RealTime::frame2RealTime(lastRetrievedBlockSize, rate);
765
766 // calculate number of frames at target rate that have elapsed
767 // since the end of the last call to getSourceSamples
768
769 if (m_trustworthyTimestamps && !looping) {
770
771 // this adjustment seems to cause more problems when looping
772 double elapsed = currentTime - lastRetrievalTimestamp;
773
774 if (elapsed > 0.0) {
775 sincerequest_t = RealTime::fromSeconds(elapsed);
776 }
777 }
778
779 } else {
780
781 lastretrieved_t = RealTime::frame2RealTime(getTargetBlockSize(), rate);
782 }
783
784 RealTime bufferedto_t = RealTime::frame2RealTime(readBufferFill, rate);
785
786 if (timeRatio != 1.0) {
787 lastretrieved_t = lastretrieved_t / timeRatio;
788 sincerequest_t = sincerequest_t / timeRatio;
789 latency_t = latency_t / timeRatio;
790 }
791
792 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
793 cout << "\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;
794 #endif
795
796 // Normally the range lists should contain at least one item each
797 // -- if playback is unconstrained, that item should report the
798 // entire source audio duration.
799
800 if (m_rangeStarts.empty()) {
801 rebuildRangeLists();
802 }
803
804 if (m_rangeStarts.empty()) {
805 // this code is only used in case of error in rebuildRangeLists
806 RealTime playing_t = bufferedto_t
807 - latency_t - stretchlat_t - lastretrieved_t - inbuffer_t
808 + sincerequest_t;
809 if (playing_t < RealTime::zeroTime) playing_t = RealTime::zeroTime;
810 sv_frame_t frame = RealTime::realTime2Frame(playing_t, rate);
811 return m_viewManager->alignPlaybackFrameToReference(frame);
812 }
813
814 int inRange = 0;
815 int index = 0;
816
817 for (int i = 0; i < (int)m_rangeStarts.size(); ++i) {
818 if (bufferedto_t >= m_rangeStarts[i]) {
819 inRange = index;
820 } else {
821 break;
822 }
823 ++index;
824 }
825
826 if (inRange >= int(m_rangeStarts.size())) {
827 inRange = int(m_rangeStarts.size())-1;
828 }
829
830 RealTime playing_t = bufferedto_t;
831
832 playing_t = playing_t
833 - latency_t - stretchlat_t - lastretrieved_t - inbuffer_t
834 + sincerequest_t;
835
836 // This rather gross little hack is used to ensure that latency
837 // compensation doesn't result in the playback pointer appearing
838 // to start earlier than the actual playback does. It doesn't
839 // work properly (hence the bail-out in the middle) because if we
840 // are playing a relatively short looped region, the playing time
841 // estimated from the buffer fill frame may have wrapped around
842 // the region boundary and end up being much smaller than the
843 // theoretical play start frame, perhaps even for the entire
844 // duration of playback!
845
846 if (!m_playStartFramePassed) {
847 RealTime playstart_t = RealTime::frame2RealTime(m_playStartFrame, rate);
848 if (playing_t < playstart_t) {
849 // cout << "playing_t " << playing_t << " < playstart_t "
850 // << playstart_t << endl;
851 if (/*!!! sincerequest_t > RealTime::zeroTime && */
852 m_playStartedAt + latency_t + stretchlat_t <
853 RealTime::fromSeconds(currentTime)) {
854 // cout << "but we've been playing for long enough that I think we should disregard it (it probably results from loop wrapping)" << endl;
855 m_playStartFramePassed = true;
856 } else {
857 playing_t = playstart_t;
858 }
859 } else {
860 m_playStartFramePassed = true;
861 }
862 }
863
864 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
865 cout << "playing_t " << playing_t;
866 #endif
867
868 playing_t = playing_t - m_rangeStarts[inRange];
869
870 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
871 cout << " as offset into range " << inRange << " (start =" << m_rangeStarts[inRange] << " duration =" << m_rangeDurations[inRange] << ") = " << playing_t << endl;
872 #endif
873
874 while (playing_t < RealTime::zeroTime) {
875
876 if (inRange == 0) {
877 if (looping) {
878 inRange = int(m_rangeStarts.size()) - 1;
879 } else {
880 break;
881 }
882 } else {
883 --inRange;
884 }
885
886 playing_t = playing_t + m_rangeDurations[inRange];
887 }
888
889 playing_t = playing_t + m_rangeStarts[inRange];
890
891 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
892 cout << " playing time: " << playing_t << endl;
893 #endif
894
895 if (!looping) {
896 if (inRange == (int)m_rangeStarts.size()-1 &&
897 playing_t >= m_rangeStarts[inRange] + m_rangeDurations[inRange]) {
898 cout << "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;
899 stop();
900 }
901 }
902
903 if (playing_t < RealTime::zeroTime) playing_t = RealTime::zeroTime;
904
905 sv_frame_t frame = RealTime::realTime2Frame(playing_t, rate);
906
907 if (m_lastCurrentFrame > 0 && !looping) {
908 if (frame < m_lastCurrentFrame) {
909 frame = m_lastCurrentFrame;
910 }
911 }
912
913 m_lastCurrentFrame = frame;
914
915 return m_viewManager->alignPlaybackFrameToReference(frame);
916 }
917
918 void
rebuildRangeLists()919 AudioCallbackPlaySource::rebuildRangeLists()
920 {
921 bool constrained = (m_viewManager->getPlaySelectionMode());
922
923 m_rangeStarts.clear();
924 m_rangeDurations.clear();
925
926 sv_samplerate_t sourceRate = getSourceSampleRate();
927 if (sourceRate == 0) return;
928
929 RealTime end = RealTime::frame2RealTime(m_lastModelEndFrame, sourceRate);
930 if (end == RealTime::zeroTime) return;
931
932 if (!constrained) {
933 m_rangeStarts.push_back(RealTime::zeroTime);
934 m_rangeDurations.push_back(end);
935 return;
936 }
937
938 MultiSelection::SelectionList selections = m_viewManager->getSelections();
939 MultiSelection::SelectionList::const_iterator i;
940
941 #ifdef DEBUG_AUDIO_PLAY_SOURCE
942 SVDEBUG << "AudioCallbackPlaySource::rebuildRangeLists" << endl;
943 #endif
944
945 if (!selections.empty()) {
946
947 for (i = selections.begin(); i != selections.end(); ++i) {
948
949 RealTime start =
950 (RealTime::frame2RealTime
951 (m_viewManager->alignReferenceToPlaybackFrame(i->getStartFrame()),
952 sourceRate));
953 RealTime duration =
954 (RealTime::frame2RealTime
955 (m_viewManager->alignReferenceToPlaybackFrame(i->getEndFrame()) -
956 m_viewManager->alignReferenceToPlaybackFrame(i->getStartFrame()),
957 sourceRate));
958
959 m_rangeStarts.push_back(start);
960 m_rangeDurations.push_back(duration);
961 }
962 } else {
963 m_rangeStarts.push_back(RealTime::zeroTime);
964 m_rangeDurations.push_back(end);
965 }
966
967 #ifdef DEBUG_AUDIO_PLAY_SOURCE
968 cout << "Now have " << m_rangeStarts.size() << " play ranges" << endl;
969 #endif
970 }
971
972 void
setOutputLevels(float left,float right)973 AudioCallbackPlaySource::setOutputLevels(float left, float right)
974 {
975 if (left > m_outputLeft) m_outputLeft = left;
976 if (right > m_outputRight) m_outputRight = right;
977 m_levelsSet = true;
978 }
979
980 bool
getOutputLevels(float & left,float & right)981 AudioCallbackPlaySource::getOutputLevels(float &left, float &right)
982 {
983 left = m_outputLeft;
984 right = m_outputRight;
985 bool valid = m_levelsSet;
986 m_outputLeft = 0.f;
987 m_outputRight = 0.f;
988 m_levelsSet = false;
989 return valid;
990 }
991
992 void
setSystemPlaybackSampleRate(int sr)993 AudioCallbackPlaySource::setSystemPlaybackSampleRate(int sr)
994 {
995 m_deviceSampleRate = sr;
996 }
997
998 void
setSystemPlaybackChannelCount(int count)999 AudioCallbackPlaySource::setSystemPlaybackChannelCount(int count)
1000 {
1001 m_deviceChannelCount = count;
1002 }
1003
1004 void
setAuditioningEffect(Auditionable * a)1005 AudioCallbackPlaySource::setAuditioningEffect(Auditionable *a)
1006 {
1007 RealTimePluginInstance *plugin = dynamic_cast<RealTimePluginInstance *>(a);
1008 if (a && !plugin) {
1009 SVCERR << "WARNING: AudioCallbackPlaySource::setAuditioningEffect: auditionable object " << a << " is not a real-time plugin instance" << endl;
1010 }
1011
1012 m_mutex.lock();
1013 m_auditioningPlugin = plugin;
1014 m_auditioningPluginBypassed = false;
1015 m_mutex.unlock();
1016 }
1017
1018 void
setSoloModelSet(std::set<ModelId> s)1019 AudioCallbackPlaySource::setSoloModelSet(std::set<ModelId> s)
1020 {
1021 m_audioGenerator->setSoloModelSet(s);
1022 clearRingBuffers();
1023 }
1024
1025 void
clearSoloModelSet()1026 AudioCallbackPlaySource::clearSoloModelSet()
1027 {
1028 m_audioGenerator->clearSoloModelSet();
1029 clearRingBuffers();
1030 }
1031
1032 sv_samplerate_t
getDeviceSampleRate() const1033 AudioCallbackPlaySource::getDeviceSampleRate() const
1034 {
1035 return m_deviceSampleRate;
1036 }
1037
1038 int
getSourceChannelCount() const1039 AudioCallbackPlaySource::getSourceChannelCount() const
1040 {
1041 return m_sourceChannelCount;
1042 }
1043
1044 int
getTargetChannelCount() const1045 AudioCallbackPlaySource::getTargetChannelCount() const
1046 {
1047 if (m_sourceChannelCount < 2) return 2;
1048 return m_sourceChannelCount;
1049 }
1050
1051 int
getDeviceChannelCount() const1052 AudioCallbackPlaySource::getDeviceChannelCount() const
1053 {
1054 return m_deviceChannelCount;
1055 }
1056
1057 sv_samplerate_t
getSourceSampleRate() const1058 AudioCallbackPlaySource::getSourceSampleRate() const
1059 {
1060 return m_sourceSampleRate;
1061 }
1062
1063 void
setTimeStretch(double factor)1064 AudioCallbackPlaySource::setTimeStretch(double factor)
1065 {
1066 m_stretchRatio = factor;
1067
1068 int rate = int(getSourceSampleRate());
1069 if (!rate) return; // have to make our stretcher later
1070
1071 if (m_timeStretcher || (factor == 1.0)) {
1072 // stretch ratio will be set in next process call if appropriate
1073 } else {
1074 m_stretcherInputCount = getTargetChannelCount();
1075 RubberBandStretcher *stretcher = new RubberBandStretcher
1076 (rate,
1077 m_stretcherInputCount,
1078 RubberBandStretcher::OptionProcessRealTime,
1079 factor);
1080 RubberBandStretcher *monoStretcher = new RubberBandStretcher
1081 (rate,
1082 1,
1083 RubberBandStretcher::OptionProcessRealTime,
1084 factor);
1085 m_stretcherInputs = new float *[m_stretcherInputCount];
1086 m_stretcherInputSizes = new sv_frame_t[m_stretcherInputCount];
1087 for (int c = 0; c < m_stretcherInputCount; ++c) {
1088 m_stretcherInputSizes[c] = 16384;
1089 m_stretcherInputs[c] = new float[m_stretcherInputSizes[c]];
1090 }
1091 m_monoStretcher = monoStretcher;
1092 m_timeStretcher = stretcher;
1093 }
1094
1095 emit activity(tr("Change time-stretch factor to %1").arg(factor));
1096 }
1097
1098 int
getSourceSamples(float * const * buffer,int requestedChannels,int count)1099 AudioCallbackPlaySource::getSourceSamples(float *const *buffer,
1100 int requestedChannels,
1101 int count)
1102 {
1103 // In principle, the target will handle channel mapping in cases
1104 // where our channel count differs from the device's. But that
1105 // only holds if our channel count doesn't change -- i.e. if
1106 // getApplicationChannelCount() always returns the same value as
1107 // it did when the target was created, and if this function always
1108 // returns that number of channels.
1109 //
1110 // Unfortunately that can't hold for us -- we always have at least
1111 // 2 channels but if the user opens a new main model with more
1112 // channels than that (and more than the last main model) then our
1113 // target channel count necessarily gets increased.
1114 //
1115 // We have:
1116 //
1117 // getSourceChannelCount() -> number of channels available to
1118 // provide from real model data
1119 //
1120 // getTargetChannelCount() -> number we will actually provide;
1121 // same as getSourceChannelCount() except that it is always at
1122 // least 2
1123 //
1124 // getDeviceChannelCount() -> number the device will emit, usually
1125 // equal to the value of getTargetChannelCount() at the time the
1126 // device was initialised, unless the device could not provide
1127 // that number
1128 //
1129 // requestedChannels -> number the device is expecting from us,
1130 // always equal to the value of getTargetChannelCount() at the
1131 // time the device was initialised
1132 //
1133 // If the requested channel count is at least the target channel
1134 // count, then we go ahead and provide the target channels as
1135 // expected. We just zero any spare channels.
1136 //
1137 // If the requested channel count is smaller than the target
1138 // channel count, then we don't know what to do and we provide
1139 // nothing. This shouldn't happen as long as management is on the
1140 // ball -- we emit channelCountIncreased() when the target channel
1141 // count increases, and whatever code "owns" the driver should
1142 // have reopened the audio device when it got that signal. But
1143 // there's a race condition there, which we accommodate with this
1144 // check.
1145
1146 int channels = getTargetChannelCount();
1147
1148 if (!m_playing) {
1149 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
1150 cout << "AudioCallbackPlaySource::getSourceSamples: Not playing" << endl;
1151 #endif
1152 v_zero_channels(buffer, requestedChannels, count);
1153 return 0;
1154 }
1155 if (requestedChannels < channels) {
1156 SVDEBUG << "AudioCallbackPlaySource::getSourceSamples: Not enough device channels (" << requestedChannels << ", need " << channels << "); hoping device is about to be reopened" << endl;
1157 v_zero_channels(buffer, requestedChannels, count);
1158 return 0;
1159 }
1160 if (requestedChannels > channels) {
1161 v_zero_channels(buffer + channels, requestedChannels - channels, count);
1162 }
1163
1164 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
1165 cout << "AudioCallbackPlaySource::getSourceSamples: Playing" << endl;
1166 #endif
1167
1168 // Ensure that all buffers have at least the amount of data we
1169 // need -- else reduce the size of our requests correspondingly
1170
1171 for (int ch = 0; ch < channels; ++ch) {
1172
1173 RingBuffer<float> *rb = getReadRingBuffer(ch);
1174
1175 if (!rb) {
1176 SVCERR << "WARNING: AudioCallbackPlaySource::getSourceSamples: "
1177 << "No ring buffer available for channel " << ch
1178 << ", returning no data here" << endl;
1179 count = 0;
1180 break;
1181 }
1182
1183 int rs = rb->getReadSpace();
1184 if (rs < count) {
1185 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1186 cerr << "WARNING: AudioCallbackPlaySource::getSourceSamples: "
1187 << "Ring buffer for channel " << ch << " has only "
1188 << rs << " (of " << count << ") samples available ("
1189 << "ring buffer size is " << rb->getSize() << ", write "
1190 << "space " << rb->getWriteSpace() << "), "
1191 << "reducing request size" << endl;
1192 #endif
1193 count = rs;
1194 }
1195 }
1196
1197 if (count == 0) return 0;
1198
1199 RubberBandStretcher *ts = m_timeStretcher;
1200 RubberBandStretcher *ms = m_monoStretcher;
1201
1202 double ratio = ts ? ts->getTimeRatio() : 1.0;
1203
1204 if (ratio != m_stretchRatio) {
1205 if (!ts) {
1206 SVCERR << "WARNING: AudioCallbackPlaySource::getSourceSamples: Time ratio change to " << m_stretchRatio << " is pending, but no stretcher is set" << endl;
1207 m_stretchRatio = 1.0;
1208 } else {
1209 ts->setTimeRatio(m_stretchRatio);
1210 if (ms) ms->setTimeRatio(m_stretchRatio);
1211 if (m_stretchRatio >= 1.0) m_stretchMono = false;
1212 }
1213 }
1214
1215 int stretchChannels = m_stretcherInputCount;
1216 if (m_stretchMono) {
1217 if (ms) {
1218 ts = ms;
1219 stretchChannels = 1;
1220 } else {
1221 m_stretchMono = false;
1222 }
1223 }
1224
1225 if (m_target) {
1226 m_lastRetrievedBlockSize = count;
1227 m_lastRetrievalTimestamp = m_target->getCurrentTime();
1228 }
1229
1230 if (!ts || ratio == 1.f) {
1231
1232 int got = 0;
1233
1234 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
1235 cout << "channels == " << channels << endl;
1236 #endif
1237
1238 for (int ch = 0; ch < channels; ++ch) {
1239
1240 RingBuffer<float> *rb = getReadRingBuffer(ch);
1241
1242 if (rb) {
1243
1244 // this is marginally more likely to leave our channels in
1245 // sync after a processing failure than just passing "count":
1246 sv_frame_t request = count;
1247 if (ch > 0) request = got;
1248
1249 got = rb->read(buffer[ch], int(request));
1250
1251 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
1252 cout << "AudioCallbackPlaySource::getSamples: got " << got << " (of " << count << ") samples on channel " << ch << ", signalling for more (possibly)" << endl;
1253 #endif
1254 }
1255
1256 for (int ch = 0; ch < channels; ++ch) {
1257 for (int i = got; i < count; ++i) {
1258 buffer[ch][i] = 0.0;
1259 }
1260 }
1261 }
1262
1263 applyAuditioningEffect(count, buffer);
1264
1265 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1266 cout << "AudioCallbackPlaySource::getSamples: awakening thread" << endl;
1267 #endif
1268
1269 m_condition.wakeAll();
1270
1271 return got;
1272 }
1273
1274 sv_frame_t available;
1275 sv_frame_t fedToStretcher = 0;
1276 int warned = 0;
1277
1278 // The input block for a given output is approx output / ratio,
1279 // but we can't predict it exactly, for an adaptive timestretcher.
1280
1281 while ((available = ts->available()) < count) {
1282
1283 sv_frame_t reqd = lrint(double(count - available) / ratio);
1284 reqd = std::max(reqd, sv_frame_t(ts->getSamplesRequired()));
1285 if (reqd == 0) reqd = 1;
1286
1287 sv_frame_t got = reqd;
1288
1289 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
1290 cout << "reqd = " <<reqd << ", channels = " << channels << ", ic = " << m_stretcherInputCount << endl;
1291 #endif
1292
1293 for (int c = 0; c < channels; ++c) {
1294 if (c >= m_stretcherInputCount) continue;
1295 if (reqd > m_stretcherInputSizes[c]) {
1296 if (c == 0) {
1297 SVDEBUG << "NOTE: resizing stretcher input buffer from " << m_stretcherInputSizes[c] << " to " << (reqd * 2) << endl;
1298 }
1299 delete[] m_stretcherInputs[c];
1300 m_stretcherInputSizes[c] = reqd * 2;
1301 m_stretcherInputs[c] = new float[m_stretcherInputSizes[c]];
1302 }
1303 }
1304
1305 for (int c = 0; c < channels; ++c) {
1306 if (c >= m_stretcherInputCount) continue;
1307 RingBuffer<float> *rb = getReadRingBuffer(c);
1308 if (rb) {
1309 sv_frame_t gotHere;
1310 if (stretchChannels == 1 && c > 0) {
1311 gotHere = rb->readAdding(m_stretcherInputs[0], int(got));
1312 } else {
1313 gotHere = rb->read(m_stretcherInputs[c], int(got));
1314 }
1315 if (gotHere < got) got = gotHere;
1316
1317 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
1318 if (c == 0) {
1319 cout << "feeding stretcher: got " << gotHere
1320 << ", " << rb->getReadSpace() << " remain" << endl;
1321 }
1322 #endif
1323
1324 } else {
1325 SVCERR << "WARNING: No ring buffer available for channel " << c << " in stretcher input block" << endl;
1326 }
1327 }
1328
1329 if (got < reqd) {
1330 SVCERR << "WARNING: Read underrun in playback ("
1331 << got << " < " << reqd << ")" << endl;
1332 }
1333
1334 ts->process(m_stretcherInputs, size_t(got), false);
1335
1336 fedToStretcher += got;
1337
1338 if (got == 0) break;
1339
1340 if (ts->available() == available) {
1341 SVCERR << "WARNING: AudioCallbackPlaySource::getSamples: Added " << got << " samples to time stretcher, created no new available output samples (warned = " << warned << ")" << endl;
1342 if (++warned == 5) break;
1343 }
1344 }
1345
1346 ts->retrieve(buffer, size_t(count));
1347
1348 v_zero_channels(buffer + stretchChannels, channels - stretchChannels, count);
1349
1350 applyAuditioningEffect(count, buffer);
1351
1352 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1353 cout << "AudioCallbackPlaySource::getSamples [stretched]: awakening thread" << endl;
1354 #endif
1355
1356 m_condition.wakeAll();
1357
1358 return count;
1359 }
1360
1361 void
applyAuditioningEffect(sv_frame_t count,float * const * buffers)1362 AudioCallbackPlaySource::applyAuditioningEffect(sv_frame_t count, float *const *buffers)
1363 {
1364 if (m_auditioningPluginBypassed) return;
1365 RealTimePluginInstance *plugin = m_auditioningPlugin;
1366 if (!plugin) return;
1367
1368 if ((int)plugin->getAudioInputCount() != getTargetChannelCount()) {
1369 // cout << "plugin input count " << plugin->getAudioInputCount()
1370 // << " != our channel count " << getTargetChannelCount()
1371 // << endl;
1372 return;
1373 }
1374 if ((int)plugin->getAudioOutputCount() != getTargetChannelCount()) {
1375 // cout << "plugin output count " << plugin->getAudioOutputCount()
1376 // << " != our channel count " << getTargetChannelCount()
1377 // << endl;
1378 return;
1379 }
1380 if ((int)plugin->getBufferSize() < count) {
1381 // cout << "plugin buffer size " << plugin->getBufferSize()
1382 // << " < our block size " << count
1383 // << endl;
1384 return;
1385 }
1386
1387 float **ib = plugin->getAudioInputBuffers();
1388 float **ob = plugin->getAudioOutputBuffers();
1389
1390 for (int c = 0; c < getTargetChannelCount(); ++c) {
1391 for (int i = 0; i < count; ++i) {
1392 ib[c][i] = buffers[c][i];
1393 }
1394 }
1395
1396 plugin->run(Vamp::RealTime::zeroTime, int(count));
1397
1398 for (int c = 0; c < getTargetChannelCount(); ++c) {
1399 for (int i = 0; i < count; ++i) {
1400 buffers[c][i] = ob[c][i];
1401 }
1402 }
1403 }
1404
1405 // Called from fill thread, m_playing true, mutex held
1406 bool
fillBuffers()1407 AudioCallbackPlaySource::fillBuffers()
1408 {
1409 static float *tmp = nullptr;
1410 static sv_frame_t tmpSize = 0;
1411
1412 sv_frame_t space = 0;
1413 for (int c = 0; c < getTargetChannelCount(); ++c) {
1414 RingBuffer<float> *wb = getWriteRingBuffer(c);
1415 if (wb) {
1416 sv_frame_t spaceHere = wb->getWriteSpace();
1417 if (c == 0 || spaceHere < space) space = spaceHere;
1418 }
1419 }
1420
1421 if (space == 0) {
1422 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1423 cout << "AudioCallbackPlaySourceFillThread: no space to fill" << endl;
1424 #endif
1425 return false;
1426 }
1427
1428 // space is now the number of samples that can be written on each
1429 // channel's write ringbuffer
1430
1431 sv_frame_t f = m_writeBufferFill;
1432
1433 bool readWriteEqual = (m_readBuffers == m_writeBuffers);
1434
1435 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1436 if (!readWriteEqual) {
1437 cout << "AudioCallbackPlaySourceFillThread: note read buffers != write buffers" << endl;
1438 }
1439 cout << "AudioCallbackPlaySourceFillThread: filling " << space << " frames" << endl;
1440 #endif
1441
1442 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1443 cout << "buffered to " << f << " already" << endl;
1444 #endif
1445
1446 int channels = getTargetChannelCount();
1447
1448 static float **bufferPtrs = nullptr;
1449 static int bufferPtrCount = 0;
1450
1451 if (bufferPtrCount < channels) {
1452 if (bufferPtrs) delete[] bufferPtrs;
1453 bufferPtrs = new float *[channels];
1454 bufferPtrCount = channels;
1455 }
1456
1457 sv_frame_t generatorBlockSize = m_audioGenerator->getBlockSize();
1458
1459 // space must be a multiple of generatorBlockSize
1460 sv_frame_t reqSpace = space;
1461 space = (reqSpace / generatorBlockSize) * generatorBlockSize;
1462 if (space == 0) {
1463 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1464 cout << "requested fill of " << reqSpace
1465 << " is less than generator block size of "
1466 << generatorBlockSize << ", leaving it" << endl;
1467 #endif
1468 return false;
1469 }
1470
1471 if (tmpSize < channels * space) {
1472 delete[] tmp;
1473 tmp = new float[channels * space];
1474 tmpSize = channels * space;
1475 }
1476
1477 for (int c = 0; c < channels; ++c) {
1478
1479 bufferPtrs[c] = tmp + c * space;
1480
1481 for (int i = 0; i < space; ++i) {
1482 tmp[c * space + i] = 0.0f;
1483 }
1484 }
1485
1486 sv_frame_t got = mixModels(f, space, bufferPtrs); // also modifies f
1487
1488 for (int c = 0; c < channels; ++c) {
1489
1490 RingBuffer<float> *wb = getWriteRingBuffer(c);
1491 if (wb) {
1492 int actual = wb->write(bufferPtrs[c], int(got));
1493 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1494 cout << "Wrote " << actual << " samples for ch " << c << ", now "
1495 << wb->getReadSpace() << " to read"
1496 << endl;
1497 #endif
1498 if (actual < got) {
1499 SVCERR << "WARNING: Buffer overrun in channel " << c
1500 << ": wrote " << actual << " of " << got
1501 << " samples" << endl;
1502 }
1503 }
1504 }
1505
1506 m_writeBufferFill = f;
1507 if (readWriteEqual) m_readBufferFill = f;
1508
1509 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1510 cout << "Read buffer fill is now " << m_readBufferFill << ", write buffer fill "
1511 << m_writeBufferFill << endl;
1512 #endif
1513
1514 //!!! how do we know when ended? need to mark up a fully-buffered flag and check this if we find the buffers empty in getSourceSamples
1515
1516 return true;
1517 }
1518
1519 sv_frame_t
mixModels(sv_frame_t & frame,sv_frame_t count,float ** buffers)1520 AudioCallbackPlaySource::mixModels(sv_frame_t &frame, sv_frame_t count, float **buffers)
1521 {
1522 sv_frame_t processed = 0;
1523 sv_frame_t chunkStart = frame;
1524 sv_frame_t chunkSize = count;
1525 sv_frame_t selectionSize = 0;
1526 sv_frame_t nextChunkStart = chunkStart + chunkSize;
1527
1528 bool looping = m_viewManager->getPlayLoopMode();
1529 bool constrained = (m_viewManager->getPlaySelectionMode() &&
1530 !m_viewManager->getSelections().empty());
1531
1532 int channels = getTargetChannelCount();
1533
1534 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1535 cout << "mixModels: start " << frame << ", size " << count << ", channels " << channels << endl;
1536 #endif
1537 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
1538 if (constrained) {
1539 cout << "Manager has " << m_viewManager->getSelections().size() << " selection(s):" << endl;
1540 for (auto sel: m_viewManager->getSelections()) {
1541 cout << sel.getStartFrame() << " -> " << sel.getEndFrame()
1542 << " (" << (sel.getEndFrame() - sel.getStartFrame()) << " frames)"
1543 << endl;
1544 }
1545 }
1546 #endif
1547
1548 static float **chunkBufferPtrs = nullptr;
1549 static int chunkBufferPtrCount = 0;
1550
1551 if (chunkBufferPtrCount < channels) {
1552 if (chunkBufferPtrs) delete[] chunkBufferPtrs;
1553 chunkBufferPtrs = new float *[channels];
1554 chunkBufferPtrCount = channels;
1555 }
1556
1557 for (int c = 0; c < channels; ++c) {
1558 chunkBufferPtrs[c] = buffers[c];
1559 }
1560
1561 while (processed < count) {
1562
1563 chunkSize = count - processed;
1564 nextChunkStart = chunkStart + chunkSize;
1565 selectionSize = 0;
1566
1567 sv_frame_t fadeIn = 0, fadeOut = 0;
1568
1569 if (constrained) {
1570
1571 sv_frame_t rChunkStart =
1572 m_viewManager->alignPlaybackFrameToReference(chunkStart);
1573
1574 Selection selection =
1575 m_viewManager->getContainingSelection(rChunkStart, true);
1576
1577 if (selection.isEmpty()) {
1578 if (looping) {
1579 selection = *m_viewManager->getSelections().begin();
1580 chunkStart = m_viewManager->alignReferenceToPlaybackFrame
1581 (selection.getStartFrame());
1582 fadeIn = 50;
1583 }
1584 }
1585
1586 if (selection.isEmpty()) {
1587
1588 chunkSize = 0;
1589 nextChunkStart = chunkStart;
1590
1591 } else {
1592
1593 sv_frame_t sf = m_viewManager->alignReferenceToPlaybackFrame
1594 (selection.getStartFrame());
1595 sv_frame_t ef = m_viewManager->alignReferenceToPlaybackFrame
1596 (selection.getEndFrame());
1597
1598 selectionSize = ef - sf;
1599
1600 if (chunkStart < sf) {
1601 chunkStart = sf;
1602 fadeIn = 50;
1603 }
1604
1605 nextChunkStart = chunkStart + chunkSize;
1606
1607 if (nextChunkStart >= ef) {
1608 nextChunkStart = ef;
1609 fadeOut = 50;
1610 }
1611
1612 chunkSize = nextChunkStart - chunkStart;
1613 }
1614
1615 } else if (looping && m_lastModelEndFrame > 0) {
1616
1617 if (chunkStart >= m_lastModelEndFrame) {
1618 chunkStart = 0;
1619 }
1620 if (chunkSize > m_lastModelEndFrame - chunkStart) {
1621 chunkSize = m_lastModelEndFrame - chunkStart;
1622 }
1623 nextChunkStart = chunkStart + chunkSize;
1624 }
1625
1626 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
1627 cout << "chunkStart " << chunkStart << ", chunkSize " << chunkSize << ", nextChunkStart " << nextChunkStart << ", frame " << frame << ", count " << count << ", processed " << processed << endl;
1628 #endif
1629
1630 if (!chunkSize) {
1631 // We need to maintain full buffers so that the other
1632 // thread can tell where it's got to in the playback -- so
1633 // return the full amount here
1634 frame = frame + count;
1635 if (frame < nextChunkStart) {
1636 frame = nextChunkStart;
1637 }
1638 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1639 cout << "mixModels: ending at " << nextChunkStart << ", returning frame as "
1640 << frame << endl;
1641 #endif
1642 return count;
1643 }
1644
1645 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1646 cout << "mixModels: chunk at " << chunkStart << " -> " << nextChunkStart << " (size " << chunkSize << ")" << endl;
1647 #endif
1648
1649 if (selectionSize < 100) {
1650 fadeIn = 0;
1651 fadeOut = 0;
1652 } else if (selectionSize < 300) {
1653 if (fadeIn > 0) fadeIn = 10;
1654 if (fadeOut > 0) fadeOut = 10;
1655 }
1656
1657 if (fadeIn > 0) {
1658 if (processed * 2 < fadeIn) {
1659 fadeIn = processed * 2;
1660 }
1661 }
1662
1663 if (fadeOut > 0) {
1664 if ((count - processed - chunkSize) * 2 < fadeOut) {
1665 fadeOut = (count - processed - chunkSize) * 2;
1666 }
1667 }
1668
1669 for (std::set<ModelId>::iterator mi = m_models.begin();
1670 mi != m_models.end(); ++mi) {
1671
1672 (void) m_audioGenerator->mixModel(*mi, chunkStart,
1673 chunkSize, chunkBufferPtrs,
1674 fadeIn, fadeOut);
1675 }
1676
1677 for (int c = 0; c < channels; ++c) {
1678 chunkBufferPtrs[c] += chunkSize;
1679 }
1680
1681 processed += chunkSize;
1682 chunkStart = nextChunkStart;
1683 }
1684
1685 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1686 cout << "mixModels returning " << processed << " frames to " << nextChunkStart << endl;
1687 #endif
1688
1689 frame = nextChunkStart;
1690 return processed;
1691 }
1692
1693 void
unifyRingBuffers()1694 AudioCallbackPlaySource::unifyRingBuffers()
1695 {
1696 if (m_readBuffers == m_writeBuffers) return;
1697
1698 // only unify if there will be something to read
1699 for (int c = 0; c < getTargetChannelCount(); ++c) {
1700 RingBuffer<float> *wb = getWriteRingBuffer(c);
1701 if (wb) {
1702 if (wb->getReadSpace() < m_blockSize * 2) {
1703 if ((m_writeBufferFill + m_blockSize * 2) <
1704 m_lastModelEndFrame) {
1705 // OK, we don't have enough and there's more to
1706 // read -- don't unify until we can do better
1707 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
1708 cout << "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;
1709 #endif
1710 return;
1711 }
1712 }
1713 break;
1714 }
1715 }
1716
1717 sv_frame_t rf = m_readBufferFill;
1718 RingBuffer<float> *rb = getReadRingBuffer(0);
1719 if (rb) {
1720 int rs = rb->getReadSpace();
1721 //!!! incorrect when in non-contiguous selection, see comments elsewhere
1722 // cout << "rs = " << rs << endl;
1723 if (rs < rf) rf -= rs;
1724 else rf = 0;
1725 }
1726
1727 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
1728 cout << "AudioCallbackPlaySource::unifyRingBuffers: m_readBufferFill = " << m_readBufferFill << ", rf = " << rf << ", m_writeBufferFill = " << m_writeBufferFill << endl;
1729 #endif
1730
1731 sv_frame_t wf = m_writeBufferFill;
1732 sv_frame_t skip = 0;
1733 for (int c = 0; c < getTargetChannelCount(); ++c) {
1734 RingBuffer<float> *wb = getWriteRingBuffer(c);
1735 if (wb) {
1736 if (c == 0) {
1737
1738 int wrs = wb->getReadSpace();
1739 // cout << "wrs = " << wrs << endl;
1740
1741 if (wrs < wf) wf -= wrs;
1742 else wf = 0;
1743 // cout << "wf = " << wf << endl;
1744
1745 if (wf < rf) skip = rf - wf;
1746 if (skip == 0) break;
1747 }
1748
1749 // cout << "skipping " << skip << endl;
1750 wb->skip(int(skip));
1751 }
1752 }
1753
1754 m_bufferScavenger.claim(m_readBuffers);
1755 m_readBuffers = m_writeBuffers;
1756 m_readBufferFill = m_writeBufferFill;
1757 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
1758 cout << "unified" << endl;
1759 #endif
1760 }
1761
1762 void
run()1763 AudioCallbackPlaySource::FillThread::run()
1764 {
1765 AudioCallbackPlaySource &s(m_source);
1766
1767 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1768 cout << "AudioCallbackPlaySourceFillThread starting" << endl;
1769 #endif
1770
1771 s.m_mutex.lock();
1772
1773 bool previouslyPlaying = s.m_playing;
1774 bool work = false;
1775
1776 while (!s.m_exiting) {
1777
1778 s.unifyRingBuffers();
1779 s.m_bufferScavenger.scavenge();
1780 s.m_pluginScavenger.scavenge();
1781
1782 if (work && s.m_playing && s.getSourceSampleRate()) {
1783
1784 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1785 cout << "AudioCallbackPlaySourceFillThread: not waiting" << endl;
1786 #endif
1787
1788 s.m_mutex.unlock();
1789 s.m_mutex.lock();
1790
1791 } else {
1792
1793 double ms = 100;
1794 if (s.getSourceSampleRate() > 0) {
1795 ms = double(s.m_ringBufferSize) / s.getSourceSampleRate() * 1000.0;
1796 }
1797
1798 if (s.m_playing) ms /= 10;
1799
1800 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1801 if (!s.m_playing) cout << endl;
1802 cout << "AudioCallbackPlaySourceFillThread: waiting for " << ms << "ms..." << endl;
1803 #endif
1804
1805 s.m_condition.wait(&s.m_mutex, int(ms));
1806 }
1807
1808 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1809 cout << "AudioCallbackPlaySourceFillThread: awoken" << endl;
1810 #endif
1811
1812 work = false;
1813
1814 if (!s.getSourceSampleRate()) {
1815 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1816 cout << "AudioCallbackPlaySourceFillThread: source sample rate is zero" << endl;
1817 #endif
1818 continue;
1819 }
1820
1821 bool playing = s.m_playing;
1822
1823 if (playing && !previouslyPlaying) {
1824 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1825 cout << "AudioCallbackPlaySourceFillThread: playback state changed, resetting" << endl;
1826 #endif
1827 for (int c = 0; c < s.getTargetChannelCount(); ++c) {
1828 RingBuffer<float> *rb = s.getReadRingBuffer(c);
1829 if (rb) rb->reset();
1830 }
1831 }
1832 previouslyPlaying = playing;
1833
1834 work = s.fillBuffers();
1835 }
1836
1837 s.m_mutex.unlock();
1838 }
1839
1840