comparison audioio/AudioCallbackPlaySource.cpp @ 441:aa6fb3516e28 tonioni

Merge from cxx11 branch
author Chris Cannam
date Mon, 23 Mar 2015 11:26:28 +0000
parents 8d2112977aa0 72c662fe7ea3
children 88ae0e53a5da
comparison
equal deleted inserted replaced
440:2185d52b4758 441:aa6fb3516e28
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
365 cerr << "clearRingBuffers" << endl; 365 cerr << "clearRingBuffers" << endl;
366 366
367 rebuildRangeLists(); 367 rebuildRangeLists();
368 368
369 if (count == 0) { 369 if (count == 0) {
370 if (m_writeBuffers) count = m_writeBuffers->size(); 370 if (m_writeBuffers) count = int(m_writeBuffers->size());
371 } 371 }
372 372
373 cerr << "current playing frame = " << getCurrentPlayingFrame() << endl; 373 cerr << "current playing frame = " << getCurrentPlayingFrame() << endl;
374 374
375 cerr << "write buffer fill (before) = " << m_writeBufferFill << endl; 375 cerr << "write buffer fill (before) = " << m_writeBufferFill << endl;
395 m_mutex.unlock(); 395 m_mutex.unlock();
396 } 396 }
397 } 397 }
398 398
399 void 399 void
400 AudioCallbackPlaySource::play(int startFrame) 400 AudioCallbackPlaySource::play(sv_frame_t startFrame)
401 { 401 {
402 if (!m_sourceSampleRate) { 402 if (!m_sourceSampleRate) {
403 cerr << "AudioCallbackPlaySource::play: No source sample rate available, not playing" << endl; 403 cerr << "AudioCallbackPlaySource::play: No source sample rate available, not playing" << endl;
404 return; 404 return;
405 } 405 }
591 591
592 int 592 int
593 AudioCallbackPlaySource::getTargetBlockSize() const 593 AudioCallbackPlaySource::getTargetBlockSize() const
594 { 594 {
595 // cout << "AudioCallbackPlaySource::getTargetBlockSize() -> " << m_blockSize << endl; 595 // cout << "AudioCallbackPlaySource::getTargetBlockSize() -> " << m_blockSize << endl;
596 return m_blockSize; 596 return int(m_blockSize);
597 } 597 }
598 598
599 void 599 void
600 AudioCallbackPlaySource::setTargetPlayLatency(int latency) 600 AudioCallbackPlaySource::setTargetPlayLatency(sv_frame_t latency)
601 { 601 {
602 m_playLatency = latency; 602 m_playLatency = latency;
603 } 603 }
604 604
605 int 605 sv_frame_t
606 AudioCallbackPlaySource::getTargetPlayLatency() const 606 AudioCallbackPlaySource::getTargetPlayLatency() const
607 { 607 {
608 return m_playLatency; 608 return m_playLatency;
609 } 609 }
610 610
611 int 611 sv_frame_t
612 AudioCallbackPlaySource::getCurrentPlayingFrame() 612 AudioCallbackPlaySource::getCurrentPlayingFrame()
613 { 613 {
614 // This method attempts to estimate which audio sample frame is 614 // This method attempts to estimate which audio sample frame is
615 // "currently coming through the speakers". 615 // "currently coming through the speakers".
616 616
617 int targetRate = getTargetSampleRate(); 617 sv_samplerate_t targetRate = getTargetSampleRate();
618 int latency = m_playLatency; // at target rate 618 sv_frame_t latency = m_playLatency; // at target rate
619 RealTime latency_t = RealTime::zeroTime; 619 RealTime latency_t = RealTime::zeroTime;
620 620
621 if (targetRate != 0) { 621 if (targetRate != 0) {
622 latency_t = RealTime::frame2RealTime(latency, targetRate); 622 latency_t = RealTime::frame2RealTime(latency, targetRate);
623 } 623 }
624 624
625 return getCurrentFrame(latency_t); 625 return getCurrentFrame(latency_t);
626 } 626 }
627 627
628 int 628 sv_frame_t
629 AudioCallbackPlaySource::getCurrentBufferedFrame() 629 AudioCallbackPlaySource::getCurrentBufferedFrame()
630 { 630 {
631 return getCurrentFrame(RealTime::zeroTime); 631 return getCurrentFrame(RealTime::zeroTime);
632 } 632 }
633 633
634 int 634 sv_frame_t
635 AudioCallbackPlaySource::getCurrentFrame(RealTime latency_t) 635 AudioCallbackPlaySource::getCurrentFrame(RealTime latency_t)
636 { 636 {
637 // We resample when filling the ring buffer, and time-stretch when 637 // We resample when filling the ring buffer, and time-stretch when
638 // draining it. The buffer contains data at the "target rate" and 638 // draining it. The buffer contains data at the "target rate" and
639 // the latency provided by the target is also at the target rate. 639 // the latency provided by the target is also at the target rate.
640 // Because of the multiple rates involved, we do the actual 640 // Because of the multiple rates involved, we do the actual
641 // calculation using RealTime instead. 641 // calculation using RealTime instead.
642 642
643 int sourceRate = getSourceSampleRate(); 643 sv_samplerate_t sourceRate = getSourceSampleRate();
644 int targetRate = getTargetSampleRate(); 644 sv_samplerate_t targetRate = getTargetSampleRate();
645 645
646 if (sourceRate == 0 || targetRate == 0) return 0; 646 if (sourceRate == 0 || targetRate == 0) return 0;
647 647
648 int inbuffer = 0; // at target rate 648 int inbuffer = 0; // at target rate
649 649
653 int here = rb->getReadSpace(); 653 int here = rb->getReadSpace();
654 if (c == 0 || here < inbuffer) inbuffer = here; 654 if (c == 0 || here < inbuffer) inbuffer = here;
655 } 655 }
656 } 656 }
657 657
658 int readBufferFill = m_readBufferFill; 658 sv_frame_t readBufferFill = m_readBufferFill;
659 int lastRetrievedBlockSize = m_lastRetrievedBlockSize; 659 sv_frame_t lastRetrievedBlockSize = m_lastRetrievedBlockSize;
660 double lastRetrievalTimestamp = m_lastRetrievalTimestamp; 660 double lastRetrievalTimestamp = m_lastRetrievalTimestamp;
661 double currentTime = 0.0; 661 double currentTime = 0.0;
662 if (m_target) currentTime = m_target->getCurrentTime(); 662 if (m_target) currentTime = m_target->getCurrentTime();
663 663
664 bool looping = m_viewManager->getPlayLoopMode(); 664 bool looping = m_viewManager->getPlayLoopMode();
665 665
666 RealTime inbuffer_t = RealTime::frame2RealTime(inbuffer, targetRate); 666 RealTime inbuffer_t = RealTime::frame2RealTime(inbuffer, targetRate);
667 667
668 int stretchlat = 0; 668 sv_frame_t stretchlat = 0;
669 double timeRatio = 1.0; 669 double timeRatio = 1.0;
670 670
671 if (m_timeStretcher) { 671 if (m_timeStretcher) {
672 stretchlat = m_timeStretcher->getLatency(); 672 stretchlat = m_timeStretcher->getLatency();
673 timeRatio = m_timeStretcher->getTimeRatio(); 673 timeRatio = m_timeStretcher->getTimeRatio();
737 // this code is only used in case of error in rebuildRangeLists 737 // this code is only used in case of error in rebuildRangeLists
738 RealTime playing_t = bufferedto_t 738 RealTime playing_t = bufferedto_t
739 - latency_t - stretchlat_t - lastretrieved_t - inbuffer_t 739 - latency_t - stretchlat_t - lastretrieved_t - inbuffer_t
740 + sincerequest_t; 740 + sincerequest_t;
741 if (playing_t < RealTime::zeroTime) playing_t = RealTime::zeroTime; 741 if (playing_t < RealTime::zeroTime) playing_t = RealTime::zeroTime;
742 int frame = RealTime::realTime2Frame(playing_t, sourceRate); 742 sv_frame_t frame = RealTime::realTime2Frame(playing_t, sourceRate);
743 return m_viewManager->alignPlaybackFrameToReference(frame); 743 return m_viewManager->alignPlaybackFrameToReference(frame);
744 } 744 }
745 745
746 int inRange = 0; 746 int inRange = 0;
747 int index = 0; 747 int index = 0;
753 break; 753 break;
754 } 754 }
755 ++index; 755 ++index;
756 } 756 }
757 757
758 if (inRange >= (int)m_rangeStarts.size()) inRange = m_rangeStarts.size()-1; 758 if (inRange >= int(m_rangeStarts.size())) {
759 inRange = int(m_rangeStarts.size())-1;
760 }
759 761
760 RealTime playing_t = bufferedto_t; 762 RealTime playing_t = bufferedto_t;
761 763
762 playing_t = playing_t 764 playing_t = playing_t
763 - latency_t - stretchlat_t - lastretrieved_t - inbuffer_t 765 - latency_t - stretchlat_t - lastretrieved_t - inbuffer_t
804 806
805 while (playing_t < RealTime::zeroTime) { 807 while (playing_t < RealTime::zeroTime) {
806 808
807 if (inRange == 0) { 809 if (inRange == 0) {
808 if (looping) { 810 if (looping) {
809 inRange = m_rangeStarts.size() - 1; 811 inRange = int(m_rangeStarts.size()) - 1;
810 } else { 812 } else {
811 break; 813 break;
812 } 814 }
813 } else { 815 } else {
814 --inRange; 816 --inRange;
831 } 833 }
832 } 834 }
833 835
834 if (playing_t < RealTime::zeroTime) playing_t = RealTime::zeroTime; 836 if (playing_t < RealTime::zeroTime) playing_t = RealTime::zeroTime;
835 837
836 int frame = RealTime::realTime2Frame(playing_t, sourceRate); 838 sv_frame_t frame = RealTime::realTime2Frame(playing_t, sourceRate);
837 839
838 if (m_lastCurrentFrame > 0 && !looping) { 840 if (m_lastCurrentFrame > 0 && !looping) {
839 if (frame < m_lastCurrentFrame) { 841 if (frame < m_lastCurrentFrame) {
840 frame = m_lastCurrentFrame; 842 frame = m_lastCurrentFrame;
841 } 843 }
852 bool constrained = (m_viewManager->getPlaySelectionMode()); 854 bool constrained = (m_viewManager->getPlaySelectionMode());
853 855
854 m_rangeStarts.clear(); 856 m_rangeStarts.clear();
855 m_rangeDurations.clear(); 857 m_rangeDurations.clear();
856 858
857 int sourceRate = getSourceSampleRate(); 859 sv_samplerate_t sourceRate = getSourceSampleRate();
858 if (sourceRate == 0) return; 860 if (sourceRate == 0) return;
859 861
860 RealTime end = RealTime::frame2RealTime(m_lastModelEndFrame, sourceRate); 862 RealTime end = RealTime::frame2RealTime(m_lastModelEndFrame, sourceRate);
861 if (end == RealTime::zeroTime) return; 863 if (end == RealTime::zeroTime) return;
862 864
914 right = m_outputRight; 916 right = m_outputRight;
915 return true; 917 return true;
916 } 918 }
917 919
918 void 920 void
919 AudioCallbackPlaySource::setTargetSampleRate(int sr) 921 AudioCallbackPlaySource::setTargetSampleRate(sv_samplerate_t sr)
920 { 922 {
921 bool first = (m_targetSampleRate == 0); 923 bool first = (m_targetSampleRate == 0);
922 924
923 m_targetSampleRate = sr; 925 m_targetSampleRate = sr;
924 initialiseConverter(); 926 initialiseConverter();
1031 { 1033 {
1032 m_audioGenerator->clearSoloModelSet(); 1034 m_audioGenerator->clearSoloModelSet();
1033 clearRingBuffers(); 1035 clearRingBuffers();
1034 } 1036 }
1035 1037
1036 int 1038 sv_samplerate_t
1037 AudioCallbackPlaySource::getTargetSampleRate() const 1039 AudioCallbackPlaySource::getTargetSampleRate() const
1038 { 1040 {
1039 if (m_targetSampleRate) return m_targetSampleRate; 1041 if (m_targetSampleRate) return m_targetSampleRate;
1040 else return getSourceSampleRate(); 1042 else return getSourceSampleRate();
1041 } 1043 }
1051 { 1053 {
1052 if (m_sourceChannelCount < 2) return 2; 1054 if (m_sourceChannelCount < 2) return 2;
1053 return m_sourceChannelCount; 1055 return m_sourceChannelCount;
1054 } 1056 }
1055 1057
1056 int 1058 sv_samplerate_t
1057 AudioCallbackPlaySource::getSourceSampleRate() const 1059 AudioCallbackPlaySource::getSourceSampleRate() const
1058 { 1060 {
1059 return m_sourceSampleRate; 1061 return m_sourceSampleRate;
1060 } 1062 }
1061 1063
1062 void 1064 void
1063 AudioCallbackPlaySource::setTimeStretch(float factor) 1065 AudioCallbackPlaySource::setTimeStretch(double factor)
1064 { 1066 {
1065 m_stretchRatio = factor; 1067 m_stretchRatio = factor;
1066 1068
1067 if (!getTargetSampleRate()) return; // have to make our stretcher later 1069 if (!getTargetSampleRate()) return; // have to make our stretcher later
1068 1070
1069 if (m_timeStretcher || (factor == 1.f)) { 1071 if (m_timeStretcher || (factor == 1.0)) {
1070 // stretch ratio will be set in next process call if appropriate 1072 // stretch ratio will be set in next process call if appropriate
1071 } else { 1073 } else {
1072 m_stretcherInputCount = getTargetChannelCount(); 1074 m_stretcherInputCount = getTargetChannelCount();
1073 RubberBandStretcher *stretcher = new RubberBandStretcher 1075 RubberBandStretcher *stretcher = new RubberBandStretcher
1074 (getTargetSampleRate(), 1076 (int(getTargetSampleRate()),
1075 m_stretcherInputCount, 1077 m_stretcherInputCount,
1076 RubberBandStretcher::OptionProcessRealTime, 1078 RubberBandStretcher::OptionProcessRealTime,
1077 factor); 1079 factor);
1078 RubberBandStretcher *monoStretcher = new RubberBandStretcher 1080 RubberBandStretcher *monoStretcher = new RubberBandStretcher
1079 (getTargetSampleRate(), 1081 (int(getTargetSampleRate()),
1080 1, 1082 1,
1081 RubberBandStretcher::OptionProcessRealTime, 1083 RubberBandStretcher::OptionProcessRealTime,
1082 factor); 1084 factor);
1083 m_stretcherInputs = new float *[m_stretcherInputCount]; 1085 m_stretcherInputs = new float *[m_stretcherInputCount];
1084 m_stretcherInputSizes = new int[m_stretcherInputCount]; 1086 m_stretcherInputSizes = new sv_frame_t[m_stretcherInputCount];
1085 for (int c = 0; c < m_stretcherInputCount; ++c) { 1087 for (int c = 0; c < m_stretcherInputCount; ++c) {
1086 m_stretcherInputSizes[c] = 16384; 1088 m_stretcherInputSizes[c] = 16384;
1087 m_stretcherInputs[c] = new float[m_stretcherInputSizes[c]]; 1089 m_stretcherInputs[c] = new float[m_stretcherInputSizes[c]];
1088 } 1090 }
1089 m_monoStretcher = monoStretcher; 1091 m_monoStretcher = monoStretcher;
1091 } 1093 }
1092 1094
1093 emit activity(tr("Change time-stretch factor to %1").arg(factor)); 1095 emit activity(tr("Change time-stretch factor to %1").arg(factor));
1094 } 1096 }
1095 1097
1096 int 1098 sv_frame_t
1097 AudioCallbackPlaySource::getSourceSamples(int ucount, float **buffer) 1099 AudioCallbackPlaySource::getSourceSamples(sv_frame_t count, float **buffer)
1098 { 1100 {
1099 int count = ucount;
1100
1101 if (!m_playing) { 1101 if (!m_playing) {
1102 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING 1102 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
1103 SVDEBUG << "AudioCallbackPlaySource::getSourceSamples: Not playing" << endl; 1103 SVDEBUG << "AudioCallbackPlaySource::getSourceSamples: Not playing" << endl;
1104 #endif 1104 #endif
1105 for (int ch = 0; ch < getTargetChannelCount(); ++ch) { 1105 for (int ch = 0; ch < getTargetChannelCount(); ++ch) {
1146 if (count == 0) return 0; 1146 if (count == 0) return 0;
1147 1147
1148 RubberBandStretcher *ts = m_timeStretcher; 1148 RubberBandStretcher *ts = m_timeStretcher;
1149 RubberBandStretcher *ms = m_monoStretcher; 1149 RubberBandStretcher *ms = m_monoStretcher;
1150 1150
1151 float ratio = ts ? ts->getTimeRatio() : 1.f; 1151 double ratio = ts ? ts->getTimeRatio() : 1.0;
1152 1152
1153 if (ratio != m_stretchRatio) { 1153 if (ratio != m_stretchRatio) {
1154 if (!ts) { 1154 if (!ts) {
1155 cerr << "WARNING: AudioCallbackPlaySource::getSourceSamples: Time ratio change to " << m_stretchRatio << " is pending, but no stretcher is set" << endl; 1155 cerr << "WARNING: AudioCallbackPlaySource::getSourceSamples: Time ratio change to " << m_stretchRatio << " is pending, but no stretcher is set" << endl;
1156 m_stretchRatio = 1.f; 1156 m_stretchRatio = 1.0;
1157 } else { 1157 } else {
1158 ts->setTimeRatio(m_stretchRatio); 1158 ts->setTimeRatio(m_stretchRatio);
1159 if (ms) ms->setTimeRatio(m_stretchRatio); 1159 if (ms) ms->setTimeRatio(m_stretchRatio);
1160 if (m_stretchRatio >= 1.0) m_stretchMono = false; 1160 if (m_stretchRatio >= 1.0) m_stretchMono = false;
1161 } 1161 }
1186 1186
1187 if (rb) { 1187 if (rb) {
1188 1188
1189 // this is marginally more likely to leave our channels in 1189 // this is marginally more likely to leave our channels in
1190 // sync after a processing failure than just passing "count": 1190 // sync after a processing failure than just passing "count":
1191 int request = count; 1191 sv_frame_t request = count;
1192 if (ch > 0) request = got; 1192 if (ch > 0) request = got;
1193 1193
1194 got = rb->read(buffer[ch], request); 1194 got = rb->read(buffer[ch], int(request));
1195 1195
1196 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING 1196 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
1197 cout << "AudioCallbackPlaySource::getSamples: got " << got << " (of " << count << ") samples on channel " << ch << ", signalling for more (possibly)" << endl; 1197 cout << "AudioCallbackPlaySource::getSamples: got " << got << " (of " << count << ") samples on channel " << ch << ", signalling for more (possibly)" << endl;
1198 #endif 1198 #endif
1199 } 1199 }
1215 1215
1216 return got; 1216 return got;
1217 } 1217 }
1218 1218
1219 int channels = getTargetChannelCount(); 1219 int channels = getTargetChannelCount();
1220 int available; 1220 sv_frame_t available;
1221 sv_frame_t fedToStretcher = 0;
1221 int warned = 0; 1222 int warned = 0;
1222 int fedToStretcher = 0;
1223 1223
1224 // The input block for a given output is approx output / ratio, 1224 // The input block for a given output is approx output / ratio,
1225 // but we can't predict it exactly, for an adaptive timestretcher. 1225 // but we can't predict it exactly, for an adaptive timestretcher.
1226 1226
1227 while ((available = ts->available()) < count) { 1227 while ((available = ts->available()) < count) {
1228 1228
1229 int reqd = lrintf((count - available) / ratio); 1229 sv_frame_t reqd = lrint(double(count - available) / ratio);
1230 reqd = std::max(reqd, (int)ts->getSamplesRequired()); 1230 reqd = std::max(reqd, sv_frame_t(ts->getSamplesRequired()));
1231 if (reqd == 0) reqd = 1; 1231 if (reqd == 0) reqd = 1;
1232 1232
1233 int got = reqd; 1233 sv_frame_t got = reqd;
1234 1234
1235 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING 1235 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
1236 cerr << "reqd = " <<reqd << ", channels = " << channels << ", ic = " << m_stretcherInputCount << endl; 1236 cerr << "reqd = " <<reqd << ", channels = " << channels << ", ic = " << m_stretcherInputCount << endl;
1237 #endif 1237 #endif
1238 1238
1250 1250
1251 for (int c = 0; c < channels; ++c) { 1251 for (int c = 0; c < channels; ++c) {
1252 if (c >= m_stretcherInputCount) continue; 1252 if (c >= m_stretcherInputCount) continue;
1253 RingBuffer<float> *rb = getReadRingBuffer(c); 1253 RingBuffer<float> *rb = getReadRingBuffer(c);
1254 if (rb) { 1254 if (rb) {
1255 int gotHere; 1255 sv_frame_t gotHere;
1256 if (stretchChannels == 1 && c > 0) { 1256 if (stretchChannels == 1 && c > 0) {
1257 gotHere = rb->readAdding(m_stretcherInputs[0], got); 1257 gotHere = rb->readAdding(m_stretcherInputs[0], int(got));
1258 } else { 1258 } else {
1259 gotHere = rb->read(m_stretcherInputs[c], got); 1259 gotHere = rb->read(m_stretcherInputs[c], int(got));
1260 } 1260 }
1261 if (gotHere < got) got = gotHere; 1261 if (gotHere < got) got = gotHere;
1262 1262
1263 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING 1263 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
1264 if (c == 0) { 1264 if (c == 0) {
1307 1307
1308 return count; 1308 return count;
1309 } 1309 }
1310 1310
1311 void 1311 void
1312 AudioCallbackPlaySource::applyAuditioningEffect(int count, float **buffers) 1312 AudioCallbackPlaySource::applyAuditioningEffect(sv_frame_t count, float **buffers)
1313 { 1313 {
1314 if (m_auditioningPluginBypassed) return; 1314 if (m_auditioningPluginBypassed) return;
1315 RealTimePluginInstance *plugin = m_auditioningPlugin; 1315 RealTimePluginInstance *plugin = m_auditioningPlugin;
1316 if (!plugin) return; 1316 if (!plugin) return;
1317 1317
1341 for (int i = 0; i < count; ++i) { 1341 for (int i = 0; i < count; ++i) {
1342 ib[c][i] = buffers[c][i]; 1342 ib[c][i] = buffers[c][i];
1343 } 1343 }
1344 } 1344 }
1345 1345
1346 plugin->run(Vamp::RealTime::zeroTime, count); 1346 plugin->run(Vamp::RealTime::zeroTime, int(count));
1347 1347
1348 for (int c = 0; c < getTargetChannelCount(); ++c) { 1348 for (int c = 0; c < getTargetChannelCount(); ++c) {
1349 for (int i = 0; i < count; ++i) { 1349 for (int i = 0; i < count; ++i) {
1350 buffers[c][i] = ob[c][i]; 1350 buffers[c][i] = ob[c][i];
1351 } 1351 }
1355 // Called from fill thread, m_playing true, mutex held 1355 // Called from fill thread, m_playing true, mutex held
1356 bool 1356 bool
1357 AudioCallbackPlaySource::fillBuffers() 1357 AudioCallbackPlaySource::fillBuffers()
1358 { 1358 {
1359 static float *tmp = 0; 1359 static float *tmp = 0;
1360 static int tmpSize = 0; 1360 static sv_frame_t tmpSize = 0;
1361 1361
1362 int space = 0; 1362 sv_frame_t space = 0;
1363 for (int c = 0; c < getTargetChannelCount(); ++c) { 1363 for (int c = 0; c < getTargetChannelCount(); ++c) {
1364 RingBuffer<float> *wb = getWriteRingBuffer(c); 1364 RingBuffer<float> *wb = getWriteRingBuffer(c);
1365 if (wb) { 1365 if (wb) {
1366 int spaceHere = wb->getWriteSpace(); 1366 sv_frame_t spaceHere = wb->getWriteSpace();
1367 if (c == 0 || spaceHere < space) space = spaceHere; 1367 if (c == 0 || spaceHere < space) space = spaceHere;
1368 } 1368 }
1369 } 1369 }
1370 1370
1371 if (space == 0) { 1371 if (space == 0) {
1373 cout << "AudioCallbackPlaySourceFillThread: no space to fill" << endl; 1373 cout << "AudioCallbackPlaySourceFillThread: no space to fill" << endl;
1374 #endif 1374 #endif
1375 return false; 1375 return false;
1376 } 1376 }
1377 1377
1378 int f = m_writeBufferFill; 1378 sv_frame_t f = m_writeBufferFill;
1379 1379
1380 bool readWriteEqual = (m_readBuffers == m_writeBuffers); 1380 bool readWriteEqual = (m_readBuffers == m_writeBuffers);
1381 1381
1382 #ifdef DEBUG_AUDIO_PLAY_SOURCE 1382 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1383 if (!readWriteEqual) { 1383 if (!readWriteEqual) {
1396 cout << (resample ? "" : "not ") << "resampling (source " << getSourceSampleRate() << ", target " << getTargetSampleRate() << ")" << endl; 1396 cout << (resample ? "" : "not ") << "resampling (source " << getSourceSampleRate() << ", target " << getTargetSampleRate() << ")" << endl;
1397 #endif 1397 #endif
1398 1398
1399 int channels = getTargetChannelCount(); 1399 int channels = getTargetChannelCount();
1400 1400
1401 int orig = space; 1401 sv_frame_t orig = space;
1402 int got = 0; 1402 sv_frame_t got = 0;
1403 1403
1404 static float **bufferPtrs = 0; 1404 static float **bufferPtrs = 0;
1405 static int bufferPtrCount = 0; 1405 static int bufferPtrCount = 0;
1406 1406
1407 if (bufferPtrCount < channels) { 1407 if (bufferPtrCount < channels) {
1408 if (bufferPtrs) delete[] bufferPtrs; 1408 if (bufferPtrs) delete[] bufferPtrs;
1409 bufferPtrs = new float *[channels]; 1409 bufferPtrs = new float *[channels];
1410 bufferPtrCount = channels; 1410 bufferPtrCount = channels;
1411 } 1411 }
1412 1412
1413 int generatorBlockSize = m_audioGenerator->getBlockSize(); 1413 sv_frame_t generatorBlockSize = m_audioGenerator->getBlockSize();
1414 1414
1415 if (resample && !m_converter) { 1415 if (resample && !m_converter) {
1416 static bool warned = false; 1416 static bool warned = false;
1417 if (!warned) { 1417 if (!warned) {
1418 cerr << "WARNING: sample rates differ, but no converter available!" << endl; 1418 cerr << "WARNING: sample rates differ, but no converter available!" << endl;
1422 1422
1423 if (resample && m_converter) { 1423 if (resample && m_converter) {
1424 1424
1425 double ratio = 1425 double ratio =
1426 double(getTargetSampleRate()) / double(getSourceSampleRate()); 1426 double(getTargetSampleRate()) / double(getSourceSampleRate());
1427 orig = int(orig / ratio + 0.1); 1427 orig = sv_frame_t(double(orig) / ratio + 0.1);
1428 1428
1429 // orig must be a multiple of generatorBlockSize 1429 // orig must be a multiple of generatorBlockSize
1430 orig = (orig / generatorBlockSize) * generatorBlockSize; 1430 orig = (orig / generatorBlockSize) * generatorBlockSize;
1431 if (orig == 0) return false; 1431 if (orig == 0) return false;
1432 1432
1433 int work = std::max(orig, space); 1433 sv_frame_t work = std::max(orig, space);
1434 1434
1435 // We only allocate one buffer, but we use it in two halves. 1435 // We only allocate one buffer, but we use it in two halves.
1436 // We place the non-interleaved values in the second half of 1436 // We place the non-interleaved values in the second half of
1437 // the buffer (orig samples for channel 0, orig samples for 1437 // the buffer (orig samples for channel 0, orig samples for
1438 // channel 1 etc), and then interleave them into the first 1438 // channel 1 etc), and then interleave them into the first
1490 err = src_process(m_crapConverter, &data); 1490 err = src_process(m_crapConverter, &data);
1491 } else { 1491 } else {
1492 err = src_process(m_converter, &data); 1492 err = src_process(m_converter, &data);
1493 } 1493 }
1494 1494
1495 int toCopy = int(got * ratio + 0.1); 1495 sv_frame_t toCopy = sv_frame_t(double(got) * ratio + 0.1);
1496 1496
1497 if (err) { 1497 if (err) {
1498 cerr 1498 cerr
1499 << "AudioCallbackPlaySourceFillThread: ERROR in samplerate conversion: " 1499 << "AudioCallbackPlaySourceFillThread: ERROR in samplerate conversion: "
1500 << src_strerror(err) << endl; 1500 << src_strerror(err) << endl;
1510 for (int c = 0; c < channels; ++c) { 1510 for (int c = 0; c < channels; ++c) {
1511 for (int i = 0; i < toCopy; ++i) { 1511 for (int i = 0; i < toCopy; ++i) {
1512 tmp[i] = srcout[channels * i + c]; 1512 tmp[i] = srcout[channels * i + c];
1513 } 1513 }
1514 RingBuffer<float> *wb = getWriteRingBuffer(c); 1514 RingBuffer<float> *wb = getWriteRingBuffer(c);
1515 if (wb) wb->write(tmp, toCopy); 1515 if (wb) wb->write(tmp, int(toCopy));
1516 } 1516 }
1517 1517
1518 m_writeBufferFill = f; 1518 m_writeBufferFill = f;
1519 if (readWriteEqual) m_readBufferFill = f; 1519 if (readWriteEqual) m_readBufferFill = f;
1520 1520
1521 } else { 1521 } else {
1522 1522
1523 // space must be a multiple of generatorBlockSize 1523 // space must be a multiple of generatorBlockSize
1524 int reqSpace = space; 1524 sv_frame_t reqSpace = space;
1525 space = (reqSpace / generatorBlockSize) * generatorBlockSize; 1525 space = (reqSpace / generatorBlockSize) * generatorBlockSize;
1526 if (space == 0) { 1526 if (space == 0) {
1527 #ifdef DEBUG_AUDIO_PLAY_SOURCE 1527 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1528 cout << "requested fill of " << reqSpace 1528 cout << "requested fill of " << reqSpace
1529 << " is less than generator block size of " 1529 << " is less than generator block size of "
1545 for (int i = 0; i < space; ++i) { 1545 for (int i = 0; i < space; ++i) {
1546 tmp[c * space + i] = 0.0f; 1546 tmp[c * space + i] = 0.0f;
1547 } 1547 }
1548 } 1548 }
1549 1549
1550 int got = mixModels(f, space, bufferPtrs); // also modifies f 1550 sv_frame_t got = mixModels(f, space, bufferPtrs); // also modifies f
1551 1551
1552 for (int c = 0; c < channels; ++c) { 1552 for (int c = 0; c < channels; ++c) {
1553 1553
1554 RingBuffer<float> *wb = getWriteRingBuffer(c); 1554 RingBuffer<float> *wb = getWriteRingBuffer(c);
1555 if (wb) { 1555 if (wb) {
1556 int actual = wb->write(bufferPtrs[c], got); 1556 int actual = wb->write(bufferPtrs[c], int(got));
1557 #ifdef DEBUG_AUDIO_PLAY_SOURCE 1557 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1558 cout << "Wrote " << actual << " samples for ch " << c << ", now " 1558 cout << "Wrote " << actual << " samples for ch " << c << ", now "
1559 << wb->getReadSpace() << " to read" 1559 << wb->getReadSpace() << " to read"
1560 << endl; 1560 << endl;
1561 #endif 1561 #endif
1578 } 1578 }
1579 1579
1580 return true; 1580 return true;
1581 } 1581 }
1582 1582
1583 int 1583 sv_frame_t
1584 AudioCallbackPlaySource::mixModels(int &frame, int count, float **buffers) 1584 AudioCallbackPlaySource::mixModels(sv_frame_t &frame, sv_frame_t count, float **buffers)
1585 { 1585 {
1586 int processed = 0; 1586 sv_frame_t processed = 0;
1587 int chunkStart = frame; 1587 sv_frame_t chunkStart = frame;
1588 int chunkSize = count; 1588 sv_frame_t chunkSize = count;
1589 int selectionSize = 0; 1589 sv_frame_t selectionSize = 0;
1590 int nextChunkStart = chunkStart + chunkSize; 1590 sv_frame_t nextChunkStart = chunkStart + chunkSize;
1591 1591
1592 bool looping = m_viewManager->getPlayLoopMode(); 1592 bool looping = m_viewManager->getPlayLoopMode();
1593 bool constrained = (m_viewManager->getPlaySelectionMode() && 1593 bool constrained = (m_viewManager->getPlaySelectionMode() &&
1594 !m_viewManager->getSelections().empty()); 1594 !m_viewManager->getSelections().empty());
1595 1595
1615 1615
1616 chunkSize = count - processed; 1616 chunkSize = count - processed;
1617 nextChunkStart = chunkStart + chunkSize; 1617 nextChunkStart = chunkStart + chunkSize;
1618 selectionSize = 0; 1618 selectionSize = 0;
1619 1619
1620 int fadeIn = 0, fadeOut = 0; 1620 sv_frame_t fadeIn = 0, fadeOut = 0;
1621 1621
1622 if (constrained) { 1622 if (constrained) {
1623 1623
1624 int rChunkStart = 1624 sv_frame_t rChunkStart =
1625 m_viewManager->alignPlaybackFrameToReference(chunkStart); 1625 m_viewManager->alignPlaybackFrameToReference(chunkStart);
1626 1626
1627 Selection selection = 1627 Selection selection =
1628 m_viewManager->getContainingSelection(rChunkStart, true); 1628 m_viewManager->getContainingSelection(rChunkStart, true);
1629 1629
1641 chunkSize = 0; 1641 chunkSize = 0;
1642 nextChunkStart = chunkStart; 1642 nextChunkStart = chunkStart;
1643 1643
1644 } else { 1644 } else {
1645 1645
1646 int sf = m_viewManager->alignReferenceToPlaybackFrame 1646 sv_frame_t sf = m_viewManager->alignReferenceToPlaybackFrame
1647 (selection.getStartFrame()); 1647 (selection.getStartFrame());
1648 int ef = m_viewManager->alignReferenceToPlaybackFrame 1648 sv_frame_t ef = m_viewManager->alignReferenceToPlaybackFrame
1649 (selection.getEndFrame()); 1649 (selection.getEndFrame());
1650 1650
1651 selectionSize = ef - sf; 1651 selectionSize = ef - sf;
1652 1652
1653 if (chunkStart < sf) { 1653 if (chunkStart < sf) {
1759 } 1759 }
1760 break; 1760 break;
1761 } 1761 }
1762 } 1762 }
1763 1763
1764 int rf = m_readBufferFill; 1764 sv_frame_t rf = m_readBufferFill;
1765 RingBuffer<float> *rb = getReadRingBuffer(0); 1765 RingBuffer<float> *rb = getReadRingBuffer(0);
1766 if (rb) { 1766 if (rb) {
1767 int rs = rb->getReadSpace(); 1767 int rs = rb->getReadSpace();
1768 //!!! incorrect when in non-contiguous selection, see comments elsewhere 1768 //!!! incorrect when in non-contiguous selection, see comments elsewhere
1769 // cout << "rs = " << rs << endl; 1769 // cout << "rs = " << rs << endl;
1773 1773
1774 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING 1774 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
1775 SVDEBUG << "AudioCallbackPlaySource::unifyRingBuffers: m_readBufferFill = " << m_readBufferFill << ", rf = " << rf << ", m_writeBufferFill = " << m_writeBufferFill << endl; 1775 SVDEBUG << "AudioCallbackPlaySource::unifyRingBuffers: m_readBufferFill = " << m_readBufferFill << ", rf = " << rf << ", m_writeBufferFill = " << m_writeBufferFill << endl;
1776 #endif 1776 #endif
1777 1777
1778 int wf = m_writeBufferFill; 1778 sv_frame_t wf = m_writeBufferFill;
1779 int skip = 0; 1779 sv_frame_t skip = 0;
1780 for (int c = 0; c < getTargetChannelCount(); ++c) { 1780 for (int c = 0; c < getTargetChannelCount(); ++c) {
1781 RingBuffer<float> *wb = getWriteRingBuffer(c); 1781 RingBuffer<float> *wb = getWriteRingBuffer(c);
1782 if (wb) { 1782 if (wb) {
1783 if (c == 0) { 1783 if (c == 0) {
1784 1784
1792 if (wf < rf) skip = rf - wf; 1792 if (wf < rf) skip = rf - wf;
1793 if (skip == 0) break; 1793 if (skip == 0) break;
1794 } 1794 }
1795 1795
1796 // cout << "skipping " << skip << endl; 1796 // cout << "skipping " << skip << endl;
1797 wb->skip(skip); 1797 wb->skip(int(skip));
1798 } 1798 }
1799 } 1799 }
1800 1800
1801 m_bufferScavenger.claim(m_readBuffers); 1801 m_bufferScavenger.claim(m_readBuffers);
1802 m_readBuffers = m_writeBuffers; 1802 m_readBuffers = m_writeBuffers;
1835 s.m_mutex.unlock(); 1835 s.m_mutex.unlock();
1836 s.m_mutex.lock(); 1836 s.m_mutex.lock();
1837 1837
1838 } else { 1838 } else {
1839 1839
1840 float ms = 100; 1840 double ms = 100;
1841 if (s.getSourceSampleRate() > 0) { 1841 if (s.getSourceSampleRate() > 0) {
1842 ms = float(s.m_ringBufferSize) / 1842 ms = double(s.m_ringBufferSize) / s.getSourceSampleRate() * 1000.0;
1843 float(s.getSourceSampleRate()) * 1000.0;
1844 } 1843 }
1845 1844
1846 if (s.m_playing) ms /= 10; 1845 if (s.m_playing) ms /= 10;
1847 1846
1848 #ifdef DEBUG_AUDIO_PLAY_SOURCE 1847 #ifdef DEBUG_AUDIO_PLAY_SOURCE