diff --git a/sflphone-common/src/audio/alsa/alsalayer.cpp b/sflphone-common/src/audio/alsa/alsalayer.cpp index a636de6840b6ca57b68e1fe6fe916f2c493313e0..a24aeef2e82c5fbb958560dc866ef4f5f1ff1f58 100644 --- a/sflphone-common/src/audio/alsa/alsalayer.cpp +++ b/sflphone-common/src/audio/alsa/alsalayer.cpp @@ -33,8 +33,6 @@ #include "managerimpl.h" -int framesPerBufferAlsa = 2048; - // Constructor AlsaLayer::AlsaLayer (ManagerImpl* manager) : AudioLayer (manager , ALSA) @@ -428,7 +426,7 @@ bool AlsaLayer::alsa_set_params (snd_pcm_t *pcm_handle, int type, int rate) /* Set sample rate. If we can't set to the desired exact value, we set to the nearest acceptable */ dir=0; - rate = getSampleRate(); + rate = _audioSampleRate; exact_ivalue = rate; @@ -825,12 +823,12 @@ AlsaLayer::soundCardGetIndex (std::string description) void AlsaLayer::audioCallback (void) { - int toGet, urgentAvailBytes, normalAvailBytes; + int urgentAvailBytes; unsigned short spkrVolume, micVolume; AudioLoop *tone; AudioLoop *file_tone; - - SFLDataFormat *out = NULL; + unsigned int _mainBufferSampleRate = getMainBuffer()->getInternalSamplingRate(); + bool resample = _audioSampleRate != _mainBufferSampleRate; notifyincomingCall(); @@ -853,119 +851,68 @@ void AlsaLayer::audioCallback (void) int playbackAvailBytes = playbackAvailSmpl*sizeof (SFLDataFormat); if (urgentAvailBytes > 0) { - // Urgent data (dtmf, incoming call signal) come first. - toGet = (urgentAvailBytes < (int) (playbackAvailBytes)) ? urgentAvailBytes : playbackAvailBytes; - out = (SFLDataFormat*) malloc (toGet); - memset (out, 0, toGet); - - if (out) { - _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); - } - - out=NULL; - + int toGet = urgentAvailBytes; + if (toGet > playbackAvailBytes) + toGet = playbackAvailBytes; + SFLDataFormat *out = (SFLDataFormat*) malloc (toGet); + _urgentRingBuffer.Get (out, toGet); + if (spkrVolume != 100) + for (unsigned int i=0; i < toGet / sizeof (SFLDataFormat); i++) + out[i] = out[i] * spkrVolume / 100; + + write (out, toGet, _PlaybackHandle); + free (out); // Consume the regular one as well (same amount of bytes) getMainBuffer()->discard (toGet); - } else { - - normalAvailBytes = getMainBuffer()->availForGet(); - - if (tone && (normalAvailBytes <= 0)) { - - out = (SFLDataFormat *) malloc (playbackAvailBytes); - memset (out, 0, playbackAvailBytes); - - if (out) { - _debug("Write tone (normal %d) (playbackAvail %d)", normalAvailBytes, playbackAvailBytes); - tone->getNext (out, playbackAvailSmpl, spkrVolume); - write (out , playbackAvailBytes, _PlaybackHandle); - free (out); - } - - out = NULL; - - } else if (file_tone && !_RingtoneHandle && (normalAvailBytes <= 0)) { - - out = (SFLDataFormat *) malloc (playbackAvailBytes); - memset (out, 0, playbackAvailBytes); - - if (out) { - file_tone->getNext (out, playbackAvailSmpl, spkrVolume); - write (out, playbackAvailBytes, _PlaybackHandle); - free (out); - } - - out = NULL; - + // regular audio data + int toGet = getMainBuffer()->availForGet(); + + if (toGet <= 0) { + // no audio available, play tone or silence + SFLDataFormat *out = (SFLDataFormat *) malloc (playbackAvailBytes); + + if (tone) + tone->getNext (out, playbackAvailSmpl, spkrVolume); + else if (file_tone && !_RingtoneHandle) + file_tone->getNext (out, playbackAvailSmpl, spkrVolume); + else + memset(out, 0, playbackAvailBytes); + + write (out, playbackAvailBytes, _PlaybackHandle); + free (out); } else { - // If nothing urgent, play the regular sound samples + // play the regular sound samples - int _mainBufferSampleRate = getMainBuffer()->getInternalSamplingRate(); - int maxNbSamplesToGet = playbackAvailSmpl; int maxNbBytesToGet = playbackAvailBytes; - - // Compute maximal value to get into the ring buffer - - if (_mainBufferSampleRate && ( (int) _audioSampleRate != _mainBufferSampleRate)) { - - double upsampleFactor = (double) _audioSampleRate / _mainBufferSampleRate; - maxNbSamplesToGet = (int) ( (double) playbackAvailSmpl / upsampleFactor); - maxNbBytesToGet = maxNbSamplesToGet * sizeof (SFLDataFormat); - - } - - toGet = (normalAvailBytes < (int) maxNbBytesToGet) ? normalAvailBytes : maxNbBytesToGet; - - out = (SFLDataFormat*) malloc (maxNbBytesToGet); - memset (out, 0, maxNbBytesToGet); - - if (normalAvailBytes) { - 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); - - _converter->resample ( (SFLDataFormat*) out, rsmpl_out, _mainBufferSampleRate, _audioSampleRate, toGet / sizeof (SFLDataFormat)); - write (rsmpl_out, toGet, _PlaybackHandle); - free (rsmpl_out); - - } else { - - write (out, toGet, _PlaybackHandle); - - } - } else { - - if (!tone && !file_tone) { - - SFLDataFormat *zeros = (SFLDataFormat*) malloc (playbackAvailBytes); - - if (zeros) { - bzero (zeros, playbackAvailBytes); - write (zeros, playbackAvailBytes, _PlaybackHandle); - free (zeros); - } - - zeros = NULL; - } + // Compute maximal value to get from the ring buffer + double resampleFactor = 1.0; + if (resample) { + resampleFactor = (double) _audioSampleRate / _mainBufferSampleRate; + maxNbBytesToGet = (double) toGet / resampleFactor; } - _urgentRingBuffer.Discard (toGet); - - free (out); - out = NULL; + if (toGet > maxNbBytesToGet) + toGet = maxNbBytesToGet; + + SFLDataFormat *out = (SFLDataFormat*) malloc (toGet); + getMainBuffer()->getData (out, toGet); + if (spkrVolume!=100) + for (unsigned int i=0; i<toGet / sizeof (SFLDataFormat); i++) + out[i] = out[i] * spkrVolume / 100; + + if (resample) { + int inSamples = toGet / sizeof(SFLDataFormat); + int outSamples = inSamples * resampleFactor; + SFLDataFormat *rsmpl_out = (SFLDataFormat*) malloc (outSamples * sizeof(SFLDataFormat)); + _converter->resample (out, rsmpl_out, _mainBufferSampleRate, _audioSampleRate, inSamples); + write (rsmpl_out, outSamples * sizeof(SFLDataFormat), _PlaybackHandle); + free (rsmpl_out); + } else { + write (out, toGet, _PlaybackHandle); + } + free (out); } } @@ -973,96 +920,68 @@ void AlsaLayer::audioCallback (void) int ringtoneAvailSmpl = snd_pcm_avail_update (_RingtoneHandle); int ringtoneAvailBytes = ringtoneAvailSmpl*sizeof (SFLDataFormat); - out = (SFLDataFormat *) malloc (ringtoneAvailBytes); - - if (out) { - file_tone->getNext (out, ringtoneAvailSmpl, spkrVolume); - write (out, ringtoneAvailBytes, _RingtoneHandle); - free (out); - } - - out = NULL; - + SFLDataFormat *out = (SFLDataFormat *) malloc (ringtoneAvailBytes); + file_tone->getNext (out, ringtoneAvailSmpl, spkrVolume); + write (out, ringtoneAvailBytes, _RingtoneHandle); + free (out); } else if (_RingtoneHandle) { int ringtoneAvailSmpl = snd_pcm_avail_update (_RingtoneHandle); int ringtoneAvailBytes = ringtoneAvailSmpl*sizeof (SFLDataFormat); - out = (SFLDataFormat *) malloc (ringtoneAvailBytes); - - if (out) { - memset (out, 0, ringtoneAvailBytes); - write (out, ringtoneAvailBytes, _RingtoneHandle); - free (out); - } - - out = NULL; + SFLDataFormat *out = (SFLDataFormat *) malloc (ringtoneAvailBytes); + memset (out, 0, ringtoneAvailBytes); + write (out, ringtoneAvailBytes, _RingtoneHandle); + free (out); } // Additionally handle the mic's audio stream - int micAvailBytes; - int toPut; - - SFLDataFormat* in = NULL; - if (!is_capture_running()) return; - micAvailBytes = snd_pcm_avail_update (_CaptureHandle); - - if (micAvailBytes < 0) - _debug ("Audio: Mic error: %s", snd_strerror (micAvailBytes)); - if (micAvailBytes <= 0) + int toPutSamples = snd_pcm_avail_update (_CaptureHandle); + if (toPutSamples <= 0) { + if (toPutSamples < 0) + _error ("Audio: Mic error: %s", snd_strerror (toPutSamples)); return; + } - toPut = (micAvailBytes <= framesPerBufferAlsa) ? micAvailBytes : framesPerBufferAlsa; - in = (SFLDataFormat*) malloc (toPut * sizeof (SFLDataFormat)); - toPut = read (in, toPut* sizeof (SFLDataFormat)); - - adjustVolume (in, toPut, SFL_PCM_CAPTURE); - - int _mainBufferSampleRate = getMainBuffer()->getInternalSamplingRate(); - - if (_mainBufferSampleRate && ( (int) _audioSampleRate != _mainBufferSampleRate)) { - - SFLDataFormat* rsmpl_out = (SFLDataFormat*) malloc (framesPerBufferAlsa * sizeof (SFLDataFormat)); - - _converter->resample ( (SFLDataFormat*) in, rsmpl_out, _mainBufferSampleRate, _audioSampleRate, toPut / sizeof (SFLDataFormat)); - - _audiofilter->processAudio (rsmpl_out, toPut); - - getMainBuffer()->putData (rsmpl_out, toPut); - + const int framesPerBufferAlsa = 2048; + if (toPutSamples > framesPerBufferAlsa) + toPutSamples = framesPerBufferAlsa; + + int toPutBytes = toPutSamples * sizeof(SFLDataFormat); + SFLDataFormat* in = (SFLDataFormat*) malloc (toPutBytes); + int bytes = read (in, toPutBytes); + if (toPutBytes != bytes) { + _error("ALSA MIC : Couldn't read!"); + free(in); + return; + } + adjustVolume (in, toPutSamples, _manager->getSpkrVolume()); + + if (resample) { + int outSamples = toPutSamples * ((double) _audioSampleRate / _mainBufferSampleRate); + int outBytes = outSamples * sizeof (SFLDataFormat); + SFLDataFormat* rsmpl_out = (SFLDataFormat*) malloc (outBytes); + _converter->resample ( (SFLDataFormat*) in, rsmpl_out, _mainBufferSampleRate, _audioSampleRate, toPutSamples); + _audiofilter->processAudio (rsmpl_out, outBytes); + getMainBuffer()->putData (rsmpl_out, outBytes); free (rsmpl_out); } else { - SFLDataFormat* filter_out = (SFLDataFormat*) malloc (framesPerBufferAlsa * sizeof (SFLDataFormat)); - - if (filter_out) { - _audiofilter->processAudio (in, filter_out, toPut); - // captureFile->write ( (const char *) filter_out, toPut); - getMainBuffer()->putData (filter_out, toPut); - free (filter_out); - } + SFLDataFormat* filter_out = (SFLDataFormat*) malloc (toPutBytes); + _audiofilter->processAudio (in, filter_out, toPutBytes); + // captureFile->write ( (const char *) filter_out, toPut); + getMainBuffer()->putData (filter_out, toPutBytes); + free (filter_out); } free (in); } -void* AlsaLayer::adjustVolume (void* buffer , int len, int stream) +void AlsaLayer::adjustVolume (SFLDataFormat *src , int samples, int volume) { - int vol = (stream == SFL_PCM_PLAYBACK) - ? _manager->getSpkrVolume() - : _manager->getMicVolume(); - - SFLDataFormat *src = (SFLDataFormat*) buffer; - - if (vol != 100) { - int i, size = len / sizeof (SFLDataFormat); - - for (i = 0 ; i < size ; i++) { - src[i] = src[i] * vol / 100 ; - } - } - - return src ; + if (volume != 100) + for (int i = 0 ; i < samples; i++) + src[i] = src[i] * volume / 100 ; } diff --git a/sflphone-common/src/audio/alsa/alsalayer.h b/sflphone-common/src/audio/alsa/alsalayer.h index c317700327a35d44b9c63a8a9c81157cf7e5d1f4..f35f322a4b521edaa2164e2bd2d9b923b29e5f41 100644 --- a/sflphone-common/src/audio/alsa/alsalayer.h +++ b/sflphone-common/src/audio/alsa/alsalayer.h @@ -292,7 +292,7 @@ class AlsaLayer : public AudioLayer */ void handle_xrun_playback (snd_pcm_t *handle); - void* adjustVolume (void* buffer , int len, int stream); + void adjustVolume (SFLDataFormat* buffer , int samples, int volume); /** * Handles to manipulate playback stream diff --git a/sflphone-common/src/audio/audioloop.cpp b/sflphone-common/src/audio/audioloop.cpp index ebfc29edddeafdfaf4394bb1fff620faeb7f06a8..7bd8afe3987f90556066810ab97975eaab1114fb 100644 --- a/sflphone-common/src/audio/audioloop.cpp +++ b/sflphone-common/src/audio/audioloop.cpp @@ -46,20 +46,19 @@ AudioLoop::~AudioLoop() _buffer = 0; } -int -AudioLoop::getNext (SFLDataFormat* output, int nb, short volume) +void +AudioLoop::getNext (SFLDataFormat* output, int samples, short volume) { - int copied = 0; int block; int pos = _pos; if(_size == 0) { _error("AudioLoop: Error: Audio loop size is 0"); - return 0; + return; } - while (nb) { - block = nb; + while (samples) { + block = samples; if (block > (_size-pos)) { block = _size-pos; @@ -79,13 +78,9 @@ AudioLoop::getNext (SFLDataFormat* output, int nb, short volume) // should adjust sound here, in output??? pos = (pos + block) % _size; - nb -= block; - - copied += block; + samples -= block; } _pos = pos; - - return copied; } diff --git a/sflphone-common/src/audio/audioloop.h b/sflphone-common/src/audio/audioloop.h index 2eb1c7bc4e86c1e6e366250529888dedad5d8a78..5e6616e710c825fba5c2243adcdf642c84f89318 100644 --- a/sflphone-common/src/audio/audioloop.h +++ b/sflphone-common/src/audio/audioloop.h @@ -60,9 +60,8 @@ class AudioLoop * @param output The data buffer * @param nb of int16 to send * @param volume The volume - * @return the number of int16 sent (nb*2) */ - int getNext (SFLDataFormat* output, int nb, short volume=100); + void getNext (SFLDataFormat* output, int samples, short volume=100); /** * Reset the pointer position diff --git a/sflphone-common/src/audio/audiortp/AudioRtpRecordHandler.cpp b/sflphone-common/src/audio/audiortp/AudioRtpRecordHandler.cpp index c27b1533a3fa905e186bfad51f2d260bba709510..8a5503ecf1f781cf765286a18a6059ea077f741b 100644 --- a/sflphone-common/src/audio/audiortp/AudioRtpRecordHandler.cpp +++ b/sflphone-common/src/audio/audiortp/AudioRtpRecordHandler.cpp @@ -42,18 +42,10 @@ static const SFLDataFormat initFadeinFactor = 32000; AudioRtpRecord::AudioRtpRecord () : _audioCodec (NULL) , _hasDynamicPayloadType (false) - , _micData (NULL) - , _micDataConverted (NULL) - , _micDataEncoded (NULL) - , _spkrDataDecoded (NULL) - , _spkrDataConverted (NULL) , _converter (NULL) , _codecSampleRate (0) , _codecFrameSize (0) - , _micFadeInComplete (false) - , _spkrFadeInComplete (false) , _micAmplFactor (initFadeinFactor) - , _spkrAmplFactor (initFadeinFactor) , _audioProcess (NULL) , _noiseSuppress (NULL) , _callId ("") @@ -65,35 +57,10 @@ AudioRtpRecord::AudioRtpRecord () : _audioCodec (NULL) AudioRtpRecord::~AudioRtpRecord() { - _debug ("AudioRtpRecord: Delete audio rtp internal data"); - - delete [] _micData; - - delete [] _micDataConverted; - - delete [] _micDataEncoded; - - delete [] _micDataEchoCancelled; - - delete [] _spkrDataDecoded; - - delete [] _spkrDataConverted; - delete _converter; - - audioCodecMutex.enter(); - delete _audioCodec; - - audioCodecMutex.leave(); - - audioProcessMutex.enter(); - delete _audioProcess; - delete _noiseSuppress; - - audioProcessMutex.leave(); } @@ -124,93 +91,41 @@ void AudioRtpRecordHandler::updateRtpMedia (AudioCodec *audioCodec) { int lastSamplingRate = _audioRtpRecord._codecSampleRate; - _audioRtpRecord.audioCodecMutex.enter(); - - if (_audioRtpRecord._audioCodec) { - delete _audioRtpRecord._audioCodec; - _audioRtpRecord._audioCodec = NULL; - } - - _audioRtpRecord._audioCodec = audioCodec; - _audioRtpRecord._codecPayloadType = audioCodec->getPayloadType(); - _audioRtpRecord._codecSampleRate = audioCodec->getClockRate(); - _audioRtpRecord._codecFrameSize = audioCodec->getFrameSize(); - _audioRtpRecord._hasDynamicPayloadType = audioCodec->hasDynamicPayload(); - - _audioRtpRecord.audioCodecMutex.leave(); + setRtpMedia(audioCodec); Manager::instance().audioSamplingRateChanged(_audioRtpRecord._codecSampleRate); - if (lastSamplingRate != _audioRtpRecord._codecSampleRate) - updateNoiseSuppress(); -} - -void AudioRtpRecordHandler::init() -{ + if (lastSamplingRate != _audioRtpRecord._codecSampleRate) { + _debug ("AudioRtpSession: Update noise suppressor with sampling rate %d and frame size %d", getCodecSampleRate(), getCodecFrameSize()); + initNoiseSuppress(); + } } void AudioRtpRecordHandler::initBuffers() { - int codecSampleRate = _audioRtpRecord._codecSampleRate; - // Set sampling rate, main buffer choose the highest one // Manager::instance().getMainBuffer()->setInternalSamplingRate (codecSampleRate); - Manager::instance().audioSamplingRateChanged(codecSampleRate); + Manager::instance().audioSamplingRateChanged(_audioRtpRecord._codecSampleRate); // initialize SampleRate converter using AudioLayer's sampling rate // (internal buffers initialized with maximal sampling rate and frame size) - int rate = getCodecSampleRate(); - _audioRtpRecord._converter = new SamplerateConverter (rate); - - int nbSamplesMax = (int) ( (getCodecSampleRate() * getCodecFrameSize() / 1000)); - _audioRtpRecord._micData = new SFLDataFormat[nbSamplesMax]; - _audioRtpRecord._micDataConverted = new SFLDataFormat[nbSamplesMax]; - _audioRtpRecord._micDataEchoCancelled = new SFLDataFormat[nbSamplesMax]; - _audioRtpRecord._micDataEncoded = new unsigned char[nbSamplesMax * 2]; - _audioRtpRecord._spkrDataConverted = new SFLDataFormat[nbSamplesMax]; - _audioRtpRecord._spkrDataDecoded = new SFLDataFormat[nbSamplesMax]; + delete _audioRtpRecord._converter; + _audioRtpRecord._converter = new SamplerateConverter (getCodecSampleRate()); } void AudioRtpRecordHandler::initNoiseSuppress() { _audioRtpRecord.audioProcessMutex.enter(); - NoiseSuppress *noiseSuppress = new NoiseSuppress (getCodecFrameSize(), getCodecSampleRate()); - AudioProcessing *processing = new AudioProcessing (noiseSuppress); + delete _audioRtpRecord._audioProcess; + delete _audioRtpRecord._noiseSuppress; - _audioRtpRecord._noiseSuppress = noiseSuppress; - _audioRtpRecord._audioProcess = processing; + _audioRtpRecord._noiseSuppress = new NoiseSuppress (getCodecFrameSize(), getCodecSampleRate()); + _audioRtpRecord._audioProcess = new AudioProcessing (_audioRtpRecord._noiseSuppress); _audioRtpRecord.audioProcessMutex.leave(); } -void AudioRtpRecordHandler::updateNoiseSuppress() -{ - - _audioRtpRecord.audioProcessMutex.enter(); - - if (_audioRtpRecord._audioProcess) - delete _audioRtpRecord._audioProcess; - - _audioRtpRecord._audioProcess = NULL; - - if (_audioRtpRecord._noiseSuppress) - delete _audioRtpRecord._noiseSuppress; - - _audioRtpRecord._noiseSuppress = NULL; - - _debug ("AudioRtpSession: Update noise suppressor with sampling rate %d and frame size %d", getCodecSampleRate(), getCodecFrameSize()); - - NoiseSuppress *noiseSuppress = new NoiseSuppress (getCodecFrameSize(), getCodecSampleRate()); - AudioProcessing *processing = new AudioProcessing (noiseSuppress); - - _audioRtpRecord._noiseSuppress = noiseSuppress; - _audioRtpRecord._audioProcess = processing; - - _audioRtpRecord.audioProcessMutex.leave(); - -} - void AudioRtpRecordHandler::putDtmfEvent (int digit) { sfl::DtmfEvent *dtmf = new sfl::DtmfEvent(); @@ -230,73 +145,54 @@ std::ofstream teststream("test_process_data_encode.raw"); int AudioRtpRecordHandler::processDataEncode (void) { - SFLDataFormat *micData = _audioRtpRecord._micData; - unsigned char *micDataEncoded = _audioRtpRecord._micDataEncoded; - SFLDataFormat *micDataConverted = _audioRtpRecord._micDataConverted; + SFLDataFormat *micData = _audioRtpRecord.decData; + unsigned char *micDataEncoded = _audioRtpRecord.encodedData; + SFLDataFormat *micDataConverted = _audioRtpRecord.resampledData; int codecSampleRate = getCodecSampleRate(); int mainBufferSampleRate = Manager::instance().getMainBuffer()->getInternalSamplingRate(); - // compute codec framesize in ms - 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 = (int) ( ( (float) mainBufferSampleRate * fixedCodecFramesize * sizeof (SFLDataFormat)) / 1000.0); + double resampleFactor = (double)mainBufferSampleRate / codecSampleRate; - if (Manager::instance().getMainBuffer()->availForGet (id_) < bytesToGet) + // compute nb of byte to get coresponding to 1 audio frame + int samplesToGet = resampleFactor * getCodecFrameSize(); + int bytesToGet = samplesToGet * sizeof (SFLDataFormat); + + if (Manager::instance().getMainBuffer()->availForGet (id_) < bytesToGet) { + _error("%s : not enough data available", __PRETTY_FUNCTION__); return 0; + } int bytes = Manager::instance().getMainBuffer()->getData (micData, bytesToGet, id_); - if (bytes == 0) + if (bytes != bytesToGet) { + _error("%s : asked %d bytes from mainbuffer, got %d", __PRETTY_FUNCTION__, bytesToGet, bytes); return 0; + } - if (!_audioRtpRecord._micFadeInComplete) - _audioRtpRecord._micFadeInComplete = fadeIn (micData, bytes / sizeof(SFLDataFormat), &_audioRtpRecord._micAmplFactor); - - // nb bytes to be sent over RTP - int compSize; - - // test if resampling is required - if (codecSampleRate != mainBufferSampleRate) { - _audioRtpRecord._converter->resample (micData, micDataConverted, codecSampleRate, mainBufferSampleRate, bytes / sizeof(SFLDataFormat)); - - _audioRtpRecord.audioProcessMutex.enter(); - - if (Manager::instance().audioPreference.getNoiseReduce()) { - _audioRtpRecord._audioProcess->processAudio (micDataConverted, bytes); - } - - if(Manager::instance().getEchoCancelState() == "enabled") { - echoCanceller.getData(micData); - } - - _audioRtpRecord.audioProcessMutex.leave(); - - _audioRtpRecord.audioCodecMutex.enter(); - - compSize = _audioRtpRecord._audioCodec->encode (micDataEncoded, micData, bytes); - - _audioRtpRecord.audioCodecMutex.leave(); + fadeIn (micData, bytesToGet / sizeof(SFLDataFormat), &_audioRtpRecord._micAmplFactor); - } else { // no resampling required - _audioRtpRecord.audioProcessMutex.enter(); + if(Manager::instance().getEchoCancelState() == "enabled") + echoCanceller.getData(micData); - if (Manager::instance().audioPreference.getNoiseReduce()) - _audioRtpRecord._audioProcess->processAudio (micData, bytes); + _audioRtpRecord.audioProcessMutex.enter(); + if (Manager::instance().audioPreference.getNoiseReduce()) + _audioRtpRecord._audioProcess->processAudio (micData, bytesToGet); + _audioRtpRecord.audioProcessMutex.leave(); - if(Manager::instance().getEchoCancelState() == "enabled") - echoCanceller.getData(micData); - #ifdef DUMP_PROCESS_DATA_ENCODE - teststream.write(reinterpret_cast<char *>(micData), nbSample * sizeof(SFLDataFormat)); + teststream.write(reinterpret_cast<char *>(micData), bytesToGet); #endif - - _audioRtpRecord.audioProcessMutex.leave(); - _audioRtpRecord.audioCodecMutex.enter(); - compSize = _audioRtpRecord._audioCodec->encode (micDataEncoded, micData, bytes); - _audioRtpRecord.audioCodecMutex.leave(); + SFLDataFormat *out = micData; + if (codecSampleRate != mainBufferSampleRate) { + out = micDataConverted; + _audioRtpRecord._converter->resample (micData, micDataConverted, codecSampleRate, mainBufferSampleRate, samplesToGet); } + _audioRtpRecord.audioCodecMutex.enter(); + int compSize = _audioRtpRecord._audioCodec->encode (micDataEncoded, out, getCodecFrameSize()); + _audioRtpRecord.audioCodecMutex.leave(); + return compSize; } @@ -304,8 +200,8 @@ void AudioRtpRecordHandler::processDataDecode (unsigned char *spkrData, unsigned { int codecSampleRate = getCodecSampleRate(); - SFLDataFormat *spkrDataDecoded = _audioRtpRecord._spkrDataConverted; - SFLDataFormat *spkrDataConverted = _audioRtpRecord._spkrDataDecoded; + SFLDataFormat *spkrDataDecoded = _audioRtpRecord.decData; + SFLDataFormat *spkrDataConverted = _audioRtpRecord.resampledData; int mainBufferSampleRate = Manager::instance().getMainBuffer()->getInternalSamplingRate(); @@ -316,50 +212,38 @@ void AudioRtpRecordHandler::processDataDecode (unsigned char *spkrData, unsigned _audioRtpRecord.audioCodecMutex.leave(); - // buffer _receiveDataDecoded ----> short int or int16, coded on 2 bytes - int nbSample = expandedSize / sizeof (SFLDataFormat); + int inSamples = expandedSize / sizeof (SFLDataFormat); - if (!_audioRtpRecord._spkrFadeInComplete) { - _audioRtpRecord._spkrFadeInComplete = fadeIn (spkrDataDecoded, nbSample, &_audioRtpRecord._micAmplFactor); - } + fadeIn (spkrDataDecoded, inSamples, &_audioRtpRecord._micAmplFactor); // Normalize incomming signal - gainController.process(spkrDataDecoded, nbSample); + gainController.process(spkrDataDecoded, inSamples); + SFLDataFormat *out = spkrDataDecoded; + int outSamples = inSamples; // test if resampling is required if (codecSampleRate != mainBufferSampleRate) { // Do sample rate conversion - _audioRtpRecord._converter->resample (spkrDataDecoded, spkrDataConverted, codecSampleRate, mainBufferSampleRate, nbSample); - - if(Manager::instance().getEchoCancelState() == "enabled") { - echoCanceller.putData(spkrDataConverted, expandedSize); - } - - // put data in audio layer, size in byte - Manager::instance().getMainBuffer()->putData (spkrDataConverted, expandedSize, id_); - - } else { - if(Manager::instance().getEchoCancelState() == "enabled") { - echoCanceller.putData(spkrDataDecoded, expandedSize); - } - // put data in audio layer, size in byte - Manager::instance().getMainBuffer()->putData (spkrDataDecoded, expandedSize, id_); + outSamples = ((float) inSamples * ( (float) mainBufferSampleRate / (float) codecSampleRate)); + _audioRtpRecord._converter->resample (spkrDataDecoded, spkrDataConverted, codecSampleRate, mainBufferSampleRate, inSamples); + out = spkrDataConverted; } + + if(Manager::instance().getEchoCancelState() == "enabled") + echoCanceller.putData(out, outSamples * sizeof (SFLDataFormat)); + Manager::instance().getMainBuffer()->putData (out, outSamples * sizeof (SFLDataFormat), id_); } -bool AudioRtpRecordHandler::fadeIn (SFLDataFormat *audio, int size, SFLDataFormat *factor) +void AudioRtpRecordHandler::fadeIn (SFLDataFormat *audio, int size, SFLDataFormat *factor) { - // if factor reach 0, this function should no be called anymore + // if factor reach 0, this function should have no effect if (*factor <= 0) - return true; + return; while (size) audio[--size] /= *factor; *factor /= FADEIN_STEP_SIZE; - - return *factor <= 0; } } - diff --git a/sflphone-common/src/audio/audiortp/AudioRtpRecordHandler.h b/sflphone-common/src/audio/audiortp/AudioRtpRecordHandler.h index 87bd6e4814e0021486d3de23beef46d0d1c039a7..c9d64998660d61db534146a7dd44c854a8c90453 100644 --- a/sflphone-common/src/audio/audiortp/AudioRtpRecordHandler.h +++ b/sflphone-common/src/audio/audiortp/AudioRtpRecordHandler.h @@ -95,21 +95,15 @@ class AudioRtpRecord ost::Mutex audioCodecMutex; int _codecPayloadType; bool _hasDynamicPayloadType; - SFLDataFormat *_micData; - SFLDataFormat *_micDataConverted; - SFLDataFormat *_micDataEchoCancelled; - unsigned char *_micDataEncoded; - SFLDataFormat *_spkrDataDecoded; - SFLDataFormat *_spkrDataConverted; + SFLDataFormat decData[DEC_BUFFER_SIZE]; + SFLDataFormat resampledData[DEC_BUFFER_SIZE]; + unsigned char encodedData[DEC_BUFFER_SIZE]; SamplerateConverter *_converter; int _codecSampleRate; int _codecFrameSize; int _converterSamplingRate; EventQueue _eventQueue; - bool _micFadeInComplete; - bool _spkrFadeInComplete; SFLDataFormat _micAmplFactor; - SFLDataFormat _spkrAmplFactor; AudioProcessing *_audioProcess; NoiseSuppress *_noiseSuppress; ost::Mutex audioProcessMutex; @@ -162,30 +156,14 @@ class AudioRtpRecordHandler return _audioRtpRecord._eventQueue.size(); } - SFLDataFormat *getMicData (void) { - return _audioRtpRecord._micData; + const unsigned char *getMicDataEncoded (void) const { + return _audioRtpRecord.encodedData; } - SFLDataFormat *getMicDataConverted (void) const { - return _audioRtpRecord._micDataConverted; - } - - unsigned char *getMicDataEncoded (void) const { - return _audioRtpRecord._micDataEncoded; - } - - void init (void); - - /** - * Allocate memory for RTP buffers and fill them with zeros - * @prereq Session codec needs to be initialized prior calling this method - */ void initBuffers (void); void initNoiseSuppress (void); - void updateNoiseSuppress (void); - /** * Encode audio data from mainbuffer */ @@ -199,7 +177,7 @@ class AudioRtpRecordHandler /** * Ramp In audio data to avoid audio click from peer */ - bool fadeIn (SFLDataFormat *audio, int size, SFLDataFormat *factor); + void fadeIn (SFLDataFormat *audio, int size, SFLDataFormat *factor); void setDtmfPayloadType(unsigned int payloadType) { _audioRtpRecord._dtmfPayloadType = payloadType; diff --git a/sflphone-common/src/audio/codecs/audiocodec.h b/sflphone-common/src/audio/codecs/audiocodec.h index 7f443db054fd4447269073c76bcc60068c1e9727..aa05c008e4f2d2a532d863168de087e93dee07f5 100644 --- a/sflphone-common/src/audio/codecs/audiocodec.h +++ b/sflphone-common/src/audio/codecs/audiocodec.h @@ -38,6 +38,11 @@ #include "Codec.h" +// We assume all decoders will be fed 20ms of audio or less +// And we'll resample them to 44.1kHz or less +// Also assume mono +#define DEC_BUFFER_SIZE ((44100 * 20) / 1000) + namespace ost { class PayloadFormat; class DynamicPayloadFormat; diff --git a/sflphone-common/src/audio/codecs/audiocodecfactory.cpp b/sflphone-common/src/audio/codecs/audiocodecfactory.cpp index 2142e5bc1be5e213d91adad47b0e86e87fc42740..9c429336aba12fce69d78c9ce5cd964c8fa219aa 100644 --- a/sflphone-common/src/audio/codecs/audiocodecfactory.cpp +++ b/sflphone-common/src/audio/codecs/audiocodecfactory.cpp @@ -388,7 +388,6 @@ bool AudioCodecFactory::isCodecLoaded (int payload) std::vector <std::string> AudioCodecFactory::getCodecSpecifications (const int32_t& payload) { - _debug ("CodecDescriptor: Gathering codec specifications for payload %i", payload); std::vector<std::string> v; @@ -408,5 +407,4 @@ std::vector <std::string> AudioCodecFactory::getCodecSpecifications (const int32 ss.str (""); return v; - } diff --git a/sflphone-common/src/audio/pulseaudio/pulselayer.cpp b/sflphone-common/src/audio/pulseaudio/pulselayer.cpp index dbc3457b04215abe4fa9cad72cf2d1f8350c726d..db24a223a154ee47cd6953739bd9d60f6cd8ce36 100644 --- a/sflphone-common/src/audio/pulseaudio/pulselayer.cpp +++ b/sflphone-common/src/audio/pulseaudio/pulselayer.cpp @@ -719,132 +719,86 @@ void PulseLayer::setNoiseSuppressState (bool state) void PulseLayer::writeToSpeaker (void) { - /** Bytes available in the urgent ringbuffer ( reserved for DTMF ) */ - int urgentAvailBytes; - /** Bytes available in the regular ringbuffer ( reserved for voice ) */ - int normalAvailBytes; - /** Bytes to get in the ring buffer **/ - int byteToGet; - notifyincomingCall(); - SFLDataFormat* out;// = (SFLDataFormat*)pa_xmalloc(framesPerBuffer); - urgentAvailBytes = _urgentRingBuffer.AvailForGet(); - // available bytes to be written in pulseaudio internal buffer - int writeableSize = pa_stream_writable_size (playback->pulseStream()); - - if (writeableSize < 0) { - _warn ("Audio: playback error : %s", pa_strerror (writeableSize)); - } - - AudioLoop *toneToPlay = _manager->getTelephoneTone(); - - if (urgentAvailBytes > writeableSize) { - - out = (SFLDataFormat*) pa_xmalloc (writeableSize); - memset (out, 0, writeableSize); - - _urgentRingBuffer.Get (out, writeableSize); - - pa_stream_write (playback->pulseStream(), out, writeableSize, NULL, 0, PA_SEEK_RELATIVE); - + int writeableSizeBytes = pa_stream_writable_size (playback->pulseStream()); + if (writeableSizeBytes < 0) { + _error ("Audio: playback error : %s", pa_strerror (writeableSizeBytes)); + return; + } + + int urgentBytes = _urgentRingBuffer.AvailForGet(); + if (urgentBytes > writeableSizeBytes) + urgentBytes = writeableSizeBytes; + if (urgentBytes) { + SFLDataFormat *out = (SFLDataFormat*) pa_xmalloc (urgentBytes); + _urgentRingBuffer.Get (out, urgentBytes); + pa_stream_write (playback->pulseStream(), out, urgentBytes, NULL, 0, PA_SEEK_RELATIVE); pa_xfree (out); - // Consume the regular one as well (same amount of bytes) - getMainBuffer()->discard (writeableSize); - - - } - else if (toneToPlay != 0) { - - if (playback->getStreamState() == PA_STREAM_READY) { - - out = (SFLDataFormat*) pa_xmalloc (writeableSize); - memset (out, 0, writeableSize); - - int copied = toneToPlay->getNext (out, writeableSize / sizeof (SFLDataFormat), 100); - - //spkrFile->write ( (const char *) out, copied*sizeof (SFLDataFormat)); - pa_stream_write (playback->pulseStream(), out, copied * sizeof (SFLDataFormat), NULL, 0, PA_SEEK_RELATIVE); - - pa_xfree (out); - } + getMainBuffer()->discard (urgentBytes); + return; } - else { - - // We must test if data have been received from network in case of early media - normalAvailBytes = getMainBuffer()->availForGet(); - - // flush remaining samples in _urgentRingBuffer - flushUrgent(); - - int _mainBufferSampleRate = getMainBuffer()->getInternalSamplingRate(); - - int maxNbBytesToGet = 0; - - // test if audio resampling is needed - if (_mainBufferSampleRate && ( (int) _audioSampleRate != _mainBufferSampleRate)) { - double upsampleFactor = (double) _mainBufferSampleRate / _audioSampleRate; - maxNbBytesToGet = ( (double) writeableSize * upsampleFactor); - } else { - maxNbBytesToGet = writeableSize; - } - - byteToGet = (normalAvailBytes < (int) (maxNbBytesToGet)) ? normalAvailBytes : maxNbBytesToGet; - - if (byteToGet) { - // Sending an odd number of byte breaks the audio! - byteToGet &= ~1; - - out = (SFLDataFormat*) pa_xmalloc (maxNbBytesToGet); - memset (out, 0, maxNbBytesToGet); - - 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); - _converter->resample ( (SFLDataFormat*) out, rsmpl_out, _mainBufferSampleRate, _audioSampleRate, byteToGet / sizeof (SFLDataFormat)); - - if ( byteToGet > (unsigned int) writeableSize) - _warn ("Audio: Error: nbsbyte exceed buffer length"); - - pa_stream_write (playback->pulseStream(), rsmpl_out, byteToGet, NULL, 0, PA_SEEK_RELATIVE); + AudioLoop *toneToPlay = _manager->getTelephoneTone(); + if (toneToPlay) { + if (playback->getStreamState() == PA_STREAM_READY) { + SFLDataFormat *out = (SFLDataFormat*) pa_xmalloc (writeableSizeBytes); + toneToPlay->getNext (out, writeableSizeBytes / sizeof (SFLDataFormat), 100); + //spkrFile->write ( (const char *) out, writeableSize); + pa_stream_write (playback->pulseStream(), out, writeableSizeBytes, NULL, 0, PA_SEEK_RELATIVE); + pa_xfree (out); + } + return; + } - pa_xfree (rsmpl_out); + flushUrgent(); // flush remaining samples in _urgentRingBuffer - } else { - // write origin data - pa_stream_write (playback->pulseStream(), out, byteToGet, NULL, 0, PA_SEEK_RELATIVE); - } + int availSamples = getMainBuffer()->availForGet() / sizeof(SFLDataFormat); + if (availSamples == 0) { + // play silence + SFLDataFormat* zeros = (SFLDataFormat*) pa_xmalloc0(writeableSizeBytes); + pa_stream_write (playback->pulseStream(), zeros, writeableSizeBytes, NULL, 0, PA_SEEK_RELATIVE); + pa_xfree (zeros); + return; + } - // free audio buffer used to get data from - pa_xfree (out); + unsigned int mainBufferSampleRate = getMainBuffer()->getInternalSamplingRate(); + bool resample = _audioSampleRate != mainBufferSampleRate; - } else { + // how much samples we can write in the output + int outSamples = writeableSizeBytes / sizeof(SFLDataFormat); - // Get ringtone - // AudioLoop *fileToPlay = _manager->getTelephoneTone(); + // how much samples we want to read from the buffer + int inSamples = outSamples; - // If audio stream is open and there is realy nothing to play (i.e. audio voce is late and audio layer is underrun) - if (toneToPlay == NULL) { + double resampleFactor = 1.; + if (resample) { + resampleFactor = (double) _audioSampleRate / mainBufferSampleRate; + inSamples = (double) inSamples / resampleFactor; + } - SFLDataFormat* zeros = (SFLDataFormat*) pa_xmalloc (writeableSize); - bzero (zeros, writeableSize); + if (inSamples > availSamples) + inSamples = availSamples; + int outBytes = (double)inSamples * resampleFactor * sizeof(SFLDataFormat); - pa_stream_write (playback->pulseStream(), zeros, writeableSize, NULL, 0, PA_SEEK_RELATIVE); + int inBytes = inSamples * sizeof (SFLDataFormat); + SFLDataFormat *out = (SFLDataFormat*) pa_xmalloc (inBytes); + getMainBuffer()->getData (out, inBytes); - pa_xfree (zeros); + // test if resampling is required + if (resample) { + SFLDataFormat* rsmpl_out = (SFLDataFormat*) pa_xmalloc (outBytes); + _converter->resample (out, rsmpl_out, mainBufferSampleRate, _audioSampleRate, inSamples); + pa_stream_write (playback->pulseStream(), rsmpl_out, outBytes, NULL, 0, PA_SEEK_RELATIVE); + pa_xfree (rsmpl_out); - } - } + } else { + pa_stream_write (playback->pulseStream(), out, inBytes, NULL, 0, PA_SEEK_RELATIVE); + } - _urgentRingBuffer.Discard (byteToGet); - - } + pa_xfree (out); } void PulseLayer::readFromMic (void) @@ -852,51 +806,37 @@ void PulseLayer::readFromMic (void) const char* data = NULL; size_t r; - int readableSize = pa_stream_readable_size (record->pulseStream()); - + unsigned int mainBufferSampleRate = getMainBuffer()->getInternalSamplingRate(); + bool resample = _audioSampleRate != mainBufferSampleRate; if (pa_stream_peek (record->pulseStream() , (const void**) &data , &r) < 0 || !data) { - _warn ("Audio: Error capture stream peek failed: %s" , pa_strerror (pa_context_errno (context))); + _error("Audio: Error capture stream peek failed: %s" , pa_strerror (pa_context_errno (context))); + goto end; } - if (data != 0) { - - int _mainBufferSampleRate = getMainBuffer()->getInternalSamplingRate(); - - // test if resampling is required - if (_mainBufferSampleRate && ( (int) _audioSampleRate != _mainBufferSampleRate)) { - - SFLDataFormat* rsmpl_out = (SFLDataFormat*) pa_xmalloc (readableSize); - memset (rsmpl_out, 0, readableSize); - - _converter->resample ( (SFLDataFormat *) data, rsmpl_out, _mainBufferSampleRate, _audioSampleRate, r / sizeof (SFLDataFormat)); - - // remove dc offset - _audiofilter->processAudio (rsmpl_out, r); + if (resample) { + int inSamples = r / sizeof(SFLDataFormat); + double resampleFactor = (double) _audioSampleRate / mainBufferSampleRate; + int outSamples = (double) inSamples * resampleFactor; + int outBytes = outSamples * sizeof(SFLDataFormat); - getMainBuffer()->putData (rsmpl_out, r); - - pa_xfree (rsmpl_out); - - } else { - - - SFLDataFormat* filter_out = (SFLDataFormat*) pa_xmalloc (r); - memset (filter_out, 0, r); - - // remove dc offset - _audiofilter->processAudio ( (SFLDataFormat *) data, filter_out, r); - - getMainBuffer()->putData (filter_out, r); - - pa_xfree (filter_out); - } - } - - if (pa_stream_drop (record->pulseStream()) < 0) { - _warn ("Audio: Error: capture stream drop failed: %s" , pa_strerror (pa_context_errno (context))); - } + SFLDataFormat* rsmpl_out = (SFLDataFormat*) pa_xmalloc (outBytes); + _converter->resample ( (SFLDataFormat *) data, rsmpl_out, mainBufferSampleRate, _audioSampleRate, inSamples); + // remove dc offset + _audiofilter->processAudio (rsmpl_out, outBytes); + getMainBuffer()->putData (rsmpl_out, outBytes); + pa_xfree (rsmpl_out); + } else { + SFLDataFormat* filter_out = (SFLDataFormat*) pa_xmalloc (r); + // remove dc offset + _audiofilter->processAudio ( (SFLDataFormat *) data, filter_out, r); + getMainBuffer()->putData (filter_out, r); + pa_xfree (filter_out); + } +end: + if (pa_stream_drop (record->pulseStream()) < 0) + _error ("Audio: Error: capture stream drop failed: %s" , pa_strerror (pa_context_errno (context))); } @@ -923,12 +863,8 @@ void PulseLayer::ringtoneToSpeaker (void) memset (out, 0, writableSize); - int copied = fileToPlay->getNext (out, writableSize/sizeof (SFLDataFormat), 100); - if(copied == 0) { - copied = writableSize/sizeof(SFLDataFormat); - } - - pa_stream_write (ringtone->pulseStream(), out, copied*sizeof (SFLDataFormat), NULL, 0, PA_SEEK_RELATIVE); + fileToPlay->getNext (out, writableSize/sizeof (SFLDataFormat), 100); + pa_stream_write (ringtone->pulseStream(), out, writableSize, NULL, 0, PA_SEEK_RELATIVE); pa_xfree (out); } @@ -940,10 +876,6 @@ void PulseLayer::ringtoneToSpeaker (void) } out = (SFLDataFormat*) pa_xmalloc (writableSize); - if(out == NULL) { - _error("PulseAudio: Error: Could not allocate memory for buffer"); - return; - } memset (out, 0, writableSize); pa_stream_write (ringtone->pulseStream(), out, writableSize, NULL, 0, PA_SEEK_RELATIVE); diff --git a/sflphone-common/src/audio/samplerateconverter.cpp b/sflphone-common/src/audio/samplerateconverter.cpp index 411c20389c39b4b6e415f93a8ef3ca5085522e1c..ca4e54def666fd2ef60f2a90695b2b55afef214b 100644 --- a/sflphone-common/src/audio/samplerateconverter.cpp +++ b/sflphone-common/src/audio/samplerateconverter.cpp @@ -66,8 +66,8 @@ void SamplerateConverter::resample (SFLDataFormat* dataIn , SFLDataFormat* dataO { assert(outputFreq <= _maxFreq); - double sampleFactor = (double) inputFreq / outputFreq; - if (sampleFactor == 1) + double sampleFactor = (double) outputFreq / inputFreq; + if (sampleFactor == 1.0) return; int outSamples = nbSamples * sampleFactor; diff --git a/sflphone-common/src/audio/sound/audiofile.cpp b/sflphone-common/src/audio/sound/audiofile.cpp index b10382945d52fd9da91ec7af22011fa8d13f206c..9c8d4d25ddc41425fd5a700131b4499349bf00db 100644 --- a/sflphone-common/src/audio/sound/audiofile.cpp +++ b/sflphone-common/src/audio/sound/audiofile.cpp @@ -241,19 +241,9 @@ WaveFile::WaveFile (const std::string& fileName, unsigned int audioSamplingRate) } if (srate != audioSamplingRate) { - nbSamples = (int) ( (float) nbSamples * ( (float) audioSamplingRate / (float) srate)); - - _buffer = new SFLDataFormat[nbSamples]; - if (_buffer == NULL) { - delete[] tempBuffer; - throw AudioFileException("Could not allocate buffer for audio"); - } - - if (srate < audioSamplingRate) - _converter.resample (tempBuffer, _buffer, srate, audioSamplingRate, nbSamples); - else if (srate > audioSamplingRate) - _converter.resample (tempBuffer, _buffer, audioSamplingRate, srate, nbSamples); - + int outSamples = ((float) nbSamples * ( (float) audioSamplingRate / (float) srate)); + _buffer = new SFLDataFormat[outSamples]; + _converter.resample (tempBuffer, _buffer, srate, audioSamplingRate, nbSamples); delete[] tempBuffer; } else { _buffer = tempBuffer; diff --git a/sflphone-common/src/iax/iaxvoiplink.cpp b/sflphone-common/src/iax/iaxvoiplink.cpp index ba70c8628ea47d4b11ab77f959e1dd38b567a45c..9c597dfb5652766a861025286a3d26c755fd2577 100644 --- a/sflphone-common/src/iax/iaxvoiplink.cpp +++ b/sflphone-common/src/iax/iaxvoiplink.cpp @@ -62,11 +62,6 @@ IAXVoIPLink::IAXVoIPLink (const std::string& accountID) : VoIPLink () , _regSession (NULL) , _nextRefreshStamp (0) , audiolayer (NULL) - , micData (NULL) - , micDataConverted (NULL) - , micDataEncoded (NULL) - , spkrDataDecoded (NULL) - , spkrDataConverted (NULL) , converter (NULL) , converterSamplingRate (0) , urlhook (NULL) @@ -78,17 +73,6 @@ IAXVoIPLink::IAXVoIPLink (const std::string& accountID) : VoIPLink () srand (time (NULL)); converter = new SamplerateConverter (44100); - - // int nbSamplesMax = (int) (converter->getFrequence() * converter->getFramesize() / 1000); - int nbSamplesMax = (44100 * 20) / 1000; - - micData = new SFLDataFormat[nbSamplesMax]; - micDataConverted = new SFLDataFormat[nbSamplesMax]; - micDataEncoded = new unsigned char[nbSamplesMax]; - - spkrDataConverted = new SFLDataFormat[nbSamplesMax]; - spkrDataDecoded = new SFLDataFormat[nbSamplesMax]; - urlhook = new UrlHook (); } @@ -102,11 +86,6 @@ IAXVoIPLink::~IAXVoIPLink() terminate(); delete converter; - delete [] micData; - delete [] micDataConverted; - delete [] micDataEncoded; - delete [] spkrDataDecoded; - delete [] spkrDataConverted; } bool @@ -282,53 +261,50 @@ IAXVoIPLink::sendAudioFromMic (void) // do not use the current ID in Manager (it may refer to a conference also) // currentCall = getIAXCall (Manager::instance().getCurrentCallId()); - CallMap::iterator iter_call = _callMap.begin(); - - while (iter_call != _callMap.end()) { - IAXCall *currentCall = (IAXCall*) iter_call->second; - iter_call++; - + for (CallMap::iterator iter = _callMap.begin(); iter != _callMap.end() ; ++iter) { + IAXCall *currentCall = (IAXCall*) iter->second; if (!currentCall || currentCall->getState() != Call::Active) continue; AudioCodecType codecType = currentCall->getAudioCodec(); sfl::AudioCodec *audioCodec = static_cast<sfl::AudioCodec *>(currentCall->getAudioCodecFactory().getCodec (codecType)); - // Send sound here - if (!audioCodec || !audiolayer) continue; Manager::instance().getMainBuffer()->setInternalSamplingRate (audioCodec->getClockRate()); - int _mainBufferSampleRate = audiolayer->getMainBuffer()->getInternalSamplingRate(); + unsigned int mainBufferSampleRate = audiolayer->getMainBuffer()->getInternalSamplingRate(); // we have to get 20ms of data from the mic *20/1000 = /50 // rate/50 shall be lower than IAX__20S_48KHZ_MAX - int needed = _mainBufferSampleRate * audiolayer->getFrameSize() / 1000 * sizeof (SFLDataFormat); - if (audiolayer->getMainBuffer()->availForGet (currentCall->getCallId()) < needed) + int bytesNeeded = mainBufferSampleRate * 20 / 1000 * sizeof (SFLDataFormat); + if (audiolayer->getMainBuffer()->availForGet (currentCall->getCallId()) < bytesNeeded) continue; // Get bytes from micRingBuffer to data_from_mic - int bytes = audiolayer->getMainBuffer()->getData (micData, needed, currentCall->getCallId()) / sizeof (SFLDataFormat); + int bytes = audiolayer->getMainBuffer()->getData (decData, bytesNeeded, currentCall->getCallId()); + int samples = bytes / sizeof(SFLDataFormat); int compSize; - if (audioCodec->getClockRate() && ((int) audioCodec->getClockRate() != _mainBufferSampleRate)) { - // resample - converter->resample (micData , micDataConverted , (int) audioCodec->getClockRate(), _mainBufferSampleRate, bytes); - compSize = audioCodec->encode (micDataEncoded, micDataConverted , bytes); + unsigned int audioRate = audioCodec->getClockRate(); + int outSamples; + if (audioRate != mainBufferSampleRate) { + int outSamples = ((float) samples * ( (float) mainBufferSampleRate / (float) audioRate)); + converter->resample (decData , resampledData , audioRate, mainBufferSampleRate, samples); + compSize = audioCodec->encode (encodedData, resampledData , outSamples * sizeof(SFLDataFormat)); } else { - compSize = audioCodec->encode (micDataEncoded, micData, bytes); + outSamples = samples; + compSize = audioCodec->encode (encodedData, decData, bytes); } // Send it out! _mutexIAX.enterMutex(); // Make sure the session and the call still exists. - if (currentCall->getSession() && (micDataEncoded != NULL) && (bytes > 0)) { - if (iax_send_voice (currentCall->getSession(), currentCall->getFormat(), micDataEncoded, compSize, bytes) == -1) { - _debug ("IAX: Error sending voice data."); - } + if (currentCall->getSession() && (bytes > 0)) { + if (iax_send_voice (currentCall->getSession(), currentCall->getFormat(), encodedData, compSize, outSamples) == -1) + _error ("IAX: Error sending voice data."); } _mutexIAX.leaveMutex(); @@ -479,13 +455,12 @@ IAXVoIPLink::hangup (const std::string& id) throw (VoipLinkException) throw VoipLinkException("Could not find call"); } - std::string reason = "Dumped Call"; CHK_VALID_CALL; Manager::instance().getMainBuffer()->unBindAll (call->getCallId()); _mutexIAX.enterMutex(); - iax_hangup (call->getSession(), (char*) reason.c_str()); + iax_hangup (call->getSession(), (char*) "Dumped Call"); _mutexIAX.leaveMutex(); call->setSession (NULL); @@ -505,7 +480,6 @@ IAXVoIPLink::peerHungup (const std::string& id) throw (VoipLinkException) throw VoipLinkException("Could not find call"); } - std::string reason = "Dumped Call"; CHK_VALID_CALL; Manager::instance().getMainBuffer()->unBindAll (call->getCallId()); @@ -589,12 +563,11 @@ bool IAXVoIPLink::refuse (const std::string& id) { IAXCall* call = getIAXCall (id); - std::string reason = "Call rejected manually."; CHK_VALID_CALL; _mutexIAX.enterMutex(); - iax_reject (call->getSession(), (char*) reason.c_str()); + iax_reject (call->getSession(), (char*) "Call rejected manually."); _mutexIAX.leaveMutex(); removeCall (id); @@ -745,9 +718,8 @@ IAXVoIPLink::iaxHandleCallEvent (iax_event* event, IAXCall* call) /* _debug("IAXVoIPLink::iaxHandleCallEvent, peer hangup have been called"); - std::string reason = "Dumped Call"; _mutexIAX.enterMutex(); - iax_hangup(call->getSession(), (char*)reason.c_str()); + iax_hangup(call->getSession(), (char*)"Dumped Call"); _mutexIAX.leaveMutex(); call->setSession(NULL); audiolayer->stopStream(); @@ -905,39 +877,23 @@ IAXVoIPLink::iaxHandleCallEvent (iax_event* event, IAXCall* call) void IAXVoIPLink::iaxHandleVoiceEvent (iax_event* event, IAXCall* call) { - - unsigned char *data; - unsigned int size, max, nbInt16; - int expandedSize, nbSample_; - sfl::AudioCodec *audioCodec; - - if (!call) { - return; - } - if (!event->datalen) { // Skip this empty packet. //_debug("IAX: Skipping empty jitter-buffer interpolated packet"); return; } - AudioCodecType audioCodecType = call->getAudioCodec(); - audioCodec = static_cast<sfl::AudioCodec *>(call->getAudioCodecFactory().getCodec (audioCodecType)); - - if (!audioCodec) - 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 + sfl::AudioCodec *audioCodec = static_cast<sfl::AudioCodec *>(call->getAudioCodecFactory().getCodec (call->getAudioCodec())); + if (!audioCodec) + return; - int _mainBufferSampleRate = Manager::instance().getMainBuffer()->getInternalSamplingRate(); + Manager::instance().getMainBuffer ()->setInternalSamplingRate (audioCodec->getClockRate ()); + unsigned 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 @@ -948,26 +904,26 @@ IAXVoIPLink::iaxHandleVoiceEvent (iax_event* event, IAXCall* call) call->setFormat (event->subclass); } - data = (unsigned char*) event->data; - - size = event->datalen; + unsigned char *data = (unsigned char*) event->data; + unsigned int size = event->datalen; // Decode data with relevant codec - max = (int) (audioCodec->getClockRate() * audiolayer->getFrameSize() / 1000); + unsigned int max = 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); - - if (audioCodec->getClockRate() && ((int) audioCodec->getClockRate() != _mainBufferSampleRate)) { - converter->resample (spkrDataDecoded, spkrDataConverted, audioCodec->getClockRate(), _mainBufferSampleRate, expandedSize); - audiolayer->getMainBuffer()->putData (spkrDataConverted, expandedSize, call->getCallId()); - + int expandedSize = audioCodec->decode (decData, data , size); + unsigned int audioRate = audioCodec->getClockRate(); + int inSamples = expandedSize / sizeof(SFLDataFormat); + if (audioRate != mainBufferSampleRate) { + int outSize = expandedSize * (mainBufferSampleRate / audioRate); + converter->resample (decData, resampledData, mainBufferSampleRate, audioRate, inSamples); + audiolayer->getMainBuffer()->putData (resampledData, outSize, call->getCallId()); } else { - audiolayer->getMainBuffer()->putData (spkrDataDecoded, expandedSize, call->getCallId()); + audiolayer->getMainBuffer()->putData (decData, expandedSize, call->getCallId()); } } @@ -1034,7 +990,6 @@ int IAXVoIPLink::processIAXMsgCount (int msgcount) // msgcount >= 256 => msgcount/256 old messages , msgcount%256 new messages (RULES) return msgcount%256; - } @@ -1043,7 +998,6 @@ IAXVoIPLink::iaxHandlePrecallEvent (iax_event* event) { IAXCall* call = NULL; std::string id; - std::string reason = "Error ringing user."; switch (event->etype) { @@ -1117,10 +1071,8 @@ IAXVoIPLink::iaxHandlePrecallEvent (iax_event* event) } else { // reject call, unable to add it - iax_reject (event->session, (char*) reason.c_str()); - + iax_reject (event->session, (char*) "Error ringing user."); delete call; - call = NULL; } break; @@ -1150,7 +1102,6 @@ IAXVoIPLink::iaxHandlePrecallEvent (iax_event* event) void IAXVoIPLink::updateAudiolayer (void) { _mutexIAX.enterMutex(); - audiolayer = NULL; audiolayer = Manager::instance().getAudioDriver(); _mutexIAX.leaveMutex(); } diff --git a/sflphone-common/src/iax/iaxvoiplink.h b/sflphone-common/src/iax/iaxvoiplink.h index 88da9088d337fe3a74b9d03d42f2e63d0c0639ef..245c09fa6cb1dcbc412766b83c2be820fe20a68f 100644 --- a/sflphone-common/src/iax/iaxvoiplink.h +++ b/sflphone-common/src/iax/iaxvoiplink.h @@ -306,14 +306,10 @@ class IAXVoIPLink : public VoIPLink /** Connection to audio card/device */ AudioLayer* audiolayer; - /** Mic-data related buffers */ - SFLDataFormat* micData; - SFLDataFormat* micDataConverted; - unsigned char* micDataEncoded; - - /** Speaker-data related buffers */ - SFLDataFormat* spkrDataDecoded; - SFLDataFormat* spkrDataConverted; + /** encoder/decoder/resampler buffers */ + SFLDataFormat decData[DEC_BUFFER_SIZE]; + SFLDataFormat resampledData[DEC_BUFFER_SIZE]; + unsigned char encodedData[DEC_BUFFER_SIZE]; /** Sample rate converter object */ SamplerateConverter* converter;