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