# HG changeset patch # User Chris Cannam # Date 1215449393 0 # Node ID 4c9c0464568541db786bdddfcf2afec614476548 # Parent df5f16b3c9252c8fe4d9dffa2428997da033ee0c * Reduce time stretcher to one channel when overload occurs diff -r df5f16b3c925 -r 4c9c04645685 audioio/AudioCallbackPlaySource.cpp --- a/audioio/AudioCallbackPlaySource.cpp Thu Jun 26 12:41:23 2008 +0000 +++ b/audioio/AudioCallbackPlaySource.cpp Mon Jul 07 16:49:53 2008 +0000 @@ -69,6 +69,7 @@ m_playStartFrame(0), m_playStartFramePassed(false), m_timeStretcher(0), + m_monoStretcher(0), m_stretchRatio(1.0), m_stretcherInputCount(0), m_stretcherInputs(0), @@ -122,6 +123,9 @@ delete[] m_stretcherInputSizes; delete[] m_stretcherInputs; + delete m_timeStretcher; + delete m_monoStretcher; + m_bufferScavenger.scavenge(true); m_pluginScavenger.scavenge(true); } @@ -388,6 +392,9 @@ if (m_timeStretcher) { m_timeStretcher->reset(); } + if (m_monoStretcher) { + m_monoStretcher->reset(); + } m_readBufferFill = m_writeBufferFill = startFrame; if (m_readBuffers) { @@ -469,10 +476,24 @@ void AudioCallbackPlaySource::audioProcessingOverload() { + std::cerr << "Audio processing overload!" << std::endl; + + if (!m_playing) return; + RealTimePluginInstance *ap = m_auditioningPlugin; - if (ap && m_playing && !m_auditioningPluginBypassed) { + if (ap && !m_auditioningPluginBypassed) { m_auditioningPluginBypassed = true; emit audioOverloadPluginDisabled(); + return; + } + + if (m_timeStretcher && + m_timeStretcher->getTimeRatio() < 1.0 && + m_stretcherInputCount > 1 && + m_monoStretcher && !m_stretchMono) { + m_stretchMono = true; + emit audioTimeStretchMultiChannelDisabled(); + return; } } @@ -956,23 +977,31 @@ m_stretcherInputCount, RubberBandStretcher::OptionProcessRealTime, factor); + RubberBandStretcher *monoStretcher = new RubberBandStretcher + (getTargetSampleRate(), + 1, + RubberBandStretcher::OptionProcessRealTime, + factor); m_stretcherInputs = new float *[m_stretcherInputCount]; m_stretcherInputSizes = new size_t[m_stretcherInputCount]; for (size_t c = 0; c < m_stretcherInputCount; ++c) { m_stretcherInputSizes[c] = 16384; m_stretcherInputs[c] = new float[m_stretcherInputSizes[c]]; } + m_monoStretcher = monoStretcher; m_timeStretcher = stretcher; return; } } size_t -AudioCallbackPlaySource::getSourceSamples(size_t count, float **buffer) +AudioCallbackPlaySource::getSourceSamples(size_t ucount, float **buffer) { + int count = ucount; + if (!m_playing) { for (size_t ch = 0; ch < getTargetChannelCount(); ++ch) { - for (size_t i = 0; i < count; ++i) { + for (int i = 0; i < count; ++i) { buffer[ch][i] = 0.0; } } @@ -1009,6 +1038,8 @@ if (count == 0) return 0; RubberBandStretcher *ts = m_timeStretcher; + RubberBandStretcher *ms = m_monoStretcher; + float ratio = ts ? ts->getTimeRatio() : 1.f; if (ratio != m_stretchRatio) { @@ -1017,6 +1048,18 @@ m_stretchRatio = 1.f; } else { ts->setTimeRatio(m_stretchRatio); + if (ms) ms->setTimeRatio(m_stretchRatio); + if (m_stretchRatio >= 1.0) m_stretchMono = false; + } + } + + int stretchChannels = m_stretcherInputCount; + if (m_stretchMono) { + if (ms) { + ts = ms; + stretchChannels = 1; + } else { + m_stretchMono = false; } } @@ -1027,7 +1070,7 @@ if (!ts || ratio == 1.f) { - size_t got = 0; + int got = 0; for (size_t ch = 0; ch < getTargetChannelCount(); ++ch) { @@ -1048,7 +1091,7 @@ } for (size_t ch = 0; ch < getTargetChannelCount(); ++ch) { - for (size_t i = got; i < count; ++i) { + for (int i = got; i < count; ++i) { buffer[ch][i] = 0.0; } } @@ -1082,7 +1125,7 @@ #endif for (size_t c = 0; c < channels; ++c) { - if (c >= m_stretcherInputCount) continue; + if (c >= m_stretcherInputSizes) continue; if (reqd > m_stretcherInputSizes[c]) { if (c == 0) { std::cerr << "WARNING: resizing stretcher input buffer from " << m_stretcherInputSizes[c] << " to " << (reqd * 2) << std::endl; @@ -1094,10 +1137,15 @@ } for (size_t c = 0; c < channels; ++c) { - if (c >= m_stretcherInputCount) continue; + if (c >= m_stretcherInputSizes) continue; RingBuffer *rb = getReadRingBuffer(c); if (rb) { - size_t gotHere = rb->read(m_stretcherInputs[c], got); + size_t gotHere; + if (stretchChannels == 1 && c > 0) { + gotHere = rb->readAdding(m_stretcherInputs[0], got); + } else { + gotHere = rb->read(m_stretcherInputs[c], got); + } if (gotHere < got) got = gotHere; #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING @@ -1131,6 +1179,12 @@ ts->retrieve(buffer, count); + for (int c = stretchChannels; c < getTargetChannelCount(); ++c) { + for (int i = 0; i < count; ++i) { + buffer[c][i] = buffer[0][i]; + } + } + applyAuditioningEffect(count, buffer); m_condition.wakeAll(); diff -r df5f16b3c925 -r 4c9c04645685 audioio/AudioCallbackPlaySource.h --- a/audioio/AudioCallbackPlaySource.h Thu Jun 26 12:41:23 2008 +0000 +++ b/audioio/AudioCallbackPlaySource.h Mon Jul 07 16:49:53 2008 +0000 @@ -247,6 +247,7 @@ void sampleRateMismatch(size_t requested, size_t available, bool willResample); void audioOverloadPluginDisabled(); + void audioTimeStretchMultiChannelDisabled(); public slots: void audioProcessingOverload(); @@ -324,7 +325,9 @@ void unifyRingBuffers(); RubberBand::RubberBandStretcher *m_timeStretcher; + RubberBand::RubberBandStretcher *m_monoStretcher; float m_stretchRatio; + bool m_stretchMono; size_t m_stretcherInputCount; float **m_stretcherInputs; diff -r df5f16b3c925 -r 4c9c04645685 audioio/AudioPortAudioTarget.cpp --- a/audioio/AudioPortAudioTarget.cpp Thu Jun 26 12:41:23 2008 +0000 +++ b/audioio/AudioPortAudioTarget.cpp Mon Jul 07 16:49:53 2008 +0000 @@ -262,6 +262,10 @@ m_source->setOutputLevels(peakLeft, peakRight); + if (Pa_GetStreamCpuLoad(m_stream) > 0.7) { + if (m_source) m_source->audioProcessingOverload(); + } + return 0; } diff -r df5f16b3c925 -r 4c9c04645685 audioio/AudioPulseAudioTarget.cpp --- a/audioio/AudioPulseAudioTarget.cpp Thu Jun 26 12:41:23 2008 +0000 +++ b/audioio/AudioPulseAudioTarget.cpp Mon Jul 07 16:49:53 2008 +0000 @@ -412,9 +412,13 @@ } void -AudioPulseAudioTarget::streamUnderflowStatic(pa_stream *, void *) +AudioPulseAudioTarget::streamUnderflowStatic(pa_stream *, void *data) { std::cerr << "AudioPulseAudioTarget::streamUnderflowStatic: Underflow!" << std::endl; + AudioPulseAudioTarget *target = (AudioPulseAudioTarget *)data; + if (target && target->m_source) { + target->m_source->audioProcessingOverload(); + } } #endif /* HAVE_PULSEAUDIO */ diff -r df5f16b3c925 -r 4c9c04645685 framework/MainWindowBase.cpp --- a/framework/MainWindowBase.cpp Thu Jun 26 12:41:23 2008 +0000 +++ b/framework/MainWindowBase.cpp Mon Jul 07 16:49:53 2008 +0000 @@ -177,6 +177,8 @@ this, SLOT(sampleRateMismatch(size_t, size_t, bool))); connect(m_playSource, SIGNAL(audioOverloadPluginDisabled()), this, SLOT(audioOverloadPluginDisabled())); + connect(m_playSource, SIGNAL(audioTimeStretchMultiChannelDisabled()), + this, SLOT(audioTimeStretchMultiChannelDisabled())); connect(m_viewManager, SIGNAL(outputLevelsChanged(float, float)), this, SLOT(outputLevelsChanged(float, float))); @@ -2138,7 +2140,7 @@ void MainWindowBase::viewCentreFrameChanged(View *v, unsigned long frame) { - std::cerr << "MainWindowBase::viewCentreFrameChanged(" << v << "," << frame << ")" << std::endl; +// std::cerr << "MainWindowBase::viewCentreFrameChanged(" << v << "," << frame << ")" << std::endl; if (m_viewDataDialogMap.find(v) != m_viewDataDialogMap.end()) { for (DataDialogSet::iterator i = m_viewDataDialogMap[v].begin(); diff -r df5f16b3c925 -r 4c9c04645685 framework/MainWindowBase.h --- a/framework/MainWindowBase.h Thu Jun 26 12:41:23 2008 +0000 +++ b/framework/MainWindowBase.h Mon Jul 07 16:49:53 2008 +0000 @@ -185,6 +185,7 @@ virtual void sampleRateMismatch(size_t, size_t, bool) = 0; virtual void audioOverloadPluginDisabled() = 0; + virtual void audioTimeStretchMultiChannelDisabled() = 0; virtual void playbackFrameChanged(unsigned long); virtual void globalCentreFrameChanged(unsigned long);