changeset 130:4c9c04645685

* Reduce time stretcher to one channel when overload occurs
author Chris Cannam
date Mon, 07 Jul 2008 16:49:53 +0000
parents df5f16b3c925
children 883f7fc7fd34
files audioio/AudioCallbackPlaySource.cpp audioio/AudioCallbackPlaySource.h audioio/AudioPortAudioTarget.cpp audioio/AudioPulseAudioTarget.cpp framework/MainWindowBase.cpp framework/MainWindowBase.h
diffstat 6 files changed, 78 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- 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<float> *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();
--- 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;
--- 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;
 }
 
--- 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 */
--- 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();
--- 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);