comparison audioio/AudioCallbackPlaySource.cpp @ 450:d9d132c0e240 alignment_view

Merge from default branch
author Chris Cannam
date Mon, 20 Apr 2015 09:21:32 +0100
parents c48bc6ddfe17
children 3e2a2ca24d90
comparison
equal deleted inserted replaced
430:adfb2948fabf 450:d9d132c0e240
147 void 147 void
148 AudioCallbackPlaySource::addModel(Model *model) 148 AudioCallbackPlaySource::addModel(Model *model)
149 { 149 {
150 if (m_models.find(model) != m_models.end()) return; 150 if (m_models.find(model) != m_models.end()) return;
151 151
152 bool canPlay = m_audioGenerator->addModel(model); 152 bool willPlay = m_audioGenerator->addModel(model);
153 153
154 m_mutex.lock(); 154 m_mutex.lock();
155 155
156 m_models.insert(model); 156 m_models.insert(model);
157 if (model->getEndFrame() > m_lastModelEndFrame) { 157 if (model->getEndFrame() > m_lastModelEndFrame) {
223 223
224 if (!m_writeBuffers || (int)m_writeBuffers->size() < getTargetChannelCount()) { 224 if (!m_writeBuffers || (int)m_writeBuffers->size() < getTargetChannelCount()) {
225 clearRingBuffers(true, getTargetChannelCount()); 225 clearRingBuffers(true, getTargetChannelCount());
226 buffersChanged = true; 226 buffersChanged = true;
227 } else { 227 } else {
228 if (canPlay) clearRingBuffers(true); 228 if (willPlay) clearRingBuffers(true);
229 } 229 }
230 230
231 if (buffersChanged || srChanged) { 231 if (buffersChanged || srChanged) {
232 if (m_converter) { 232 if (m_converter) {
233 src_delete(m_converter); 233 src_delete(m_converter);
254 254
255 if (buffersChanged || srChanged) { 255 if (buffersChanged || srChanged) {
256 emit modelReplaced(); 256 emit modelReplaced();
257 } 257 }
258 258
259 connect(model, SIGNAL(modelChangedWithin(int, int)), 259 connect(model, SIGNAL(modelChangedWithin(sv_frame_t, sv_frame_t)),
260 this, SLOT(modelChangedWithin(int, int))); 260 this, SLOT(modelChangedWithin(sv_frame_t, sv_frame_t)));
261 261
262 #ifdef DEBUG_AUDIO_PLAY_SOURCE 262 #ifdef DEBUG_AUDIO_PLAY_SOURCE
263 cout << "AudioCallbackPlaySource::addModel: awakening thread" << endl; 263 cout << "AudioCallbackPlaySource::addModel: awakening thread" << endl;
264 #endif 264 #endif
265 265
266 m_condition.wakeAll(); 266 m_condition.wakeAll();
267 } 267 }
268 268
269 void 269 void
270 AudioCallbackPlaySource::modelChangedWithin(int 270 AudioCallbackPlaySource::modelChangedWithin(sv_frame_t
271 #ifdef DEBUG_AUDIO_PLAY_SOURCE 271 #ifdef DEBUG_AUDIO_PLAY_SOURCE
272 startFrame 272 startFrame
273 #endif 273 #endif
274 , int endFrame) 274 , sv_frame_t endFrame)
275 { 275 {
276 #ifdef DEBUG_AUDIO_PLAY_SOURCE 276 #ifdef DEBUG_AUDIO_PLAY_SOURCE
277 SVDEBUG << "AudioCallbackPlaySource::modelChangedWithin(" << startFrame << "," << endFrame << ")" << endl; 277 SVDEBUG << "AudioCallbackPlaySource::modelChangedWithin(" << startFrame << "," << endFrame << ")" << endl;
278 #endif 278 #endif
279 if (endFrame > m_lastModelEndFrame) { 279 if (endFrame > m_lastModelEndFrame) {
289 289
290 #ifdef DEBUG_AUDIO_PLAY_SOURCE 290 #ifdef DEBUG_AUDIO_PLAY_SOURCE
291 cout << "AudioCallbackPlaySource::removeModel(" << model << ")" << endl; 291 cout << "AudioCallbackPlaySource::removeModel(" << model << ")" << endl;
292 #endif 292 #endif
293 293
294 disconnect(model, SIGNAL(modelChangedWithin(int, int)), 294 disconnect(model, SIGNAL(modelChangedWithin(sv_frame_t, sv_frame_t)),
295 this, SLOT(modelChangedWithin(int, int))); 295 this, SLOT(modelChangedWithin(sv_frame_t, sv_frame_t)));
296 296
297 m_models.erase(model); 297 m_models.erase(model);
298 298
299 if (m_models.empty()) { 299 if (m_models.empty()) {
300 if (m_converter) { 300 if (m_converter) {
304 m_crapConverter = 0; 304 m_crapConverter = 0;
305 } 305 }
306 m_sourceSampleRate = 0; 306 m_sourceSampleRate = 0;
307 } 307 }
308 308
309 int lastEnd = 0; 309 sv_frame_t lastEnd = 0;
310 for (std::set<Model *>::const_iterator i = m_models.begin(); 310 for (std::set<Model *>::const_iterator i = m_models.begin();
311 i != m_models.end(); ++i) { 311 i != m_models.end(); ++i) {
312 #ifdef DEBUG_AUDIO_PLAY_SOURCE 312 #ifdef DEBUG_AUDIO_PLAY_SOURCE
313 cout << "AudioCallbackPlaySource::removeModel(" << model << "): checking end frame on model " << *i << endl; 313 cout << "AudioCallbackPlaySource::removeModel(" << model << "): checking end frame on model " << *i << endl;
314 #endif 314 #endif
360 void 360 void
361 AudioCallbackPlaySource::clearRingBuffers(bool haveLock, int count) 361 AudioCallbackPlaySource::clearRingBuffers(bool haveLock, int count)
362 { 362 {
363 if (!haveLock) m_mutex.lock(); 363 if (!haveLock) m_mutex.lock();
364 364
365 #ifdef DEBUG_AUDIO_PLAY_SOURCE
365 cerr << "clearRingBuffers" << endl; 366 cerr << "clearRingBuffers" << endl;
367 #endif
366 368
367 rebuildRangeLists(); 369 rebuildRangeLists();
368 370
369 if (count == 0) { 371 if (count == 0) {
370 if (m_writeBuffers) count = m_writeBuffers->size(); 372 if (m_writeBuffers) count = int(m_writeBuffers->size());
371 } 373 }
372 374
375 #ifdef DEBUG_AUDIO_PLAY_SOURCE
373 cerr << "current playing frame = " << getCurrentPlayingFrame() << endl; 376 cerr << "current playing frame = " << getCurrentPlayingFrame() << endl;
374 377
375 cerr << "write buffer fill (before) = " << m_writeBufferFill << endl; 378 cerr << "write buffer fill (before) = " << m_writeBufferFill << endl;
376 379 #endif
380
377 m_writeBufferFill = getCurrentBufferedFrame(); 381 m_writeBufferFill = getCurrentBufferedFrame();
378 382
383 #ifdef DEBUG_AUDIO_PLAY_SOURCE
379 cerr << "current buffered frame = " << m_writeBufferFill << endl; 384 cerr << "current buffered frame = " << m_writeBufferFill << endl;
385 #endif
380 386
381 if (m_readBuffers != m_writeBuffers) { 387 if (m_readBuffers != m_writeBuffers) {
382 delete m_writeBuffers; 388 delete m_writeBuffers;
383 } 389 }
384 390
386 392
387 for (int i = 0; i < count; ++i) { 393 for (int i = 0; i < count; ++i) {
388 m_writeBuffers->push_back(new RingBuffer<float>(m_ringBufferSize)); 394 m_writeBuffers->push_back(new RingBuffer<float>(m_ringBufferSize));
389 } 395 }
390 396
397 m_audioGenerator->reset();
398
391 // cout << "AudioCallbackPlaySource::clearRingBuffers: Created " 399 // cout << "AudioCallbackPlaySource::clearRingBuffers: Created "
392 // << count << " write buffers" << endl; 400 // << count << " write buffers" << endl;
393 401
394 if (!haveLock) { 402 if (!haveLock) {
395 m_mutex.unlock(); 403 m_mutex.unlock();
396 } 404 }
397 } 405 }
398 406
399 void 407 void
400 AudioCallbackPlaySource::play(int startFrame) 408 AudioCallbackPlaySource::play(sv_frame_t startFrame)
401 { 409 {
402 if (!m_sourceSampleRate) { 410 if (!m_sourceSampleRate) {
403 cerr << "AudioCallbackPlaySource::play: No source sample rate available, not playing" << endl; 411 cerr << "AudioCallbackPlaySource::play: No source sample rate available, not playing" << endl;
404 return; 412 return;
405 } 413 }
591 599
592 int 600 int
593 AudioCallbackPlaySource::getTargetBlockSize() const 601 AudioCallbackPlaySource::getTargetBlockSize() const
594 { 602 {
595 // cout << "AudioCallbackPlaySource::getTargetBlockSize() -> " << m_blockSize << endl; 603 // cout << "AudioCallbackPlaySource::getTargetBlockSize() -> " << m_blockSize << endl;
596 return m_blockSize; 604 return int(m_blockSize);
597 } 605 }
598 606
599 void 607 void
600 AudioCallbackPlaySource::setTargetPlayLatency(int latency) 608 AudioCallbackPlaySource::setTargetPlayLatency(sv_frame_t latency)
601 { 609 {
602 m_playLatency = latency; 610 m_playLatency = latency;
603 } 611 }
604 612
605 int 613 sv_frame_t
606 AudioCallbackPlaySource::getTargetPlayLatency() const 614 AudioCallbackPlaySource::getTargetPlayLatency() const
607 { 615 {
608 return m_playLatency; 616 return m_playLatency;
609 } 617 }
610 618
611 int 619 sv_frame_t
612 AudioCallbackPlaySource::getCurrentPlayingFrame() 620 AudioCallbackPlaySource::getCurrentPlayingFrame()
613 { 621 {
614 // This method attempts to estimate which audio sample frame is 622 // This method attempts to estimate which audio sample frame is
615 // "currently coming through the speakers". 623 // "currently coming through the speakers".
616 624
617 int targetRate = getTargetSampleRate(); 625 sv_samplerate_t targetRate = getTargetSampleRate();
618 int latency = m_playLatency; // at target rate 626 sv_frame_t latency = m_playLatency; // at target rate
619 RealTime latency_t = RealTime::zeroTime; 627 RealTime latency_t = RealTime::zeroTime;
620 628
621 if (targetRate != 0) { 629 if (targetRate != 0) {
622 latency_t = RealTime::frame2RealTime(latency, targetRate); 630 latency_t = RealTime::frame2RealTime(latency, targetRate);
623 } 631 }
624 632
625 return getCurrentFrame(latency_t); 633 return getCurrentFrame(latency_t);
626 } 634 }
627 635
628 int 636 sv_frame_t
629 AudioCallbackPlaySource::getCurrentBufferedFrame() 637 AudioCallbackPlaySource::getCurrentBufferedFrame()
630 { 638 {
631 return getCurrentFrame(RealTime::zeroTime); 639 return getCurrentFrame(RealTime::zeroTime);
632 } 640 }
633 641
634 int 642 sv_frame_t
635 AudioCallbackPlaySource::getCurrentFrame(RealTime latency_t) 643 AudioCallbackPlaySource::getCurrentFrame(RealTime latency_t)
636 { 644 {
637 // We resample when filling the ring buffer, and time-stretch when 645 // We resample when filling the ring buffer, and time-stretch when
638 // draining it. The buffer contains data at the "target rate" and 646 // draining it. The buffer contains data at the "target rate" and
639 // the latency provided by the target is also at the target rate. 647 // the latency provided by the target is also at the target rate.
640 // Because of the multiple rates involved, we do the actual 648 // Because of the multiple rates involved, we do the actual
641 // calculation using RealTime instead. 649 // calculation using RealTime instead.
642 650
643 int sourceRate = getSourceSampleRate(); 651 sv_samplerate_t sourceRate = getSourceSampleRate();
644 int targetRate = getTargetSampleRate(); 652 sv_samplerate_t targetRate = getTargetSampleRate();
645 653
646 if (sourceRate == 0 || targetRate == 0) return 0; 654 if (sourceRate == 0 || targetRate == 0) return 0;
647 655
648 int inbuffer = 0; // at target rate 656 int inbuffer = 0; // at target rate
649 657
653 int here = rb->getReadSpace(); 661 int here = rb->getReadSpace();
654 if (c == 0 || here < inbuffer) inbuffer = here; 662 if (c == 0 || here < inbuffer) inbuffer = here;
655 } 663 }
656 } 664 }
657 665
658 int readBufferFill = m_readBufferFill; 666 sv_frame_t readBufferFill = m_readBufferFill;
659 int lastRetrievedBlockSize = m_lastRetrievedBlockSize; 667 sv_frame_t lastRetrievedBlockSize = m_lastRetrievedBlockSize;
660 double lastRetrievalTimestamp = m_lastRetrievalTimestamp; 668 double lastRetrievalTimestamp = m_lastRetrievalTimestamp;
661 double currentTime = 0.0; 669 double currentTime = 0.0;
662 if (m_target) currentTime = m_target->getCurrentTime(); 670 if (m_target) currentTime = m_target->getCurrentTime();
663 671
664 bool looping = m_viewManager->getPlayLoopMode(); 672 bool looping = m_viewManager->getPlayLoopMode();
665 673
666 RealTime inbuffer_t = RealTime::frame2RealTime(inbuffer, targetRate); 674 RealTime inbuffer_t = RealTime::frame2RealTime(inbuffer, targetRate);
667 675
668 int stretchlat = 0; 676 sv_frame_t stretchlat = 0;
669 double timeRatio = 1.0; 677 double timeRatio = 1.0;
670 678
671 if (m_timeStretcher) { 679 if (m_timeStretcher) {
672 stretchlat = m_timeStretcher->getLatency(); 680 stretchlat = m_timeStretcher->getLatency();
673 timeRatio = m_timeStretcher->getTimeRatio(); 681 timeRatio = m_timeStretcher->getTimeRatio();
737 // this code is only used in case of error in rebuildRangeLists 745 // this code is only used in case of error in rebuildRangeLists
738 RealTime playing_t = bufferedto_t 746 RealTime playing_t = bufferedto_t
739 - latency_t - stretchlat_t - lastretrieved_t - inbuffer_t 747 - latency_t - stretchlat_t - lastretrieved_t - inbuffer_t
740 + sincerequest_t; 748 + sincerequest_t;
741 if (playing_t < RealTime::zeroTime) playing_t = RealTime::zeroTime; 749 if (playing_t < RealTime::zeroTime) playing_t = RealTime::zeroTime;
742 int frame = RealTime::realTime2Frame(playing_t, sourceRate); 750 sv_frame_t frame = RealTime::realTime2Frame(playing_t, sourceRate);
743 return m_viewManager->alignPlaybackFrameToReference(frame); 751 return m_viewManager->alignPlaybackFrameToReference(frame);
744 } 752 }
745 753
746 int inRange = 0; 754 int inRange = 0;
747 int index = 0; 755 int index = 0;
753 break; 761 break;
754 } 762 }
755 ++index; 763 ++index;
756 } 764 }
757 765
758 if (inRange >= (int)m_rangeStarts.size()) inRange = m_rangeStarts.size()-1; 766 if (inRange >= int(m_rangeStarts.size())) {
767 inRange = int(m_rangeStarts.size())-1;
768 }
759 769
760 RealTime playing_t = bufferedto_t; 770 RealTime playing_t = bufferedto_t;
761 771
762 playing_t = playing_t 772 playing_t = playing_t
763 - latency_t - stretchlat_t - lastretrieved_t - inbuffer_t 773 - latency_t - stretchlat_t - lastretrieved_t - inbuffer_t
804 814
805 while (playing_t < RealTime::zeroTime) { 815 while (playing_t < RealTime::zeroTime) {
806 816
807 if (inRange == 0) { 817 if (inRange == 0) {
808 if (looping) { 818 if (looping) {
809 inRange = m_rangeStarts.size() - 1; 819 inRange = int(m_rangeStarts.size()) - 1;
810 } else { 820 } else {
811 break; 821 break;
812 } 822 }
813 } else { 823 } else {
814 --inRange; 824 --inRange;
831 } 841 }
832 } 842 }
833 843
834 if (playing_t < RealTime::zeroTime) playing_t = RealTime::zeroTime; 844 if (playing_t < RealTime::zeroTime) playing_t = RealTime::zeroTime;
835 845
836 int frame = RealTime::realTime2Frame(playing_t, sourceRate); 846 sv_frame_t frame = RealTime::realTime2Frame(playing_t, sourceRate);
837 847
838 if (m_lastCurrentFrame > 0 && !looping) { 848 if (m_lastCurrentFrame > 0 && !looping) {
839 if (frame < m_lastCurrentFrame) { 849 if (frame < m_lastCurrentFrame) {
840 frame = m_lastCurrentFrame; 850 frame = m_lastCurrentFrame;
841 } 851 }
852 bool constrained = (m_viewManager->getPlaySelectionMode()); 862 bool constrained = (m_viewManager->getPlaySelectionMode());
853 863
854 m_rangeStarts.clear(); 864 m_rangeStarts.clear();
855 m_rangeDurations.clear(); 865 m_rangeDurations.clear();
856 866
857 int sourceRate = getSourceSampleRate(); 867 sv_samplerate_t sourceRate = getSourceSampleRate();
858 if (sourceRate == 0) return; 868 if (sourceRate == 0) return;
859 869
860 RealTime end = RealTime::frame2RealTime(m_lastModelEndFrame, sourceRate); 870 RealTime end = RealTime::frame2RealTime(m_lastModelEndFrame, sourceRate);
861 if (end == RealTime::zeroTime) return; 871 if (end == RealTime::zeroTime) return;
862 872
914 right = m_outputRight; 924 right = m_outputRight;
915 return true; 925 return true;
916 } 926 }
917 927
918 void 928 void
919 AudioCallbackPlaySource::setTargetSampleRate(int sr) 929 AudioCallbackPlaySource::setTargetSampleRate(sv_samplerate_t sr)
920 { 930 {
921 bool first = (m_targetSampleRate == 0); 931 bool first = (m_targetSampleRate == 0);
922 932
923 m_targetSampleRate = sr; 933 m_targetSampleRate = sr;
924 initialiseConverter(); 934 initialiseConverter();
1031 { 1041 {
1032 m_audioGenerator->clearSoloModelSet(); 1042 m_audioGenerator->clearSoloModelSet();
1033 clearRingBuffers(); 1043 clearRingBuffers();
1034 } 1044 }
1035 1045
1036 int 1046 sv_samplerate_t
1037 AudioCallbackPlaySource::getTargetSampleRate() const 1047 AudioCallbackPlaySource::getTargetSampleRate() const
1038 { 1048 {
1039 if (m_targetSampleRate) return m_targetSampleRate; 1049 if (m_targetSampleRate) return m_targetSampleRate;
1040 else return getSourceSampleRate(); 1050 else return getSourceSampleRate();
1041 } 1051 }
1051 { 1061 {
1052 if (m_sourceChannelCount < 2) return 2; 1062 if (m_sourceChannelCount < 2) return 2;
1053 return m_sourceChannelCount; 1063 return m_sourceChannelCount;
1054 } 1064 }
1055 1065
1056 int 1066 sv_samplerate_t
1057 AudioCallbackPlaySource::getSourceSampleRate() const 1067 AudioCallbackPlaySource::getSourceSampleRate() const
1058 { 1068 {
1059 return m_sourceSampleRate; 1069 return m_sourceSampleRate;
1060 } 1070 }
1061 1071
1062 void 1072 void
1063 AudioCallbackPlaySource::setTimeStretch(float factor) 1073 AudioCallbackPlaySource::setTimeStretch(double factor)
1064 { 1074 {
1065 m_stretchRatio = factor; 1075 m_stretchRatio = factor;
1066 1076
1067 if (!getTargetSampleRate()) return; // have to make our stretcher later 1077 if (!getTargetSampleRate()) return; // have to make our stretcher later
1068 1078
1069 if (m_timeStretcher || (factor == 1.f)) { 1079 if (m_timeStretcher || (factor == 1.0)) {
1070 // stretch ratio will be set in next process call if appropriate 1080 // stretch ratio will be set in next process call if appropriate
1071 } else { 1081 } else {
1072 m_stretcherInputCount = getTargetChannelCount(); 1082 m_stretcherInputCount = getTargetChannelCount();
1073 RubberBandStretcher *stretcher = new RubberBandStretcher 1083 RubberBandStretcher *stretcher = new RubberBandStretcher
1074 (getTargetSampleRate(), 1084 (int(getTargetSampleRate()),
1075 m_stretcherInputCount, 1085 m_stretcherInputCount,
1076 RubberBandStretcher::OptionProcessRealTime, 1086 RubberBandStretcher::OptionProcessRealTime,
1077 factor); 1087 factor);
1078 RubberBandStretcher *monoStretcher = new RubberBandStretcher 1088 RubberBandStretcher *monoStretcher = new RubberBandStretcher
1079 (getTargetSampleRate(), 1089 (int(getTargetSampleRate()),
1080 1, 1090 1,
1081 RubberBandStretcher::OptionProcessRealTime, 1091 RubberBandStretcher::OptionProcessRealTime,
1082 factor); 1092 factor);
1083 m_stretcherInputs = new float *[m_stretcherInputCount]; 1093 m_stretcherInputs = new float *[m_stretcherInputCount];
1084 m_stretcherInputSizes = new int[m_stretcherInputCount]; 1094 m_stretcherInputSizes = new sv_frame_t[m_stretcherInputCount];
1085 for (int c = 0; c < m_stretcherInputCount; ++c) { 1095 for (int c = 0; c < m_stretcherInputCount; ++c) {
1086 m_stretcherInputSizes[c] = 16384; 1096 m_stretcherInputSizes[c] = 16384;
1087 m_stretcherInputs[c] = new float[m_stretcherInputSizes[c]]; 1097 m_stretcherInputs[c] = new float[m_stretcherInputSizes[c]];
1088 } 1098 }
1089 m_monoStretcher = monoStretcher; 1099 m_monoStretcher = monoStretcher;
1091 } 1101 }
1092 1102
1093 emit activity(tr("Change time-stretch factor to %1").arg(factor)); 1103 emit activity(tr("Change time-stretch factor to %1").arg(factor));
1094 } 1104 }
1095 1105
1096 int 1106 sv_frame_t
1097 AudioCallbackPlaySource::getSourceSamples(int ucount, float **buffer) 1107 AudioCallbackPlaySource::getSourceSamples(sv_frame_t count, float **buffer)
1098 { 1108 {
1099 int count = ucount;
1100
1101 if (!m_playing) { 1109 if (!m_playing) {
1102 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING 1110 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
1103 SVDEBUG << "AudioCallbackPlaySource::getSourceSamples: Not playing" << endl; 1111 SVDEBUG << "AudioCallbackPlaySource::getSourceSamples: Not playing" << endl;
1104 #endif 1112 #endif
1105 for (int ch = 0; ch < getTargetChannelCount(); ++ch) { 1113 for (int ch = 0; ch < getTargetChannelCount(); ++ch) {
1146 if (count == 0) return 0; 1154 if (count == 0) return 0;
1147 1155
1148 RubberBandStretcher *ts = m_timeStretcher; 1156 RubberBandStretcher *ts = m_timeStretcher;
1149 RubberBandStretcher *ms = m_monoStretcher; 1157 RubberBandStretcher *ms = m_monoStretcher;
1150 1158
1151 float ratio = ts ? ts->getTimeRatio() : 1.f; 1159 double ratio = ts ? ts->getTimeRatio() : 1.0;
1152 1160
1153 if (ratio != m_stretchRatio) { 1161 if (ratio != m_stretchRatio) {
1154 if (!ts) { 1162 if (!ts) {
1155 cerr << "WARNING: AudioCallbackPlaySource::getSourceSamples: Time ratio change to " << m_stretchRatio << " is pending, but no stretcher is set" << endl; 1163 cerr << "WARNING: AudioCallbackPlaySource::getSourceSamples: Time ratio change to " << m_stretchRatio << " is pending, but no stretcher is set" << endl;
1156 m_stretchRatio = 1.f; 1164 m_stretchRatio = 1.0;
1157 } else { 1165 } else {
1158 ts->setTimeRatio(m_stretchRatio); 1166 ts->setTimeRatio(m_stretchRatio);
1159 if (ms) ms->setTimeRatio(m_stretchRatio); 1167 if (ms) ms->setTimeRatio(m_stretchRatio);
1160 if (m_stretchRatio >= 1.0) m_stretchMono = false; 1168 if (m_stretchRatio >= 1.0) m_stretchMono = false;
1161 } 1169 }
1186 1194
1187 if (rb) { 1195 if (rb) {
1188 1196
1189 // this is marginally more likely to leave our channels in 1197 // this is marginally more likely to leave our channels in
1190 // sync after a processing failure than just passing "count": 1198 // sync after a processing failure than just passing "count":
1191 int request = count; 1199 sv_frame_t request = count;
1192 if (ch > 0) request = got; 1200 if (ch > 0) request = got;
1193 1201
1194 got = rb->read(buffer[ch], request); 1202 got = rb->read(buffer[ch], int(request));
1195 1203
1196 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING 1204 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
1197 cout << "AudioCallbackPlaySource::getSamples: got " << got << " (of " << count << ") samples on channel " << ch << ", signalling for more (possibly)" << endl; 1205 cout << "AudioCallbackPlaySource::getSamples: got " << got << " (of " << count << ") samples on channel " << ch << ", signalling for more (possibly)" << endl;
1198 #endif 1206 #endif
1199 } 1207 }
1215 1223
1216 return got; 1224 return got;
1217 } 1225 }
1218 1226
1219 int channels = getTargetChannelCount(); 1227 int channels = getTargetChannelCount();
1220 int available; 1228 sv_frame_t available;
1229 sv_frame_t fedToStretcher = 0;
1221 int warned = 0; 1230 int warned = 0;
1222 int fedToStretcher = 0;
1223 1231
1224 // The input block for a given output is approx output / ratio, 1232 // The input block for a given output is approx output / ratio,
1225 // but we can't predict it exactly, for an adaptive timestretcher. 1233 // but we can't predict it exactly, for an adaptive timestretcher.
1226 1234
1227 while ((available = ts->available()) < count) { 1235 while ((available = ts->available()) < count) {
1228 1236
1229 int reqd = lrintf((count - available) / ratio); 1237 sv_frame_t reqd = lrint(double(count - available) / ratio);
1230 reqd = std::max(reqd, (int)ts->getSamplesRequired()); 1238 reqd = std::max(reqd, sv_frame_t(ts->getSamplesRequired()));
1231 if (reqd == 0) reqd = 1; 1239 if (reqd == 0) reqd = 1;
1232 1240
1233 int got = reqd; 1241 sv_frame_t got = reqd;
1234 1242
1235 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING 1243 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
1236 cerr << "reqd = " <<reqd << ", channels = " << channels << ", ic = " << m_stretcherInputCount << endl; 1244 cerr << "reqd = " <<reqd << ", channels = " << channels << ", ic = " << m_stretcherInputCount << endl;
1237 #endif 1245 #endif
1238 1246
1250 1258
1251 for (int c = 0; c < channels; ++c) { 1259 for (int c = 0; c < channels; ++c) {
1252 if (c >= m_stretcherInputCount) continue; 1260 if (c >= m_stretcherInputCount) continue;
1253 RingBuffer<float> *rb = getReadRingBuffer(c); 1261 RingBuffer<float> *rb = getReadRingBuffer(c);
1254 if (rb) { 1262 if (rb) {
1255 int gotHere; 1263 sv_frame_t gotHere;
1256 if (stretchChannels == 1 && c > 0) { 1264 if (stretchChannels == 1 && c > 0) {
1257 gotHere = rb->readAdding(m_stretcherInputs[0], got); 1265 gotHere = rb->readAdding(m_stretcherInputs[0], int(got));
1258 } else { 1266 } else {
1259 gotHere = rb->read(m_stretcherInputs[c], got); 1267 gotHere = rb->read(m_stretcherInputs[c], int(got));
1260 } 1268 }
1261 if (gotHere < got) got = gotHere; 1269 if (gotHere < got) got = gotHere;
1262 1270
1263 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING 1271 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
1264 if (c == 0) { 1272 if (c == 0) {
1307 1315
1308 return count; 1316 return count;
1309 } 1317 }
1310 1318
1311 void 1319 void
1312 AudioCallbackPlaySource::applyAuditioningEffect(int count, float **buffers) 1320 AudioCallbackPlaySource::applyAuditioningEffect(sv_frame_t count, float **buffers)
1313 { 1321 {
1314 if (m_auditioningPluginBypassed) return; 1322 if (m_auditioningPluginBypassed) return;
1315 RealTimePluginInstance *plugin = m_auditioningPlugin; 1323 RealTimePluginInstance *plugin = m_auditioningPlugin;
1316 if (!plugin) return; 1324 if (!plugin) return;
1317 1325
1341 for (int i = 0; i < count; ++i) { 1349 for (int i = 0; i < count; ++i) {
1342 ib[c][i] = buffers[c][i]; 1350 ib[c][i] = buffers[c][i];
1343 } 1351 }
1344 } 1352 }
1345 1353
1346 plugin->run(Vamp::RealTime::zeroTime, count); 1354 plugin->run(Vamp::RealTime::zeroTime, int(count));
1347 1355
1348 for (int c = 0; c < getTargetChannelCount(); ++c) { 1356 for (int c = 0; c < getTargetChannelCount(); ++c) {
1349 for (int i = 0; i < count; ++i) { 1357 for (int i = 0; i < count; ++i) {
1350 buffers[c][i] = ob[c][i]; 1358 buffers[c][i] = ob[c][i];
1351 } 1359 }
1355 // Called from fill thread, m_playing true, mutex held 1363 // Called from fill thread, m_playing true, mutex held
1356 bool 1364 bool
1357 AudioCallbackPlaySource::fillBuffers() 1365 AudioCallbackPlaySource::fillBuffers()
1358 { 1366 {
1359 static float *tmp = 0; 1367 static float *tmp = 0;
1360 static int tmpSize = 0; 1368 static sv_frame_t tmpSize = 0;
1361 1369
1362 int space = 0; 1370 sv_frame_t space = 0;
1363 for (int c = 0; c < getTargetChannelCount(); ++c) { 1371 for (int c = 0; c < getTargetChannelCount(); ++c) {
1364 RingBuffer<float> *wb = getWriteRingBuffer(c); 1372 RingBuffer<float> *wb = getWriteRingBuffer(c);
1365 if (wb) { 1373 if (wb) {
1366 int spaceHere = wb->getWriteSpace(); 1374 sv_frame_t spaceHere = wb->getWriteSpace();
1367 if (c == 0 || spaceHere < space) space = spaceHere; 1375 if (c == 0 || spaceHere < space) space = spaceHere;
1368 } 1376 }
1369 } 1377 }
1370 1378
1371 if (space == 0) { 1379 if (space == 0) {
1373 cout << "AudioCallbackPlaySourceFillThread: no space to fill" << endl; 1381 cout << "AudioCallbackPlaySourceFillThread: no space to fill" << endl;
1374 #endif 1382 #endif
1375 return false; 1383 return false;
1376 } 1384 }
1377 1385
1378 int f = m_writeBufferFill; 1386 sv_frame_t f = m_writeBufferFill;
1379 1387
1380 bool readWriteEqual = (m_readBuffers == m_writeBuffers); 1388 bool readWriteEqual = (m_readBuffers == m_writeBuffers);
1381 1389
1382 #ifdef DEBUG_AUDIO_PLAY_SOURCE 1390 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1383 if (!readWriteEqual) { 1391 if (!readWriteEqual) {
1396 cout << (resample ? "" : "not ") << "resampling (source " << getSourceSampleRate() << ", target " << getTargetSampleRate() << ")" << endl; 1404 cout << (resample ? "" : "not ") << "resampling (source " << getSourceSampleRate() << ", target " << getTargetSampleRate() << ")" << endl;
1397 #endif 1405 #endif
1398 1406
1399 int channels = getTargetChannelCount(); 1407 int channels = getTargetChannelCount();
1400 1408
1401 int orig = space; 1409 sv_frame_t orig = space;
1402 int got = 0; 1410 sv_frame_t got = 0;
1403 1411
1404 static float **bufferPtrs = 0; 1412 static float **bufferPtrs = 0;
1405 static int bufferPtrCount = 0; 1413 static int bufferPtrCount = 0;
1406 1414
1407 if (bufferPtrCount < channels) { 1415 if (bufferPtrCount < channels) {
1408 if (bufferPtrs) delete[] bufferPtrs; 1416 if (bufferPtrs) delete[] bufferPtrs;
1409 bufferPtrs = new float *[channels]; 1417 bufferPtrs = new float *[channels];
1410 bufferPtrCount = channels; 1418 bufferPtrCount = channels;
1411 } 1419 }
1412 1420
1413 int generatorBlockSize = m_audioGenerator->getBlockSize(); 1421 sv_frame_t generatorBlockSize = m_audioGenerator->getBlockSize();
1414 1422
1415 if (resample && !m_converter) { 1423 if (resample && !m_converter) {
1416 static bool warned = false; 1424 static bool warned = false;
1417 if (!warned) { 1425 if (!warned) {
1418 cerr << "WARNING: sample rates differ, but no converter available!" << endl; 1426 cerr << "WARNING: sample rates differ, but no converter available!" << endl;
1422 1430
1423 if (resample && m_converter) { 1431 if (resample && m_converter) {
1424 1432
1425 double ratio = 1433 double ratio =
1426 double(getTargetSampleRate()) / double(getSourceSampleRate()); 1434 double(getTargetSampleRate()) / double(getSourceSampleRate());
1427 orig = int(orig / ratio + 0.1); 1435 orig = sv_frame_t(double(orig) / ratio + 0.1);
1428 1436
1429 // orig must be a multiple of generatorBlockSize 1437 // orig must be a multiple of generatorBlockSize
1430 orig = (orig / generatorBlockSize) * generatorBlockSize; 1438 orig = (orig / generatorBlockSize) * generatorBlockSize;
1431 if (orig == 0) return false; 1439 if (orig == 0) return false;
1432 1440
1433 int work = std::max(orig, space); 1441 sv_frame_t work = std::max(orig, space);
1434 1442
1435 // We only allocate one buffer, but we use it in two halves. 1443 // We only allocate one buffer, but we use it in two halves.
1436 // We place the non-interleaved values in the second half of 1444 // We place the non-interleaved values in the second half of
1437 // the buffer (orig samples for channel 0, orig samples for 1445 // the buffer (orig samples for channel 0, orig samples for
1438 // channel 1 etc), and then interleave them into the first 1446 // channel 1 etc), and then interleave them into the first
1490 err = src_process(m_crapConverter, &data); 1498 err = src_process(m_crapConverter, &data);
1491 } else { 1499 } else {
1492 err = src_process(m_converter, &data); 1500 err = src_process(m_converter, &data);
1493 } 1501 }
1494 1502
1495 int toCopy = int(got * ratio + 0.1); 1503 sv_frame_t toCopy = sv_frame_t(double(got) * ratio + 0.1);
1496 1504
1497 if (err) { 1505 if (err) {
1498 cerr 1506 cerr
1499 << "AudioCallbackPlaySourceFillThread: ERROR in samplerate conversion: " 1507 << "AudioCallbackPlaySourceFillThread: ERROR in samplerate conversion: "
1500 << src_strerror(err) << endl; 1508 << src_strerror(err) << endl;
1510 for (int c = 0; c < channels; ++c) { 1518 for (int c = 0; c < channels; ++c) {
1511 for (int i = 0; i < toCopy; ++i) { 1519 for (int i = 0; i < toCopy; ++i) {
1512 tmp[i] = srcout[channels * i + c]; 1520 tmp[i] = srcout[channels * i + c];
1513 } 1521 }
1514 RingBuffer<float> *wb = getWriteRingBuffer(c); 1522 RingBuffer<float> *wb = getWriteRingBuffer(c);
1515 if (wb) wb->write(tmp, toCopy); 1523 if (wb) wb->write(tmp, int(toCopy));
1516 } 1524 }
1517 1525
1518 m_writeBufferFill = f; 1526 m_writeBufferFill = f;
1519 if (readWriteEqual) m_readBufferFill = f; 1527 if (readWriteEqual) m_readBufferFill = f;
1520 1528
1521 } else { 1529 } else {
1522 1530
1523 // space must be a multiple of generatorBlockSize 1531 // space must be a multiple of generatorBlockSize
1524 int reqSpace = space; 1532 sv_frame_t reqSpace = space;
1525 space = (reqSpace / generatorBlockSize) * generatorBlockSize; 1533 space = (reqSpace / generatorBlockSize) * generatorBlockSize;
1526 if (space == 0) { 1534 if (space == 0) {
1527 #ifdef DEBUG_AUDIO_PLAY_SOURCE 1535 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1528 cout << "requested fill of " << reqSpace 1536 cout << "requested fill of " << reqSpace
1529 << " is less than generator block size of " 1537 << " is less than generator block size of "
1545 for (int i = 0; i < space; ++i) { 1553 for (int i = 0; i < space; ++i) {
1546 tmp[c * space + i] = 0.0f; 1554 tmp[c * space + i] = 0.0f;
1547 } 1555 }
1548 } 1556 }
1549 1557
1550 int got = mixModels(f, space, bufferPtrs); // also modifies f 1558 sv_frame_t got = mixModels(f, space, bufferPtrs); // also modifies f
1551 1559
1552 for (int c = 0; c < channels; ++c) { 1560 for (int c = 0; c < channels; ++c) {
1553 1561
1554 RingBuffer<float> *wb = getWriteRingBuffer(c); 1562 RingBuffer<float> *wb = getWriteRingBuffer(c);
1555 if (wb) { 1563 if (wb) {
1556 int actual = wb->write(bufferPtrs[c], got); 1564 int actual = wb->write(bufferPtrs[c], int(got));
1557 #ifdef DEBUG_AUDIO_PLAY_SOURCE 1565 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1558 cout << "Wrote " << actual << " samples for ch " << c << ", now " 1566 cout << "Wrote " << actual << " samples for ch " << c << ", now "
1559 << wb->getReadSpace() << " to read" 1567 << wb->getReadSpace() << " to read"
1560 << endl; 1568 << endl;
1561 #endif 1569 #endif
1578 } 1586 }
1579 1587
1580 return true; 1588 return true;
1581 } 1589 }
1582 1590
1583 int 1591 sv_frame_t
1584 AudioCallbackPlaySource::mixModels(int &frame, int count, float **buffers) 1592 AudioCallbackPlaySource::mixModels(sv_frame_t &frame, sv_frame_t count, float **buffers)
1585 { 1593 {
1586 int processed = 0; 1594 sv_frame_t processed = 0;
1587 int chunkStart = frame; 1595 sv_frame_t chunkStart = frame;
1588 int chunkSize = count; 1596 sv_frame_t chunkSize = count;
1589 int selectionSize = 0; 1597 sv_frame_t selectionSize = 0;
1590 int nextChunkStart = chunkStart + chunkSize; 1598 sv_frame_t nextChunkStart = chunkStart + chunkSize;
1591 1599
1592 bool looping = m_viewManager->getPlayLoopMode(); 1600 bool looping = m_viewManager->getPlayLoopMode();
1593 bool constrained = (m_viewManager->getPlaySelectionMode() && 1601 bool constrained = (m_viewManager->getPlaySelectionMode() &&
1594 !m_viewManager->getSelections().empty()); 1602 !m_viewManager->getSelections().empty());
1595 1603
1615 1623
1616 chunkSize = count - processed; 1624 chunkSize = count - processed;
1617 nextChunkStart = chunkStart + chunkSize; 1625 nextChunkStart = chunkStart + chunkSize;
1618 selectionSize = 0; 1626 selectionSize = 0;
1619 1627
1620 int fadeIn = 0, fadeOut = 0; 1628 sv_frame_t fadeIn = 0, fadeOut = 0;
1621 1629
1622 if (constrained) { 1630 if (constrained) {
1623 1631
1624 int rChunkStart = 1632 sv_frame_t rChunkStart =
1625 m_viewManager->alignPlaybackFrameToReference(chunkStart); 1633 m_viewManager->alignPlaybackFrameToReference(chunkStart);
1626 1634
1627 Selection selection = 1635 Selection selection =
1628 m_viewManager->getContainingSelection(rChunkStart, true); 1636 m_viewManager->getContainingSelection(rChunkStart, true);
1629 1637
1641 chunkSize = 0; 1649 chunkSize = 0;
1642 nextChunkStart = chunkStart; 1650 nextChunkStart = chunkStart;
1643 1651
1644 } else { 1652 } else {
1645 1653
1646 int sf = m_viewManager->alignReferenceToPlaybackFrame 1654 sv_frame_t sf = m_viewManager->alignReferenceToPlaybackFrame
1647 (selection.getStartFrame()); 1655 (selection.getStartFrame());
1648 int ef = m_viewManager->alignReferenceToPlaybackFrame 1656 sv_frame_t ef = m_viewManager->alignReferenceToPlaybackFrame
1649 (selection.getEndFrame()); 1657 (selection.getEndFrame());
1650 1658
1651 selectionSize = ef - sf; 1659 selectionSize = ef - sf;
1652 1660
1653 if (chunkStart < sf) { 1661 if (chunkStart < sf) {
1759 } 1767 }
1760 break; 1768 break;
1761 } 1769 }
1762 } 1770 }
1763 1771
1764 int rf = m_readBufferFill; 1772 sv_frame_t rf = m_readBufferFill;
1765 RingBuffer<float> *rb = getReadRingBuffer(0); 1773 RingBuffer<float> *rb = getReadRingBuffer(0);
1766 if (rb) { 1774 if (rb) {
1767 int rs = rb->getReadSpace(); 1775 int rs = rb->getReadSpace();
1768 //!!! incorrect when in non-contiguous selection, see comments elsewhere 1776 //!!! incorrect when in non-contiguous selection, see comments elsewhere
1769 // cout << "rs = " << rs << endl; 1777 // cout << "rs = " << rs << endl;
1773 1781
1774 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING 1782 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
1775 SVDEBUG << "AudioCallbackPlaySource::unifyRingBuffers: m_readBufferFill = " << m_readBufferFill << ", rf = " << rf << ", m_writeBufferFill = " << m_writeBufferFill << endl; 1783 SVDEBUG << "AudioCallbackPlaySource::unifyRingBuffers: m_readBufferFill = " << m_readBufferFill << ", rf = " << rf << ", m_writeBufferFill = " << m_writeBufferFill << endl;
1776 #endif 1784 #endif
1777 1785
1778 int wf = m_writeBufferFill; 1786 sv_frame_t wf = m_writeBufferFill;
1779 int skip = 0; 1787 sv_frame_t skip = 0;
1780 for (int c = 0; c < getTargetChannelCount(); ++c) { 1788 for (int c = 0; c < getTargetChannelCount(); ++c) {
1781 RingBuffer<float> *wb = getWriteRingBuffer(c); 1789 RingBuffer<float> *wb = getWriteRingBuffer(c);
1782 if (wb) { 1790 if (wb) {
1783 if (c == 0) { 1791 if (c == 0) {
1784 1792
1792 if (wf < rf) skip = rf - wf; 1800 if (wf < rf) skip = rf - wf;
1793 if (skip == 0) break; 1801 if (skip == 0) break;
1794 } 1802 }
1795 1803
1796 // cout << "skipping " << skip << endl; 1804 // cout << "skipping " << skip << endl;
1797 wb->skip(skip); 1805 wb->skip(int(skip));
1798 } 1806 }
1799 } 1807 }
1800 1808
1801 m_bufferScavenger.claim(m_readBuffers); 1809 m_bufferScavenger.claim(m_readBuffers);
1802 m_readBuffers = m_writeBuffers; 1810 m_readBuffers = m_writeBuffers;
1835 s.m_mutex.unlock(); 1843 s.m_mutex.unlock();
1836 s.m_mutex.lock(); 1844 s.m_mutex.lock();
1837 1845
1838 } else { 1846 } else {
1839 1847
1840 float ms = 100; 1848 double ms = 100;
1841 if (s.getSourceSampleRate() > 0) { 1849 if (s.getSourceSampleRate() > 0) {
1842 ms = float(s.m_ringBufferSize) / 1850 ms = double(s.m_ringBufferSize) / s.getSourceSampleRate() * 1000.0;
1843 float(s.getSourceSampleRate()) * 1000.0;
1844 } 1851 }
1845 1852
1846 if (s.m_playing) ms /= 10; 1853 if (s.m_playing) ms /= 10;
1847 1854
1848 #ifdef DEBUG_AUDIO_PLAY_SOURCE 1855 #ifdef DEBUG_AUDIO_PLAY_SOURCE