diff --git a/sflphone-common/src/audio/algorithm.h b/sflphone-common/src/audio/algorithm.h index 4b897b9da70f632bf7bef0bfacc7d125c8a24d06..e0f177a6266445df46b79f5a41486512b2e90c53 100644 --- a/sflphone-common/src/audio/algorithm.h +++ b/sflphone-common/src/audio/algorithm.h @@ -64,16 +64,10 @@ class Algorithm * for audio processing that require synchronization between spkrdata and */ virtual int process (SFLDataFormat *inputData, SFLDataFormat *outputData, int nbBytes) = 0; - - /** - * Class implementing this interface must define this function - * for audio processing that require synchronization between spkr and mic - * \param micData - * \param spkrData - * \param outputData + /* + * Ensure that implementors of this interface will be deleted properly + * if we delete them via a pointer to their base class. */ - virtual void process (SFLDataFormat *micData, SFLDataFormat *spkrData, SFLDataFormat *outputData, int nbBytes) = 0; - virtual ~Algorithm() {}; }; diff --git a/sflphone-common/src/audio/alsa/alsalayer.cpp b/sflphone-common/src/audio/alsa/alsalayer.cpp index 4261eb4896e793f6e50b215e233b7eb5b846af78..a05eef17780b702cb48c03cabd5ae16a09730dcf 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)); @@ -830,7 +830,6 @@ void AlsaLayer::audioCallback (void) AudioLoop *file_tone; SFLDataFormat *out = NULL; - SFLDataFormat *rsmpl_out = NULL; notifyincomingCall(); @@ -860,7 +859,11 @@ void AlsaLayer::audioCallback (void) memset (out, 0, toGet); if (out) { - _urgentRingBuffer.Get (out, toGet, spkrVolume); + _urgentRingBuffer.Get (out, toGet); + if (spkrVolume!=100) + for (int i=0; i<toGet / sizeof (SFLDataFormat); i++) + out[i] = out[i] * spkrVolume / 100; + write (out, toGet, _PlaybackHandle); free (out); } @@ -924,24 +927,18 @@ void AlsaLayer::audioCallback (void) memset (out, 0, maxNbBytesToGet); if (normalAvailBytes) { - - getMainBuffer()->getData (out, toGet, spkrVolume); + getMainBuffer()->getData (out, toGet); + if (spkrVolume!=100) + for (int i=0; i<toGet / sizeof (SFLDataFormat); i++) + out[i] = out[i] * spkrVolume / 100; if (_mainBufferSampleRate && ( (int) _audioSampleRate != _mainBufferSampleRate)) { + SFLDataFormat *rsmpl_out = (SFLDataFormat*) malloc (playbackAvailBytes); + memset (out, 0, playbackAvailBytes); - // Do sample rate conversion - int nb_sample_down = toGet / sizeof (SFLDataFormat); - - if (rsmpl_out) { - rsmpl_out = (SFLDataFormat*) malloc (playbackAvailBytes); - memset (out, 0, playbackAvailBytes); - - int nbSample = _converter->upsampleData ( (SFLDataFormat*) out, rsmpl_out, _mainBufferSampleRate, _audioSampleRate, nb_sample_down); - write (rsmpl_out, nbSample*sizeof (SFLDataFormat), _PlaybackHandle); - free (rsmpl_out); - } - - rsmpl_out = 0; + _converter->resample ( (SFLDataFormat*) out, rsmpl_out, _mainBufferSampleRate, _audioSampleRate, toGet / sizeof (SFLDataFormat)); + write (rsmpl_out, toGet, _PlaybackHandle); + free (rsmpl_out); } else { @@ -1003,7 +1000,6 @@ void AlsaLayer::audioCallback (void) // Additionally handle the mic's audio stream int micAvailBytes; - int micAvailPut; int toPut; SFLDataFormat* in = NULL; @@ -1018,7 +1014,6 @@ void AlsaLayer::audioCallback (void) if (micAvailBytes <= 0) return; - micAvailPut = getMainBuffer()->availForPut(); toPut = (micAvailBytes <= framesPerBufferAlsa) ? micAvailBytes : framesPerBufferAlsa; in = (SFLDataFormat*) malloc (toPut * sizeof (SFLDataFormat)); toPut = read (in, toPut* sizeof (SFLDataFormat)); @@ -1031,14 +1026,11 @@ void AlsaLayer::audioCallback (void) SFLDataFormat* rsmpl_out = (SFLDataFormat*) malloc (framesPerBufferAlsa * sizeof (SFLDataFormat)); - int nbSample = toPut / sizeof (SFLDataFormat); - int nb_sample_up = nbSample; - - nbSample = _converter->downsampleData ( (SFLDataFormat*) in, rsmpl_out, _mainBufferSampleRate, _audioSampleRate, nb_sample_up); + _converter->resample ( (SFLDataFormat*) in, rsmpl_out, _mainBufferSampleRate, _audioSampleRate, toPut / sizeof (SFLDataFormat)); - _audiofilter->processAudio (rsmpl_out, nbSample*sizeof (SFLDataFormat)); + _audiofilter->processAudio (rsmpl_out, toPut); - getMainBuffer()->putData (rsmpl_out, nbSample * sizeof (SFLDataFormat)); + getMainBuffer()->putData (rsmpl_out, toPut); free (rsmpl_out); } else { diff --git a/sflphone-common/src/audio/audiolayer.cpp b/sflphone-common/src/audio/audiolayer.cpp index 1615d97c71317f10ba23ef9eac06cedcbbe9baf0..330a7858fa9ce4c0d1378191d3612315bab3c2dc 100644 --- a/sflphone-common/src/audio/audiolayer.cpp +++ b/sflphone-common/src/audio/audiolayer.cpp @@ -48,37 +48,11 @@ void AudioLayer::flushUrgent (void) } -int AudioLayer::putUrgent (void* buffer, int toCopy) +void AudioLayer::putUrgent (void* buffer, int toCopy) { - int a; - ost::MutexLock guard (_mutex); - a = _urgentRingBuffer.AvailForPut(); - - if (a >= toCopy) { - return _urgentRingBuffer.Put (buffer, toCopy); - } else { - return _urgentRingBuffer.Put (buffer, a); - } - - return 0; -} - -int AudioLayer::putMain (void *buffer, int toCopy, std::string call_id) -{ - int a; - - ost::MutexLock guard (_mutex); - a = getMainBuffer()->availForPut (call_id); - - if (a >= toCopy) { - return getMainBuffer()->putData (buffer, toCopy, call_id); - } else { - _debug ("Chopping sound, Ouch! RingBuffer full ?"); - return getMainBuffer()->putData (buffer, a, call_id); - } - return 0; + _urgentRingBuffer.Put (buffer, toCopy); } void AudioLayer::notifyincomingCall() diff --git a/sflphone-common/src/audio/audiolayer.h b/sflphone-common/src/audio/audiolayer.h index 89ea65bb9be66a8e6d4c37d9278e0b66afc068b3..eb83ed7ffd5387b9340cfbdd9a31eaee4fd5cfdb 100644 --- a/sflphone-common/src/audio/audiolayer.h +++ b/sflphone-common/src/audio/audiolayer.h @@ -134,17 +134,8 @@ class AudioLayer * Copy data in the urgent buffer. * @param buffer The buffer containing the data to be played ( ringtones ) * @param toCopy The size of the buffer - * @return int The number of bytes copied in the urgent buffer */ - int putUrgent (void* buffer, int toCopy); - - /** - * Put voice data in the main sound buffer - * @param buffer The buffer containing the voice data () - * @param toCopy The size of the buffer - * @return int The number of bytes copied - */ - int putMain (void* buffer, int toCopy, std::string call_id = default_id); + void putUrgent (void* buffer, int toCopy); void flushMain (void); diff --git a/sflphone-common/src/audio/audioloop.cpp b/sflphone-common/src/audio/audioloop.cpp index 4053e82f5e77c67acb826b8da16649f30265a593..ebfc29edddeafdfaf4394bb1fff620faeb7f06a8 100644 --- a/sflphone-common/src/audio/audioloop.cpp +++ b/sflphone-common/src/audio/audioloop.cpp @@ -34,7 +34,7 @@ #include "audioloop.h" #include <math.h> -#include <strings.h> +#include <cstring> AudioLoop::AudioLoop() :_buffer (0), _size (0), _pos (0), _sampleRate (0) { @@ -65,8 +65,7 @@ AudioLoop::getNext (SFLDataFormat* output, int nb, short volume) block = _size-pos; } - // src, dest, len - bcopy (_buffer+pos, output, block*sizeof (SFLDataFormat)); // short>char conversion + memcpy(output, _buffer+pos, block*sizeof (SFLDataFormat)); // short>char conversion if (volume!=100) { for (int i=0; i<block; i++) { diff --git a/sflphone-common/src/audio/audioloop.h b/sflphone-common/src/audio/audioloop.h index 4d1ceece8dfc33a23e924f900e9a0ad9f32cf77c..2eb1c7bc4e86c1e6e366250529888dedad5d8a78 100644 --- a/sflphone-common/src/audio/audioloop.h +++ b/sflphone-common/src/audio/audioloop.h @@ -84,14 +84,14 @@ class AudioLoop /** The data buffer */ SFLDataFormat* _buffer; - /** Number of int16 inside the buffer, not the delay */ + /** Number of samples inside the buffer */ int _size; /** current position, set to 0, when initialize */ int _pos; /** Sample rate */ - int _sampleRate; + unsigned int _sampleRate; private: diff --git a/sflphone-common/src/audio/audioprocessing.cpp b/sflphone-common/src/audio/audioprocessing.cpp index e2b42c283bbcc8b2f09d8151aafe0cca6f022fff..f7aba723f50b2bab92d9082c534256696a9e0421 100644 --- a/sflphone-common/src/audio/audioprocessing.cpp +++ b/sflphone-common/src/audio/audioprocessing.cpp @@ -71,10 +71,3 @@ int AudioProcessing::processAudio (SFLDataFormat *inputData, SFLDataFormat *outp else return 0; } - - -void AudioProcessing::processAudio (SFLDataFormat *micData, SFLDataFormat *spkrData, SFLDataFormat *outputData, int nbBytes) -{ - if (_algorithm) - _algorithm->process (micData, spkrData, outputData, nbBytes); -} diff --git a/sflphone-common/src/audio/audioprocessing.h b/sflphone-common/src/audio/audioprocessing.h index c92b7503d10f57b3e4528c4c9ab8b5e4d4fd2371..195549a4d60b43c12d977f2dc7f3255492a3cff4 100644 --- a/sflphone-common/src/audio/audioprocessing.h +++ b/sflphone-common/src/audio/audioprocessing.h @@ -83,11 +83,6 @@ class AudioProcessing */ int processAudio (SFLDataFormat *inputData, SFLDataFormat *outputData, int nbBytes); - /** - * Process some audio data. - */ - void processAudio (SFLDataFormat *micData, SFLDataFormat *spkrData, SFLDataFormat *outputData, int nbBytes); - private: Algorithm *_algorithm; diff --git a/sflphone-common/src/audio/audiorecorder.cpp b/sflphone-common/src/audio/audiorecorder.cpp index e2f5b37aa7feff843d595d8f123e3fc65fb10d50..4b1ddfc7d9cd1ef1bf214db1c4aa644c29792561 100644 --- a/sflphone-common/src/audio/audiorecorder.cpp +++ b/sflphone-common/src/audio/audiorecorder.cpp @@ -71,7 +71,7 @@ void AudioRecorder::run (void) int toGet = (availBytes < bufferLength) ? availBytes : bufferLength; - mbuffer->getData (buffer, toGet, 100, recorderId); + mbuffer->getData (buffer, toGet, recorderId); if (availBytes > 0) { diff --git a/sflphone-common/src/audio/audiortp/AudioRtpRecordHandler.cpp b/sflphone-common/src/audio/audiortp/AudioRtpRecordHandler.cpp index 6cc6862971f6d76f30d811ffcafa9304fc16c578..c27b1533a3fa905e186bfad51f2d260bba709510 100644 --- a/sflphone-common/src/audio/audiortp/AudioRtpRecordHandler.cpp +++ b/sflphone-common/src/audio/audiortp/AudioRtpRecordHandler.cpp @@ -67,60 +67,31 @@ AudioRtpRecord::~AudioRtpRecord() { _debug ("AudioRtpRecord: Delete audio rtp internal data"); - if (_micData) - delete [] _micData; + delete [] _micData; - _micData = NULL; + delete [] _micDataConverted; - if (_micDataConverted) - delete [] _micDataConverted; + delete [] _micDataEncoded; - _micDataConverted = NULL; + delete [] _micDataEchoCancelled; - if (_micDataEncoded) - delete [] _micDataEncoded; + delete [] _spkrDataDecoded; - if(_micDataEchoCancelled) - delete [] _micDataEchoCancelled; + delete [] _spkrDataConverted; - _micDataEncoded = NULL; - - if (_spkrDataDecoded) - delete [] _spkrDataDecoded; - - _spkrDataDecoded = NULL; - - if (_spkrDataConverted) - delete [] _spkrDataConverted; - - _spkrDataConverted = NULL; - - - if (_converter) - delete _converter; - - _converter = NULL; + delete _converter; audioCodecMutex.enter(); - if (_audioCodec) { - delete _audioCodec; - _audioCodec = NULL; - } + delete _audioCodec; audioCodecMutex.leave(); audioProcessMutex.enter(); - if (_audioProcess) { - delete _audioProcess; - _audioProcess = NULL; - } + delete _audioProcess; - if (_noiseSuppress) { - delete _noiseSuppress; - _noiseSuppress = NULL; - } + delete _noiseSuppress; audioProcessMutex.leave(); } @@ -188,7 +159,8 @@ void AudioRtpRecordHandler::initBuffers() // initialize SampleRate converter using AudioLayer's sampling rate // (internal buffers initialized with maximal sampling rate and frame size) - _audioRtpRecord._converter = new SamplerateConverter (); + int rate = getCodecSampleRate(); + _audioRtpRecord._converter = new SamplerateConverter (rate); int nbSamplesMax = (int) ( (getCodecSampleRate() * getCodecFrameSize() / 1000)); _audioRtpRecord._micData = new SFLDataFormat[nbSamplesMax]; @@ -262,47 +234,35 @@ int AudioRtpRecordHandler::processDataEncode (void) unsigned char *micDataEncoded = _audioRtpRecord._micDataEncoded; SFLDataFormat *micDataConverted = _audioRtpRecord._micDataConverted; - int codecFrameSize = getCodecFrameSize(); int codecSampleRate = getCodecSampleRate(); - int mainBufferSampleRate = Manager::instance().getMainBuffer()->getInternalSamplingRate(); // compute codec framesize in ms - float fixedCodecFramesize = computeCodecFrameSize (codecFrameSize, codecSampleRate); - + float fixedCodecFramesize = ((float)getCodecFrameSize() * 1000.0) / (float)codecSampleRate; // compute nb of byte to get coresponding to 20 ms at audio layer frame size (44.1 khz) - int bytesToGet = computeNbByteAudioLayer (mainBufferSampleRate, fixedCodecFramesize); - - // available bytes inside ringbuffer - int availBytesFromMic = Manager::instance().getMainBuffer()->availForGet (id_); + int bytesToGet = (int) ( ( (float) mainBufferSampleRate * fixedCodecFramesize * sizeof (SFLDataFormat)) / 1000.0); - if (availBytesFromMic < bytesToGet) + if (Manager::instance().getMainBuffer()->availForGet (id_) < bytesToGet) return 0; - // Get bytes from micRingBuffer to data_from_mic - int nbSample = Manager::instance().getMainBuffer()->getData (micData, bytesToGet, 100, id_) / sizeof (SFLDataFormat); + int bytes = Manager::instance().getMainBuffer()->getData (micData, bytesToGet, id_); + if (bytes == 0) + return 0; - // process mic fade in if (!_audioRtpRecord._micFadeInComplete) - _audioRtpRecord._micFadeInComplete = fadeIn (micData, nbSample, &_audioRtpRecord._micAmplFactor); - - if (nbSample == 0) - return nbSample; + _audioRtpRecord._micFadeInComplete = fadeIn (micData, bytes / sizeof(SFLDataFormat), &_audioRtpRecord._micAmplFactor); // nb bytes to be sent over RTP - int compSize = 0; + int compSize; // test if resampling is required if (codecSampleRate != mainBufferSampleRate) { - - int nbSampleUp = nbSample; - - nbSample = _audioRtpRecord._converter->downsampleData (micData, micDataConverted, codecSampleRate, mainBufferSampleRate, nbSampleUp); + _audioRtpRecord._converter->resample (micData, micDataConverted, codecSampleRate, mainBufferSampleRate, bytes / sizeof(SFLDataFormat)); _audioRtpRecord.audioProcessMutex.enter(); if (Manager::instance().audioPreference.getNoiseReduce()) { - _audioRtpRecord._audioProcess->processAudio (micDataConverted, nbSample * sizeof (SFLDataFormat)); + _audioRtpRecord._audioProcess->processAudio (micDataConverted, bytes); } if(Manager::instance().getEchoCancelState() == "enabled") { @@ -313,22 +273,18 @@ int AudioRtpRecordHandler::processDataEncode (void) _audioRtpRecord.audioCodecMutex.enter(); - compSize = _audioRtpRecord._audioCodec->encode (micDataEncoded, micData, nbSample * sizeof (SFLDataFormat)); + compSize = _audioRtpRecord._audioCodec->encode (micDataEncoded, micData, bytes); _audioRtpRecord.audioCodecMutex.leave(); - } else { - + } else { // no resampling required _audioRtpRecord.audioProcessMutex.enter(); - if (Manager::instance().audioPreference.getNoiseReduce()) { - _audioRtpRecord._audioProcess->processAudio (micData, nbSample * sizeof (SFLDataFormat)); - } + if (Manager::instance().audioPreference.getNoiseReduce()) + _audioRtpRecord._audioProcess->processAudio (micData, bytes); - if(Manager::instance().getEchoCancelState() == "enabled") { + if(Manager::instance().getEchoCancelState() == "enabled") echoCanceller.getData(micData); - } - #ifdef DUMP_PROCESS_DATA_ENCODE teststream.write(reinterpret_cast<char *>(micData), nbSample * sizeof(SFLDataFormat)); @@ -337,10 +293,7 @@ int AudioRtpRecordHandler::processDataEncode (void) _audioRtpRecord.audioProcessMutex.leave(); _audioRtpRecord.audioCodecMutex.enter(); - - // no resampling required - compSize = _audioRtpRecord._audioCodec->encode (micDataEncoded, micData, nbSample * sizeof (SFLDataFormat)); - + compSize = _audioRtpRecord._audioCodec->encode (micDataEncoded, micData, bytes); _audioRtpRecord.audioCodecMutex.leave(); } @@ -376,15 +329,14 @@ void AudioRtpRecordHandler::processDataDecode (unsigned char *spkrData, unsigned // test if resampling is required if (codecSampleRate != mainBufferSampleRate) { // Do sample rate conversion - nbSample = _audioRtpRecord._converter->upsampleData (spkrDataDecoded, spkrDataConverted, codecSampleRate, mainBufferSampleRate, nbSample); + _audioRtpRecord._converter->resample (spkrDataDecoded, spkrDataConverted, codecSampleRate, mainBufferSampleRate, nbSample); if(Manager::instance().getEchoCancelState() == "enabled") { - echoCanceller.putData(spkrDataConverted, nbSample * sizeof(SFLDataFormat)); + echoCanceller.putData(spkrDataConverted, expandedSize); } // put data in audio layer, size in byte - Manager::instance().getMainBuffer()->putData (spkrDataConverted, nbSample * sizeof (SFLDataFormat), id_); - + Manager::instance().getMainBuffer()->putData (spkrDataConverted, expandedSize, id_); } else { if(Manager::instance().getEchoCancelState() == "enabled") { diff --git a/sflphone-common/src/audio/audiortp/AudioRtpRecordHandler.h b/sflphone-common/src/audio/audiortp/AudioRtpRecordHandler.h index 42fa78d6d543726a1b2ed1831173249db8c3cfd3..87bd6e4814e0021486d3de23beef46d0d1c039a7 100644 --- a/sflphone-common/src/audio/audiortp/AudioRtpRecordHandler.h +++ b/sflphone-common/src/audio/audiortp/AudioRtpRecordHandler.h @@ -174,14 +174,6 @@ class AudioRtpRecordHandler return _audioRtpRecord._micDataEncoded; } - float computeCodecFrameSize (int codecSamplePerFrame, int codecClockRate) const { - return ( (float) codecSamplePerFrame * 1000.0) / (float) codecClockRate; - } - - int computeNbByteAudioLayer (int mainBufferSamplingRate, float codecFrameSize) const { - return (int) ( ( (float) mainBufferSamplingRate * codecFrameSize * sizeof (SFLDataFormat)) / 1000.0); - } - void init (void); /** diff --git a/sflphone-common/src/audio/dcblocker.cpp b/sflphone-common/src/audio/dcblocker.cpp index 08766e6774658f9eb05271419e9422d8d40a4cf4..0d83af22fe8d5446c49591007b5896f267b6a4f0 100644 --- a/sflphone-common/src/audio/dcblocker.cpp +++ b/sflphone-common/src/audio/dcblocker.cpp @@ -86,5 +86,3 @@ int DcBlocker::process (SFLDataFormat *inputData, SFLDataFormat *outputData, int return 0; } - -void DcBlocker::process (SFLDataFormat *micData UNUSED, SFLDataFormat *spkrData UNUSED, SFLDataFormat *outputData UNUSED, int nbBytes UNUSED) {} diff --git a/sflphone-common/src/audio/dcblocker.h b/sflphone-common/src/audio/dcblocker.h index ebaef02b2cad83a37bfda83903d5fea6dd4e615a..563fd82b99e27fe4b01ad58894cc0aa1f39c31a7 100644 --- a/sflphone-common/src/audio/dcblocker.h +++ b/sflphone-common/src/audio/dcblocker.h @@ -69,14 +69,6 @@ class DcBlocker : public Algorithm */ virtual int process (SFLDataFormat *inputData, SFLDataFormat *outputData, int nbBytes); - /** - * Perform echo cancellation, application must provide its own buffer - * \param micData containing mixed echo and voice data - * \param spkrData containing far-end voice data to be sent to speakers - * \param outputData containing the processed data - */ - virtual void process (SFLDataFormat *micData, SFLDataFormat *spkrData, SFLDataFormat *outputData, int nbBytes); - private: SFLDataFormat _y, _x, _xm1, _ym1; diff --git a/sflphone-common/src/audio/delaydetection.cpp b/sflphone-common/src/audio/delaydetection.cpp index 5ff2b8818f8267d8aed16c7c3dd3f707b2cf6ca3..a68f5588bbc7393eca4ed94a417e49350b6da21a 100644 --- a/sflphone-common/src/audio/delaydetection.cpp +++ b/sflphone-common/src/audio/delaydetection.cpp @@ -217,8 +217,6 @@ int DelayDetection::process (SFLDataFormat *intputData UNUSED, SFLDataFormat *ou return 0; } -void DelayDetection::process (SFLDataFormat *micData UNUSED, SFLDataFormat *spkrData UNUSED, SFLDataFormat *outputData UNUSED, int nbBytes UNUSED) {} - void DelayDetection::crossCorrelate (float *ref, float *seg, float *res, int refSize, int segSize) { diff --git a/sflphone-common/src/audio/delaydetection.h b/sflphone-common/src/audio/delaydetection.h index 45b5e6d1b6bd987c10afabd1114f998ea4152593..17aab0f41dbc0ef11668fa111f1a7de251727a59 100644 --- a/sflphone-common/src/audio/delaydetection.h +++ b/sflphone-common/src/audio/delaydetection.h @@ -114,8 +114,6 @@ class DelayDetection : public Algorithm virtual int process (SFLDataFormat *inputData, SFLDataFormat *outputData, int nbBytes); - virtual void process (SFLDataFormat *micData, SFLDataFormat *spkrData, SFLDataFormat *outputData, int nbBytes); - private: enum State { diff --git a/sflphone-common/src/audio/echocancel.cpp b/sflphone-common/src/audio/echocancel.cpp index 41008db3c56ea41c27a4d50ba3714d40a291ab40..5f2c47c37c610f4fac649afe05e2426ffa5c9b79 100644 --- a/sflphone-common/src/audio/echocancel.cpp +++ b/sflphone-common/src/audio/echocancel.cpp @@ -250,7 +250,7 @@ int EchoCancel::process (SFLDataFormat *inputData, SFLDataFormat *outputData, in _delayDetector.process (inputData, nbBytes); if (_spkrStoped) { - bcopy (inputData, outputData, nbBytes); + memcpy(outputData, inputData, nbBytes); return nbBytes; } @@ -299,7 +299,7 @@ int EchoCancel::process (SFLDataFormat *inputData, SFLDataFormat *outputData, in // echoFile->write((const char *)_tmpOut, byteSize); - bcopy (_tmpOut, outputData+ (nbFrame*_smplPerFrame), byteSize); + memcpy(outputData+ (nbFrame*_smplPerFrame), _tmpOut, byteSize); // used to sync with speaker _processedByte += byteSize; @@ -314,7 +314,7 @@ int EchoCancel::process (SFLDataFormat *inputData, SFLDataFormat *outputData, in performEchoCancelNoSpkr (_tmpMic, _tmpOut); - bcopy (_tmpOut, outputData+ (nbFrame*_smplPerFrame), byteSize); + memcpy (outputData+ (nbFrame*_smplPerFrame), _tmpOut, byteSize); ++nbFrame; } @@ -330,11 +330,6 @@ int EchoCancel::process (SFLDataFormat *inputData, SFLDataFormat *outputData, in return nbFrame * _smplPerFrame; } -void EchoCancel::process (SFLDataFormat *micData UNUSED, SFLDataFormat *spkrData UNUSED, SFLDataFormat *outputData UNUSED, int nbBytes UNUSED) -{ - -} - void EchoCancel::setSamplingRate (int smplRate) { diff --git a/sflphone-common/src/audio/echocancel.h b/sflphone-common/src/audio/echocancel.h index 594ba4d815e65342e3b66287babb77b5cf506cfd..66802d89f2259346f04d697e44358b2e46f79762 100644 --- a/sflphone-common/src/audio/echocancel.h +++ b/sflphone-common/src/audio/echocancel.h @@ -106,14 +106,6 @@ class EchoCancel : public Algorithm */ virtual int process (SFLDataFormat *inputData, SFLDataFormat *outputData, int nbBytes); - /** - * Perform echo cancellation, application must provide its own buffer - * \param micData containing mixed echo and voice data - * \param spkrData containing far-end voice data to be sent to speakers - * \param outputData containing the processed data - */ - virtual void process (SFLDataFormat *micData, SFLDataFormat *spkrData, SFLDataFormat *outputData, int nbBytes); - /** * Set echo canceller internal sampling rate, reset if sampling rate changed */ diff --git a/sflphone-common/src/audio/echosuppress.cpp b/sflphone-common/src/audio/echosuppress.cpp index b3df5b8f00251c84c3eb46d9577b7593837b2a91..4ea38262632489c03f2aaf38c83b82259dd4a192 100644 --- a/sflphone-common/src/audio/echosuppress.cpp +++ b/sflphone-common/src/audio/echosuppress.cpp @@ -74,5 +74,3 @@ int EchoSuppress::getData(SFLDataFormat *outputData) void EchoSuppress::process (SFLDataFormat *data UNUSED, int nbBytes UNUSED) {} int EchoSuppress::process (SFLDataFormat *inputData, SFLDataFormat *outputData, int nbBytes) { return 0; } - -void EchoSuppress::process (SFLDataFormat *micData UNUSED, SFLDataFormat *spkrData UNUSED, SFLDataFormat *outputData UNUSED, int nbBytes UNUSED) {} diff --git a/sflphone-common/src/audio/echosuppress.h b/sflphone-common/src/audio/echosuppress.h index 1298c77f4abae0ef5b056823e6754d3b62d43f43..a60c7152e7d2a7dfcdb9660e37373f19416073f9 100644 --- a/sflphone-common/src/audio/echosuppress.h +++ b/sflphone-common/src/audio/echosuppress.h @@ -40,16 +40,6 @@ public: * \param outputData containing */ virtual int process (SFLDataFormat *, SFLDataFormat *, int); - - /** - * Perform echo cancellation, application must provide its own buffer - * \param micData containing mixed echo and voice data - * \param spkrData containing far-end voice data to be sent to speakers - * \param outputData containing the processed data - * \param size in bytes - */ - virtual void process (SFLDataFormat *, SFLDataFormat *, SFLDataFormat *, int); - private: /** diff --git a/sflphone-common/src/audio/mainbuffer.cpp b/sflphone-common/src/audio/mainbuffer.cpp index c14096a9f7910abfce7535dfee3e44632de22880..0c6c281af7606b124b880259e8d0e536c2445abb 100644 --- a/sflphone-common/src/audio/mainbuffer.cpp +++ b/sflphone-common/src/audio/mainbuffer.cpp @@ -301,47 +301,16 @@ void MainBuffer::unBindAllHalfDuplexOut (std::string process_id) } -int MainBuffer::putData (void *buffer, int toCopy, std::string call_id) +void MainBuffer::putData (void *buffer, int toCopy, std::string call_id) { ost::MutexLock guard (_mutex); RingBuffer* ring_buffer = getRingBuffer (call_id); - - if (ring_buffer == NULL) { - return 0; - } - - int a; - - a = ring_buffer->AvailForPut(); - - if (a >= toCopy) { - - return ring_buffer->Put (buffer, toCopy); - - } else { - - return ring_buffer->Put (buffer, a); - } - + if (ring_buffer) + ring_buffer->Put (buffer, toCopy); } -int MainBuffer::availForPut (std::string call_id) -{ - - ost::MutexLock guard (_mutex); - - RingBuffer* ringbuffer = getRingBuffer (call_id); - - if (ringbuffer == NULL) - return 0; - else - return ringbuffer->AvailForPut(); - -} - - -int MainBuffer::getData (void *buffer, int toCopy, unsigned short volume, std::string call_id) +int MainBuffer::getData (void *buffer, int toCopy, std::string call_id) { ost::MutexLock guard (_mutex); @@ -356,7 +325,7 @@ int MainBuffer::getData (void *buffer, int toCopy, unsigned short volume, std::s CallIDSet::iterator iter_id = callid_set->begin(); if (iter_id != callid_set->end()) { - return getDataByID (buffer, toCopy, volume, *iter_id, call_id); + return getDataByID (buffer, toCopy, *iter_id, call_id); } else return 0; } else { @@ -370,7 +339,7 @@ int MainBuffer::getData (void *buffer, int toCopy, unsigned short volume, std::s int nbSmplToCopy = toCopy / sizeof (SFLDataFormat); SFLDataFormat mixBuffer[nbSmplToCopy]; memset (mixBuffer, 0, toCopy); - size = getDataByID (mixBuffer, toCopy, volume, *iter_id, call_id); + size = getDataByID (mixBuffer, toCopy, *iter_id, call_id); if (size > 0) { for (int k = 0; k < nbSmplToCopy; k++) { @@ -386,7 +355,7 @@ int MainBuffer::getData (void *buffer, int toCopy, unsigned short volume, std::s } -int MainBuffer::getDataByID (void *buffer, int toCopy, unsigned short volume, std::string call_id, std::string reader_id) +int MainBuffer::getDataByID (void *buffer, int toCopy, std::string call_id, std::string reader_id) { RingBuffer* ring_buffer = getRingBuffer (call_id); @@ -394,7 +363,7 @@ int MainBuffer::getDataByID (void *buffer, int toCopy, unsigned short volume, st return 0; } - return ring_buffer->Get (buffer, toCopy, volume, reader_id); + return ring_buffer->Get (buffer, toCopy, reader_id); } diff --git a/sflphone-common/src/audio/mainbuffer.h b/sflphone-common/src/audio/mainbuffer.h index 8d74dc3deb532cbf1ec122d46b727f1b958bcc86..5346d94f34bb8ba17f1d9648e45b6489687c658c 100644 --- a/sflphone-common/src/audio/mainbuffer.h +++ b/sflphone-common/src/audio/mainbuffer.h @@ -89,11 +89,9 @@ class MainBuffer void unBindAllHalfDuplexOut (std::string process_id); - int putData (void *buffer, int toCopy, std::string call_id = default_id); + void putData (void *buffer, int toCopy, std::string call_id = default_id); - int getData (void *buffer, int toCopy, unsigned short volume = 100, std::string call_id = default_id); - - int availForPut (std::string call_id = default_id); + int getData (void *buffer, int toCopy, std::string call_id = default_id); int availForGet (std::string call_id = default_id); @@ -133,7 +131,7 @@ class MainBuffer RingBuffer* getRingBuffer (std::string call_id); - int getDataByID (void *buffer, int toCopy, unsigned short volume, std::string call_id, std::string reader_id); + int getDataByID (void *buffer, int toCopy, std::string call_id, std::string reader_id); int availForGetByID (std::string call_id, std::string reader_id); diff --git a/sflphone-common/src/audio/noisesuppress.cpp b/sflphone-common/src/audio/noisesuppress.cpp index 2c7d09423e4771107b8a66f2245356570f0a119f..7016b5f10d1c87440d52d83095853a96e2566b2e 100644 --- a/sflphone-common/src/audio/noisesuppress.cpp +++ b/sflphone-common/src/audio/noisesuppress.cpp @@ -69,8 +69,6 @@ int NoiseSuppress::process (SFLDataFormat *inputData, SFLDataFormat *outputData, return 0; } -void NoiseSuppress::process (SFLDataFormat *micData, SFLDataFormat *spkrData, SFLDataFormat *outputData, int nbBytes) {} - void NoiseSuppress::initNewNoiseSuppressor (int smplPerFrame, int samplingRate) { _noiseState = speex_preprocess_state_init (smplPerFrame, samplingRate); diff --git a/sflphone-common/src/audio/noisesuppress.h b/sflphone-common/src/audio/noisesuppress.h index 6f54ccad84cbbdce402279f95476f068236f1866..19897cb4b0cb18e71e9fea4a643b0fffd4bb6278 100644 --- a/sflphone-common/src/audio/noisesuppress.h +++ b/sflphone-common/src/audio/noisesuppress.h @@ -70,11 +70,6 @@ class NoiseSuppress : public Algorithm */ virtual int process (SFLDataFormat *inputData, SFLDataFormat *outputData, int nbBytes); - /** - * Unused - */ - virtual void process (SFLDataFormat *micData, SFLDataFormat *spkrData, SFLDataFormat *outputData, int nbBytes); - private: void initNewNoiseSuppressor (int _smplPerFrame, int samplingRate); diff --git a/sflphone-common/src/audio/pulseaudio/audiostream.h b/sflphone-common/src/audio/pulseaudio/audiostream.h index 1af25cab930697930fd33d250d12f19e1404b65c..00d405efafd09274fdb02ec5815599b05fc95edc 100644 --- a/sflphone-common/src/audio/pulseaudio/audiostream.h +++ b/sflphone-common/src/audio/pulseaudio/audiostream.h @@ -74,14 +74,6 @@ public: */ ~AudioStream(); - /** - * Write data to the main abstraction ring buffer. - * @param buffer The buffer containing the data to be played - * @param toCopy The number of samples, in bytes - * @return int The number of bytes played - */ - int putMain(void* buffer, int toCopy); - /** * Write data to the urgent abstraction ring buffer. ( dtmf , double calls ) * @param buffer The buffer containing the data to be played diff --git a/sflphone-common/src/audio/pulseaudio/pulselayer.cpp b/sflphone-common/src/audio/pulseaudio/pulselayer.cpp index 03e3049d401b7ee886a3d653504a263908446f81..9cd8269f3c83f552454ed4322bc41ee14ed066bc 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(); @@ -744,7 +744,7 @@ void PulseLayer::writeToSpeaker (void) out = (SFLDataFormat*) pa_xmalloc (writeableSize); memset (out, 0, writeableSize); - _urgentRingBuffer.Get (out, writeableSize, 100); + _urgentRingBuffer.Get (out, writeableSize); pa_stream_write (playback->pulseStream(), out, writeableSize, NULL, 0, PA_SEEK_RELATIVE); @@ -768,7 +768,6 @@ void PulseLayer::writeToSpeaker (void) pa_stream_write (playback->pulseStream(), out, copied * sizeof (SFLDataFormat), NULL, 0, PA_SEEK_RELATIVE); pa_xfree (out); - } } else { @@ -794,42 +793,32 @@ void PulseLayer::writeToSpeaker (void) byteToGet = (normalAvailBytes < (int) (maxNbBytesToGet)) ? normalAvailBytes : maxNbBytesToGet; if (byteToGet) { - // Sending an odd number of byte breaks the audio! - if ( (byteToGet%2) != 0) { - byteToGet = byteToGet-1; - } + byteToGet &= ~1; out = (SFLDataFormat*) pa_xmalloc (maxNbBytesToGet); memset (out, 0, maxNbBytesToGet); - getMainBuffer()->getData (out, byteToGet, 100); + getMainBuffer()->getData (out, byteToGet); // test if resampling is required if (_mainBufferSampleRate && ( (int) _audioSampleRate != _mainBufferSampleRate)) { - SFLDataFormat* rsmpl_out = (SFLDataFormat*) pa_xmalloc (writeableSize); memset (out, 0, writeableSize); - // Do sample rate conversion - int nb_sample_down = byteToGet / sizeof (SFLDataFormat); + _converter->resample ( (SFLDataFormat*) out, rsmpl_out, _mainBufferSampleRate, _audioSampleRate, byteToGet / sizeof (SFLDataFormat)); - int nbSample = _converter->upsampleData ( (SFLDataFormat*) out, rsmpl_out, _mainBufferSampleRate, _audioSampleRate, nb_sample_down); - - if ( (nbSample*sizeof (SFLDataFormat)) > (unsigned int) writeableSize) { + if ( byteToGet > (unsigned int) writeableSize) _warn ("Audio: Error: nbsbyte exceed buffer length"); - } - // write resample data - pa_stream_write (playback->pulseStream(), rsmpl_out, nbSample*sizeof (SFLDataFormat), NULL, 0, PA_SEEK_RELATIVE); + pa_stream_write (playback->pulseStream(), rsmpl_out, byteToGet, NULL, 0, PA_SEEK_RELATIVE); - // free resampling buffer pa_xfree (rsmpl_out); } else { // write origin data pa_stream_write (playback->pulseStream(), out, byteToGet, NULL, 0, PA_SEEK_RELATIVE); - } + } // free audio buffer used to get data from pa_xfree (out); @@ -855,7 +844,6 @@ void PulseLayer::writeToSpeaker (void) _urgentRingBuffer.Discard (byteToGet); } - } void PulseLayer::readFromMic (void) @@ -880,16 +868,12 @@ void PulseLayer::readFromMic (void) SFLDataFormat* rsmpl_out = (SFLDataFormat*) pa_xmalloc (readableSize); memset (rsmpl_out, 0, readableSize); - int nbSample = r / sizeof (SFLDataFormat); - - int nb_sample_up = nbSample; - - nbSample = _converter->downsampleData ( (SFLDataFormat *) data, rsmpl_out, _mainBufferSampleRate, _audioSampleRate, nb_sample_up); + _converter->resample ( (SFLDataFormat *) data, rsmpl_out, _mainBufferSampleRate, _audioSampleRate, r / sizeof (SFLDataFormat)); // remove dc offset - _audiofilter->processAudio (rsmpl_out, nbSample*sizeof (SFLDataFormat)); + _audiofilter->processAudio (rsmpl_out, r); - getMainBuffer()->putData (rsmpl_out, nbSample*sizeof (SFLDataFormat)); + getMainBuffer()->putData (rsmpl_out, r); pa_xfree (rsmpl_out); diff --git a/sflphone-common/src/audio/ringbuffer.cpp b/sflphone-common/src/audio/ringbuffer.cpp index 2b15ef80b36f55a5b189e1f215f3ea17cd414348..2304b29709a76e8a647317273022403e014c4996 100644 --- a/sflphone-common/src/audio/ringbuffer.cpp +++ b/sflphone-common/src/audio/ringbuffer.cpp @@ -90,56 +90,30 @@ RingBuffer::flushAll () int RingBuffer::putLen() { - int mStart; - - if (_readpointer.size() >= 1) { - mStart = getSmallestReadPointer(); - } else { - mStart = 0; - } - - int length = (mEnd + mBufferSize - mStart) % mBufferSize; - - return length; + int mStart = (_readpointer.size() >= 1) ? getSmallestReadPointer() : 0; + return (mEnd + mBufferSize - mStart) % mBufferSize; } int RingBuffer::getLen (std::string call_id) { - - int mStart = getReadPointer (call_id); - - int length = (mEnd + mBufferSize - mStart) % mBufferSize; - - - // _debug(" *RingBuffer::getLen: buffer_id %s, call_id %s, mStart %i, mEnd %i, length %i, buffersie %i", buffer_id.c_str(), call_id.c_str(), mStart, mEnd, length, mBufferSize); - return length; - + return (mEnd + mBufferSize - getReadPointer (call_id)) % mBufferSize; } void RingBuffer::debug() { - int mStart = getSmallestReadPointer(); - - _debug ("Start=%d; End=%d; BufferSize=%d", mStart, mEnd, mBufferSize); + _debug ("Start=%d; End=%d; BufferSize=%d", getSmallestReadPointer(), mEnd, mBufferSize); } int RingBuffer::getReadPointer (std::string call_id) { - if (getNbReadPointer() == 0) return 0; ReadPointer::iterator iter = _readpointer.find (call_id); - - if (iter == _readpointer.end()) { - return 0; - } else { - return iter->second; - } - + return (iter != _readpointer.end()) ? iter->second : 0; } int @@ -150,22 +124,17 @@ RingBuffer::getSmallestReadPointer() int smallest = mBufferSize; - ReadPointer::iterator iter = _readpointer.begin(); - - while (iter != _readpointer.end()) { + ReadPointer::iterator iter; + for (iter = _readpointer.begin(); iter != _readpointer.end(); ++iter) if (iter->second < smallest) smallest = iter->second; - iter++; - } - return smallest; } void RingBuffer::storeReadPointer (int pointer_value, std::string call_id) { - ReadPointer::iterator iter = _readpointer.find (call_id); if (iter != _readpointer.end()) { @@ -173,7 +142,6 @@ RingBuffer::storeReadPointer (int pointer_value, std::string call_id) } else { _debug ("storeReadPointer: Cannot find \"%s\" readPointer in \"%s\" ringbuffer", call_id.c_str(), buffer_id.c_str()); } - } @@ -182,7 +150,6 @@ RingBuffer::createReadPointer (std::string call_id) { if (!hasThisReadPointer (call_id)) _readpointer.insert (std::pair<std::string, int> (call_id, mEnd)); - } @@ -190,7 +157,6 @@ void RingBuffer::removeReadPointer (std::string call_id) { ReadPointer::iterator iter = _readpointer.find (call_id); - if (iter != _readpointer.end()) _readpointer.erase (iter); } @@ -199,13 +165,7 @@ RingBuffer::removeReadPointer (std::string call_id) bool RingBuffer::hasThisReadPointer (std::string call_id) { - ReadPointer::iterator iter = _readpointer.find (call_id); - - if (iter == _readpointer.end()) { - return false; - } else { - return true; - } + return _readpointer.find (call_id) != _readpointer.end(); } @@ -218,60 +178,31 @@ RingBuffer::getNbReadPointer() // // For the writer only: // -int -RingBuffer::AvailForPut() -{ - // Always keep 4 bytes safe (?) - - return mBufferSize - putLen(); -} // This one puts some data inside the ring buffer. -int +void RingBuffer::Put (void* buffer, int toCopy) { - samplePtr src; - int block; - int copied; - int pos; - int len = putLen(); - - if (toCopy > mBufferSize - len) toCopy = mBufferSize - len; - src = (samplePtr) buffer; - - - copied = 0; + unsigned char *src = (unsigned char *) buffer; - pos = mEnd; + int pos = mEnd; while (toCopy) { - block = toCopy; - - // Wrap block around ring ? - if (block > (mBufferSize - pos)) { - // Fill in to the end of the buffer - block = mBufferSize - pos; - } - - bcopy (src, mBuffer + pos, block); + int block = toCopy; + if (block > mBufferSize - pos) // Wrap block around ring ? + block = mBufferSize - pos; // Fill in to the end of the buffer + memcpy (mBuffer + pos, src, block); src += block; - pos = (pos + block) % mBufferSize; - toCopy -= block; - - copied += block; } mEnd = pos; - - // How many items copied. - return copied; } // @@ -288,64 +219,34 @@ RingBuffer::AvailForGet (std::string call_id) // Get will move 'toCopy' bytes from the internal FIFO to 'buffer' int -RingBuffer::Get (void *buffer, int toCopy, unsigned short volume, std::string call_id) +RingBuffer::Get (void *buffer, int toCopy, std::string call_id) { - if (getNbReadPointer() == 0) return 0; if (!hasThisReadPointer (call_id)) return 0; - samplePtr dest; - - int block; - - int copied; - int len = getLen (call_id); - - if (toCopy > len) toCopy = len; + int copied = toCopy; - dest = (samplePtr) buffer; - - copied = 0; - + unsigned char *dest = (unsigned char *) buffer; int mStart = getReadPointer (call_id); - //fprintf(stderr, "G"); while (toCopy) { - block = toCopy; - - if (block > (mBufferSize - mStart)) { + int block = toCopy; + if (block > mBufferSize - mStart) block = mBufferSize - mStart; - } - - if (volume!=100) { - SFLDataFormat* start = (SFLDataFormat*) (mBuffer + mStart); - int nbSample = block / sizeof (SFLDataFormat); - - for (int i=0; i<nbSample; i++) { - start[i] = start[i] * volume / 100; - } - } - - // bcopy(src, dest, len) - bcopy (mBuffer + mStart, dest, block); + memcpy (dest, mBuffer + mStart, block); dest += block; - mStart = (mStart + block) % mBufferSize; - toCopy -= block; - - copied += block; } storeReadPointer (mStart, call_id); - return copied; } diff --git a/sflphone-common/src/audio/ringbuffer.h b/sflphone-common/src/audio/ringbuffer.h index 8b84e94418212005a45c590095956f05c9927bac..4fbb34aa2e0f87f9ea7576574b416f9c6d0239d4 100644 --- a/sflphone-common/src/audio/ringbuffer.h +++ b/sflphone-common/src/audio/ringbuffer.h @@ -26,9 +26,6 @@ #include <fstream> - -typedef unsigned char* samplePtr; - typedef std::map<std::string, int> ReadPointer; static std::string default_id = "audiolayer_id"; @@ -97,19 +94,12 @@ class RingBuffer int getNbReadPointer(); - /** - * To get how much space is available in the buffer to write in - * @return int The available size - */ - int AvailForPut (void); - /** * Write data in the ring buffer * @param buffer Data to copied * @param toCopy Number of bytes to copy - * @return int Number of bytes copied */ - int Put (void* buffer, int toCopy); + void Put (void* buffer, int toCopy); /** * To get how much space is available in the buffer to read in @@ -121,10 +111,9 @@ class RingBuffer * Get data in the ring buffer * @param buffer Data to copied * @param toCopy Number of bytes to copy - * @param volume The volume * @return int Number of bytes copied */ - int Get (void* buffer, int toCopy, unsigned short volume = 100, std::string call_id = default_id); + int Get (void* buffer, int toCopy, std::string call_id = default_id); /** * Discard data from the buffer @@ -160,7 +149,7 @@ class RingBuffer /** Buffer size */ int mBufferSize; /** Data */ - samplePtr mBuffer; + unsigned char *mBuffer; ReadPointer _readpointer; diff --git a/sflphone-common/src/audio/samplerateconverter.cpp b/sflphone-common/src/audio/samplerateconverter.cpp index e9a75b21fdd315646571070f9f165958095685d3..411c20389c39b4b6e415f93a8ef3ca5085522e1c 100644 --- a/sflphone-common/src/audio/samplerateconverter.cpp +++ b/sflphone-common/src/audio/samplerateconverter.cpp @@ -30,73 +30,25 @@ #include "samplerateconverter.h" #include "manager.h" +#include <cassert> -SamplerateConverter::SamplerateConverter (int freq , int fs) - : _frequence (freq) - , _framesize (fs) - , _floatBufferDownMic (NULL) - , _floatBufferUpMic (NULL) - , _src_state_mic (NULL) - , _floatBufferDownSpkr (NULL) - , _floatBufferUpSpkr (NULL) - , _src_state_spkr (NULL) - , _src_err (0) -{ - init(); -} - -SamplerateConverter::~SamplerateConverter (void) +SamplerateConverter::SamplerateConverter (int freq) : _maxFreq(freq) { + int err; + _src_state = src_new (SRC_LINEAR, 1, &err); - if (_floatBufferUpMic) { - delete [] _floatBufferUpMic; - _floatBufferUpMic = NULL; - } - - if (_floatBufferDownMic) { - delete [] _floatBufferDownMic; - _floatBufferDownMic = NULL; - } + _samples = (freq * 20) / 1000; // start with 20 ms buffers - if (_floatBufferUpSpkr) { - delete [] _floatBufferUpSpkr; - _floatBufferUpSpkr = NULL; - } - - if (_floatBufferDownSpkr) { - delete [] _floatBufferDownSpkr; - _floatBufferDownSpkr = NULL; - } - - // libSamplerateConverter-related - if (_src_state_mic) { - _src_state_mic = src_delete (_src_state_mic); - _src_state_mic = NULL; - } - - if (_src_state_spkr) { - _src_state_spkr = src_delete (_src_state_spkr); - _src_state_spkr = NULL; - } + _floatBufferIn = new float32[_samples]; + _floatBufferOut = new float32[_samples]; } -void SamplerateConverter::init (void) +SamplerateConverter::~SamplerateConverter (void) { + delete [] _floatBufferIn; + delete [] _floatBufferOut; - // libSamplerateConverter-related - // Set the converter type for the upsampling and the downsampling - // interpolator SRC_SINC_BEST_QUALITY - // interpolator SRC_SINC_FASTEST - // interpolator SRC_LINEAR - _src_state_mic = src_new (SRC_LINEAR, 1, &_src_err); - _src_state_spkr = src_new (SRC_LINEAR, 1, &_src_err); - - int nbSamplesMax = (int) ( (_frequence * _framesize) / 1000); - - _floatBufferDownMic = new float32[nbSamplesMax]; - _floatBufferUpMic = new float32[nbSamplesMax]; - _floatBufferDownSpkr = new float32[nbSamplesMax]; - _floatBufferUpSpkr = new float32[nbSamplesMax]; + src_delete (_src_state); } void @@ -104,73 +56,40 @@ SamplerateConverter::Short2FloatArray (const short *in, float *out, int len) { // factor is 1/(2^15), used to rescale the short int range to the // [-1.0 - 1.0] float range. -#define S2F_FACTOR .000030517578125f; - while (len) { - len--; - out[len] = (float) in[len] * S2F_FACTOR; - } + while (len--) + out[len] = (float) in[len] * .000030517578125f; } - //TODO Add ifdef for int16 or float32 type -int SamplerateConverter::upsampleData (SFLDataFormat* dataIn , SFLDataFormat* dataOut, int samplerate1 , int samplerate2 , int nbSamples) +void SamplerateConverter::resample (SFLDataFormat* dataIn , SFLDataFormat* dataOut , int inputFreq , int outputFreq , int nbSamples) { - - double upsampleFactor = (double) samplerate2 / samplerate1 ; - - int nbSamplesMax = (int) (samplerate2 * _framesize / 1000); - - if (upsampleFactor != 1 && dataIn != NULL) { - SRC_DATA src_data; - 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 - // _debug(" upsample %d %d %f %d" , src_data.input_frames , src_data.output_frames, src_data.src_ratio , nbSamples); - // Override libsamplerate conversion function - Short2FloatArray (dataIn , _floatBufferDownSpkr, nbSamples); - //src_short_to_float_array (dataIn , _floatBufferDownSpkr, nbSamples); - //_debug("upsample %d %f %d" , src_data.output_frames, src_data.src_ratio , nbSamples); - src_process (_src_state_spkr, &src_data); - // _debug(" upsample %d %d %d" , samplerate1, samplerate2 , nbSamples); - nbSamples = (src_data.output_frames_gen > nbSamplesMax) ? nbSamplesMax : src_data.output_frames_gen; - src_float_to_short_array (_floatBufferUpSpkr, dataOut, nbSamples); - //_debug("upsample %d %d %d" , samplerate1, samplerate2 , nbSamples); + 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]; } - return nbSamples; -} - -//TODO Add ifdef for int16 or float32 type -int SamplerateConverter::downsampleData (SFLDataFormat* dataIn , SFLDataFormat* dataOut , int samplerate1 , int samplerate2 , int nbSamples) -{ + SRC_DATA src_data; + src_data.data_in = _floatBufferIn; + src_data.data_out = _floatBufferOut; + src_data.input_frames = nbSamples; + src_data.output_frames = outSamples; + src_data.src_ratio = sampleFactor; + src_data.end_of_input = 0; // More data will come - double downsampleFactor = (double) samplerate1 / samplerate2; - - int nbSamplesMax = (int) (samplerate1 * _framesize / 1000); - - if (downsampleFactor != 1) { - SRC_DATA src_data; - 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 - //_debug("downsample %d %f %d" , src_data.output_frames, src_data.src_ratio , nbSamples); - // Override libsamplerate conversion function - Short2FloatArray (dataIn , _floatBufferUpMic, nbSamples); - //src_short_to_float_array (dataIn, _floatBufferUpMic, nbSamples); - //_debug("downsample %d %f %d" , src_data.output_frames, src_data.src_ratio , nbSamples); - src_process (_src_state_mic, &src_data); - //_debug("downsample %d %f %d" , src_data.output_frames, src_data.src_ratio , nbSamples); - nbSamples = (src_data.output_frames_gen > nbSamplesMax) ? nbSamplesMax : src_data.output_frames_gen; - //_debug("downsample %d %f %d" , src_data.output_frames, src_data.src_ratio , nbSamples); - src_float_to_short_array (_floatBufferDownMic , dataOut , nbSamples); - } + Short2FloatArray (dataIn , _floatBufferIn, nbSamples); + src_process (_src_state, &src_data); - return 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 a6c3b50ef7c08ef7212ce90e4ff45b5c868155ad..6d17b8d671f84e056ec32cdc1a0c1a5f9fd17af2 100644 --- a/sflphone-common/src/audio/samplerateconverter.h +++ b/sflphone-common/src/audio/samplerateconverter.h @@ -47,30 +47,19 @@ class SamplerateConverter * internal buffer size. Converter must be reinitialized * every time these parameters change */ - SamplerateConverter (int freq=44100, int frameSize=20); + SamplerateConverter (int freq); /** Destructor */ ~SamplerateConverter (void); /** - * Upsample from the samplerate1 to the samplerate2 + * resample from the samplerate1 to the samplerate2 * @param data The data buffer - * @param SamplerateConverter1 The lower sample rate - * @param SamplerateConverter2 The higher sample rate + * @param SamplerateConverter1 The original sample rate + * @param SamplerateConverter2 The desired 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); + void resample (SFLDataFormat* dataIn , SFLDataFormat* dataOut , int samplerate1 , int samplerate2 , int nbSamples); /** * Convert short table to floats for audio processing @@ -88,27 +77,13 @@ class SamplerateConverter // Assignment Operator SamplerateConverter& operator= (const SamplerateConverter& rh); - 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; - + /* temporary buffers */ + float32* _floatBufferIn; + float32* _floatBufferOut; + size_t _samples; // size in samples of temporary buffers + int _maxFreq; // maximal output frequency + SRC_STATE* _src_state; }; #endif //_SAMPLE_RATE_H diff --git a/sflphone-common/src/audio/sound/audiofile.cpp b/sflphone-common/src/audio/sound/audiofile.cpp index 311e0ee914f6f04b8ea574c89ccc3eb64e859401..b10382945d52fd9da91ec7af22011fa8d13f206c 100644 --- a/sflphone-common/src/audio/sound/audiofile.cpp +++ b/sflphone-common/src/audio/sound/audiofile.cpp @@ -1,7 +1,4 @@ -/* - - if(_dbus) - _dbus * Copyright (C) 2004, 2005, 2006, 2008, 2009, 2010, 2011 Savoir-Faire Linux Inc. +/** Copyright (C) 2004, 2005, 2006, 2008, 2009, 2010, 2011 Savoir-Faire Linux Inc. * Author: Yan Morin <yan.morin@savoirfairelinux.com> * * Inspired by tonegenerator of @@ -46,35 +43,15 @@ #include "manager.h" -RawFile::RawFile() : audioCodec (NULL) -{ - AudioFile::_start = false; -} - -RawFile::~RawFile() -{ -} - // load file in mono format -void RawFile::loadFile (const std::string& name, sfl::AudioCodec* codec, unsigned int sampleRate = 8000) throw(AudioFileException) +RawFile::RawFile(const std::string& name, sfl::AudioCodec* codec, unsigned int sampleRate) + : audioCodec (codec) { - _debug("RawFile: Load new file %s", name.c_str()); - - audioCodec = codec; - - // if the filename was already load, with the same samplerate - // we do nothing - - if ((filepath == name) && (_sampleRate == (int)sampleRate)) { - return; - } - filepath = name; // no filename to load - if (filepath.empty()) { + if (filepath.empty()) throw AudioFileException("Unable to open audio file: filename is empty"); - } std::fstream file; @@ -164,102 +141,28 @@ void RawFile::loadFile (const std::string& name, sfl::AudioCodec* codec, unsigne } - - -WaveFile::WaveFile () : byteCounter (0) - , nbChannels (1) - , fileLength (0) - , dataOffset (0) - , channels (0) - , dataType (0) - , fileRate (0) -{ - AudioFile::_start = false; -} - - -WaveFile::~WaveFile() -{ - _debug ("WaveFile: Destructor Called!"); -} - - - -void WaveFile::openFile (const std::string& fileName, int audioSamplingRate) throw(AudioFileException) -{ - try { - - if (isFileExist (fileName)) { - openExistingWaveFile (fileName, audioSamplingRate); - } - } - catch(AudioFileException &e) { - throw; - } -} - - - -bool WaveFile::closeFile() -{ - fileStream.close(); - - return true; -} - - -bool WaveFile::isFileExist (const std::string& fileName) +WaveFile::WaveFile (const std::string& fileName, unsigned int audioSamplingRate) { std::fstream fs (fileName.c_str(), std::ios_base::in); + if (!fs) + throw AudioFileException("File " + fileName + " doesn't exist"); - if (!fs) { - _debug ("WaveFile: file \"%s\" doesn't exist", fileName.c_str()); - return false; - } - - _debug ("WaveFile: File \"%s\" exists", fileName.c_str()); - return true; -} - - -bool WaveFile::isFileOpened() -{ - - if (fileStream.is_open()) { - _debug ("WaveFile: file is openened"); - return true; - } else { - _debug ("WaveFile: file is not openend"); - return false; - } -} - - -void WaveFile::openExistingWaveFile (const std::string& fileName, int audioSamplingRate) throw(AudioFileException) -{ - - int maxIteration = 0; - - _debug ("WaveFile: Opening %s", fileName.c_str()); filepath = fileName; - + std::fstream fileStream; fileStream.open (fileName.c_str(), std::ios::in | std::ios::binary); - char riff[4] = {}; + char riff[4] = { 0, 0, 0, 0 }; fileStream.read (riff, 4); - if (strncmp ("RIFF", riff, 4) != 0) { + if (strncmp ("RIFF", riff, 4) != 0) throw AudioFileException("File is not of RIFF format"); - } - char fmt[4] = {}; - maxIteration = 10; - while ((maxIteration > 0) && strncmp ("fmt ", fmt, 4)) { + char fmt[4] = { 0, 0, 0, 0 }; + int maxIteration = 10; + while (maxIteration-- && strncmp ("fmt ", fmt, 4)) fileStream.read (fmt, 4); - maxIteration--; - } - if(maxIteration == 0) { + + if(maxIteration == 0) throw AudioFileException("Could not find \"fmt \" chunk"); - } SINT32 chunk_size; // fmt chunk size unsigned short formatTag; // data compression tag @@ -267,188 +170,95 @@ void WaveFile::openExistingWaveFile (const std::string& fileName, int audioSampl fileStream.read ( (char*) &chunk_size, 4); // Read fmt chunk size. fileStream.read ( (char*) &formatTag, 2); - _debug ("WaveFile: Chunk size: %d", chunk_size); - _debug ("WaveFile: Format tag: %d", formatTag); - - if (formatTag != 1) { // PCM = 1, FLOAT = 3 + if (formatTag != 1) // PCM = 1, FLOAT = 3 throw AudioFileException("File contains an unsupported data format type"); - } // Get number of channels from the header. SINT16 chan; fileStream.read ( (char*) &chan, 2); - channels = chan; - _debug ("WaveFile: Channel %d", channels); + if(chan > 2) + throw AudioFileException("WaveFile: unsupported number of channels"); // Get file sample rate from the header. SINT32 srate; fileStream.read ( (char*) &srate, 4); - fileRate = (double) srate; - _debug ("WaveFile: Sampling rate %d", srate); SINT32 avgb; fileStream.read ( (char*) &avgb, 4); - _debug ("WaveFile: Average byte %d", avgb);\ SINT16 blockal; fileStream.read ( (char*) &blockal, 2); - _debug ("WaveFile: Block alignment %d", blockal); - // Determine the data type - dataType = 0; + SOUND_FORMAT dataType; SINT16 dt; fileStream.read ( (char*) &dt, 2); - _debug ("WaveFile: dt %d", dt); - if (formatTag == 1) { - if (dt == 8) - dataType = 1; // SINT8; - else if (dt == 16) - dataType = 2; // SINT16; - else if (dt == 32) - dataType = 3; // SINT32; - } - else { - throw AudioFileException("File's bits per sample with is not supported"); - } + if (dt == 8) + dataType = 1; // SINT8; + else if (dt == 16) + dataType = 2; // SINT16; + else if (dt == 32) + dataType = 3; // SINT32; + else { + throw AudioFileException("File's bits per sample with is not supported"); + } // Find the "data" chunk - char data[4] = {}; + char data[4] = { 0, 0, 0, 0 }; maxIteration = 10; - while ((maxIteration > 0) && strncmp ("data", data, 4)) { + while (maxIteration-- && strncmp ("data", data, 4)) fileStream.read (data, 4); - maxIteration--; - } - // Sample rate converter initialized with 88200 sample long int converterSamples = (srate > audioSamplingRate) ? srate : audioSamplingRate; - SamplerateConverter _converter (converterSamples, 2000); - - int nbSampleMax = 512; + SamplerateConverter _converter (converterSamples); // Get length of data from the header. SINT32 bytes; fileStream.read ( (char*) &bytes, 4); - _debug ("WaveFile: data size in byte %d", bytes); - fileLength = 8 * bytes / dt / channels; // sample frames - _debug ("WaveFile: data size in frame %ld", fileLength); + unsigned long nbSamples = 8 * bytes / dt / chan; // sample frames + + _debug ("WaveFile: frame size %ld, data size %d align %d rate %d avgbyte %d chunk size %d dt %d", + nbSamples, bytes, blockal, srate, avgb, chunk_size, dt); // Should not be longer than a minute - if (fileLength > (unsigned int) (60*srate)) - fileLength = 60*srate; + if (nbSamples > (unsigned int) (60*srate)) + nbSamples = 60*srate; - SFLDataFormat *tempBuffer = new SFLDataFormat[fileLength]; - if (!tempBuffer) { + SFLDataFormat *tempBuffer = new SFLDataFormat[nbSamples]; + if (!tempBuffer) throw AudioFileException("Could not allocate temporary buffer"); - } - - SFLDataFormat *tempBufferRsmpl = NULL; - fileStream.read ( (char *) tempBuffer, fileLength*sizeof (SFLDataFormat)); + fileStream.read ( (char *) tempBuffer, nbSamples*sizeof (SFLDataFormat)); // mix two channels together if stereo - if(channels == 2) { - int tmp = 0; - unsigned j = 0; - for(unsigned int i = 0; i < fileLength-1; i+=2) { - tmp = (tempBuffer[i] + tempBuffer[i+1]) / 2; - // saturate - if(tmp > SHRT_MAX) { - tmp = SHRT_MAX; - } - tempBuffer[j++] = (SFLDataFormat)tmp; - } - - fileLength /= 2; - } - else if(channels > 2) { - delete [] tempBuffer; - throw AudioFileException("WaveFile: unsupported number of channels"); - } - - // compute size of final buffer - int nbSample; - - if (srate != audioSamplingRate) { - nbSample = (int) ( (float) fileLength * ( (float) audioSamplingRate / (float) srate)); - } else { - nbSample = fileLength; + if(chan == 2) { + for(unsigned int i = 0; i < nbSamples-1; i+=2) + tempBuffer[i/2] = (tempBuffer[i] + tempBuffer[i+1]) / 2; + nbSamples /= 2; } - int totalprocessed = 0; - - // require resampling if (srate != audioSamplingRate) { + nbSamples = (int) ( (float) nbSamples * ( (float) audioSamplingRate / (float) srate)); - // initialize remaining samples to process - int remainingSamples = fileLength; - - tempBufferRsmpl = new SFLDataFormat[nbSample]; - if (!tempBufferRsmpl) { - throw AudioFileException("Could not allocate temporary buffer for ressampling"); - } - - SFLDataFormat *in = tempBuffer; - SFLDataFormat *out = tempBufferRsmpl; - - while (remainingSamples > 0) { - - int toProcess = remainingSamples > nbSampleMax ? nbSampleMax : remainingSamples; - int nbSamplesConverted = 0; - - if (srate < audioSamplingRate) { - nbSamplesConverted = _converter.upsampleData (in, out, srate, audioSamplingRate, toProcess); - } else if (srate > audioSamplingRate) { - nbSamplesConverted = _converter.downsampleData (in, out, audioSamplingRate, srate, toProcess); - } + _buffer = new SFLDataFormat[nbSamples]; + if (_buffer == NULL) { + delete[] tempBuffer; + throw AudioFileException("Could not allocate buffer for audio"); + } - // nbSamplesConverted = nbSamplesConverted*2; + if (srate < audioSamplingRate) + _converter.resample (tempBuffer, _buffer, srate, audioSamplingRate, nbSamples); + else if (srate > audioSamplingRate) + _converter.resample (tempBuffer, _buffer, audioSamplingRate, srate, nbSamples); - in += toProcess; - out += nbSamplesConverted; - remainingSamples -= toProcess; - totalprocessed += nbSamplesConverted; - } - } - - // Init audio loop buffer info - _buffer = new SFLDataFormat[nbSample]; - if (_buffer == NULL) { - throw AudioFileException("Could not allocate buffer for audio"); - } - - _size = nbSample; - _sampleRate = (int) audioSamplingRate; - - // Copy audio into audioloopi - if (srate != audioSamplingRate) { - memcpy ( (void *) _buffer, (void *) tempBufferRsmpl, nbSample*sizeof (SFLDataFormat)); - } - else { - memcpy ( (void *) _buffer, (void *) tempBuffer, nbSample*sizeof (SFLDataFormat)); - } - - _debug ("WaveFile: file successfully opened"); - - delete[] tempBuffer; - - if (tempBufferRsmpl) { - delete[] tempBufferRsmpl; + delete[] tempBuffer; + } else { + _buffer = tempBuffer; } -} - - -void WaveFile::loadFile (const std::string& name, sfl::AudioCodec * /*codec*/, unsigned int sampleRate) throw(AudioFileException) -{ - _debug("WaveFile: Load new file %s", name.c_str()); - try { - openFile (name, sampleRate); - } - catch(AudioFileException &e) { - throw; - } + _size = nbSamples; + _sampleRate = audioSamplingRate; } diff --git a/sflphone-common/src/audio/sound/audiofile.h b/sflphone-common/src/audio/sound/audiofile.h index dde6e06c9ecd2b05b67041991dc20349161ee29d..a51f84d91899aff435b90cbf518c26930f466eb3 100644 --- a/sflphone-common/src/audio/sound/audiofile.h +++ b/sflphone-common/src/audio/sound/audiofile.h @@ -56,52 +56,13 @@ public: class AudioFile : public AudioLoop { public: - - /** - * Load a sound file in memory - * - * @param filename The absolute path to the file - * @param codec The codec to decode and encode it - * @param sampleRate The sample rate to read it - * @return bool True on success - */ - virtual void loadFile (const std::string &, sfl::AudioCodec *, unsigned int) throw(AudioFileException) = 0; - - std::string getFilePath(void) { - return filepath; - } - - /** - * Start the sound file - */ - void start() { - _start = true; - } - - /** - * Stop the sound file - */ - void stop() { - _start = false; - } - - /** - * Tells whether or not the file is playing - * @return bool True if yes - * false otherwise - */ - bool isStarted() { - return _start; + const std::string &getFilePath(void) const{ + return filepath; } protected: - - /** start or not */ - bool _start; - /** The absolute path to the sound file */ std::string filepath; - }; @@ -117,22 +78,7 @@ class RawFile : public AudioFile /** * Constructor */ - RawFile(); - - /** - * Destructor - */ - ~RawFile(); - - - /** - * Load a sound file in memory - * @param filename The absolute path to the file - * @param codec The codec to decode and encode it - * @param sampleRate The sample rate to read it - * @return bool True on success - */ - virtual void loadFile (const std::string&, sfl::AudioCodec *, unsigned int sampleRate) throw(AudioFileException); + RawFile(const std::string& name, sfl::AudioCodec* codec, unsigned int sampleRate = 8000); private: // Copy Constructor @@ -149,99 +95,12 @@ class WaveFile : public AudioFile { public: - - WaveFile(); - - ~WaveFile(); - - /** - * Open a file give a file name - * - * @param A reference to a string containing the filename - * @param The internal sampling rate, file will be resampled - * if it's sampling rate does not correspond to internal one - */ - void openFile (const std::string&, int) throw(AudioFileException); - - /** - * Close an opened file - */ - bool closeFile(); - - /** - * Test if the specified file already exist - */ - bool isFileExist (const std::string&); - - /** - * Test if file opend - */ - bool isFileOpened(); - - /** - * Load a sound file in memory - * @param filename The absolute path to the file - * @param codec The codec to decode and encode it - * @param sampleRate The sample rate to read it - * @return bool True on success - */ - virtual void loadFile (const std::string&, sfl::AudioCodec *, unsigned int) throw(AudioFileException); - - private: - - /** - * Open an existing wave file - * @param File name - * @param Audio sampling rate - */ - void openExistingWaveFile (const std::string&, int) throw(AudioFileException); - - /** - * Sound format for this file (16/32 bits) - */ - SOUND_FORMAT sndFormat; - - /** - * Nb of bytes for this file - */ - long byteCounter; - - /** - * Number of channels for this file - */ - int nbChannels; - - /** - * Total file length - */ - unsigned long fileLength; - - /** - * Audio data start offset in bytes - */ - unsigned long dataOffset; - - /** - * Channels - */ - SINT16 channels; - - /** - * Data type - */ - SOUND_FORMAT dataType; - - /** - * File sampling rate - */ - double fileRate; - - /** - * File stream - */ - std::fstream fileStream; - + /** + * Load a sound file in memory + * @param filename The absolute path to the file + * @param sampleRate The sample rate to read it + */ + WaveFile(const std::string&, unsigned int); }; #endif - diff --git a/sflphone-common/src/audio/sound/tone.cpp b/sflphone-common/src/audio/sound/tone.cpp index a32fe5d4791ef01c0bf395f8745315e4e5fbce53..d45064ef43a9d65b921a813601c1af642cfdd094 100644 --- a/sflphone-common/src/audio/sound/tone.cpp +++ b/sflphone-common/src/audio/sound/tone.cpp @@ -37,7 +37,7 @@ #include "tone.h" #include <math.h> #include <cstdlib> -#include <strings.h> +#include <cstring> #define TABLE_LENGTH 4096 double TWOPI = 2 * M_PI; @@ -130,8 +130,7 @@ Tone::genBuffer (const std::string& definition) _buffer = new SFLDataFormat[_size]; - // src, dest, tocopy - bcopy (buffer, _buffer, _size*sizeof (SFLDataFormat)); // copy char, not SFLDataFormat. + memcpy (_buffer, buffer, _size*sizeof (SFLDataFormat)); // copy char, not SFLDataFormat. delete[] buffer; diff --git a/sflphone-common/src/audio/speexechocancel.cpp b/sflphone-common/src/audio/speexechocancel.cpp index 1d5a17384d1d47bcb3c4ee7e67d4e55b5aaf310d..130f04f3cf988ea60a43a1724d23aadd1e867183 100644 --- a/sflphone-common/src/audio/speexechocancel.cpp +++ b/sflphone-common/src/audio/speexechocancel.cpp @@ -205,8 +205,3 @@ int SpeexEchoCancel::process (SFLDataFormat *inputData, SFLDataFormat *outputDat return nbFrame * EC_FRAME_SIZE * sizeof(SFLDataFormat); } - -void SpeexEchoCancel::process (SFLDataFormat *micData UNUSED, SFLDataFormat *spkrData UNUSED, SFLDataFormat *outputData UNUSED, int nbBytes UNUSED) -{ - -} diff --git a/sflphone-common/src/audio/speexechocancel.h b/sflphone-common/src/audio/speexechocancel.h index 788546848e6f71d5ea5283aa5d2ae3c90aef4c11..74e9bbf00a0f07785443d253096118b8abddc3eb 100644 --- a/sflphone-common/src/audio/speexechocancel.h +++ b/sflphone-common/src/audio/speexechocancel.h @@ -57,16 +57,6 @@ class SpeexEchoCancel : public Algorithm */ virtual int process (SFLDataFormat *, SFLDataFormat *, int); - /** - * Perform echo cancellation, application must provide its own buffer - * \param micData containing mixed echo and voice data - * \param spkrData containing far-end voice data to be sent to speakers - * \param outputData containing the processed data - * \param size in bytes - */ - - virtual void process (SFLDataFormat *, SFLDataFormat *, SFLDataFormat *, int); - private: SpeexEchoState *_echoState; diff --git a/sflphone-common/src/iax/iaxvoiplink.cpp b/sflphone-common/src/iax/iaxvoiplink.cpp index 5a23dfdd35df029dc3f9e370e2973f299e9147d9..ba70c8628ea47d4b11ab77f959e1dd38b567a45c 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; @@ -310,12 +310,12 @@ IAXVoIPLink::sendAudioFromMic (void) continue; // Get bytes from micRingBuffer to data_from_mic - int bytes = audiolayer->getMainBuffer()->getData (micData, needed, 100, currentCall->getCallId()) / sizeof (SFLDataFormat); + int bytes = audiolayer->getMainBuffer()->getData (micData, needed, currentCall->getCallId()) / sizeof (SFLDataFormat); int compSize; if (audioCodec->getClockRate() && ((int) audioCodec->getClockRate() != _mainBufferSampleRate)) { // resample - bytes = converter->downsampleData (micData , micDataConverted , (int) audioCodec->getClockRate(), _mainBufferSampleRate, bytes); + converter->resample (micData , micDataConverted , (int) audioCodec->getClockRate(), _mainBufferSampleRate, bytes); compSize = audioCodec->encode (micDataEncoded, micDataConverted , bytes); } else { compSize = audioCodec->encode (micDataEncoded, micData, bytes); @@ -928,67 +928,47 @@ IAXVoIPLink::iaxHandleVoiceEvent (iax_event* event, IAXCall* call) return; if (audiolayer) { + _debug ("IAX: incoming audio, but no sound card open"); + return; + } - Manager::instance().getMainBuffer ()->setInternalSamplingRate (audioCodec->getClockRate ()); - - // If we receive datalen == 0, some things of the jitter buffer in libiax2/iax.c - // were triggered - - int _mainBufferSampleRate = Manager::instance().getMainBuffer()->getInternalSamplingRate(); - - // 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()) { - _debug ("iaxHandleVoiceEvent: no format found in call setting it to %i", event->subclass); - call->setFormat (event->subclass); - } - - data = (unsigned char*) event->data; - - size = event->datalen; - - // Decode data with relevant codec - max = (int) (audioCodec->getClockRate() * audiolayer->getFrameSize() / 1000); - - if (size > max) { - _debug ("The size %d is bigger than expected %d. Packet cropped. Ouch!", size, max); - size = max; - } - - expandedSize = audioCodec->decode (spkrDataDecoded , data , size); - - nbInt16 = expandedSize/sizeof (int16); + Manager::instance().getMainBuffer ()->setInternalSamplingRate (audioCodec->getClockRate ()); - if (nbInt16 > max) { - _debug ("We have decoded an IAX VOICE packet larger than expected: %i VS %i. Cropping.", nbInt16, max); - nbInt16 = max; - } + // If we receive datalen == 0, some things of the jitter buffer in libiax2/iax.c + // were triggered - nbSample_ = nbInt16; + int _mainBufferSampleRate = Manager::instance().getMainBuffer()->getInternalSamplingRate(); - // test if resampling is required + // 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 (audioCodec->getClockRate() && ((int) audioCodec->getClockRate() != _mainBufferSampleRate)) { + if (event->subclass && event->subclass != call->getFormat()) { + _debug ("iaxHandleVoiceEvent: no format found in call setting it to %i", event->subclass); + call->setFormat (event->subclass); + } - // resample - nbInt16 = converter->upsampleData (spkrDataDecoded, spkrDataConverted, audioCodec->getClockRate(), _mainBufferSampleRate, nbSample_); + data = (unsigned char*) event->data; - /* Write the data to the mic ring buffer */ - audiolayer->getMainBuffer()->putData (spkrDataConverted, nbInt16 * sizeof (SFLDataFormat), call->getCallId()); + size = event->datalen; - } else { + // Decode data with relevant codec + max = (int) (audioCodec->getClockRate() * audiolayer->getFrameSize() / 1000); - /* Write the data to the mic ring buffer */ - audiolayer->getMainBuffer()->putData (spkrDataDecoded, nbInt16 * sizeof (SFLDataFormat), call->getCallId()); + if (size > max) { + _debug ("The size %d is bigger than expected %d. Packet cropped. Ouch!", size, max); + size = max; + } - } + expandedSize = audioCodec->decode (spkrDataDecoded , data , size); - } else { - _debug ("IAX: incoming audio, but no sound card open"); - } + if (audioCodec->getClockRate() && ((int) audioCodec->getClockRate() != _mainBufferSampleRate)) { + converter->resample (spkrDataDecoded, spkrDataConverted, audioCodec->getClockRate(), _mainBufferSampleRate, expandedSize); + audiolayer->getMainBuffer()->putData (spkrDataConverted, expandedSize, call->getCallId()); + } else { + audiolayer->getMainBuffer()->putData (spkrDataDecoded, expandedSize, call->getCallId()); + } } /** diff --git a/sflphone-common/src/managerimpl.cpp b/sflphone-common/src/managerimpl.cpp index f2ee3cf58449dca0121666d665b997e7a5741954..0334461383f8aad400b244c248562cea622c434c 100644 --- a/sflphone-common/src/managerimpl.cpp +++ b/sflphone-common/src/managerimpl.cpp @@ -2318,11 +2318,9 @@ void ManagerImpl::stopTone () } if (_audiofile) { - std::string filepath = _audiofile->getFilePath(); - _dbus->getCallManager()->recordPlaybackStoped(filepath); - _audiofile->stop(); - delete _audiofile; - _audiofile = NULL; + std::string filepath = _audiofile->getFilePath(); + _dbus->getCallManager()->recordPlaybackStoped(filepath); + delete _audiofile; } _toneMutex.leaveMutex(); @@ -2367,90 +2365,73 @@ void ManagerImpl::ringback () */ void ManagerImpl::ringtone (const std::string& accountID) { - std::string ringchoice; - sfl::AudioCodec *codecForTone; - int samplerate; - - _debug ("Manager: Ringtone"); - Account *account = getAccount (accountID); - if (!account) { _warn ("Manager: Warning: invalid account in ringtone"); return; } - if (account->getRingtoneEnabled()) { - - _debug ("Manager: Tone is enabled"); - //TODO Comment this because it makes the daemon crashes since the main thread - //synchronizes the ringtone thread. - - ringchoice = account->getRingtonePath(); - //if there is no / inside the path - - if (ringchoice.find (DIR_SEPARATOR_CH) == std::string::npos) { - // check inside global share directory - ringchoice = std::string (PROGSHAREDIR) + DIR_SEPARATOR_STR - + RINGDIR + DIR_SEPARATOR_STR + ringchoice; - } - - audioLayerMutexLock(); - - - if (!_audiodriver) { - _error ("Manager: Error: no audio layer in ringtone"); - audioLayerMutexUnlock(); - return; - } + if (!account->getRingtoneEnabled()) { + ringback(); + return; + } - samplerate = _audiodriver->getSampleRate(); - codecForTone = static_cast<sfl::AudioCodec *>(_audioCodecFactory.getFirstCodecAvailable()); + std::string ringchoice = account->getRingtonePath(); + if (ringchoice.find (DIR_SEPARATOR_CH) == std::string::npos) { + // check inside global share directory + ringchoice = std::string (PROGSHAREDIR) + DIR_SEPARATOR_STR + + RINGDIR + DIR_SEPARATOR_STR + ringchoice; + } - audioLayerMutexUnlock(); + audioLayerMutexLock(); - _toneMutex.enterMutex(); + if (!_audiodriver) { + _error ("Manager: Error: no audio layer in ringtone"); + audioLayerMutexUnlock(); + return; + } - if (_audiofile) { - if(_dbus) { - std::string filepath = _audiofile->getFilePath(); - _dbus->getCallManager()->recordPlaybackStoped(filepath); - } - delete _audiofile; - _audiofile = NULL; - } + int samplerate = _audiodriver->getSampleRate(); - std::string wave (".wav"); - size_t found = ringchoice.find (wave); + audioLayerMutexUnlock(); - try { + _toneMutex.enterMutex(); - if (found != std::string::npos) { - _audiofile = static_cast<AudioFile *> (new WaveFile()); - } - else { - _audiofile = static_cast<AudioFile *> (new RawFile()); - } - - _debug ("Manager: ringChoice: %s, codecForTone: %d, samplerate %d", ringchoice.c_str(), codecForTone->getPayloadType(), samplerate); + if (_audiofile) { + if(_dbus) + _dbus->getCallManager()->recordPlaybackStoped(_audiofile->getFilePath()); + delete _audiofile; + _audiofile = NULL; + } - _audiofile->loadFile (ringchoice, codecForTone, samplerate); - } - catch (AudioFileException &e) { - _error("Manager: Exception: %s", e.what()); - } - - _audiofile->start(); - _toneMutex.leaveMutex(); + try { + if (ringchoice.find (".wav") != std::string::npos) { + _audiofile = new WaveFile(ringchoice, samplerate); + } + else { + sfl::Codec *codec; + if (ringchoice.find (".ul") != std::string::npos) + codec = _audioCodecFactory.getCodec(PAYLOAD_CODEC_ULAW); + /* + * FIXME : RawFile() only handles ULAW + else if (ringchoice.find (".au") != std::string::npos) + codec = _audioCodecFactory.getCodec(PAYLOAD_CODEC_GSM); + */ + else + throw AudioFileException("Couldn't guess an appropriate decoder"); + _audiofile = new RawFile(ringchoice, static_cast<sfl::AudioCodec *>(codec), samplerate); + } + } + catch (AudioFileException &e) { + _error("Manager: Exception: %s", e.what()); + } - audioLayerMutexLock(); - // start audio if not started AND flush all buffers (main and urgent) - _audiodriver->startStream(); - audioLayerMutexUnlock(); + _toneMutex.leaveMutex(); - } else { - ringback(); - } + audioLayerMutexLock(); + // start audio if not started AND flush all buffers (main and urgent) + _audiodriver->startStream(); + audioLayerMutexUnlock(); } AudioLoop* @@ -2469,15 +2450,7 @@ ManagerImpl::getTelephoneFile () { ost::MutexLock m (_toneMutex); - if (!_audiofile) { - return NULL; - } - - if (_audiofile->isStarted()) { - return _audiofile; - } else { - return NULL; - } + return _audiofile; } void ManagerImpl::notificationIncomingCall (void) @@ -3002,16 +2975,9 @@ void ManagerImpl::setRecordingCall (const std::string& id) bool ManagerImpl::isRecording (const std::string& id) { - std::string accountid = getAccountFromCall (id); Recordable* rec = (Recordable*) getAccountLink (accountid)->getCall (id); - - bool ret = false; - - if (rec) - ret = rec->isRecording(); - - return ret; + return rec && rec->isRecording(); } bool ManagerImpl::startRecordedFilePlayback(const std::string& filepath) @@ -3033,25 +2999,19 @@ bool ManagerImpl::startRecordedFilePlayback(const std::string& filepath) _toneMutex.enterMutex(); if(_audiofile) { - if(_dbus) { - std::string file = _audiofile->getFilePath(); - _dbus->getCallManager()->recordPlaybackStoped(file); - } - delete _audiofile; - _audiofile = NULL; + if(_dbus) + _dbus->getCallManager()->recordPlaybackStoped(_audiofile->getFilePath()); + delete _audiofile; + _audiofile = NULL; } try { - _audiofile = static_cast<AudioFile *>(new WaveFile()); - - _audiofile->loadFile(filepath, NULL, sampleRate); + _audiofile = new WaveFile(filepath, sampleRate); } - catch(AudioFileException &e) { + catch(const AudioFileException &e) { _error("Manager: Exception: %s", e.what()); } - _audiofile->start(); - _toneMutex.leaveMutex(); audioLayerMutexLock(); @@ -3071,11 +3031,8 @@ void ManagerImpl::stopRecordedFilePlayback(const std::string& filepath) audioLayerMutexUnlock(); _toneMutex.enterMutex(); - if(_audiofile != NULL) { - _audiofile->stop(); - delete _audiofile; + delete _audiofile; _audiofile = NULL; - } _toneMutex.leaveMutex(); } diff --git a/sflphone-common/test/historytest.cpp b/sflphone-common/test/historytest.cpp index babe871c93187cc15d04e8229530d2fd05748030..f8efbee22d7416f1f12feafbb3e3fd7ed0a39b21 100644 --- a/sflphone-common/test/historytest.cpp +++ b/sflphone-common/test/historytest.cpp @@ -30,6 +30,7 @@ #include <stdio.h> #include <sstream> +#include <cstdlib> #include "historytest.h" #include "manager.h" @@ -41,6 +42,7 @@ using std::endl; void HistoryTest::setUp() { + system("cp " HISTORY_SAMPLE " " HISTORY_SAMPLE ".bak"); // Instanciate the cleaner singleton history = new HistoryManager(); } @@ -51,11 +53,7 @@ void HistoryTest::test_create_history_path() _debug ("-------------------- HistoryTest::test_create_history_path --------------------\n"); int result; - char *cpath; - std::string path; - - cpath = getenv ("XDG_DATA_HOME"); - (cpath != NULL) ? path = std::string (cpath) : path = std::string ("/") + HISTORY_SAMPLE; + std::string path(HISTORY_SAMPLE); result = history->create_history_path(path); CPPUNIT_ASSERT (result == 0); @@ -228,4 +226,5 @@ void HistoryTest::tearDown() // Delete the history object delete history; history = 0; + system("mv " HISTORY_SAMPLE ".bak " HISTORY_SAMPLE); } diff --git a/sflphone-common/test/main.cpp b/sflphone-common/test/main.cpp index ed843d847072480ca5203c57d5eb16e927ddc510..3a7af6754b06002720721196e66b5931e15f83ba 100644 --- a/sflphone-common/test/main.cpp +++ b/sflphone-common/test/main.cpp @@ -32,6 +32,8 @@ #include <manager.h> #include <constants.h> +#include <cstdlib> + #include <cppunit/CompilerOutputter.h> #include <cppunit/XmlOutputter.h> #include <cppunit/extensions/TestFactoryRegistry.h> @@ -39,7 +41,6 @@ int main (int argc, char* argv[]) { - printf ("\nSFLphone Daemon Test Suite, by Savoir-Faire Linux 2004-2010\n\n"); Logger::setConsoleLog (true); Logger::setDebugMode (true); @@ -65,7 +66,7 @@ int main (int argc, char* argv[]) printf (" - %s\n", suite->getChildTestAt (i)->getName().c_str()); } - exit (0); + return 0; } else if (strcmp ("--debug", argv[1]) == 0) { argvIndex++; @@ -89,6 +90,7 @@ int main (int argc, char* argv[]) } printf ("\n\n=== SFLphone initialization ===\n\n"); + system("cp " CONFIG_SAMPLE " " CONFIG_SAMPLE ".bak"); Manager::instance().initConfigFile (true, CONFIG_SAMPLE); Manager::instance().init(); @@ -98,7 +100,8 @@ int main (int argc, char* argv[]) if (suite->getChildTestCount() == 0) { _error ("Invalid test suite name: %s", testSuiteName.c_str()); - exit (-1); + system("mv " CONFIG_SAMPLE ".bak " CONFIG_SAMPLE); + return 1; } // Adds the test to the list of test to run @@ -120,6 +123,7 @@ int main (int argc, char* argv[]) Manager::instance().terminate(); - // Return error code 1 if the one of test failed. + system("mv " CONFIG_SAMPLE ".bak " CONFIG_SAMPLE); + return wasSucessful ? 0 : 1; } diff --git a/sflphone-common/test/mainbuffertest.cpp b/sflphone-common/test/mainbuffertest.cpp index 68c4d087de9d9e40e63c77f89dd9f81cd6bcf2fe..05958fe473981f12ed3b41c8a4d597e1b4b2a887 100644 --- a/sflphone-common/test/mainbuffertest.cpp +++ b/sflphone-common/test/mainbuffertest.cpp @@ -388,7 +388,7 @@ void MainBufferTest::testRingBufferNonDefaultID() CPPUNIT_ASSERT (test_ring_buffer->AvailForGet (test_id) == 2*sizeof (int)); CPPUNIT_ASSERT (test_ring_buffer->getLen (test_id) == 2*sizeof (int)); - CPPUNIT_ASSERT (test_ring_buffer->Get (&testget, sizeof (int), 100, test_id) == sizeof (int)); + CPPUNIT_ASSERT (test_ring_buffer->Get (&testget, sizeof (int), test_id) == sizeof (int)); CPPUNIT_ASSERT (test_ring_buffer->AvailForGet (test_id) == sizeof (int)); CPPUNIT_ASSERT (test_ring_buffer->getLen (test_id) == sizeof (int)); CPPUNIT_ASSERT (testget == testint1); @@ -911,7 +911,7 @@ void MainBufferTest::testGetPutDataByID() // put by default_id get by test_id without preleminary put avail_for_put_defaultid = _mainbuffer.availForPut(); CPPUNIT_ASSERT (_mainbuffer.availForGetByID (default_id, test_id) == 0); - CPPUNIT_ASSERT (_mainbuffer.getDataByID (&test_output, sizeof (int), 100, default_id, test_id) == 0); + CPPUNIT_ASSERT (_mainbuffer.getDataByID (&test_output, sizeof (int), default_id, test_id) == 0); // put by default_id, get by test_id CPPUNIT_ASSERT (_mainbuffer.availForPut() == avail_for_put_defaultid); @@ -1120,13 +1120,13 @@ void MainBufferTest::testRingBufferSeveralPointers() CPPUNIT_ASSERT (test_ring_buffer->AvailForGet (test_pointer2) == 4*sizeof (int)); - CPPUNIT_ASSERT (test_ring_buffer->Get (&testoutput, sizeof (int), 100, test_pointer1) == sizeof (int)); + CPPUNIT_ASSERT (test_ring_buffer->Get (&testoutput, sizeof (int), test_pointer1) == sizeof (int)); CPPUNIT_ASSERT (testoutput == testint1); CPPUNIT_ASSERT (test_ring_buffer->AvailForPut() == initPutLen - 4* (int) sizeof (int)); CPPUNIT_ASSERT (test_ring_buffer->AvailForGet (test_pointer1) == 3*sizeof (int)); CPPUNIT_ASSERT (test_ring_buffer->AvailForGet (test_pointer2) == 4*sizeof (int)); - CPPUNIT_ASSERT (test_ring_buffer->Get (&testoutput, sizeof (int), 100, test_pointer2) == sizeof (int)); + CPPUNIT_ASSERT (test_ring_buffer->Get (&testoutput, sizeof (int), test_pointer2) == sizeof (int)); CPPUNIT_ASSERT (testoutput == testint1); CPPUNIT_ASSERT (test_ring_buffer->AvailForPut() == initPutLen - 3* (int) sizeof (int)); CPPUNIT_ASSERT (test_ring_buffer->AvailForGet (test_pointer1) == 3*sizeof (int)); diff --git a/sflphone-common/test/sdptest.cpp b/sflphone-common/test/sdptest.cpp index a9fd2147f3e2f4d1f118d536c526f292f864cec4..e701b79b297196591cf3ee3f49745e1a7f7a134a 100644 --- a/sflphone-common/test/sdptest.cpp +++ b/sflphone-common/test/sdptest.cpp @@ -114,8 +114,6 @@ void SDPTest::tearDown() { delete _session; _session = NULL; - - pj_pool_release(_testPool); }