comparison audioio/AudioCallbackPlaySource.cpp @ 12:ee967635c728

* Some work on making the time stretcher squash as well as stretch
author Chris Cannam
date Tue, 12 Sep 2006 16:43:00 +0000
parents 40116f709d3b
children 00ed645f4175
comparison
equal deleted inserted replaced
11:0dbd08e365ce 12:ee967635c728
26 26
27 #include <iostream> 27 #include <iostream>
28 #include <cassert> 28 #include <cassert>
29 29
30 //#define DEBUG_AUDIO_PLAY_SOURCE 1 30 //#define DEBUG_AUDIO_PLAY_SOURCE 1
31 //#define DEBUG_AUDIO_PLAY_SOURCE_PLAYING 1 31 #define DEBUG_AUDIO_PLAY_SOURCE_PLAYING 1
32 32
33 //const size_t AudioCallbackPlaySource::m_ringBufferSize = 102400; 33 //const size_t AudioCallbackPlaySource::m_ringBufferSize = 102400;
34 const size_t AudioCallbackPlaySource::m_ringBufferSize = 131071; 34 const size_t AudioCallbackPlaySource::m_ringBufferSize = 131071;
35 35
36 AudioCallbackPlaySource::AudioCallbackPlaySource(ViewManager *manager) : 36 AudioCallbackPlaySource::AudioCallbackPlaySource(ViewManager *manager) :
587 { 587 {
588 return m_sourceSampleRate; 588 return m_sourceSampleRate;
589 } 589 }
590 590
591 AudioCallbackPlaySource::TimeStretcherData::TimeStretcherData(size_t channels, 591 AudioCallbackPlaySource::TimeStretcherData::TimeStretcherData(size_t channels,
592 size_t factor, 592 float factor,
593 size_t blockSize) : 593 size_t blockSize) :
594 m_factor(factor), 594 m_factor(factor),
595 m_blockSize(blockSize) 595 m_blockSize(blockSize)
596 { 596 {
597 // std::cerr << "TimeStretcherData::TimeStretcherData(" << channels << ", " << factor << ", " << blockSize << ")" << std::endl; 597 // std::cerr << "TimeStretcherData::TimeStretcherData(" << channels << ", " << factor << ", " << blockSize << ")" << std::endl;
599 for (size_t ch = 0; ch < channels; ++ch) { 599 for (size_t ch = 0; ch < channels; ++ch) {
600 m_stretcher[ch] = StretcherBuffer 600 m_stretcher[ch] = StretcherBuffer
601 //!!! We really need to measure performance and work out 601 //!!! We really need to measure performance and work out
602 //what sort of quality level to use -- or at least to 602 //what sort of quality level to use -- or at least to
603 //allow the user to configure it 603 //allow the user to configure it
604 (new IntegerTimeStretcher(factor, blockSize, 128), 604 (new IntegerTimeStretcher(factor, blockSize, 1024),
605 new float[blockSize * factor]); 605 new float[lrintf(blockSize * factor)]);
606 } 606 }
607 m_stretchInputBuffer = new float[blockSize]; 607 m_stretchInputBuffer = new float[blockSize];
608 } 608 }
609 609
610 AudioCallbackPlaySource::TimeStretcherData::~TimeStretcherData() 610 AudioCallbackPlaySource::TimeStretcherData::~TimeStretcherData()
644 getOutputBuffer(channel), 644 getOutputBuffer(channel),
645 m_blockSize); 645 m_blockSize);
646 } 646 }
647 647
648 void 648 void
649 AudioCallbackPlaySource::setSlowdownFactor(size_t factor) 649 AudioCallbackPlaySource::setSlowdownFactor(float factor)
650 { 650 {
651 // Avoid locks -- create, assign, mark old one for scavenging 651 // Avoid locks -- create, assign, mark old one for scavenging
652 // later (as a call to getSourceSamples may still be using it) 652 // later (as a call to getSourceSamples may still be using it)
653 653
654 TimeStretcherData *existingStretcher = m_timeStretcher; 654 TimeStretcherData *existingStretcher = m_timeStretcher;
655 655
656 if (existingStretcher && existingStretcher->getFactor() == factor) { 656 if (existingStretcher && existingStretcher->getFactor() == factor) {
657 return; 657 return;
658 } 658 }
659 659
660 if (factor > 1) { 660 if (factor != 1) {
661 TimeStretcherData *newStretcher = new TimeStretcherData 661 TimeStretcherData *newStretcher = new TimeStretcherData
662 (getTargetChannelCount(), factor, getTargetBlockSize()); 662 (getTargetChannelCount(), factor,
663 factor > 1 ? getTargetBlockSize() : getTargetBlockSize() / factor);
663 m_slowdownCounter = 0; 664 m_slowdownCounter = 0;
664 m_timeStretcher = newStretcher; 665 m_timeStretcher = newStretcher;
665 } else { 666 } else {
666 m_timeStretcher = 0; 667 m_timeStretcher = 0;
667 } 668 }
716 717
717 m_condition.wakeAll(); 718 m_condition.wakeAll();
718 return got; 719 return got;
719 } 720 }
720 721
722 /*!!!
721 if (m_slowdownCounter == 0) { 723 if (m_slowdownCounter == 0) {
722 724
723 size_t got = 0; 725 size_t got = 0;
724 float *ib = timeStretcher->getInputBuffer(); 726 float *ib = timeStretcher->getInputBuffer();
725 727
731 733
732 size_t request = count; 734 size_t request = count;
733 if (ch > 0) request = got; // see above 735 if (ch > 0) request = got; // see above
734 got = rb->read(buffer[ch], request); 736 got = rb->read(buffer[ch], request);
735 737
736 #ifdef DEBUG_AUDIO_PLAY_SOURCE 738 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
737 std::cout << "AudioCallbackPlaySource::getSamples: got " << got << " samples on channel " << ch << ", running time stretcher" << std::endl; 739 std::cout << "AudioCallbackPlaySource::getSamples: got " << got << " samples on channel " << ch << ", running time stretcher" << std::endl;
738 #endif 740 #endif
739 741
740 for (size_t i = 0; i < count; ++i) { 742 for (size_t i = 0; i < count; ++i) {
741 ib[i] = buffer[ch][i]; 743 ib[i] = buffer[ch][i];
753 755
754 for (size_t ch = 0; ch < getTargetChannelCount(); ++ch) { 756 for (size_t ch = 0; ch < getTargetChannelCount(); ++ch) {
755 757
756 float *ob = timeStretcher->getOutputBuffer(ch); 758 float *ob = timeStretcher->getOutputBuffer(ch);
757 759
758 #ifdef DEBUG_AUDIO_PLAY_SOURCE 760 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
759 std::cerr << "AudioCallbackPlaySource::getSamples: Copying from (" << (m_slowdownCounter * count) << "," << count << ") to buffer" << std::endl; 761 std::cerr << "AudioCallbackPlaySource::getSamples: Copying from (" << (m_slowdownCounter * count) << "," << count << ") to buffer" << std::endl;
760 #endif 762 #endif
761 763
762 for (size_t i = 0; i < count; ++i) { 764 for (size_t i = 0; i < count; ++i) {
763 buffer[ch][i] = ob[m_slowdownCounter * count + i]; 765 buffer[ch][i] = ob[m_slowdownCounter * count + i];
764 } 766 }
765 } 767 }
768 */
769
770 for (size_t ch = 0; ch < getTargetChannelCount(); ++ch) {
771
772 RingBuffer<float> *rb = getReadRingBuffer(ch);
773
774 if (rb) {
775
776 float ratio = timeStretcher->getStretcher(ch)->getRatio();
777 size_t request = lrintf(count / ratio);
778 // if (ch > 0) request = got; // see above
779
780 float *ib = new float[request]; //!!!
781
782 size_t got = rb->read(ib, request);
783
784 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
785 std::cout << "AudioCallbackPlaySource::getSamples: got " << got << " samples on channel " << ch << " (count=" << count << ", ratio=" << timeStretcher->getStretcher(ch)->getRatio() << ", got*ratio=" << got * ratio << "), running time stretcher" << std::endl;
786 #endif
787
788 timeStretcher->getStretcher(ch)->process(ib, buffer[ch], request);
789
790 delete[] ib;
791
792 // for (size_t i = 0; i < count; ++i) {
793 // ib[i] = buffer[ch][i];
794 // }
795
796 // timeStretcher->run(ch);
797
798
799
800 }
801 }
802
803
766 804
767 //!!! if (m_slowdownCounter == 0) m_condition.wakeAll(); 805 //!!! if (m_slowdownCounter == 0) m_condition.wakeAll();
768 m_slowdownCounter = (m_slowdownCounter + 1) % timeStretcher->getFactor(); 806 // m_slowdownCounter = (m_slowdownCounter + 1) % timeStretcher->getFactor();
769 return count; 807 return count;
770 } 808 }
771 809
772 // Called from fill thread, m_playing true, mutex held 810 // Called from fill thread, m_playing true, mutex held
773 bool 811 bool