Mercurial > hg > sonic-visualiser
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 |