From 4df0d6a2a47e449414ce2f9e73cdf6bac52be91a Mon Sep 17 00:00:00 2001
From: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com>
Date: Tue, 10 Jun 2008 15:39:28 -0400
Subject: [PATCH] Sample rate conversion stands in one place, tight to the
 config

---
 debian/changelog            |   5 +
 src/audio/audiortp.cpp      | 151 ++-------
 src/audio/audiortp.h        |  52 +---
 src/iaxvoiplink.cpp         | 602 +++++++++++++++---------------------
 src/iaxvoiplink.h           |  38 +--
 src/samplerateconverter.cpp |  81 +++--
 src/samplerateconverter.h   |  25 +-
 7 files changed, 378 insertions(+), 576 deletions(-)

diff --git a/debian/changelog b/debian/changelog
index fb8e8a8865..1429b6ba5e 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,8 @@
+sflphone (0.9.2) unstable; urgency=low
+  * Ticket #14: Sample rate conversion stands in one place now
+
+ -- Emmanuel Milou <emmanuel.milou@savoirfairelinux.com>  Thu, 22 May 2008 11:14:25 -0500
+
 sflphone (0.9.1) unstable; urgency=low
   * Add a search tool in the history
   * Migrate some gtk_entry_new to sexy_icon_entry_new
diff --git a/src/audio/audiortp.cpp b/src/audio/audiortp.cpp
index d4fd9f04ed..81eaa33853 100644
--- a/src/audio/audiortp.cpp
+++ b/src/audio/audiortp.cpp
@@ -39,7 +39,6 @@
 #include "ringbuffer.h"
 #include "../user_cfg.h"
 #include "../sipcall.h"
-#include <samplerate.h>
 
 ////////////////////////////////////////////////////////////////////////////////
 // AudioRtp                                                          
@@ -103,9 +102,6 @@ AudioRtpRTX::AudioRtpRTX (SIPCall *sipcall, bool sym)
   _ca = sipcall;
   _sym = sym;
   // AudioRtpRTX should be close if we change sample rate
-  //int IDcodec= _ca->getAudioCodec();
-  //_codecSampleRate = _ca->getAudioCodec()->getClockRate();
-  //_codecDesc = Manager::instance().getCodecDescriptorMap(); 
   // TODO: Change bind address according to user settings.
   // TODO: this should be the local ip not the external (router) IP
   std::string localipConfig = _ca->getLocalIp(); // _ca->getLocalIp();
@@ -119,13 +115,6 @@ AudioRtpRTX::AudioRtpRTX (SIPCall *sipcall, bool sym)
     _sessionRecv = NULL;
     _sessionSend = NULL;
   }
-
-  // libsamplerate-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);
-
 }
 
 AudioRtpRTX::~AudioRtpRTX () {
@@ -146,41 +135,34 @@ AudioRtpRTX::~AudioRtpRTX () {
     delete _session;     _session = NULL;
   }
 
-  delete [] _intBufferDown; _intBufferDown = NULL;
-  delete [] _floatBufferUp; _floatBufferUp = NULL;
-  delete [] _floatBufferDown; _floatBufferDown = NULL;
-  delete [] _dataAudioLayer; _dataAudioLayer = NULL;
+  delete [] micData;  micData = NULL;
+  delete [] micDataConverted;  micDataConverted = NULL;
+  delete [] micDataEncoded;  micDataEncoded = NULL;
 
-  delete [] _sendDataEncoded; _sendDataEncoded = NULL;
-  delete [] _receiveDataDecoded; _receiveDataDecoded = NULL;
+  delete [] spkrDataDecoded; spkrDataDecoded = NULL;
+  delete [] spkrDataConverted; spkrDataConverted = NULL;
 
   delete time; time = NULL;
-
-  // libsamplerate-related
-  _src_state_mic  = src_delete(_src_state_mic);
-  _src_state_spkr = src_delete(_src_state_spkr);
 }
 
   void
 AudioRtpRTX::initBuffers()
 {
-  converter = new SamplerateConverter();
+  converter = new SamplerateConverter( _layerSampleRate , _layerFrameSize );
 
   int nbSamplesMax = (int) (_layerSampleRate * _layerFrameSize /1000);
-  _dataAudioLayer = new SFLDataFormat[nbSamplesMax];
-  _receiveDataDecoded = new int16[nbSamplesMax];
-  _floatBufferDown  = new float32[nbSamplesMax];
-  _floatBufferUp = new float32[nbSamplesMax];
-  _sendDataEncoded = new unsigned char[nbSamplesMax];
-  _intBufferDown = new int16[nbSamplesMax];
+
+  micData = new SFLDataFormat[nbSamplesMax];
+  micDataConverted = new SFLDataFormat[nbSamplesMax];
+  micDataEncoded = new unsigned char[nbSamplesMax];
+
+  spkrDataConverted = new SFLDataFormat[nbSamplesMax];
+  spkrDataDecoded = new SFLDataFormat[nbSamplesMax];
 }
 
   void
 AudioRtpRTX::initAudioRtpSession (void) 
 {
-
-
-
   try {
     if (_ca == 0) { return; }
     _audiocodec = Manager::instance().getCodecDescriptorMap().getCodec( _ca->getAudioCodec() );
@@ -257,7 +239,6 @@ AudioRtpRTX::sendSessionFromMic(int timestamp)
   //   3. encode it
   //   4. send it
   try {
-    int16* toSIP = NULL;
 
     timestamp += time->getSecond();
     if (_ca==0) { _debug(" !ARTP: No call associated (mic)\n"); return; } // no call, so we do nothing
@@ -270,50 +251,38 @@ AudioRtpRTX::sendSessionFromMic(int timestamp)
     int maxBytesToGet = _layerSampleRate * _layerFrameSize * sizeof(SFLDataFormat) / 1000;
     // available bytes inside ringbuffer
     int availBytesFromMic = audiolayer->canGetMic();
-    //printf("%i \n", availBytesFromMic);
 
     // take the lowest
     int bytesAvail = (availBytesFromMic < maxBytesToGet) ? availBytesFromMic : maxBytesToGet;
-    //printf("%i\n", bytesAvail);
     // Get bytes from micRingBuffer to data_from_mic
-    int nbSample = audiolayer->getMic(_dataAudioLayer, bytesAvail) / sizeof(SFLDataFormat);
+    //_debug("get data from mic\n");
+    int nbSample = audiolayer->getMic( micData , bytesAvail ) / sizeof(SFLDataFormat);
     int nb_sample_up = nbSample;
     int nbSamplesMax = _layerFrameSize * _audiocodec->getClockRate() / 1000;
 
+    //_debug("resample data\n");
     nbSample = reSampleData(_audiocodec->getClockRate(), nb_sample_up, DOWN_SAMPLING);	
 
-    toSIP = _intBufferDown;
-
     if ( nbSample < nbSamplesMax - 10 ) { // if only 10 is missing, it's ok
       // fill end with 0...
-      //_debug("begin: %p, nbSample: %d\n", toSIP, nbSample);
-      memset(toSIP + nbSample, 0, (nbSamplesMax-nbSample)*sizeof(int16));
+      memset( micDataConverted + nbSample, 0, (nbSamplesMax-nbSample)*sizeof(int16));
       nbSample = nbSamplesMax;
     }
-    // debug - dump sound in a file
-    //_debug("AR: Nb sample: %d int, [0]=%d [1]=%d [2]=%d\n", nbSample, toSIP[0], toSIP[1], toSIP[2]);
-    // for the mono: range = 0 to RTP_FRAME2SEND * sizeof(int16)
-    // codecEncode(char *dest, int16* src, size in bytes of the src)
-    int compSize = _audiocodec->codecEncode(_sendDataEncoded, toSIP, nbSample*sizeof(int16));
-    //printf("jusqu'ici tout vas bien\n");
-
+    int compSize = _audiocodec->codecEncode( micDataEncoded , micDataConverted , nbSample*sizeof(int16));
     // encode divise by two
     // Send encoded audio sample over the network
     if (compSize > nbSamplesMax) { _debug("! ARTP: %d should be %d\n", compSize, nbSamplesMax);}
     if (!_sym) {
-      _sessionSend->putData(timestamp, _sendDataEncoded, compSize);
+      _sessionSend->putData(timestamp, micDataEncoded, compSize);
     } else {
-      _session->putData(timestamp, _sendDataEncoded, compSize);
+      _session->putData(timestamp, micDataEncoded, compSize);
     }
-    toSIP = NULL;
   } catch(...) {
     _debugException("! ARTP: sending failed");
     throw;
   }
 }
 
-
-
   void
 AudioRtpRTX::receiveSessionForSpkr (int& countTime)
 {
@@ -338,11 +307,9 @@ AudioRtpRTX::receiveSessionForSpkr (int& countTime)
     }
 
     int payload = adu->getType(); // codec type
-    unsigned char* data  = (unsigned char*)adu->getData(); // data in char
+    unsigned char* spkrData  = (unsigned char*)adu->getData(); // data in char
     unsigned int size = adu->getSize(); // size in char
 
-
-    //_fstream.write((char*) data, size);
     // Decode data with relevant codec
     int max = (int)(_codecSampleRate * _layerFrameSize / 1000);
 
@@ -352,13 +319,9 @@ AudioRtpRTX::receiveSessionForSpkr (int& countTime)
       size=max;
     }
 
-    //printf("size = %i\n", size);
-
     if (_audiocodec != NULL) {
 
-      int expandedSize = _audiocodec->codecDecode(_receiveDataDecoded, data, size);
-      //	printf("%i\n", expandedSize);
-      //_fstream.write((char*) _receiveDataDecoded, );
+      int expandedSize = _audiocodec->codecDecode( spkrDataDecoded , spkrData , size );
       //buffer _receiveDataDecoded ----> short int or int16, coded on 2 bytes
       int nbInt16 = expandedSize / sizeof(int16);
       //nbInt16 represents the number of samples we just decoded
@@ -366,21 +329,16 @@ AudioRtpRTX::receiveSessionForSpkr (int& countTime)
 	_debug("We have decoded an RTP packet larger than expected: %s VS %s. Cropping.\n", nbInt16, max);
 	nbInt16=max;
       }
-
-      SFLDataFormat* toAudioLayer;
       int nbSample = nbInt16;
 
       // Do sample rate conversion
       int nb_sample_down = nbSample;
       nbSample = reSampleData(_codecSampleRate , nb_sample_down, UP_SAMPLING);
 #ifdef DATAFORMAT_IS_FLOAT
-      toAudioLayer = _floatBufferUp;
 #else
-      toAudioLayer = _dataAudioLayer;
 #endif
 
-
-      audiolayer->playSamples(toAudioLayer, nbSample * sizeof(SFLDataFormat), true);
+      audiolayer->playSamples( spkrDataConverted , nbSample * sizeof(SFLDataFormat), true);
       // Notify (with a beep) an incoming call when there is already a call 
       countTime += time->getSecond();
       if (Manager::instance().incomingCallWaiting() > 0) {
@@ -393,7 +351,6 @@ AudioRtpRTX::receiveSessionForSpkr (int& countTime)
     } else {
       countTime += time->getSecond();
     }
-
     delete adu; adu = NULL;
   } catch(...) {
     _debugException("! ARTP: receiving failed");
@@ -407,75 +364,20 @@ AudioRtpRTX::receiveSessionForSpkr (int& countTime)
 AudioRtpRTX::reSampleData(int sampleRate_codec, int nbSamples, int status)
 {
   if(status==UP_SAMPLING){
-    //return upSampleData(sampleRate_codec, nbSamples);
-    return converter->upsampleData( _receiveDataDecoded , _dataAudioLayer, sampleRate_codec , _layerSampleRate , nbSamples );
+    return converter->upsampleData( spkrDataDecoded , spkrDataConverted , sampleRate_codec , _layerSampleRate , nbSamples );
   }
   else if(status==DOWN_SAMPLING){
-    //return downSampleData(sampleRate_codec, nbSamples);
-    return converter->downsampleData( _dataAudioLayer , _intBufferDown, sampleRate_codec , _layerSampleRate , nbSamples );
+    return converter->downsampleData( micData , micDataConverted , sampleRate_codec , _layerSampleRate , nbSamples );
   }
   else
     return 0;
 }
 
-////////////////////////////////////////////////////////////////////
-//////////// RESAMPLING FUNCTIONS /////////////////////////////////
-//////////////////////////////////////////////////////////////////
-
-  int
-AudioRtpRTX::upSampleData(int sampleRate_codec, int nbSamples)
-{
-  double upsampleFactor = (double) _layerSampleRate / sampleRate_codec;
-  int nbSamplesMax = (int) (_layerSampleRate * _layerFrameSize /1000);
-  if( upsampleFactor != 1 )
-  {
-    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(_receiveDataDecoded, _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, _dataAudioLayer, nbSamples);
-  }
-
-  return nbSamples;
-}	
-
-  int
-AudioRtpRTX::downSampleData(int sampleRate_codec, int nbSamples)
-{
-  double downsampleFactor = (double) sampleRate_codec / _layerSampleRate;
-  int nbSamplesMax = (int) (sampleRate_codec * _layerFrameSize / 1000);
-  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(_dataAudioLayer, _floatBufferUp, nbSamples);
-    src_process(_src_state_mic, &src_data);
-    nbSamples  = ( src_data.output_frames_gen > nbSamplesMax) ? nbSamplesMax : src_data.output_frames_gen;
-    src_float_to_short_array(_floatBufferDown, _intBufferDown, nbSamples);
-  }
-  return nbSamples;
-
-}
-
-//////////////////////// END RESAMPLING //////////////////////////////////////////////////////
-
 void
 AudioRtpRTX::run () {
   //mic, we receive from soundcard in stereo, and we send encoded
   //encoding before sending
   AudioLayer *audiolayer = Manager::instance().getAudioDriver();
-  //loadCodec(_ca->getAudioCodec());
   _layerFrameSize = audiolayer->getFrameSize(); // en ms
   _layerSampleRate = audiolayer->getSampleRate();	
   initBuffers();
@@ -499,7 +401,6 @@ AudioRtpRTX::run () {
     int countTime = 0; // for receive
     TimerPort::setTimer(_layerFrameSize);
 
-    //audiolayer->flushMic();
     audiolayer->startStream();
     _start.post();
     _debug("- ARTP Action: Start\n");
@@ -517,8 +418,6 @@ AudioRtpRTX::run () {
       Thread::sleep(TimerPort::getTimer());
       TimerPort::incTimer(_layerFrameSize); // 'frameSize' ms
     }
-    //_fstream.close();
-    //unloadCodec();
     //_debug("stop stream for audiortp loop\n");
     audiolayer->stopStream();
   } catch(std::exception &e) {
diff --git a/src/audio/audiortp.h b/src/audio/audiortp.h
index 6e61f6054a..a0cb003bf3 100644
--- a/src/audio/audiortp.h
+++ b/src/audio/audiortp.h
@@ -28,8 +28,6 @@
 #include <ccrtp/rtp.h>
 #include <cc++/numbers.h>
 
-#include <samplerate.h>
-
 #include "../global.h"
 #include "../samplerateconverter.h"
 
@@ -85,34 +83,16 @@ class AudioRtpRTX : public ost::Thread, public ost::TimerPort {
     /** Is the session symmetric or not */
     bool _sym;
 
-    /** When we receive data, we decode it inside this buffer */
-    int16* _receiveDataDecoded;
-
-    /** Buffers used for send data from the mic */
-    unsigned char* _sendDataEncoded;
-    
-    /** Downsampled int16 buffer */
-    int16* _intBufferDown;
-
-    /** After that we send the data inside this buffer if there is a format conversion or rate conversion */
-    /** Also use for getting mic-ringbuffer data */
-    SFLDataFormat* _dataAudioLayer;
-
-    /** Downsampled float buffer */
-    float32* _floatBufferDown;
+    /** Mic-data related buffers */
+    SFLDataFormat* micData;
+    SFLDataFormat* micDataConverted;
+    unsigned char* micDataEncoded;
 
-    /** Upsampled float buffer */
-    float32* _floatBufferUp;
-
-    /** libsamplerate converter for incoming voice */
-    SRC_STATE*    _src_state_spkr;
-
-    /** libsamplerate converter for outgoing voice */
-    SRC_STATE*    _src_state_mic;
-
-    /** libsamplerate error */
-    int _src_err;
+    /** Speaker-data related buffers */
+    SFLDataFormat* spkrDataDecoded;
+    SFLDataFormat* spkrDataConverted;
 
+    /** Sample rate converter object */
     SamplerateConverter* converter;
 
     /** Variables to process audio stream: sample rate for playing sound (typically 44100HZ) */
@@ -158,22 +138,6 @@ class AudioRtpRTX : public ost::Thread, public ost::TimerPort {
      */ 
     int reSampleData(int sampleRate_codec, int nbSamples, int status);
     
-    /**
-     * Upsample the data from the clock rate of the codec to the sample rate of the layer
-     * @param sampleRate_codec	The sample rate of the codec selected to encode/decode the data
-     * @param nbSamples		Number of samples to process
-     * @return int The number of samples after process
-     */
-    int upSampleData(int sampleRate_codec, int nbSamples);
-    
-    /**
-     * Downsample the data from the sample rate of the layer to the clock rate of the codec
-     * @param sampleRate_codec	The sample rate of the codec selected to encode/decode the data
-     * @param nbSamples		Number of samples to process
-     * @return int The number of samples after process
-     */
-    int downSampleData(int sampleRate_codec, int nbSamples);
-
     /** The audio codec used during the session */
     AudioCodec* _audiocodec;	
 };
diff --git a/src/iaxvoiplink.cpp b/src/iaxvoiplink.cpp
index 1cc5a5d264..6b76c9c123 100644
--- a/src/iaxvoiplink.cpp
+++ b/src/iaxvoiplink.cpp
@@ -25,12 +25,10 @@
 #include "manager.h"
 #include "audio/audiolayer.h"
 
-#include <samplerate.h>
 //#include <iax/iax-client.h>
 #include <math.h>
 #include <dlfcn.h>
 
-
 #define IAX_BLOCKING    1
 #define IAX_NONBLOCKING 0
 
@@ -40,20 +38,12 @@
 #define RANDOM_IAX_PORT   rand() % 64000 + 1024
 
 #define MUSIC_ONHOLD true
-#define NO_MUSIC_ONHOLD	false
-
-// from IAXC : iaxclient.h
-
-#define IAX__20S_8KHZ_MAX   320 //320 samples, IAX packets can have more than 20ms.
-#define IAX__20S_48KHZ_MAX  1920 // 320*6 samples = 1920, 6 = 48000/8000 
 
 #define CHK_VALID_CALL   if (call == NULL) { _debug("IAX: Call doesn't exists\n"); \
-                                             return false; }
-
+  return false; }
 
-
-IAXVoIPLink::IAXVoIPLink(const AccountID& accountID)
-  : VoIPLink(accountID)
+  IAXVoIPLink::IAXVoIPLink(const AccountID& accountID)
+: VoIPLink(accountID)
 {
   _evThread = new EventThread(this);
   _regSession = NULL;
@@ -64,19 +54,16 @@ IAXVoIPLink::IAXVoIPLink(const AccountID& accountID)
 
   audiolayer = NULL;
 
-  _receiveDataDecoded = new int16[IAX__20S_48KHZ_MAX];
-  _sendDataEncoded   =  new unsigned char[IAX__20S_8KHZ_MAX];
+  converter = new SamplerateConverter();
 
-  // we estimate that the number of format after a conversion 8000->48000 is expanded to 6 times
-  _dataAudioLayer = new SFLDataFormat[IAX__20S_48KHZ_MAX];
-  _floatBuffer8000  = new float32[IAX__20S_8KHZ_MAX];
-  _floatBuffer48000 = new float32[IAX__20S_48KHZ_MAX];
-  _intBuffer8000  = new int16[IAX__20S_8KHZ_MAX];
+  int nbSamplesMax = (int) ( converter->getFrequence() * converter->getFramesize() / 1000 );
 
-  // libsamplerate-related
-  _src_state_mic  = src_new(SRC_SINC_BEST_QUALITY, 1, &_src_err);
-  _src_state_spkr = src_new(SRC_SINC_BEST_QUALITY, 1, &_src_err);
+  micData = new SFLDataFormat[nbSamplesMax];
+  micDataConverted = new SFLDataFormat[nbSamplesMax];
+  micDataEncoded = new unsigned char[nbSamplesMax];
 
+  spkrDataConverted = new SFLDataFormat[nbSamplesMax];
+  spkrDataDecoded = new SFLDataFormat[nbSamplesMax];
 }
 
 
@@ -87,20 +74,16 @@ IAXVoIPLink::~IAXVoIPLink()
   terminate();
 
   audiolayer = NULL;
-  delete [] _intBuffer8000; _intBuffer8000 = NULL;
-  delete [] _floatBuffer48000; _floatBuffer48000 = NULL;
-  delete [] _floatBuffer8000; _floatBuffer8000 = NULL;
-  delete [] _dataAudioLayer; _dataAudioLayer = NULL;
 
-  delete [] _sendDataEncoded; _sendDataEncoded = NULL;
-  delete [] _receiveDataDecoded; _receiveDataDecoded = NULL;
+  delete [] micData;  micData = NULL;
+  delete [] micDataConverted;  micDataConverted = NULL;
+  delete [] micDataEncoded;  micDataEncoded = NULL;
 
-  // libsamplerate-related
-  _src_state_mic  = src_delete(_src_state_mic);
-  _src_state_spkr = src_delete(_src_state_spkr);
+  delete [] spkrDataDecoded; spkrDataDecoded = NULL;
+  delete [] spkrDataConverted; spkrDataConverted = NULL;
 }
 
-bool
+  bool
 IAXVoIPLink::init()
 {
   // If it was done, don't do it again, until we call terminate()
@@ -139,15 +122,14 @@ IAXVoIPLink::init()
   }
   if (port == IAX_FAILURE || nbTry==0) {
     _debug("Fail to initialize iax\n");
-    
+
     _initDone = false;
   }
-  
 
   return returnValue;
 }
 
-void
+  void
 IAXVoIPLink::terminate()
 {
   // If it was done, don't do it again, until we call init()
@@ -162,7 +144,7 @@ IAXVoIPLink::terminate()
   _initDone = false;
 }
 
-void
+  void
 IAXVoIPLink::terminateIAXCall()
 {
   std::string reason = "Dumped Call";
@@ -183,7 +165,7 @@ IAXVoIPLink::terminateIAXCall()
   _callMap.clear();
 }
 
-void
+  void
 IAXVoIPLink::getEvent() 
 {
   IAXCall* call = NULL;
@@ -214,7 +196,7 @@ IAXVoIPLink::getEvent()
       // We've got an event before it's associated with any call
       iaxHandlePrecallEvent(event);
     }
-    
+
     iax_event_free(event);
   }
   _mutexIAX.leaveMutex();
@@ -233,7 +215,7 @@ IAXVoIPLink::getEvent()
   _evThread->sleep(3);
 }
 
-void
+  void
 IAXVoIPLink::sendAudioFromMic(void)
 {
   IAXCall* currentCall = getIAXCall(Manager::instance().getCurrentCallId());
@@ -242,7 +224,7 @@ IAXVoIPLink::sendAudioFromMic(void)
     // Let's mind our own business.
     return;
   }
-  
+
   if( currentCall -> getAudioCodec() < 0 )
     return;
 
@@ -266,13 +248,13 @@ IAXVoIPLink::sendAudioFromMic(void)
     }
     return;
   }
-  
+
   // Send sound here
   if (audiolayer) {
 
     // we have to get 20ms of data from the mic *20/1000 = /50
     // rate/50 shall be lower than IAX__20S_48KHZ_MAX
-    int maxBytesToGet = audiolayer->getSampleRate()/50*sizeof(SFLDataFormat);
+    int maxBytesToGet = audiolayer->getSampleRate()* audiolayer->getFrameSize() / 1000 * sizeof(SFLDataFormat);
 
     // available bytes inside ringbuffer
     int availBytesFromMic = audiolayer->canGetMic();
@@ -285,59 +267,21 @@ IAXVoIPLink::sendAudioFromMic(void)
     // take the lowest
     int bytesAvail = (availBytesFromMic < maxBytesToGet) ? availBytesFromMic : maxBytesToGet;
     //_debug("available = %d, maxBytesToGet = %d\n", availBytesFromMic, maxBytesToGet);
-    
+
     // Get bytes from micRingBuffer to data_from_mic
-    int nbSample = audiolayer->getMic(_dataAudioLayer, bytesAvail) / sizeof(SFLDataFormat);
-
-    // Audio ici est PARFAIT
-    int16* toIAX = NULL;
-    //if (audiolayer->getSampleRate() != audiocodec->getClockRate() && nbSample) {
-    if (audiolayer->getSampleRate() != ac ->getClockRate() && nbSample) {
-      SRC_DATA src_data;
-#ifdef DATAFORMAT_IS_FLOAT   
-      src_data.data_in = _dataAudioLayer;
-#else
-      src_short_to_float_array(_dataAudioLayer, _floatBuffer48000, nbSample);
-      src_data.data_in = _floatBuffer48000; 
-#endif
-      
-      // Audio parfait à ce point.
-      double factord = (double) ac->getClockRate() / audiolayer->getSampleRate();
-      
-      src_data.src_ratio = factord;
-      src_data.input_frames = nbSample;
-      src_data.output_frames = (int) floor(factord * nbSample);
-      src_data.data_out = _floatBuffer8000;
-      src_data.end_of_input = 0; 
-      
-      src_process(_src_state_mic, &src_data);
-      
-      nbSample = src_data.output_frames_gen;
-
-      // Bon, l'audio en float 8000 est laid mais yé consistant.
-      src_float_to_short_array (_floatBuffer8000, _intBuffer8000, nbSample);
-      toIAX = _intBuffer8000;
-
-      // Audio bon ici aussi..
-    } else {
-#ifdef DATAFORMAT_IS_FLOAT
-      // convert _receiveDataDecoded to float inside _receiveData
-      src_float_to_short_array(_dataAudioLayer, _intBuffer8000, nbSample);
-      toIAX = _intBuffer8000;
-      //if (nbSample > IAX__20S_8KHZ_MAX) { _debug("Alert from mic, nbSample %d is bigger than expected %d\n", nbSample, IAX__20S_8KHZ_MAX); }
-#else
-      toIAX = _dataAudioLayer; // int to int
-#endif
-    }
+    int nbSample = audiolayer->getMic( micData, bytesAvail ) / sizeof(SFLDataFormat);
+
+    // resample
+    nbSample = converter->downsampleData( micData , micDataConverted , (int)ac ->getClockRate() ,  (int)audiolayer->getSampleRate() , nbSample );
 
     // for the mono: range = 0 to IAX_FRAME2SEND * sizeof(int16)
-    int compSize = ac->codecEncode(_sendDataEncoded, toIAX, nbSample*sizeof(int16));
+    int compSize = ac->codecEncode( micDataEncoded, micDataConverted , nbSample*sizeof(int16));
 
     // Send it out!
     _mutexIAX.enterMutex();
     // Make sure the session and the call still exists.
     if (currentCall->getSession()) {
-      if ( iax_send_voice(currentCall->getSession(), currentCall->getFormat(), (unsigned char*)_sendDataEncoded, compSize, nbSample) == -1) {
+      if ( iax_send_voice(currentCall->getSession(), currentCall->getFormat(), micDataEncoded, compSize, nbSample) == -1) {
 	_debug("IAX: Error sending voice data.\n");
       }
     }
@@ -346,7 +290,7 @@ IAXVoIPLink::sendAudioFromMic(void)
 }
 
 
-IAXCall* 
+  IAXCall* 
 IAXVoIPLink::getIAXCall(const CallID& id) 
 {
   Call* call = getCall(id);
@@ -358,7 +302,7 @@ IAXVoIPLink::getIAXCall(const CallID& id)
 
 
 
-bool
+  bool
 IAXVoIPLink::sendRegister() 
 {
   bool result = false;
@@ -412,7 +356,7 @@ IAXVoIPLink::sendRegister()
 
 
 
-bool
+  bool
 IAXVoIPLink::sendUnregister()
 {
   _mutexIAX.enterMutex();
@@ -434,7 +378,7 @@ IAXVoIPLink::sendUnregister()
   return false;
 }
 
-Call* 
+  Call* 
 IAXVoIPLink::newOutgoingCall(const CallID& id, const std::string& toUrl)
 {
   IAXCall* call = new IAXCall(id, Call::Outgoing);
@@ -456,12 +400,12 @@ IAXVoIPLink::newOutgoingCall(const CallID& id, const std::string& toUrl)
 }
 
 
-bool 
+  bool 
 IAXVoIPLink::answer(const CallID& id)
 {
   IAXCall* call = getIAXCall(id);
   call->setCodecMap(Manager::instance().getCodecDescriptorMap());
-  
+
   CHK_VALID_CALL;
 
   _mutexIAX.enterMutex();
@@ -477,7 +421,7 @@ IAXVoIPLink::answer(const CallID& id)
   return true;
 }
 
-bool 
+  bool 
 IAXVoIPLink::hangup(const CallID& id)
 {
   IAXCall* call = getIAXCall(id);
@@ -495,7 +439,7 @@ IAXVoIPLink::hangup(const CallID& id)
   return true;	
 }
 
-bool 
+  bool 
 IAXVoIPLink::onhold(const CallID& id) 
 {
   IAXCall* call = getIAXCall(id);
@@ -503,7 +447,7 @@ IAXVoIPLink::onhold(const CallID& id)
   CHK_VALID_CALL;
 
   //if (call->getState() == Call::Hold) { _debug("Call is already on hold\n"); return false; }
-  
+
   _mutexIAX.enterMutex();
   iax_quelch_moh(call->getSession() , MUSIC_ONHOLD);
   _mutexIAX.leaveMutex();
@@ -512,7 +456,7 @@ IAXVoIPLink::onhold(const CallID& id)
   return true;
 }
 
-bool 
+  bool 
 IAXVoIPLink::offhold(const CallID& id)
 {
   IAXCall* call = getIAXCall(id);
@@ -528,7 +472,7 @@ IAXVoIPLink::offhold(const CallID& id)
   return true;
 }
 
-bool 
+  bool 
 IAXVoIPLink::transfer(const CallID& id, const std::string& to)
 {
   IAXCall* call = getIAXCall(id);
@@ -537,7 +481,7 @@ IAXVoIPLink::transfer(const CallID& id, const std::string& to)
 
   char callto[to.length()+1];
   strcpy(callto, to.c_str());
-  
+
   _mutexIAX.enterMutex();
   iax_transfer(call->getSession(), callto); 
   _mutexIAX.leaveMutex();
@@ -546,7 +490,7 @@ IAXVoIPLink::transfer(const CallID& id, const std::string& to)
   // removeCall(id);
 }
 
-bool 
+  bool 
 IAXVoIPLink::refuse(const CallID& id)
 {
   IAXCall* call = getIAXCall(id);
@@ -560,7 +504,7 @@ IAXVoIPLink::refuse(const CallID& id)
   removeCall(id);
 }
 
-bool
+  bool
 IAXVoIPLink::carryingDTMFdigits(const CallID& id, char code)
 {
   IAXCall* call = getIAXCall(id);
@@ -574,7 +518,7 @@ IAXVoIPLink::carryingDTMFdigits(const CallID& id, char code)
 
 
 
-bool
+  bool
 IAXVoIPLink::iaxOutgoingInvite(IAXCall* call) 
 {
   struct iax_session *newsession;
@@ -582,18 +526,18 @@ IAXVoIPLink::iaxOutgoingInvite(IAXCall* call)
 
   newsession = iax_session_new();
   if (!newsession) {
-     _debug("IAX Error: Can't make new session for a new call\n");
-     return false;
+    _debug("IAX Error: Can't make new session for a new call\n");
+    return false;
   }
   call->setSession(newsession);
   /* reset activity and ping "timers" */
   // iaxc_note_activity(callNo);
-  
+
   std::string strNum = _user + ":" + _pass + "@" + _host + "/" + call->getPeerNumber();  
 
   char user[_user.length()+1];
   strcpy(user, _user.c_str());
-  
+
   char num[strNum.length()+1];
   strcpy(num, strNum.c_str());
 
@@ -610,7 +554,7 @@ IAXVoIPLink::iaxOutgoingInvite(IAXCall* call)
 }
 
 
-IAXCall* 
+  IAXCall* 
 IAXVoIPLink::iaxFindCallBySession(struct iax_session* session) 
 {
   // access to callMap shoud use that
@@ -628,7 +572,7 @@ IAXVoIPLink::iaxFindCallBySession(struct iax_session* session)
   return NULL; // not found
 }
 
-void
+  void
 IAXVoIPLink::iaxHandleCallEvent(iax_event* event, IAXCall* call) 
 {
   // call should not be 0
@@ -636,192 +580,158 @@ IAXVoIPLink::iaxHandleCallEvent(iax_event* event, IAXCall* call)
   //
   CallID id = call->getCallId();
   int16* output = 0; // for audio output
-  
+
   switch(event->etype) {
-  case IAX_EVENT_HANGUP:
-    Manager::instance().peerHungupCall(id); 
-    if (Manager::instance().isCurrentCall(id)) {
-      audiolayer->stopStream();
-      // stop audio
-    }
-    removeCall(id);
-    break;
-    
-  case IAX_EVENT_REJECT:
-    //Manager::instance().peerHungupCall(id); 
-    if (Manager::instance().isCurrentCall(id)) {
-      // stop audio
-      audiolayer->stopStream();
-    }
-    call->setConnectionState(Call::Connected);
-    call->setState(Call::Error);
-    Manager::instance().callFailure(id);
-    removeCall(id);
-    break;
-
-  case IAX_EVENT_ACCEPT:
-    // Call accepted over there by the computer, not the user yet.
-    if (event->ies.format) {
-      call->setFormat(event->ies.format);
-    }
-    break;
-    
-  case IAX_EVENT_ANSWER:
-    if (call->getConnectionState() != Call::Connected){
+    case IAX_EVENT_HANGUP:
+      Manager::instance().peerHungupCall(id); 
+      if (Manager::instance().isCurrentCall(id)) {
+	audiolayer->stopStream();
+	// stop audio
+      }
+      removeCall(id);
+      break;
+
+    case IAX_EVENT_REJECT:
+      //Manager::instance().peerHungupCall(id); 
+      if (Manager::instance().isCurrentCall(id)) {
+	// stop audio
+	audiolayer->stopStream();
+      }
       call->setConnectionState(Call::Connected);
-      call->setState(Call::Active);
+      call->setState(Call::Error);
+      Manager::instance().callFailure(id);
+      removeCall(id);
+      break;
 
+    case IAX_EVENT_ACCEPT:
+      // Call accepted over there by the computer, not the user yet.
       if (event->ies.format) {
-	// Should not get here, should have been set in EVENT_ACCEPT
 	call->setFormat(event->ies.format);
       }
-      
-      Manager::instance().peerAnsweredCall(id);
-      //audiolayer->flushMic();
-      audiolayer->startStream();
-      // start audio here?
-    } else {
-      // deja connecté ?
-    }
-    break;
-    
-  case IAX_EVENT_BUSY:
-    call->setConnectionState(Call::Connected);
-    call->setState(Call::Busy);
-    Manager::instance().callBusy(id);
-    removeCall(id);
-    break;
-    
-  case IAX_EVENT_VOICE:
-    //_debug("Should have a decent value!!!!!! = %i\n" , call -> getAudioCodec());
-    if( !audiolayer -> isCaptureActive())
-      audiolayer->startStream();
-    iaxHandleVoiceEvent(event, call);
-    break;
-    
-  case IAX_EVENT_TEXT:
-    break;
-    
-  case IAX_EVENT_RINGA:
-    call->setConnectionState(Call::Ringing);
-    Manager::instance().peerRingingCall(call->getCallId());
-    break;
-    
-  case IAX_IE_MSGCOUNT:	
-   // _debug("messssssssssssssssssssssssssssssssssssssssssssssssages\n");
-    break;
-  case IAX_EVENT_PONG:
-    break;
-    
-  case IAX_EVENT_URL:
-    break;
-    
-    //    case IAX_EVENT_CNG: ??
-    //    break;
-    
-  case IAX_EVENT_TIMEOUT:
-    break;
-    
-  case IAX_EVENT_TRANSFER:
-    break;
-    
-  default:
-    _debug("Unknown event type (in call event): %d\n", event->etype);
-    
+      break;
+
+    case IAX_EVENT_ANSWER:
+      if (call->getConnectionState() != Call::Connected){
+	call->setConnectionState(Call::Connected);
+	call->setState(Call::Active);
+
+	if (event->ies.format) {
+	  // Should not get here, should have been set in EVENT_ACCEPT
+	  call->setFormat(event->ies.format);
+	}
+
+	Manager::instance().peerAnsweredCall(id);
+	//audiolayer->flushMic();
+	audiolayer->startStream();
+	// start audio here?
+      } else {
+	// deja connecté ?
+      }
+      break;
+
+    case IAX_EVENT_BUSY:
+      call->setConnectionState(Call::Connected);
+      call->setState(Call::Busy);
+      Manager::instance().callBusy(id);
+      removeCall(id);
+      break;
+
+    case IAX_EVENT_VOICE:
+      //_debug("Should have a decent value!!!!!! = %i\n" , call -> getAudioCodec());
+      //if( !audiolayer -> isCaptureActive())
+      //audiolayer->startStream();
+      iaxHandleVoiceEvent(event, call);
+      break;
+
+    case IAX_EVENT_TEXT:
+      break;
+
+    case IAX_EVENT_RINGA:
+      call->setConnectionState(Call::Ringing);
+      Manager::instance().peerRingingCall(call->getCallId());
+      break;
+
+    case IAX_IE_MSGCOUNT:	
+      break;
+    case IAX_EVENT_PONG:
+      break;
+
+    case IAX_EVENT_URL:
+      break;
+
+      //    case IAX_EVENT_CNG: ??
+      //    break;
+
+    case IAX_EVENT_TIMEOUT:
+      break;
+
+    case IAX_EVENT_TRANSFER:
+      break;
+
+    default:
+      _debug("Unknown event type (in call event): %d\n", event->etype);
+
   }
 }
 
 
 /* Handle audio event, VOICE packet received */
-void
+  void
 IAXVoIPLink::iaxHandleVoiceEvent(iax_event* event, IAXCall* call)
 { 
-    // If we receive datalen == 0, some things of the jitter buffer in libiax2/iax.c
-    // were triggered
-    if (!event->datalen) {
-      // Skip this empty packet.
-      //_debug("IAX: Skipping empty jitter-buffer interpolated packet\n");
-      return;
+  // If we receive datalen == 0, some things of the jitter buffer in libiax2/iax.c
+  // were triggered
+  if (!event->datalen) {
+    // Skip this empty packet.
+    //_debug("IAX: Skipping empty jitter-buffer interpolated packet\n");
+    return;
+  }
+
+  if (audiolayer) {
+    // On-the-fly codec changing (normally, when we receive a full packet)
+    // as per http://tools.ietf.org/id/draft-guy-iax-03.txt
+    // - subclass holds the voiceformat property.
+    if (event->subclass && event->subclass != call->getFormat()) {
+      call->setFormat(event->subclass);
     }
+    //_debug("Receive: len=%d, format=%d, _receiveDataDecoded=%p\n", event->datalen, call->getFormat(), _receiveDataDecoded);
+    AudioCodec* ac = call->getCodecMap().getCodec( call -> getAudioCodec() );
 
-    if (audiolayer) {
-  //    _debug("codec = %i\n" , call->getFormat());
-   //   _debug("codec = %i\n" , _audiocodec->getPayload());
-      //_debug("codec = %s\n" , _audiocodec->getCodecName().c_str());
-      // On-the-fly codec changing (normally, when we receive a full packet)
-      // as per http://tools.ietf.org/id/draft-guy-iax-03.txt
-      // - subclass holds the voiceformat property.
-      if (event->subclass && event->subclass != call->getFormat()) {
-	call->setFormat(event->subclass);
-      }
-      //_debug("Receive: len=%d, format=%d, _receiveDataDecoded=%p\n", event->datalen, call->getFormat(), _receiveDataDecoded);
-      AudioCodec* ac = call->getCodecMap().getCodec( call -> getAudioCodec() );
+    unsigned char* data = (unsigned char*)event->data;
+    unsigned int size   = event->datalen;
 
-      unsigned char* data = (unsigned char*)event->data;
-      unsigned int size   = event->datalen;
+    // Decode data with relevant codec
+    int max = (int)( ac->getClockRate() * audiolayer->getFrameSize() / 1000 );
 
-      if (size > IAX__20S_8KHZ_MAX) {
-	_debug("The size %d is bigger than expected %d. Packet cropped. Ouch!\n", size, IAX__20S_8KHZ_MAX);
-	size = IAX__20S_8KHZ_MAX;
-      }
+    if (size > max) {
+      _debug("The size %d is bigger than expected %d. Packet cropped. Ouch!\n", size, max);
+      size = max;
+    }
 
-      int expandedSize = ac->codecDecode(_receiveDataDecoded, data, size);
-      int nbInt16      = expandedSize/sizeof(int16);
+    int expandedSize = ac->codecDecode( spkrDataDecoded , data , size );
+    int nbInt16      = expandedSize/sizeof(int16);
 
-      if (nbInt16 > IAX__20S_8KHZ_MAX) {
-	_debug("We have decoded an IAX VOICE packet larger than expected: %s VS %s. Cropping.\n", nbInt16, IAX__20S_8KHZ_MAX);
-	nbInt16 = IAX__20S_8KHZ_MAX;
-      }
-      
-      SFLDataFormat* toAudioLayer;
-      int nbSample = nbInt16;
-      int nbSampleMaxRate = nbInt16 * 6;
-      
-      if ( audiolayer->getSampleRate() != ac->getClockRate() && nbSample ) {
-	// Do sample rate conversion
-	double factord = (double) audiolayer->getSampleRate() / ac->getClockRate();
-	// SRC_DATA from samplerate.h
-	SRC_DATA src_data;
-	src_data.data_in = _floatBuffer8000;
-	src_data.data_out = _floatBuffer48000;
-	src_data.input_frames = nbSample;
-	src_data.output_frames = (int) floor(factord * nbSample);
-	src_data.src_ratio = factord;
-	src_data.end_of_input = 0;
-	src_short_to_float_array(_receiveDataDecoded, _floatBuffer8000, nbSample);
-
-	// samplerate convert, go!
-	src_process(_src_state_spkr, &src_data);
-	
-	nbSample = ( src_data.output_frames_gen > IAX__20S_48KHZ_MAX) ? IAX__20S_48KHZ_MAX : src_data.output_frames_gen;
-#ifdef DATAFORMAT_IS_FLOAT
-	toAudioLayer = _floatBuffer48000;
-#else
-	src_float_to_short_array(_floatBuffer48000, _dataAudioLayer, nbSample);
-	toAudioLayer = _dataAudioLayer;
-#endif
-  	
-      } else {
-	nbSample = nbInt16;
-#ifdef DATAFORMAT_IS_FLOAT
-	// convert _receiveDataDecoded to float inside _receiveData
-	src_short_to_float_array(_receiveDataDecoded, _floatBuffer8000, nbSample);
-	toAudioLayer = _floatBuffer8000;
-#else
-	toAudioLayer = _receiveDataDecoded; // int to int
-#endif
-      }
-      audiolayer->playSamples(toAudioLayer, nbSample * sizeof(SFLDataFormat), true);
-    } else {
-      _debug("IAX: incoming audio, but no sound card open");
+    if (nbInt16 > max) {
+      _debug("We have decoded an IAX VOICE packet larger than expected: %s VS %s. Cropping.\n", nbInt16, max);
+      nbInt16 = max;
     }
 
+    int nbSample = nbInt16;
+    // resample
+    nbInt16 = converter->upsampleData( spkrDataDecoded , spkrDataConverted , ac->getClockRate() , audiolayer->getSampleRate() , nbSample);
+
+    audiolayer->playSamples( spkrDataConverted , nbInt16 * sizeof(SFLDataFormat), true);
+
+  } else {
+    _debug("IAX: incoming audio, but no sound card open");
+  }
+
 }
 
 /**
  * Handle the registration process
  */
-void
+  void
 IAXVoIPLink::iaxHandleRegReply(iax_event* event) 
 {
   if (event->etype == IAX_EVENT_REGREJ) {
@@ -846,7 +756,7 @@ IAXVoIPLink::iaxHandleRegReply(iax_event* event)
   }
 }
 
-void
+  void
 IAXVoIPLink::iaxHandlePrecallEvent(iax_event* event)
 {
   IAXCall* call = NULL;
@@ -854,96 +764,96 @@ IAXVoIPLink::iaxHandlePrecallEvent(iax_event* event)
   std::string reason = "Error ringing user.";
 
   switch(event->etype) {
-  case IAX_EVENT_REGACK:
-  case IAX_EVENT_REGREJ:
-    _debug("IAX Registration Event in a pre-call setup\n");
-    break;
-    
-  case IAX_EVENT_REGREQ:
-    // Received when someone wants to register to us!?!
-    // Asterisk receives and answers to that, not us, we're a phone.
-    _debug("Registration by a peer, don't allow it\n");
-    break;
-    
-  case IAX_EVENT_CONNECT:
-    // We've got an incoming call! Yikes!
-    _debug("> IAX_EVENT_CONNECT (receive)\n");
-
-    id = Manager::instance().getNewCallID();
-
-
-    call = new IAXCall(id, Call::Incoming);
-
-    if (!call) {
-      _debug("! IAX Failure: unable to create an incoming call");
-      return;
-    }
+    case IAX_EVENT_REGACK:
+    case IAX_EVENT_REGREJ:
+      _debug("IAX Registration Event in a pre-call setup\n");
+      break;
 
-    // Setup the new IAXCall
-    // Associate the call to the session.
-    call->setSession(event->session);
+    case IAX_EVENT_REGREQ:
+      // Received when someone wants to register to us!?!
+      // Asterisk receives and answers to that, not us, we're a phone.
+      _debug("Registration by a peer, don't allow it\n");
+      break;
 
-    // setCallAudioLocal(call);
-    call->setCodecMap(Manager::instance().getCodecDescriptorMap());
-    call->setConnectionState(Call::Progressing);
+    case IAX_EVENT_CONNECT:
+      // We've got an incoming call! Yikes!
+      _debug("> IAX_EVENT_CONNECT (receive)\n");
 
+      id = Manager::instance().getNewCallID();
 
-    if (event->ies.calling_number)
-      call->setPeerNumber(std::string(event->ies.calling_number));
-    if (event->ies.calling_name)
-      call->setPeerName(std::string(event->ies.calling_name));
 
-    if (Manager::instance().incomingCall(call, getAccountID())) {
-      /** @todo Faudra considérer éventuellement le champ CODEC PREFS pour
-       * l'établissement du codec de transmission */
+      call = new IAXCall(id, Call::Incoming);
 
-      // Remote lists its capabilities
-      int format = call->getFirstMatchingFormat(event->ies.capability);
-      // Remote asks for preferred codec voiceformat
-      int pref_format = call->getFirstMatchingFormat(event->ies.format);
+      if (!call) {
+	_debug("! IAX Failure: unable to create an incoming call");
+	return;
+      }
 
-      // Priority to remote's suggestion. In case it's a forwarding, no transcoding
-      // will be needed from the server, thus less latency.
-      if (pref_format)
-	format = pref_format;
+      // Setup the new IAXCall
+      // Associate the call to the session.
+      call->setSession(event->session);
 
-      iax_accept(event->session, format);
-      iax_ring_announce(event->session);
+      // setCallAudioLocal(call);
+      call->setCodecMap(Manager::instance().getCodecDescriptorMap());
+      call->setConnectionState(Call::Progressing);
 
-      addCall(call);
-    } else {
-      // reject call, unable to add it
-      iax_reject(event->session, (char*)reason.c_str());
 
-      delete call; call = NULL;
-    }
+      if (event->ies.calling_number)
+	call->setPeerNumber(std::string(event->ies.calling_number));
+      if (event->ies.calling_name)
+	call->setPeerName(std::string(event->ies.calling_name));
 
-    break;
-    
-  case IAX_EVENT_HANGUP:
-    // Remote peer hung up
-    call = iaxFindCallBySession(event->session);
-    id = call->getCallId();
-
-    Manager::instance().peerHungupCall(id);
-    removeCall(id);
-    break;
-    
-  case IAX_EVENT_TIMEOUT: // timeout for an unknown session
-    
-    break;
-    
-  case IAX_IE_MSGCOUNT:	
-    //_debug("messssssssssssssssssssssssssssssssssssssssssssssssages\n");
-    break;
-
-  default:
-    _debug("Unknown event type (in precall): %d\n", event->etype);
+      if (Manager::instance().incomingCall(call, getAccountID())) {
+	/** @todo Faudra considérer éventuellement le champ CODEC PREFS pour
+	 * l'établissement du codec de transmission */
+
+	// Remote lists its capabilities
+	int format = call->getFirstMatchingFormat(event->ies.capability);
+	// Remote asks for preferred codec voiceformat
+	int pref_format = call->getFirstMatchingFormat(event->ies.format);
+
+	// Priority to remote's suggestion. In case it's a forwarding, no transcoding
+	// will be needed from the server, thus less latency.
+	if (pref_format)
+	  format = pref_format;
+
+	iax_accept(event->session, format);
+	iax_ring_announce(event->session);
+
+	addCall(call);
+      } else {
+	// reject call, unable to add it
+	iax_reject(event->session, (char*)reason.c_str());
+
+	delete call; call = NULL;
+      }
+
+      break;
+
+    case IAX_EVENT_HANGUP:
+      // Remote peer hung up
+      call = iaxFindCallBySession(event->session);
+      id = call->getCallId();
+
+      Manager::instance().peerHungupCall(id);
+      removeCall(id);
+      break;
+
+    case IAX_EVENT_TIMEOUT: // timeout for an unknown session
+
+      break;
+
+    case IAX_IE_MSGCOUNT:	
+      //_debug("messssssssssssssssssssssssssssssssssssssssssssssssages\n");
+      break;
+
+    default:
+      _debug("Unknown event type (in precall): %d\n", event->etype);
   }
-  
+
 }
 
-int 
+  int 
 IAXVoIPLink::iaxCodecMapToFormat(IAXCall* call)
 {
   CodecOrder map = call->getCodecMap().getActiveCodecs();
diff --git a/src/iaxvoiplink.h b/src/iaxvoiplink.h
index ea67145ede..3a8c3fbd4a 100644
--- a/src/iaxvoiplink.h
+++ b/src/iaxvoiplink.h
@@ -1,8 +1,8 @@
 /*
- *  Copyright (C) 2006-2007 Savoir-Faire Linux inc.
+ *  Copyright (C) 2006-2007-2008 Savoir-Faire Linux inc.
+ *  Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com>
  *  Author: Alexandre Bourget <alexandre.bourget@savoirfairelinux.com>
  *  Author: Yan Morin <yan.morin@savoirfairelinux.com>
- *  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
@@ -24,9 +24,9 @@
 #include "voiplink.h"
 #include <iax2/iax-client.h>
 #include "global.h"
-#include <samplerate.h>
 
 #include "audio/codecDescriptor.h"
+#include "samplerateconverter.h"
 
 class EventThread;
 class IAXCall;
@@ -279,31 +279,17 @@ class IAXVoIPLink : public VoIPLink
     /** Connection to audio card/device */
     AudioLayer* audiolayer;
 
-    /** When we receive data, we decode it inside this buffer */
-    int16* _receiveDataDecoded;
-    /** When we send data, we encode it inside this buffer*/
-    unsigned char* _sendDataEncoded;
-
-    /** After that we send the data inside this buffer if there is a format conversion or rate conversion. */
-    /* Also use for getting mic-ringbuffer data */
-    SFLDataFormat* _dataAudioLayer;
-
-    /** Buffer for 8000hz samples in conversion */
-    float32* _floatBuffer8000;
-    /** Buffer for 48000hz samples in conversion */ 
-    float32* _floatBuffer48000;
-
-    /** Buffer for 8000hz samples for mic conversion */
-    int16* _intBuffer8000;
-
-    /** libsamplerate converter for incoming voice */
-    SRC_STATE*    _src_state_spkr;
+    /** Mic-data related buffers */
+    SFLDataFormat* micData;
+    SFLDataFormat* micDataConverted;
+    unsigned char* micDataEncoded;
 
-    /** libsamplerate converter for outgoing voice */
-    SRC_STATE*    _src_state_mic;
+    /** Speaker-data related buffers */
+    SFLDataFormat* spkrDataDecoded;
+    SFLDataFormat* spkrDataConverted;
 
-    /** libsamplerate error */
-    int           _src_err;
+    /** Sample rate converter object */
+    SamplerateConverter* converter;
 
 };
 
diff --git a/src/samplerateconverter.cpp b/src/samplerateconverter.cpp
index e9285a3d27..126c5d957c 100644
--- a/src/samplerateconverter.cpp
+++ b/src/samplerateconverter.cpp
@@ -19,71 +19,98 @@
 #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);
+  // Default values
+  _frequence = Manager::instance().getConfigInt( AUDIO , ALSA_SAMPLE_RATE ); // 44100;
+  _framesize = Manager::instance().getConfigInt( AUDIO , ALSA_FRAME_SIZE );
+
+  init();
+}
 
-  int nbSamplesMax = (int) ( 44100 * 20 /1000); // TODO Make this generic
-  _floatBufferDown  = new float32[nbSamplesMax];
-  _floatBufferUp = new float32[nbSamplesMax];
+SamplerateConverter::SamplerateConverter( int freq , int fs ) {
 
+  _frequence = freq ;
+  _framesize = fs ;
+  
+  init();
 }
 
 SamplerateConverter::~SamplerateConverter( void ) {
 
-  delete [] _floatBufferUp; _floatBufferUp = NULL;
-  delete [] _floatBufferDown; _floatBufferDown = NULL;
+  delete [] _floatBufferUpMic; _floatBufferUpMic = NULL;
+  delete [] _floatBufferDownMic; _floatBufferDownMic = NULL;
+
+  delete [] _floatBufferUpSpkr; _floatBufferUpSpkr = NULL;
+  delete [] _floatBufferDownSpkr; _floatBufferDownSpkr = NULL;
 
   // libSamplerateConverter-related
   _src_state_mic  = src_delete(_src_state_mic);
   _src_state_spkr = src_delete(_src_state_spkr);
 }
 
+void SamplerateConverter::init( 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) ( getFrequence() * getFramesize() / 1000 );
+  _floatBufferDownMic  = new float32[nbSamplesMax];
+  _floatBufferUpMic = new float32[nbSamplesMax];
+  _floatBufferDownSpkr  = new float32[nbSamplesMax];
+  _floatBufferUpSpkr = new float32[nbSamplesMax];
+}
+
+//TODO Add ifdef for int16 or float32 type
 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 )
+  int nbSamplesMax = (int) ( samplerate2 * getFramesize() / 1000 );
+  if( upsampleFactor != 1 && dataIn != NULL )
   {
-    _debug("Begin upsample data\n");
     SRC_DATA src_data;
-    src_data.data_in = _floatBufferDown;
-    src_data.data_out = _floatBufferUp;
+    src_data.data_in = _floatBufferDownSpkr;
+    src_data.data_out = _floatBufferUpSpkr;
     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);
+  //_debug("upsample %d %d %f %d\n" , src_data.input_frames , src_data.output_frames, src_data.src_ratio , nbSamples);
+    src_short_to_float_array( dataIn , _floatBufferDownSpkr, nbSamples);
+  //_debug("upsample %d %f %d\n" ,  src_data.output_frames, src_data.src_ratio , nbSamples);
     src_process(_src_state_spkr, &src_data);
+  //_debug("upsample %d %d %d\n" , samplerate1, samplerate2 , nbSamples);
     nbSamples  = ( src_data.output_frames_gen > nbSamplesMax) ? nbSamplesMax : src_data.output_frames_gen;		
-    src_float_to_short_array(_floatBufferUp, dataOut, nbSamples);
+    src_float_to_short_array(_floatBufferUpSpkr, dataOut, nbSamples);
+  //_debug("upsample %d %d %d\n" , samplerate1, samplerate2 , nbSamples);
   }
   return nbSamples;
-
 }
 
+//TODO Add ifdef for int16 or float32 type
 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
+  double downsampleFactor = (double)samplerate1 / samplerate2;
+  //_debug("factor = %f\n" , downsampleFactor);
+  int nbSamplesMax = (int) ( samplerate1 * getFramesize() / 1000 );
   if ( downsampleFactor != 1)
   {
     SRC_DATA src_data;	
-    src_data.data_in = _floatBufferUp;
-    src_data.data_out = _floatBufferDown;
+    src_data.data_in = _floatBufferUpMic;
+    src_data.data_out = _floatBufferDownMic;
     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);
+  //_debug("downsample %d %f %d\n" ,  src_data.output_frames, src_data.src_ratio , nbSamples);
+    src_short_to_float_array( dataIn, _floatBufferUpMic, nbSamples );
+  //_debug("downsample %d %f %d\n" ,  src_data.output_frames, src_data.src_ratio , nbSamples);
     src_process(_src_state_mic, &src_data);
+  //_debug("downsample %d %f %d\n" ,  src_data.output_frames, src_data.src_ratio , nbSamples);
     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");
+  //_debug("downsample %d %f %d\n" ,  src_data.output_frames, src_data.src_ratio , nbSamples);
+    src_float_to_short_array( _floatBufferDownMic , dataOut , nbSamples );
   }
   return nbSamples;
 }
diff --git a/src/samplerateconverter.h b/src/samplerateconverter.h
index bbb5886f60..86ea175319 100644
--- a/src/samplerateconverter.h
+++ b/src/samplerateconverter.h
@@ -23,11 +23,13 @@
 #include <math.h>
 
 #include "global.h"
+#include "manager.h"
 
 class SamplerateConverter {
   public:
     /** Constructor */
     SamplerateConverter( void );
+    SamplerateConverter( int freq , int fs );
     /** Destructor */
     ~SamplerateConverter( void );
 
@@ -51,19 +53,28 @@ class SamplerateConverter {
      */
     int downsampleData( SFLDataFormat* dataIn , SFLDataFormat* dataOut , int samplerate1 , int samplerate2 , int nbSamples );
 
-  private:
-    /** Downsampled float buffer */
-    float32* _floatBufferDown;
+    int getFrequence( void ) { return _frequence; }
 
-    /** Upsampled float buffer */
-    float32* _floatBufferUp;
+    int getFramesize( void ) { return _framesize; } 
 
-    /** libSamplerateConverter converter for incoming voice */
-    SRC_STATE*    _src_state_spkr;
+  private:
+    void init( void );
 
+    /** Audio layer caracteristics */
+    int _frequence;
+    int _framesize;
+
+    /** Downsampled/Upsampled float buffers for the mic data processing */
+    float32* _floatBufferDownMic;
+    float32* _floatBufferUpMic;
     /** libSamplerateConverter converter for outgoing voice */
     SRC_STATE*    _src_state_mic;
 
+    /** Downsampled/Upsampled float buffers for the speaker data processing */
+    float32* _floatBufferDownSpkr;
+    float32* _floatBufferUpSpkr;
+    /** libSamplerateConverter converter for incoming voice */
+    SRC_STATE*    _src_state_spkr;
     /** libSamplerateConverter error */
     int _src_err;
 };
-- 
GitLab