comparison audioio/AudioCallbackPlaySource.cpp @ 13:89bb89894ad6

* As previous commit
author Chris Cannam
date Fri, 17 Feb 2006 18:11:08 +0000
parents 29b38a641d43
children 6b5eaf206f0f
comparison
equal deleted inserted replaced
12:29b38a641d43 13:89bb89894ad6
20 20
21 #include <iostream> 21 #include <iostream>
22 #include <cassert> 22 #include <cassert>
23 23
24 //#define DEBUG_AUDIO_PLAY_SOURCE 1 24 //#define DEBUG_AUDIO_PLAY_SOURCE 1
25 //#define DEBUG_AUDIO_PLAY_SOURCE_PLAYING 1
25 26
26 //const size_t AudioCallbackPlaySource::m_ringBufferSize = 102400; 27 //const size_t AudioCallbackPlaySource::m_ringBufferSize = 102400;
27 const size_t AudioCallbackPlaySource::m_ringBufferSize = 131071; 28 const size_t AudioCallbackPlaySource::m_ringBufferSize = 131071;
28 29
29 AudioCallbackPlaySource::AudioCallbackPlaySource(ViewManager *manager) : 30 AudioCallbackPlaySource::AudioCallbackPlaySource(ViewManager *manager) :
30 m_viewManager(manager), 31 m_viewManager(manager),
31 m_audioGenerator(new AudioGenerator(manager)), 32 m_audioGenerator(new AudioGenerator(manager)),
32 m_readBuffers(0), 33 m_readBuffers(0),
33 m_writeBuffers(0), 34 m_writeBuffers(0),
35 m_readBufferFill(0),
36 m_writeBufferFill(0),
37 m_bufferScavenger(1),
34 m_sourceChannelCount(0), 38 m_sourceChannelCount(0),
35 m_blockSize(1024), 39 m_blockSize(1024),
36 m_sourceSampleRate(0), 40 m_sourceSampleRate(0),
37 m_targetSampleRate(0), 41 m_targetSampleRate(0),
38 m_playLatency(0), 42 m_playLatency(0),
39 m_playing(false), 43 m_playing(false),
40 m_exiting(false), 44 m_exiting(false),
41 m_bufferedToFrame(0),
42 m_lastModelEndFrame(0), 45 m_lastModelEndFrame(0),
43 m_outputLeft(0.0), 46 m_outputLeft(0.0),
44 m_outputRight(0.0), 47 m_outputRight(0.0),
45 m_slowdownCounter(0), 48 m_slowdownCounter(0),
46 m_timeStretcher(0), 49 m_timeStretcher(0),
117 m_sourceChannelCount = modelChannels; 120 m_sourceChannelCount = modelChannels;
118 } 121 }
119 122
120 std::cerr << "Adding model with " << modelChannels << " channels " << std::endl; 123 std::cerr << "Adding model with " << modelChannels << " channels " << std::endl;
121 124
122 if (!m_writeBuffers || m_writeBuffers->size() < modelChannels) { 125 if (!m_writeBuffers || (m_writeBuffers->size() < getTargetChannelCount())) {
123 m_audioGenerator->setTargetChannelCount(modelChannels); 126 clearRingBuffers(true, getTargetChannelCount());
124 }
125
126 if (!m_writeBuffers || (m_writeBuffers->size() < modelChannels)) {
127 clearRingBuffers(true, modelChannels);
128 buffersChanged = true; 127 buffersChanged = true;
129 } else { 128 } else {
130 if (canPlay) clearRingBuffers(true); 129 if (canPlay) clearRingBuffers(true);
131 } 130 }
132 131
137 } 136 }
138 } 137 }
139 138
140 m_mutex.unlock(); 139 m_mutex.unlock();
141 140
141 m_audioGenerator->setTargetChannelCount(getTargetChannelCount());
142
142 if (!m_fillThread) { 143 if (!m_fillThread) {
143 m_fillThread = new AudioCallbackPlaySourceFillThread(*this); 144 m_fillThread = new AudioCallbackPlaySourceFillThread(*this);
144 m_fillThread->start(); 145 m_fillThread->start();
145 } 146 }
146 147
211 if (!haveLock) m_mutex.lock(); 212 if (!haveLock) m_mutex.lock();
212 213
213 if (count == 0) { 214 if (count == 0) {
214 if (m_writeBuffers) count = m_writeBuffers->size(); 215 if (m_writeBuffers) count = m_writeBuffers->size();
215 } 216 }
217
218 size_t sf = m_readBufferFill;
219 RingBuffer<float> *rb = getReadRingBuffer(0);
220 if (rb) {
221 //!!! This is incorrect if we're in a non-contiguous selection
222 //Same goes for all related code (subtracting the read space
223 //from the fill frame to try to establish where the effective
224 //pre-resample/timestretch read pointer is)
225 size_t rs = rb->getReadSpace();
226 if (rs < sf) sf -= rs;
227 else sf = 0;
228 }
229 m_writeBufferFill = sf;
216 230
217 if (m_readBuffers != m_writeBuffers) { 231 if (m_readBuffers != m_writeBuffers) {
218 delete m_writeBuffers; 232 delete m_writeBuffers;
219 } 233 }
220 234
261 // starting again if we have not so far been playing, but not if 275 // starting again if we have not so far been playing, but not if
262 // we're just re-seeking. 276 // we're just re-seeking.
263 277
264 m_mutex.lock(); 278 m_mutex.lock();
265 if (m_playing) { 279 if (m_playing) {
266 m_bufferedToFrame = startFrame; 280 m_readBufferFill = m_writeBufferFill = startFrame;
267 if (m_readBuffers) { 281 if (m_readBuffers) {
268 for (size_t c = 0; c < getSourceChannelCount(); ++c) { 282 for (size_t c = 0; c < getTargetChannelCount(); ++c) {
269 RingBuffer<float> *rb = getReadRingBuffer(c); 283 RingBuffer<float> *rb = getReadRingBuffer(c);
270 if (rb) rb->reset(); 284 if (rb) rb->reset();
271 } 285 }
272 } 286 }
273 if (m_converter) src_reset(m_converter); 287 if (m_converter) src_reset(m_converter);
274 } else { 288 } else {
275 if (m_converter) src_reset(m_converter); 289 if (m_converter) src_reset(m_converter);
276 m_bufferedToFrame = startFrame; 290 m_readBufferFill = m_writeBufferFill = startFrame;
277 } 291 }
278 m_mutex.unlock(); 292 m_mutex.unlock();
279 293
280 m_audioGenerator->reset(); 294 m_audioGenerator->reset();
281 295
357 resample = true; 371 resample = true;
358 ratio = double(getSourceSampleRate()) / double(getTargetSampleRate()); 372 ratio = double(getSourceSampleRate()) / double(getTargetSampleRate());
359 } 373 }
360 374
361 size_t readSpace = 0; 375 size_t readSpace = 0;
362 for (size_t c = 0; c < getSourceChannelCount(); ++c) { 376 for (size_t c = 0; c < getTargetChannelCount(); ++c) {
363 RingBuffer<float> *rb = getReadRingBuffer(c); 377 RingBuffer<float> *rb = getReadRingBuffer(c);
364 if (rb) { 378 if (rb) {
365 size_t spaceHere = rb->getReadSpace(); 379 size_t spaceHere = rb->getReadSpace();
366 if (c == 0 || spaceHere < readSpace) readSpace = spaceHere; 380 if (c == 0 || spaceHere < readSpace) readSpace = spaceHere;
367 } 381 }
378 if (timeStretcher) { 392 if (timeStretcher) {
379 latency += timeStretcher->getStretcher(0)->getProcessingLatency(); 393 latency += timeStretcher->getStretcher(0)->getProcessingLatency();
380 } 394 }
381 395
382 latency += readSpace; 396 latency += readSpace;
383 size_t bufferedFrame = m_bufferedToFrame; 397 size_t bufferedFrame = m_readBufferFill;
384 398
385 bool looping = m_viewManager->getPlayLoopMode(); 399 bool looping = m_viewManager->getPlayLoopMode();
386 bool constrained = (m_viewManager->getPlaySelectionMode() && 400 bool constrained = (m_viewManager->getPlaySelectionMode() &&
387 !m_viewManager->getSelections().empty()); 401 !m_viewManager->getSelections().empty());
388 402
487 m_targetSampleRate = sr; 501 m_targetSampleRate = sr;
488 502
489 if (getSourceSampleRate() != getTargetSampleRate()) { 503 if (getSourceSampleRate() != getTargetSampleRate()) {
490 504
491 int err = 0; 505 int err = 0;
492 m_converter = src_new(SRC_SINC_BEST_QUALITY, m_sourceChannelCount, &err); 506 m_converter = src_new(SRC_SINC_BEST_QUALITY,
507 getTargetChannelCount(), &err);
493 if (!m_converter) { 508 if (!m_converter) {
494 std::cerr 509 std::cerr
495 << "AudioCallbackPlaySource::setModel: ERROR in creating samplerate converter: " 510 << "AudioCallbackPlaySource::setModel: ERROR in creating samplerate converter: "
496 << src_strerror(err) << std::endl; 511 << src_strerror(err) << std::endl;
497 } 512 }
508 } 523 }
509 524
510 size_t 525 size_t
511 AudioCallbackPlaySource::getSourceChannelCount() const 526 AudioCallbackPlaySource::getSourceChannelCount() const
512 { 527 {
528 return m_sourceChannelCount;
529 }
530
531 size_t
532 AudioCallbackPlaySource::getTargetChannelCount() const
533 {
534 if (m_sourceChannelCount < 2) return 2;
513 return m_sourceChannelCount; 535 return m_sourceChannelCount;
514 } 536 }
515 537
516 size_t 538 size_t
517 AudioCallbackPlaySource::getSourceSampleRate() const 539 AudioCallbackPlaySource::getSourceSampleRate() const
588 return; 610 return;
589 } 611 }
590 612
591 if (factor > 1) { 613 if (factor > 1) {
592 TimeStretcherData *newStretcher = new TimeStretcherData 614 TimeStretcherData *newStretcher = new TimeStretcherData
593 (getSourceChannelCount(), factor, getTargetBlockSize()); 615 (getTargetChannelCount(), factor, getTargetBlockSize());
594 m_slowdownCounter = 0; 616 m_slowdownCounter = 0;
595 m_timeStretcher = newStretcher; 617 m_timeStretcher = newStretcher;
596 } else { 618 } else {
597 m_timeStretcher = 0; 619 m_timeStretcher = 0;
598 } 620 }
604 626
605 size_t 627 size_t
606 AudioCallbackPlaySource::getSourceSamples(size_t count, float **buffer) 628 AudioCallbackPlaySource::getSourceSamples(size_t count, float **buffer)
607 { 629 {
608 if (!m_playing) { 630 if (!m_playing) {
609 for (size_t ch = 0; ch < getSourceChannelCount(); ++ch) { 631 for (size_t ch = 0; ch < getTargetChannelCount(); ++ch) {
610 for (size_t i = 0; i < count; ++i) { 632 for (size_t i = 0; i < count; ++i) {
611 buffer[ch][i] = 0.0; 633 buffer[ch][i] = 0.0;
612 } 634 }
613 } 635 }
614 return 0; 636 return 0;
618 640
619 if (!timeStretcher || timeStretcher->getFactor() == 1) { 641 if (!timeStretcher || timeStretcher->getFactor() == 1) {
620 642
621 size_t got = 0; 643 size_t got = 0;
622 644
623 for (size_t ch = 0; ch < getSourceChannelCount(); ++ch) { 645 for (size_t ch = 0; ch < getTargetChannelCount(); ++ch) {
624 646
625 RingBuffer<float> *rb = getReadRingBuffer(ch); 647 RingBuffer<float> *rb = getReadRingBuffer(ch);
626 648
627 if (rb) { 649 if (rb) {
628 650
636 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING 658 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
637 std::cout << "AudioCallbackPlaySource::getSamples: got " << got << " samples on channel " << ch << ", signalling for more (possibly)" << std::endl; 659 std::cout << "AudioCallbackPlaySource::getSamples: got " << got << " samples on channel " << ch << ", signalling for more (possibly)" << std::endl;
638 #endif 660 #endif
639 } 661 }
640 662
641 for (size_t ch = 0; ch < getSourceChannelCount(); ++ch) { 663 for (size_t ch = 0; ch < getTargetChannelCount(); ++ch) {
642 for (size_t i = got; i < count; ++i) { 664 for (size_t i = got; i < count; ++i) {
643 buffer[ch][i] = 0.0; 665 buffer[ch][i] = 0.0;
644 } 666 }
645 } 667 }
646 } 668 }
652 if (m_slowdownCounter == 0) { 674 if (m_slowdownCounter == 0) {
653 675
654 size_t got = 0; 676 size_t got = 0;
655 double *ib = timeStretcher->getInputBuffer(); 677 double *ib = timeStretcher->getInputBuffer();
656 678
657 for (size_t ch = 0; ch < getSourceChannelCount(); ++ch) { 679 for (size_t ch = 0; ch < getTargetChannelCount(); ++ch) {
658 680
659 RingBuffer<float> *rb = getReadRingBuffer(ch); 681 RingBuffer<float> *rb = getReadRingBuffer(ch);
660 682
661 if (rb) { 683 if (rb) {
662 684
680 // reset this in case the factor has changed leaving the 702 // reset this in case the factor has changed leaving the
681 // counter out of range 703 // counter out of range
682 m_slowdownCounter = 0; 704 m_slowdownCounter = 0;
683 } 705 }
684 706
685 for (size_t ch = 0; ch < getSourceChannelCount(); ++ch) { 707 for (size_t ch = 0; ch < getTargetChannelCount(); ++ch) {
686 708
687 double *ob = timeStretcher->getOutputBuffer(ch); 709 double *ob = timeStretcher->getOutputBuffer(ch);
688 710
689 #ifdef DEBUG_AUDIO_PLAY_SOURCE 711 #ifdef DEBUG_AUDIO_PLAY_SOURCE
690 std::cerr << "AudioCallbackPlaySource::getSamples: Copying from (" << (m_slowdownCounter * count) << "," << count << ") to buffer" << std::endl; 712 std::cerr << "AudioCallbackPlaySource::getSamples: Copying from (" << (m_slowdownCounter * count) << "," << count << ") to buffer" << std::endl;
706 { 728 {
707 static float *tmp = 0; 729 static float *tmp = 0;
708 static size_t tmpSize = 0; 730 static size_t tmpSize = 0;
709 731
710 size_t space = 0; 732 size_t space = 0;
711 for (size_t c = 0; c < getSourceChannelCount(); ++c) { 733 for (size_t c = 0; c < getTargetChannelCount(); ++c) {
712 RingBuffer<float> *wb = getWriteRingBuffer(c); 734 RingBuffer<float> *wb = getWriteRingBuffer(c);
713 if (wb) { 735 if (wb) {
714 size_t spaceHere = wb->getWriteSpace(); 736 size_t spaceHere = wb->getWriteSpace();
715 if (c == 0 || spaceHere < space) space = spaceHere; 737 if (c == 0 || spaceHere < space) space = spaceHere;
716 } 738 }
717 } 739 }
718 740
719 if (space == 0) return false; 741 if (space == 0) return false;
720 742
743 size_t f = m_writeBufferFill;
744
745 bool readWriteEqual = (m_readBuffers == m_writeBuffers);
746
721 #ifdef DEBUG_AUDIO_PLAY_SOURCE 747 #ifdef DEBUG_AUDIO_PLAY_SOURCE
722 std::cout << "AudioCallbackPlaySourceFillThread: filling " << space << " frames" << std::endl; 748 std::cout << "AudioCallbackPlaySourceFillThread: filling " << space << " frames" << std::endl;
723 #endif 749 #endif
724 750
725 size_t f = m_bufferedToFrame;
726
727 #ifdef DEBUG_AUDIO_PLAY_SOURCE 751 #ifdef DEBUG_AUDIO_PLAY_SOURCE
728 std::cout << "buffered to " << f << " already" << std::endl; 752 std::cout << "buffered to " << f << " already" << std::endl;
729 #endif 753 #endif
730 754
731 bool resample = (getSourceSampleRate() != getTargetSampleRate()); 755 bool resample = (getSourceSampleRate() != getTargetSampleRate());
732 756
733 #ifdef DEBUG_AUDIO_PLAY_SOURCE 757 #ifdef DEBUG_AUDIO_PLAY_SOURCE
734 std::cout << (resample ? "" : "not ") << "resampling (source " << getSourceSampleRate() << ", target " << getTargetSampleRate() << ")" << std::endl; 758 std::cout << (resample ? "" : "not ") << "resampling (source " << getSourceSampleRate() << ", target " << getTargetSampleRate() << ")" << std::endl;
735 #endif 759 #endif
736 760
737 size_t channels = getSourceChannelCount(); 761 size_t channels = getTargetChannelCount();
762
738 size_t orig = space; 763 size_t orig = space;
739 size_t got = 0; 764 size_t got = 0;
740 765
741 static float **bufferPtrs = 0; 766 static float **bufferPtrs = 0;
742 static size_t bufferPtrCount = 0; 767 static size_t bufferPtrCount = 0;
841 } 866 }
842 RingBuffer<float> *wb = getWriteRingBuffer(c); 867 RingBuffer<float> *wb = getWriteRingBuffer(c);
843 if (wb) wb->write(tmp, toCopy); 868 if (wb) wb->write(tmp, toCopy);
844 } 869 }
845 870
846 m_bufferedToFrame = f; 871 m_writeBufferFill = f;
847 872 if (readWriteEqual) m_readBufferFill = f;
873
848 } else { 874 } else {
849 875
850 // space must be a multiple of generatorBlockSize 876 // space must be a multiple of generatorBlockSize
851 space = (space / generatorBlockSize) * generatorBlockSize; 877 space = (space / generatorBlockSize) * generatorBlockSize;
852 if (space == 0) return false; 878 if (space == 0) return false;
879 << wb->getReadSpace() << " to read" 905 << wb->getReadSpace() << " to read"
880 << std::endl; 906 << std::endl;
881 #endif 907 #endif
882 } 908 }
883 909
884 m_bufferedToFrame = f; 910 m_writeBufferFill = f;
911 if (readWriteEqual) m_readBufferFill = f;
912
885 //!!! how do we know when ended? need to mark up a fully-buffered flag and check this if we find the buffers empty in getSourceSamples 913 //!!! how do we know when ended? need to mark up a fully-buffered flag and check this if we find the buffers empty in getSourceSamples
886 } 914 }
887 915
888 return true; 916 return true;
889 } 917 }
901 bool constrained = (m_viewManager->getPlaySelectionMode() && 929 bool constrained = (m_viewManager->getPlaySelectionMode() &&
902 !m_viewManager->getSelections().empty()); 930 !m_viewManager->getSelections().empty());
903 931
904 static float **chunkBufferPtrs = 0; 932 static float **chunkBufferPtrs = 0;
905 static size_t chunkBufferPtrCount = 0; 933 static size_t chunkBufferPtrCount = 0;
906 size_t channels = getSourceChannelCount(); 934 size_t channels = getTargetChannelCount();
907 935
908 #ifdef DEBUG_AUDIO_PLAY_SOURCE 936 #ifdef DEBUG_AUDIO_PLAY_SOURCE
909 std::cerr << "Selection playback: start " << frame << ", size " << count <<", channels " << channels << std::endl; 937 std::cerr << "Selection playback: start " << frame << ", size " << count <<", channels " << channels << std::endl;
910 #endif 938 #endif
911 939
1039 frame = nextChunkStart; 1067 frame = nextChunkStart;
1040 return processed; 1068 return processed;
1041 } 1069 }
1042 1070
1043 void 1071 void
1072 AudioCallbackPlaySource::unifyRingBuffers()
1073 {
1074 if (m_readBuffers == m_writeBuffers) return;
1075
1076 // only unify if there will be something to read
1077 for (size_t c = 0; c < getTargetChannelCount(); ++c) {
1078 RingBuffer<float> *wb = getWriteRingBuffer(c);
1079 if (wb) {
1080 if (wb->getReadSpace() < m_blockSize * 2) {
1081 if ((m_writeBufferFill + m_blockSize * 2) <
1082 m_lastModelEndFrame) {
1083 // OK, we don't have enough and there's more to
1084 // read -- don't unify until we can do better
1085 return;
1086 }
1087 }
1088 break;
1089 }
1090 }
1091
1092 size_t rf = m_readBufferFill;
1093 RingBuffer<float> *rb = getReadRingBuffer(0);
1094 if (rb) {
1095 size_t rs = rb->getReadSpace();
1096 //!!! incorrect when in non-contiguous selection, see comments elsewhere
1097 // std::cerr << "rs = " << rs << std::endl;
1098 if (rs < rf) rf -= rs;
1099 else rf = 0;
1100 }
1101
1102 //std::cerr << "m_readBufferFill = " << m_readBufferFill << ", rf = " << rf << ", m_writeBufferFill = " << m_writeBufferFill << std::endl;
1103
1104 size_t wf = m_writeBufferFill;
1105 size_t skip = 0;
1106 for (size_t c = 0; c < getTargetChannelCount(); ++c) {
1107 RingBuffer<float> *wb = getWriteRingBuffer(c);
1108 if (wb) {
1109 if (c == 0) {
1110
1111 size_t wrs = wb->getReadSpace();
1112 // std::cerr << "wrs = " << wrs << std::endl;
1113
1114 if (wrs < wf) wf -= wrs;
1115 else wf = 0;
1116 // std::cerr << "wf = " << wf << std::endl;
1117
1118 if (wf < rf) skip = rf - wf;
1119 if (skip == 0) break;
1120 }
1121
1122 // std::cerr << "skipping " << skip << std::endl;
1123 wb->skip(skip);
1124 }
1125 }
1126
1127 m_bufferScavenger.claim(m_readBuffers);
1128 m_readBuffers = m_writeBuffers;
1129 m_readBufferFill = m_writeBufferFill;
1130 std::cerr << "unified" << std::endl;
1131 }
1132
1133 void
1044 AudioCallbackPlaySource::AudioCallbackPlaySourceFillThread::run() 1134 AudioCallbackPlaySource::AudioCallbackPlaySourceFillThread::run()
1045 { 1135 {
1046 AudioCallbackPlaySource &s(m_source); 1136 AudioCallbackPlaySource &s(m_source);
1047 1137
1048 #ifdef DEBUG_AUDIO_PLAY_SOURCE 1138 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1054 bool previouslyPlaying = s.m_playing; 1144 bool previouslyPlaying = s.m_playing;
1055 bool work = false; 1145 bool work = false;
1056 1146
1057 while (!s.m_exiting) { 1147 while (!s.m_exiting) {
1058 1148
1059 if (s.m_readBuffers != s.m_writeBuffers) { 1149 s.unifyRingBuffers();
1060 s.m_bufferScavenger.claim(s.m_readBuffers);
1061 s.m_readBuffers = s.m_writeBuffers;
1062 std::cerr << "unified" << std::endl;
1063 }
1064
1065 s.m_bufferScavenger.scavenge(); 1150 s.m_bufferScavenger.scavenge();
1066 s.m_timeStretcherScavenger.scavenge(); 1151 s.m_timeStretcherScavenger.scavenge();
1067 1152
1068 if (work && s.m_playing && s.getSourceSampleRate()) { 1153 if (work && s.m_playing && s.getSourceSampleRate()) {
1069 1154
1098 1183
1099 if (playing && !previouslyPlaying) { 1184 if (playing && !previouslyPlaying) {
1100 #ifdef DEBUG_AUDIO_PLAY_SOURCE 1185 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1101 std::cout << "AudioCallbackPlaySourceFillThread: playback state changed, resetting" << std::endl; 1186 std::cout << "AudioCallbackPlaySourceFillThread: playback state changed, resetting" << std::endl;
1102 #endif 1187 #endif
1103 for (size_t c = 0; c < s.getSourceChannelCount(); ++c) { 1188 for (size_t c = 0; c < s.getTargetChannelCount(); ++c) {
1104 RingBuffer<float> *rb = s.getReadRingBuffer(c); 1189 RingBuffer<float> *rb = s.getReadRingBuffer(c);
1105 if (rb) rb->reset(); 1190 if (rb) rb->reset();
1106 } 1191 }
1107 } 1192 }
1108 previouslyPlaying = playing; 1193 previouslyPlaying = playing;