comparison audio/AudioCallbackPlaySource.cpp @ 553:2a1e9e017484 bqresample

Fixes to sample rate and latency handling
author Chris Cannam
date Fri, 09 Dec 2016 14:40:49 +0000
parents 8c11ca1ebc39
children 2683a8ca36ea
comparison
equal deleted inserted replaced
552:8c11ca1ebc39 553:2a1e9e017484
52 m_writeBufferFill(0), 52 m_writeBufferFill(0),
53 m_bufferScavenger(1), 53 m_bufferScavenger(1),
54 m_sourceChannelCount(0), 54 m_sourceChannelCount(0),
55 m_blockSize(1024), 55 m_blockSize(1024),
56 m_sourceSampleRate(0), 56 m_sourceSampleRate(0),
57 m_targetSampleRate(0), 57 m_deviceSampleRate(0),
58 m_playLatency(0), 58 m_playLatency(0),
59 m_target(0), 59 m_target(0),
60 m_lastRetrievalTimestamp(0.0), 60 m_lastRetrievalTimestamp(0.0),
61 m_lastRetrievedBlockSize(0), 61 m_lastRetrievedBlockSize(0),
62 m_trustworthyTimestamps(true), 62 m_trustworthyTimestamps(true),
229 } else { 229 } else {
230 if (willPlay) clearRingBuffers(true); 230 if (willPlay) clearRingBuffers(true);
231 } 231 }
232 232
233 if (srChanged) { 233 if (srChanged) {
234
234 SVCERR << "AudioCallbackPlaySource: Source rate changed" << endl; 235 SVCERR << "AudioCallbackPlaySource: Source rate changed" << endl;
236
235 if (m_resamplerWrapper) { 237 if (m_resamplerWrapper) {
236 SVCERR << "AudioCallbackPlaySource: Source sample rate changed to " 238 SVCERR << "AudioCallbackPlaySource: Source sample rate changed to "
237 << m_sourceSampleRate << ", updating resampler wrapper" << endl; 239 << m_sourceSampleRate << ", updating resampler wrapper" << endl;
238 m_resamplerWrapper->changeApplicationSampleRate 240 m_resamplerWrapper->changeApplicationSampleRate
239 (int(round(m_sourceSampleRate))); 241 (int(round(m_sourceSampleRate)));
240 m_resamplerWrapper->reset(); 242 m_resamplerWrapper->reset();
243 }
244
245 delete m_timeStretcher;
246 delete m_monoStretcher;
247 m_timeStretcher = 0;
248 m_monoStretcher = 0;
249
250 if (m_stretchRatio != 1.f) {
251 setTimeStretch(m_stretchRatio);
241 } 252 }
242 } 253 }
243 254
244 rebuildRangeLists(); 255 rebuildRangeLists();
245 256
630 AudioCallbackPlaySource::getCurrentPlayingFrame() 641 AudioCallbackPlaySource::getCurrentPlayingFrame()
631 { 642 {
632 // This method attempts to estimate which audio sample frame is 643 // This method attempts to estimate which audio sample frame is
633 // "currently coming through the speakers". 644 // "currently coming through the speakers".
634 645
635 sv_samplerate_t targetRate = getTargetSampleRate(); 646 sv_samplerate_t deviceRate = getDeviceSampleRate();
636 sv_frame_t latency = m_playLatency; // at target rate 647 sv_frame_t latency = m_playLatency; // at target rate
637 RealTime latency_t = RealTime::zeroTime; 648 RealTime latency_t = RealTime::zeroTime;
638 649
639 if (targetRate != 0) { 650 if (deviceRate != 0) {
640 latency_t = RealTime::frame2RealTime(latency, targetRate); 651 latency_t = RealTime::frame2RealTime(latency, deviceRate);
641 } 652 }
642 653
643 return getCurrentFrame(latency_t); 654 return getCurrentFrame(latency_t);
644 } 655 }
645 656
650 } 661 }
651 662
652 sv_frame_t 663 sv_frame_t
653 AudioCallbackPlaySource::getCurrentFrame(RealTime latency_t) 664 AudioCallbackPlaySource::getCurrentFrame(RealTime latency_t)
654 { 665 {
655 // We resample when filling the ring buffer, and time-stretch when 666 // The ring buffers contain data at the source sample rate and all
656 // draining it. The buffer contains data at the "target rate" and 667 // processing (including time stretching) happens at this
657 // the latency provided by the target is also at the target rate. 668 // rate. Resampling only happens after the audio data leaves this
658 // Because of the multiple rates involved, we do the actual 669 // class.
659 // calculation using RealTime instead. 670
660 671 // (But because historically more than one sample rate could have
661 sv_samplerate_t sourceRate = getSourceSampleRate(); 672 // been involved here, we do latency calculations using RealTime
662 sv_samplerate_t targetRate = getTargetSampleRate(); 673 // values instead of samples.)
663 674
664 if (sourceRate == 0 || targetRate == 0) return 0; 675 sv_samplerate_t rate = getSourceSampleRate();
676
677 if (rate == 0) return 0;
665 678
666 int inbuffer = 0; // at target rate 679 int inbuffer = 0; // at target rate
667 680
668 for (int c = 0; c < getTargetChannelCount(); ++c) { 681 for (int c = 0; c < getTargetChannelCount(); ++c) {
669 RingBuffer<float> *rb = getReadRingBuffer(c); 682 RingBuffer<float> *rb = getReadRingBuffer(c);
679 double currentTime = 0.0; 692 double currentTime = 0.0;
680 if (m_target) currentTime = m_target->getCurrentTime(); 693 if (m_target) currentTime = m_target->getCurrentTime();
681 694
682 bool looping = m_viewManager->getPlayLoopMode(); 695 bool looping = m_viewManager->getPlayLoopMode();
683 696
684 RealTime inbuffer_t = RealTime::frame2RealTime(inbuffer, targetRate); 697 RealTime inbuffer_t = RealTime::frame2RealTime(inbuffer, rate);
685 698
686 sv_frame_t stretchlat = 0; 699 sv_frame_t stretchlat = 0;
687 double timeRatio = 1.0; 700 double timeRatio = 1.0;
688 701
689 if (m_timeStretcher) { 702 if (m_timeStretcher) {
690 stretchlat = m_timeStretcher->getLatency(); 703 stretchlat = m_timeStretcher->getLatency();
691 timeRatio = m_timeStretcher->getTimeRatio(); 704 timeRatio = m_timeStretcher->getTimeRatio();
692 } 705 }
693 706
694 RealTime stretchlat_t = RealTime::frame2RealTime(stretchlat, targetRate); 707 RealTime stretchlat_t = RealTime::frame2RealTime(stretchlat, rate);
695 708
696 // When the target has just requested a block from us, the last 709 // When the target has just requested a block from us, the last
697 // sample it obtained was our buffer fill frame count minus the 710 // sample it obtained was our buffer fill frame count minus the
698 // amount of read space (converted back to source sample rate) 711 // amount of read space (converted back to source sample rate)
699 // remaining now. That sample is not expected to be played until 712 // remaining now. That sample is not expected to be played until
707 720
708 if (m_target && 721 if (m_target &&
709 m_trustworthyTimestamps && 722 m_trustworthyTimestamps &&
710 lastRetrievalTimestamp != 0.0) { 723 lastRetrievalTimestamp != 0.0) {
711 724
712 lastretrieved_t = RealTime::frame2RealTime 725 lastretrieved_t = RealTime::frame2RealTime(lastRetrievedBlockSize, rate);
713 (lastRetrievedBlockSize, targetRate);
714 726
715 // calculate number of frames at target rate that have elapsed 727 // calculate number of frames at target rate that have elapsed
716 // since the end of the last call to getSourceSamples 728 // since the end of the last call to getSourceSamples
717 729
718 if (m_trustworthyTimestamps && !looping) { 730 if (m_trustworthyTimestamps && !looping) {
725 } 737 }
726 } 738 }
727 739
728 } else { 740 } else {
729 741
730 lastretrieved_t = RealTime::frame2RealTime 742 lastretrieved_t = RealTime::frame2RealTime(getTargetBlockSize(), rate);
731 (getTargetBlockSize(), targetRate); 743 }
732 } 744
733 745 RealTime bufferedto_t = RealTime::frame2RealTime(readBufferFill, rate);
734 RealTime bufferedto_t = RealTime::frame2RealTime(readBufferFill, sourceRate);
735 746
736 if (timeRatio != 1.0) { 747 if (timeRatio != 1.0) {
737 lastretrieved_t = lastretrieved_t / timeRatio; 748 lastretrieved_t = lastretrieved_t / timeRatio;
738 sincerequest_t = sincerequest_t / timeRatio; 749 sincerequest_t = sincerequest_t / timeRatio;
739 latency_t = latency_t / timeRatio; 750 latency_t = latency_t / timeRatio;
755 // this code is only used in case of error in rebuildRangeLists 766 // this code is only used in case of error in rebuildRangeLists
756 RealTime playing_t = bufferedto_t 767 RealTime playing_t = bufferedto_t
757 - latency_t - stretchlat_t - lastretrieved_t - inbuffer_t 768 - latency_t - stretchlat_t - lastretrieved_t - inbuffer_t
758 + sincerequest_t; 769 + sincerequest_t;
759 if (playing_t < RealTime::zeroTime) playing_t = RealTime::zeroTime; 770 if (playing_t < RealTime::zeroTime) playing_t = RealTime::zeroTime;
760 sv_frame_t frame = RealTime::realTime2Frame(playing_t, sourceRate); 771 sv_frame_t frame = RealTime::realTime2Frame(playing_t, rate);
761 return m_viewManager->alignPlaybackFrameToReference(frame); 772 return m_viewManager->alignPlaybackFrameToReference(frame);
762 } 773 }
763 774
764 int inRange = 0; 775 int inRange = 0;
765 int index = 0; 776 int index = 0;
792 // the region boundary and end up being much smaller than the 803 // the region boundary and end up being much smaller than the
793 // theoretical play start frame, perhaps even for the entire 804 // theoretical play start frame, perhaps even for the entire
794 // duration of playback! 805 // duration of playback!
795 806
796 if (!m_playStartFramePassed) { 807 if (!m_playStartFramePassed) {
797 RealTime playstart_t = RealTime::frame2RealTime(m_playStartFrame, 808 RealTime playstart_t = RealTime::frame2RealTime(m_playStartFrame, rate);
798 sourceRate);
799 if (playing_t < playstart_t) { 809 if (playing_t < playstart_t) {
800 // cerr << "playing_t " << playing_t << " < playstart_t " 810 // cerr << "playing_t " << playing_t << " < playstart_t "
801 // << playstart_t << endl; 811 // << playstart_t << endl;
802 if (/*!!! sincerequest_t > RealTime::zeroTime && */ 812 if (/*!!! sincerequest_t > RealTime::zeroTime && */
803 m_playStartedAt + latency_t + stretchlat_t < 813 m_playStartedAt + latency_t + stretchlat_t <
851 } 861 }
852 } 862 }
853 863
854 if (playing_t < RealTime::zeroTime) playing_t = RealTime::zeroTime; 864 if (playing_t < RealTime::zeroTime) playing_t = RealTime::zeroTime;
855 865
856 sv_frame_t frame = RealTime::realTime2Frame(playing_t, sourceRate); 866 sv_frame_t frame = RealTime::realTime2Frame(playing_t, rate);
857 867
858 if (m_lastCurrentFrame > 0 && !looping) { 868 if (m_lastCurrentFrame > 0 && !looping) {
859 if (frame < m_lastCurrentFrame) { 869 if (frame < m_lastCurrentFrame) {
860 frame = m_lastCurrentFrame; 870 frame = m_lastCurrentFrame;
861 } 871 }
936 } 946 }
937 947
938 void 948 void
939 AudioCallbackPlaySource::setSystemPlaybackSampleRate(int sr) 949 AudioCallbackPlaySource::setSystemPlaybackSampleRate(int sr)
940 { 950 {
941 bool first = (m_targetSampleRate == 0); 951 m_deviceSampleRate = sr;
942
943 m_targetSampleRate = sr;
944
945 if (first && (m_stretchRatio != 1.f)) {
946 // couldn't create a stretcher before because we had no sample
947 // rate: make one now
948 setTimeStretch(m_stretchRatio);
949 }
950 } 952 }
951 953
952 void 954 void
953 AudioCallbackPlaySource::setSystemPlaybackChannelCount(int) 955 AudioCallbackPlaySource::setSystemPlaybackChannelCount(int)
954 { 956 {
981 m_audioGenerator->clearSoloModelSet(); 983 m_audioGenerator->clearSoloModelSet();
982 clearRingBuffers(); 984 clearRingBuffers();
983 } 985 }
984 986
985 sv_samplerate_t 987 sv_samplerate_t
986 AudioCallbackPlaySource::getTargetSampleRate() const 988 AudioCallbackPlaySource::getDeviceSampleRate() const
987 { 989 {
988 if (m_targetSampleRate) return m_targetSampleRate; 990 return m_deviceSampleRate;
989 else return getSourceSampleRate();
990 } 991 }
991 992
992 int 993 int
993 AudioCallbackPlaySource::getSourceChannelCount() const 994 AudioCallbackPlaySource::getSourceChannelCount() const
994 { 995 {
1011 void 1012 void
1012 AudioCallbackPlaySource::setTimeStretch(double factor) 1013 AudioCallbackPlaySource::setTimeStretch(double factor)
1013 { 1014 {
1014 m_stretchRatio = factor; 1015 m_stretchRatio = factor;
1015 1016
1016 if (!getTargetSampleRate()) return; // have to make our stretcher later 1017 int rate = int(getSourceSampleRate());
1018 if (!rate) return; // have to make our stretcher later
1017 1019
1018 if (m_timeStretcher || (factor == 1.0)) { 1020 if (m_timeStretcher || (factor == 1.0)) {
1019 // stretch ratio will be set in next process call if appropriate 1021 // stretch ratio will be set in next process call if appropriate
1020 } else { 1022 } else {
1021 m_stretcherInputCount = getTargetChannelCount(); 1023 m_stretcherInputCount = getTargetChannelCount();
1022 RubberBandStretcher *stretcher = new RubberBandStretcher 1024 RubberBandStretcher *stretcher = new RubberBandStretcher
1023 (int(getTargetSampleRate()), 1025 (rate,
1024 m_stretcherInputCount, 1026 m_stretcherInputCount,
1025 RubberBandStretcher::OptionProcessRealTime, 1027 RubberBandStretcher::OptionProcessRealTime,
1026 factor); 1028 factor);
1027 RubberBandStretcher *monoStretcher = new RubberBandStretcher 1029 RubberBandStretcher *monoStretcher = new RubberBandStretcher
1028 (int(getTargetSampleRate()), 1030 (rate,
1029 1, 1031 1,
1030 RubberBandStretcher::OptionProcessRealTime, 1032 RubberBandStretcher::OptionProcessRealTime,
1031 factor); 1033 factor);
1032 m_stretcherInputs = new float *[m_stretcherInputCount]; 1034 m_stretcherInputs = new float *[m_stretcherInputCount];
1033 m_stretcherInputSizes = new sv_frame_t[m_stretcherInputCount]; 1035 m_stretcherInputSizes = new sv_frame_t[m_stretcherInputCount];