comparison audioio/AudioCallbackPlaySource.cpp @ 26:d88d117e0c34

* Add mono timestretch toggle button; some more work on getting blocksize etc parameters through to plugins
author Chris Cannam
date Mon, 18 Sep 2006 16:43:17 +0000
parents e74f508db18c
children 37af203dbd15
comparison
equal deleted inserted replaced
25:e74f508db18c 26:d88d117e0c34
586 { 586 {
587 return m_sourceSampleRate; 587 return m_sourceSampleRate;
588 } 588 }
589 589
590 void 590 void
591 AudioCallbackPlaySource::setSlowdownFactor(float factor, bool sharpen) 591 AudioCallbackPlaySource::setTimeStretch(float factor, bool sharpen, bool mono)
592 { 592 {
593 // Avoid locks -- create, assign, mark old one for scavenging 593 // Avoid locks -- create, assign, mark old one for scavenging
594 // later (as a call to getSourceSamples may still be using it) 594 // later (as a call to getSourceSamples may still be using it)
595 595
596 PhaseVocoderTimeStretcher *existingStretcher = m_timeStretcher; 596 PhaseVocoderTimeStretcher *existingStretcher = m_timeStretcher;
597 597
598 size_t channels = getTargetChannelCount();
599 if (mono) channels = 1;
600
598 if (existingStretcher && 601 if (existingStretcher &&
599 existingStretcher->getRatio() == factor && 602 existingStretcher->getRatio() == factor &&
600 existingStretcher->getSharpening() == sharpen) { 603 existingStretcher->getSharpening() == sharpen &&
604 existingStretcher->getChannelCount() == channels) {
601 return; 605 return;
602 } 606 }
603 607
604 if (factor != 1) { 608 if (factor != 1) {
605 609
606 if (existingStretcher && 610 if (existingStretcher &&
607 existingStretcher->getSharpening() == sharpen) { 611 existingStretcher->getSharpening() == sharpen &&
612 existingStretcher->getChannelCount() == channels) {
608 existingStretcher->setRatio(factor); 613 existingStretcher->setRatio(factor);
609 return; 614 return;
610 } 615 }
611 616
612 PhaseVocoderTimeStretcher *newStretcher = new PhaseVocoderTimeStretcher 617 PhaseVocoderTimeStretcher *newStretcher = new PhaseVocoderTimeStretcher
613 (getTargetSampleRate(), 618 (getTargetSampleRate(),
614 getTargetChannelCount(), 619 channels,
615 factor, 620 factor,
616 sharpen, 621 sharpen,
617 lrintf(getTargetBlockSize() / factor)); 622 lrintf(getTargetBlockSize() / factor));
623
618 m_timeStretcher = newStretcher; 624 m_timeStretcher = newStretcher;
625
619 } else { 626 } else {
620 m_timeStretcher = 0; 627 m_timeStretcher = 0;
621 } 628 }
622 629
623 if (existingStretcher) { 630 if (existingStretcher) {
624 m_timeStretcherScavenger.claim(existingStretcher); 631 m_timeStretcherScavenger.claim(existingStretcher);
625 } 632 }
626 } 633 }
627 634
628 size_t 635 size_t
629 AudioCallbackPlaySource::getSourceSamples(size_t count, float **buffer) 636 AudioCallbackPlaySource::getSourceSamples(size_t count, float **buffer)
630 { 637 {
631 if (!m_playing) { 638 if (!m_playing) {
632 for (size_t ch = 0; ch < getTargetChannelCount(); ++ch) { 639 for (size_t ch = 0; ch < getTargetChannelCount(); ++ch) {
674 681
675 float ratio = ts->getRatio(); 682 float ratio = ts->getRatio();
676 683
677 // std::cout << "ratio = " << ratio << std::endl; 684 // std::cout << "ratio = " << ratio << std::endl;
678 685
686 size_t channels = getTargetChannelCount();
687 bool mix = (channels > 1 && ts->getChannelCount() == 1);
688
679 size_t available; 689 size_t available;
680 690
681 while ((available = ts->getAvailableOutputSamples()) < count) { 691 while ((available = ts->getAvailableOutputSamples()) < count) {
682 692
683 size_t reqd = lrintf((count - available) / ratio); 693 size_t reqd = lrintf((count - available) / ratio);
684 reqd = std::max(reqd, ts->getRequiredInputSamples()); 694 reqd = std::max(reqd, ts->getRequiredInputSamples());
685 if (reqd == 0) reqd = 1; 695 if (reqd == 0) reqd = 1;
686 696
687 size_t channels = getTargetChannelCount();
688
689 float *ib[channels]; 697 float *ib[channels];
690 698
691 size_t got = reqd; 699 size_t got = reqd;
692 700
693 for (size_t c = 0; c < channels; ++c) { 701 if (mix) {
694 ib[c] = new float[reqd]; //!!! fix -- this is a rt function 702 for (size_t c = 0; c < channels; ++c) {
695 RingBuffer<float> *rb = getReadRingBuffer(c); 703 if (c == 0) ib[c] = new float[reqd]; //!!! fix -- this is a rt function
696 if (rb) { 704 else ib[c] = 0;
697 size_t gotHere = rb->read(ib[c], got); 705 RingBuffer<float> *rb = getReadRingBuffer(c);
698 if (gotHere < got) got = gotHere; 706 if (rb) {
707 size_t gotHere;
708 if (c > 0) gotHere = rb->readAdding(ib[0], got);
709 else gotHere = rb->read(ib[0], got);
710 if (gotHere < got) got = gotHere;
711 }
712 }
713 } else {
714 for (size_t c = 0; c < channels; ++c) {
715 ib[c] = new float[reqd]; //!!! fix -- this is a rt function
716 RingBuffer<float> *rb = getReadRingBuffer(c);
717 if (rb) {
718 size_t gotHere = rb->read(ib[c], got);
719 if (gotHere < got) got = gotHere;
720 }
699 } 721 }
700 } 722 }
701 723
702 if (got < reqd) { 724 if (got < reqd) {
703 std::cerr << "WARNING: Read underrun in playback (" 725 std::cerr << "WARNING: Read underrun in playback ("
717 break; 739 break;
718 } 740 }
719 } 741 }
720 742
721 ts->getOutput(buffer, count); 743 ts->getOutput(buffer, count);
744
745 if (mix) {
746 for (size_t c = 1; c < channels; ++c) {
747 for (size_t i = 0; i < count; ++i) {
748 buffer[c][i] = buffer[0][i] / channels;
749 }
750 }
751 for (size_t i = 0; i < count; ++i) {
752 buffer[0][i] /= channels;
753 }
754 }
722 755
723 m_condition.wakeAll(); 756 m_condition.wakeAll();
724 757
725 return count; 758 return count;
726 } 759 }