From 1e9dc55b062a425f9f39b4cfa941d714dc9ad3f5 Mon Sep 17 00:00:00 2001
From: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com>
Date: Mon, 9 Jun 2008 15:52:31 -0400
Subject: [PATCH] Handle the sample rate conversion in one place

Instead of two!!
---
 src/Makefile.am             |  4 +-
 src/audio/audiortp.cpp      | 14 ++++--
 src/audio/audiortp.h        |  4 ++
 src/samplerateconverter.cpp | 89 +++++++++++++++++++++++++++++++++++++
 src/samplerateconverter.h   | 72 ++++++++++++++++++++++++++++++
 5 files changed, 177 insertions(+), 6 deletions(-)
 create mode 100644 src/samplerateconverter.cpp
 create mode 100644 src/samplerateconverter.h

diff --git a/src/Makefile.am b/src/Makefile.am
index 1d5ed8fdaf..bbba0d99aa 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -33,7 +33,7 @@ ALSAFLAG= -lasound
 SUBDIRS = audio config dbus $(ZEROCONFDIR) #contact memmanager video mixer
 
 sflphoned_SOURCES = eventthread.cpp 	main.cpp 	voiplink.cpp \
-		managerimpl.cpp	observer.cpp \
+		managerimpl.cpp	observer.cpp  samplerateconverter.cpp \
 		account.cpp sipaccount.cpp accountcreator.cpp \
                 sipvoiplink.cpp call.cpp sipcall.cpp \
 		$(IAXSOURCES)
@@ -60,7 +60,7 @@ libsflphone_la_SOURCES =
 
 noinst_LTLIBRARIES = libsflphone.la
 noinst_HEADERS = managerimpl.h manager.h global.h observer.h eventthread.h user_cfg.h \
-                 voiplink.h \
+                 voiplink.h  samplerateconverter.h \
 		 account.h sipaccount.h accountcreator.h \
                  sipvoiplink.h  call.h  sipcall.h \
 		 $(IAXHEADERS)
diff --git a/src/audio/audiortp.cpp b/src/audio/audiortp.cpp
index e98458bdc3..d4fd9f04ed 100644
--- a/src/audio/audiortp.cpp
+++ b/src/audio/audiortp.cpp
@@ -164,6 +164,8 @@ AudioRtpRTX::~AudioRtpRTX () {
   void
 AudioRtpRTX::initBuffers()
 {
+  converter = new SamplerateConverter();
+
   int nbSamplesMax = (int) (_layerSampleRate * _layerFrameSize /1000);
   _dataAudioLayer = new SFLDataFormat[nbSamplesMax];
   _receiveDataDecoded = new int16[nbSamplesMax];
@@ -404,10 +406,14 @@ AudioRtpRTX::receiveSessionForSpkr (int& countTime)
   int 
 AudioRtpRTX::reSampleData(int sampleRate_codec, int nbSamples, int status)
 {
-  if(status==UP_SAMPLING)
-    return upSampleData(sampleRate_codec, nbSamples);
-  else if(status==DOWN_SAMPLING)
-    return downSampleData(sampleRate_codec, nbSamples);
+  if(status==UP_SAMPLING){
+    //return upSampleData(sampleRate_codec, nbSamples);
+    return converter->upsampleData( _receiveDataDecoded , _dataAudioLayer, sampleRate_codec , _layerSampleRate , nbSamples );
+  }
+  else if(status==DOWN_SAMPLING){
+    //return downSampleData(sampleRate_codec, nbSamples);
+    return converter->downsampleData( _dataAudioLayer , _intBufferDown, sampleRate_codec , _layerSampleRate , nbSamples );
+  }
   else
     return 0;
 }
diff --git a/src/audio/audiortp.h b/src/audio/audiortp.h
index 0b735ac890..6e61f6054a 100644
--- a/src/audio/audiortp.h
+++ b/src/audio/audiortp.h
@@ -29,7 +29,9 @@
 #include <cc++/numbers.h>
 
 #include <samplerate.h>
+
 #include "../global.h"
+#include "../samplerateconverter.h"
 
 #define UP_SAMPLING 0
 #define DOWN_SAMPLING 1
@@ -111,6 +113,8 @@ class AudioRtpRTX : public ost::Thread, public ost::TimerPort {
     /** libsamplerate error */
     int _src_err;
 
+    SamplerateConverter* converter;
+
     /** Variables to process audio stream: sample rate for playing sound (typically 44100HZ) */
     int _layerSampleRate;  
 
diff --git a/src/samplerateconverter.cpp b/src/samplerateconverter.cpp
new file mode 100644
index 0000000000..e9285a3d27
--- /dev/null
+++ b/src/samplerateconverter.cpp
@@ -0,0 +1,89 @@
+/*
+ *  Copyright (C) 2008 Savoir-Faire Linux inc.
+ *  Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com>
+ * 
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ * 
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "samplerateconverter.h"
+
+SamplerateConverter::SamplerateConverter( void ) {
+  
+  // libSamplerateConverter-related
+  // Set the converter type for the upsampling and the downsampling
+  // interpolator SRC_SINC_BEST_QUALITY
+  _src_state_mic  = src_new(SRC_SINC_BEST_QUALITY, 1, &_src_err);
+  _src_state_spkr = src_new(SRC_SINC_BEST_QUALITY, 1, &_src_err);
+
+  int nbSamplesMax = (int) ( 44100 * 20 /1000); // TODO Make this generic
+  _floatBufferDown  = new float32[nbSamplesMax];
+  _floatBufferUp = new float32[nbSamplesMax];
+
+}
+
+SamplerateConverter::~SamplerateConverter( void ) {
+
+  delete [] _floatBufferUp; _floatBufferUp = NULL;
+  delete [] _floatBufferDown; _floatBufferDown = NULL;
+
+  // libSamplerateConverter-related
+  _src_state_mic  = src_delete(_src_state_mic);
+  _src_state_spkr = src_delete(_src_state_spkr);
+}
+
+int SamplerateConverter::upsampleData(  SFLDataFormat* dataIn , SFLDataFormat* dataOut, int samplerate1 , int samplerate2 , int nbSamples ){
+  
+  double upsampleFactor = (double)samplerate2 / samplerate1 ;
+  int nbSamplesMax = (int) (samplerate2 * 20 /1000);  // TODO get the value from the constructor
+  if( upsampleFactor != 1 )
+  {
+    _debug("Begin upsample data\n");
+    SRC_DATA src_data;
+    src_data.data_in = _floatBufferDown;
+    src_data.data_out = _floatBufferUp;
+    src_data.input_frames = nbSamples;
+    src_data.output_frames = (int) floor(upsampleFactor * nbSamples);
+    src_data.src_ratio = upsampleFactor;
+    src_data.end_of_input = 0; // More data will come
+    src_short_to_float_array( dataIn , _floatBufferDown, nbSamples);
+    src_process(_src_state_spkr, &src_data);
+    nbSamples  = ( src_data.output_frames_gen > nbSamplesMax) ? nbSamplesMax : src_data.output_frames_gen;		
+    src_float_to_short_array(_floatBufferUp, dataOut, nbSamples);
+  }
+  return nbSamples;
+
+}
+
+int SamplerateConverter::downsampleData(  SFLDataFormat* dataIn , SFLDataFormat* dataOut , int samplerate1 , int samplerate2 , int nbSamples ){
+
+  double downsampleFactor = (double) samplerate2 / samplerate1;
+  int nbSamplesMax = (int) (samplerate1 * 20 / 1000); // TODO get the value from somewhere
+  if ( downsampleFactor != 1)
+  {
+    SRC_DATA src_data;	
+    src_data.data_in = _floatBufferUp;
+    src_data.data_out = _floatBufferDown;
+    src_data.input_frames = nbSamples;
+    src_data.output_frames = (int) floor(downsampleFactor * nbSamples);
+    src_data.src_ratio = downsampleFactor;
+    src_data.end_of_input = 0; // More data will come
+    src_short_to_float_array(dataIn, _floatBufferUp, nbSamples);
+    src_process(_src_state_mic, &src_data);
+    nbSamples  = ( src_data.output_frames_gen > nbSamplesMax) ? nbSamplesMax : src_data.output_frames_gen;
+    _debug( "return %i samples\n" , nbSamples );
+    src_float_to_short_array(_floatBufferDown, dataOut, nbSamples);
+    _debug("Begin downsample data\n");
+  }
+  return nbSamples;
+}
diff --git a/src/samplerateconverter.h b/src/samplerateconverter.h
new file mode 100644
index 0000000000..bbb5886f60
--- /dev/null
+++ b/src/samplerateconverter.h
@@ -0,0 +1,72 @@
+/*
+ *  Copyright (C) 2008 Savoir-Faire Linux inc.
+ *  Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com>
+ * 
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ * 
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _SAMPLE_RATE_H
+#define _SAMPLE_RATE_H
+
+#include <samplerate.h>
+#include <math.h>
+
+#include "global.h"
+
+class SamplerateConverter {
+  public:
+    /** Constructor */
+    SamplerateConverter( void );
+    /** Destructor */
+    ~SamplerateConverter( void );
+
+    /** 
+     * Upsample from the samplerate1 to the samplerate2
+     * @param data  The data buffer
+     * @param SamplerateConverter1 The lower sample rate
+     * @param SamplerateConverter2 The higher sample rate
+     * @param nbSamples	  The number of samples to process
+     * @return int The number of samples after the operation
+     */
+    int upsampleData( SFLDataFormat* dataIn , SFLDataFormat* dataOut , int samplerate1 , int samplerate2 , int nbSamples );
+
+    /**
+     * Downsample from the samplerate1 to the samplerate2
+     * @param data  The data buffer
+     * @param SamplerateConverter1 The lower sample rate
+     * @param SamplerateConverter2 The higher sample rate
+     * @param nbSamples	  The number of samples to process
+     * @return int The number of samples after the operation
+     */
+    int downsampleData( SFLDataFormat* dataIn , SFLDataFormat* dataOut , int samplerate1 , int samplerate2 , int nbSamples );
+
+  private:
+    /** Downsampled float buffer */
+    float32* _floatBufferDown;
+
+    /** Upsampled float buffer */
+    float32* _floatBufferUp;
+
+    /** libSamplerateConverter converter for incoming voice */
+    SRC_STATE*    _src_state_spkr;
+
+    /** libSamplerateConverter converter for outgoing voice */
+    SRC_STATE*    _src_state_mic;
+
+    /** libSamplerateConverter error */
+    int _src_err;
+};
+
+#endif //_SAMPLE_RATE_H
+
-- 
GitLab