From 7cf8ce36dcb16444162415815b6295946dec1186 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rafa=C3=ABl=20Carr=C3=A9?=
 <rafael.carre@savoirfairelinux.com>
Date: Wed, 10 Aug 2011 16:15:19 -0400
Subject: [PATCH] resampler: grow internal buffers dynamically

also fix wrong assertion about the final number of samples
---
 sflphone-common/src/audio/alsa/alsalayer.cpp  |  2 +-
 .../audio/audiortp/AudioRtpRecordHandler.cpp  |  2 +-
 .../src/audio/pulseaudio/pulselayer.cpp       |  2 +-
 .../src/audio/samplerateconverter.cpp         | 34 +++++++++++--------
 .../src/audio/samplerateconverter.h           |  5 ++-
 sflphone-common/src/audio/sound/audiofile.cpp |  2 +-
 sflphone-common/src/iax/iaxvoiplink.cpp       |  2 +-
 7 files changed, 29 insertions(+), 20 deletions(-)

diff --git a/sflphone-common/src/audio/alsa/alsalayer.cpp b/sflphone-common/src/audio/alsa/alsalayer.cpp
index 9291dc1f27..a05eef1778 100644
--- a/sflphone-common/src/audio/alsa/alsalayer.cpp
+++ b/sflphone-common/src/audio/alsa/alsalayer.cpp
@@ -129,7 +129,7 @@ AlsaLayer::openDevice (int indexIn, int indexOut, int indexRing, int sampleRate,
     _audioThread = NULL;
 
     // use 1 sec buffer for resampling
-    _converter = new SamplerateConverter (_audioSampleRate, 1000);
+    _converter = new SamplerateConverter (_audioSampleRate);
 
     AudioLayer::_dcblocker = new DcBlocker();
     AudioLayer::_audiofilter = new AudioProcessing (static_cast<Algorithm *> (_dcblocker));
diff --git a/sflphone-common/src/audio/audiortp/AudioRtpRecordHandler.cpp b/sflphone-common/src/audio/audiortp/AudioRtpRecordHandler.cpp
index e4c741de1b..cc94eccff0 100644
--- a/sflphone-common/src/audio/audiortp/AudioRtpRecordHandler.cpp
+++ b/sflphone-common/src/audio/audiortp/AudioRtpRecordHandler.cpp
@@ -190,7 +190,7 @@ void AudioRtpRecordHandler::initBuffers()
     // (internal buffers initialized with maximal sampling rate and frame size)
     int rate = getCodecSampleRate();
     int fs = getCodecFrameSize();
-    _audioRtpRecord._converter = new SamplerateConverter (rate, fs);
+    _audioRtpRecord._converter = new SamplerateConverter (rate);
 
     int nbSamplesMax = (int) ( (getCodecSampleRate() * getCodecFrameSize() / 1000));
     _audioRtpRecord._micData = new SFLDataFormat[nbSamplesMax];
diff --git a/sflphone-common/src/audio/pulseaudio/pulselayer.cpp b/sflphone-common/src/audio/pulseaudio/pulselayer.cpp
index e7f0811976..9cd8269f3c 100644
--- a/sflphone-common/src/audio/pulseaudio/pulselayer.cpp
+++ b/sflphone-common/src/audio/pulseaudio/pulselayer.cpp
@@ -403,7 +403,7 @@ void PulseLayer::openDevice (int indexIn UNUSED, int indexOut UNUSED, int indexR
     flushUrgent();
 
     // use 1 sec buffer for resampling
-    _converter = new SamplerateConverter (_audioSampleRate, 1000);
+    _converter = new SamplerateConverter (_audioSampleRate);
 
     // Instantiate the algorithm
     AudioLayer::_dcblocker = new DcBlocker();
diff --git a/sflphone-common/src/audio/samplerateconverter.cpp b/sflphone-common/src/audio/samplerateconverter.cpp
index 2ea2e275c9..411c20389c 100644
--- a/sflphone-common/src/audio/samplerateconverter.cpp
+++ b/sflphone-common/src/audio/samplerateconverter.cpp
@@ -30,16 +30,17 @@
 
 #include "samplerateconverter.h"
 #include "manager.h"
+#include <cassert>
 
-SamplerateConverter::SamplerateConverter (int freq , int fs)
+SamplerateConverter::SamplerateConverter (int freq) : _maxFreq(freq)
 {
     int err;
     _src_state = src_new (SRC_LINEAR, 1, &err);
 
-    int nbSamplesMax = (int) ( (freq * fs) / 1000);
+    _samples = (freq * 20) / 1000; // start with 20 ms buffers
 
-    _floatBufferIn = new float32[nbSamplesMax];
-    _floatBufferOut = new float32[nbSamplesMax];
+    _floatBufferIn = new float32[_samples];
+    _floatBufferOut = new float32[_samples];
 }
 
 SamplerateConverter::~SamplerateConverter (void)
@@ -61,29 +62,34 @@ SamplerateConverter::Short2FloatArray (const short *in, float *out, int len)
 }
 
 //TODO Add ifdef for int16 or float32 type
-void SamplerateConverter::resample (SFLDataFormat* dataIn , SFLDataFormat* dataOut , int samplerate1 , int samplerate2 , int nbSamples)
+void SamplerateConverter::resample (SFLDataFormat* dataIn , SFLDataFormat* dataOut , int inputFreq , int outputFreq , int nbSamples)
 {
-    double sampleFactor;
-    if (samplerate1 > samplerate2)
-		sampleFactor = (double) samplerate1 / samplerate2;
-    else
-		sampleFactor = (double) samplerate2 / samplerate1;
+	assert(outputFreq <= _maxFreq);
 
+    double sampleFactor = (double) inputFreq / outputFreq;
     if (sampleFactor == 1)
 		return;
 
+    int outSamples = nbSamples * sampleFactor;
+    if (outSamples > _samples) {
+    	/* grow buffer if needed */
+    	_samples = outSamples;
+    	delete [] _floatBufferIn;
+    	delete [] _floatBufferOut;
+        _floatBufferIn = new float32[_samples];
+        _floatBufferOut = new float32[_samples];
+    }
+
 	SRC_DATA src_data;
 	src_data.data_in = _floatBufferIn;
 	src_data.data_out = _floatBufferOut;
 	src_data.input_frames = nbSamples;
-	src_data.output_frames = nbSamples;
+	src_data.output_frames = outSamples;
 	src_data.src_ratio = sampleFactor;
 	src_data.end_of_input = 0; // More data will come
 
 	Short2FloatArray (dataIn , _floatBufferIn, nbSamples);
 	src_process (_src_state, &src_data);
 
-	assert(nbSamples == src_data.output_frames_gen);
-
-	src_float_to_short_array (_floatBufferOut, dataOut , nbSamples);
+	src_float_to_short_array (_floatBufferOut, dataOut , outSamples);
 }
diff --git a/sflphone-common/src/audio/samplerateconverter.h b/sflphone-common/src/audio/samplerateconverter.h
index 18f095d735..6d17b8d671 100644
--- a/sflphone-common/src/audio/samplerateconverter.h
+++ b/sflphone-common/src/audio/samplerateconverter.h
@@ -47,7 +47,7 @@ class SamplerateConverter
         * internal buffer size. Converter must be reinitialized
         * every time these parameters change
         */
-        SamplerateConverter (int freq, int frameSize);
+        SamplerateConverter (int freq);
 
         /** Destructor */
         ~SamplerateConverter (void);
@@ -77,8 +77,11 @@ class SamplerateConverter
         // Assignment Operator
         SamplerateConverter& operator= (const SamplerateConverter& rh);
 
+        /* temporary buffers */
         float32* _floatBufferIn;
         float32* _floatBufferOut;
+        size_t _samples; // size in samples of temporary buffers
+        int _maxFreq; // maximal output frequency
 
         SRC_STATE* _src_state;
 };
diff --git a/sflphone-common/src/audio/sound/audiofile.cpp b/sflphone-common/src/audio/sound/audiofile.cpp
index 69761cdab7..b10382945d 100644
--- a/sflphone-common/src/audio/sound/audiofile.cpp
+++ b/sflphone-common/src/audio/sound/audiofile.cpp
@@ -212,7 +212,7 @@ WaveFile::WaveFile (const std::string& fileName, unsigned int audioSamplingRate)
 
     // Sample rate converter initialized with 88200 sample long
     int converterSamples  = (srate > audioSamplingRate) ? srate : audioSamplingRate;
-    SamplerateConverter _converter (converterSamples, 2000);
+    SamplerateConverter _converter (converterSamples);
 
     // Get length of data from the header.
     SINT32 bytes;
diff --git a/sflphone-common/src/iax/iaxvoiplink.cpp b/sflphone-common/src/iax/iaxvoiplink.cpp
index e6f6212ce6..ba70c8628e 100644
--- a/sflphone-common/src/iax/iaxvoiplink.cpp
+++ b/sflphone-common/src/iax/iaxvoiplink.cpp
@@ -77,7 +77,7 @@ IAXVoIPLink::IAXVoIPLink (const std::string& accountID) : VoIPLink ()
     // to get random number for RANDOM_PORT
     srand (time (NULL));
 
-    converter = new SamplerateConverter (44100, 20);
+    converter = new SamplerateConverter (44100);
 
     // int nbSamplesMax = (int) (converter->getFrequence() * converter->getFramesize() / 1000);
     int nbSamplesMax = (44100 * 20) / 1000;
-- 
GitLab