Mercurial > hg > svapp
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 |