diff --git a/sflphone-client-gnome/src/config/audioconf.c b/sflphone-client-gnome/src/config/audioconf.c index 9031c99febfd62ef4e740d56ef73b79f4b9cc88e..5dd23a4dd68a8251a7bcd0c89d409210acde3d6a 100644 --- a/sflphone-client-gnome/src/config/audioconf.c +++ b/sflphone-client-gnome/src/config/audioconf.c @@ -397,6 +397,8 @@ codec_active_toggled(GtkCellRendererToggle *renderer UNUSED, gchar *path, gpoint codec = codec_list_get_by_payload(110); else if ((g_strcasecmp(name,"speex")==0) && (g_strcasecmp(srate,"16 kHz")==0)) codec = codec_list_get_by_payload(111); + else if ((g_strcasecmp(name,"speex")==0) && (g_strcasecmp(srate,"32 kHz")==0)) + codec = codec_list_get_by_payload(112); else codec = codec_list_get_by_name(name); diff --git a/sflphone-client-gnome/src/contacts/calltree.c b/sflphone-client-gnome/src/contacts/calltree.c index f87206be01e35176d50da316777963fe9ff60d52..d1bf035968d4411f05e90c0fdea0ec5a0e461871 100644 --- a/sflphone-client-gnome/src/contacts/calltree.c +++ b/sflphone-client-gnome/src/contacts/calltree.c @@ -412,8 +412,6 @@ calltree_update_call (calltab_t* tab, callable_obj_t * c) void calltree_add_history_entry (callable_obj_t * c) { - printf("calltree_add_history_entry\n"); - if (dbus_get_history_enabled () == 0) return; @@ -473,8 +471,6 @@ void calltree_add_history_entry (callable_obj_t * c) void calltree_add_call (calltab_t* tab, callable_obj_t * c) { - printf("calltree_add_call\n"); - if (tab == history) { calltree_add_history_entry (c); diff --git a/sflphone-common/src/audio/audiortp.cpp b/sflphone-common/src/audio/audiortp.cpp index cd9906b0ac370f6f068a001a5211330f43c2ea0b..80731ac081f03ee950a4aca5e6f32151a977c4ed 100644 --- a/sflphone-common/src/audio/audiortp.cpp +++ b/sflphone-common/src/audio/audiortp.cpp @@ -98,7 +98,7 @@ AudioRtp::closeRtpSession () { throw; } AudioLayer* audiolayer = Manager::instance().getAudioDriver(); - audiolayer->stopStream(); + // audiolayer->stopStream(); return true; } @@ -398,52 +398,6 @@ AudioRtpRTX::sendSessionFromMic(int timestamp) int compSize = processDataEncode(audiolayer); - /* - // compute codec framesize in ms - float fixed_codec_framesize = computeCodecFrameSize(_audiocodec->getFrameSize(), _audiocodec->getClockRate()); - - // compute nb of byte to get coresponding to 20 ms at audio layer frame size (44.1 khz) - int maxBytesToGet = computeNbByteAudioLayer(fixed_codec_framesize); - - // available bytes inside ringbuffer - int availBytesFromMic = audiolayer->canGetMic(); - - // set available byte to maxByteToGet - int bytesAvail = (availBytesFromMic < maxBytesToGet) ? availBytesFromMic : maxBytesToGet; - - if (bytesAvail == 0) - return; - - // Get bytes from micRingBuffer to data_from_mic - int nbSample = audiolayer->getMic( micData , bytesAvail ) / sizeof(SFLDataFormat); - - // nb bytes to be sent over RTP - int compSize = 0; - - // test if resampling is required - if (_audiocodec->getClockRate() != _layerSampleRate) { - - int nb_sample_up = nbSample; - // _debug("_nbSample audiolayer->getMic(): %i \n", nbSample); - - // Store the length of the mic buffer in samples for recording - _nSamplesMic = nbSample; - - - // int nbSamplesMax = _layerFrameSize * _audiocodec->getClockRate() / 1000; - nbSample = reSampleData(micData , micDataConverted, _audiocodec->getClockRate(), nb_sample_up, DOWN_SAMPLING); - - compSize = _audiocodec->codecEncode( micDataEncoded, micDataConverted, nbSample*sizeof(int16)); - - } else { - // no resampling required - - // int nbSamplesMax = _codecFrameSize; - compSize = _audiocodec->codecEncode( micDataEncoded, micData, nbSample*sizeof(int16)); - - } - */ - // putData put the data on RTP queue, sendImmediate bypass this queue if (!_sym) { // _sessionSend->putData(timestamp, micDataEncoded, compSize); @@ -483,54 +437,10 @@ AudioRtpRTX::receiveSessionForSpkr (int& countTime) unsigned int size = adu->getSize(); // size in char processDataDecode(audiolayer, spkrData, size, countTime); - /* - if (_audiocodec != NULL) { - - // Return the size of data in bytes - int expandedSize = _audiocodec->codecDecode( spkrDataDecoded , spkrData , size ); - - // buffer _receiveDataDecoded ----> short int or int16, coded on 2 bytes - int nbSample = expandedSize / sizeof(SFLDataFormat); - - // test if resampling is required - if (_audiocodec->getClockRate() != _layerSampleRate) { - - // Do sample rate conversion - int nb_sample_down = nbSample; - nbSample = reSampleData(spkrDataDecoded , spkrDataConverted, _codecSampleRate , nb_sample_down, UP_SAMPLING); - - // Store the number of samples for recording - _nSamplesSpkr = nbSample; - - // put data in audio layer, size in byte - audiolayer->putMain (spkrDataConverted, nbSample * sizeof(SFLDataFormat)); - - } else { - - // Stor the number of samples for recording - _nSamplesSpkr = nbSample; - - // put data in audio layer, size in byte - audiolayer->putMain (spkrDataDecoded, nbSample * sizeof(SFLDataFormat)); - } - - // Notify (with a beep) an incoming call when there is already a call - countTime += time->getSecond(); - if (Manager::instance().incomingCallWaiting() > 0) { - countTime = countTime % 500; // more often... - if (countTime == 0) { - Manager::instance().notificationIncomingCall(); - } - } - - } else { - countTime += time->getSecond(); - } - delete adu; adu = NULL; - */ - + } + int AudioRtpRTX::reSampleData(SFLDataFormat *input, SFLDataFormat *output, int sampleRate_codec, int nbSamples, int status) { @@ -634,7 +544,7 @@ AudioRtpRTX::run () { } - audiolayer->stopStream(); + // audiolayer->stopStream(); _debug("- ARTP Action: Stop call %s\n",_ca->getCallId().c_str()); //} catch(std::exception &e) { //_start.post(); diff --git a/sflphone-common/src/audio/audiostream.cpp b/sflphone-common/src/audio/audiostream.cpp index 08587fdb310803fe561ae208c025869f6b7ab86b..abfb5ab34f92f598d327899751a6f7ed609d88e7 100644 --- a/sflphone-common/src/audio/audiostream.cpp +++ b/sflphone-common/src/audio/audiostream.cpp @@ -49,10 +49,6 @@ AudioStream::connectStream() if(!_audiostream) _audiostream = createStream( _context ); - else { - disconnectStream(); - _audiostream = createStream( _context ); - } return true; } diff --git a/sflphone-common/src/audio/codecs/Makefile.am b/sflphone-common/src/audio/codecs/Makefile.am index 028a178cfd0342945ada0fcd9a169923e6c3f621..10a005f1c85bcd86a54a1997627352cd30d07cbd 100644 --- a/sflphone-common/src/audio/codecs/Makefile.am +++ b/sflphone-common/src/audio/codecs/Makefile.am @@ -31,6 +31,14 @@ libcodec_speex_wb_so_LDFLAGS = --shared -lc -lspeex $(SPEEX_NIMP) INSTALL_SPEEX_WB_RULE = install-libcodec_speex_wb_so endif +if BUILD_SPEEX +SPEEX_UB_LIB = libcodec_speex_ub.so +libcodec_speex_ub_so_SOURCES = speexcodec_ub.cpp +libcodec_speex_ub_so_CFLAGS = -fPIC -g -Wall +libcodec_speex_ub_so_CXXFLAGS = -fPIC -g -Wall $(SPEEXDSP) +libcodec_speex_ub_so_LDFLAGS = --shared -lc -lspeex $(SPEEX_NIMP) +INSTALL_SPEEX_UB_RULE = install-libcodec_speex_ub_so +endif if BUILD_CELT CELT_LIB = libcodec_celt.so @@ -52,7 +60,7 @@ INSTALL_ILBC_RULE = install-libcodec_ilbc_so SUBDIRS = ilbc endif -noinst_PROGRAMS = libcodec_ulaw.so libcodec_alaw.so libcodec_g722.so $(GSM_LIB) $(SPEEX_NB_LIB) $(SPEEX_WB_LIB) $(CELT_LIB) $(ILBC_LIB) +noinst_PROGRAMS = libcodec_ulaw.so libcodec_alaw.so libcodec_g722.so $(GSM_LIB) $(SPEEX_NB_LIB) $(SPEEX_WB_LIB) $(SPEEX_UB_LIB) $(CELT_LIB) $(ILBC_LIB) noinst_HEADERS = audiocodec.h @@ -72,8 +80,8 @@ libcodec_g722_so_CFLAGS = -fPIC -g -Wall libcodec_g722_so_CXXFLAGS = -fPIC -g -Wall libcodec_g722_so_LDFLAGS = --shared -lc -install-exec-local: install-libcodec_ulaw_so install-libcodec_alaw_so install-libcodec_g722_so $(INSTALL_GSM_RULE) $(INSTALL_SPEEX_NB_RULE) $(INSTALL_SPEEX_WB_RULE) $(INSTALL_CELT_RULE) $(INSTALL_ILBC_RULE) -uninstall-local: uninstall-libcodec_ulaw_so uninstall-libcodec_alaw_so uninstall-libcodec_g722_so uninstall-libcodec_gsm_so uninstall-libcodec_speex_nb_so uninstall-libcodec_speex_wb_so uninstall-libcodec_celt_so +install-exec-local: install-libcodec_ulaw_so install-libcodec_alaw_so install-libcodec_g722_so $(INSTALL_GSM_RULE) $(INSTALL_SPEEX_NB_RULE) $(INSTALL_SPEEX_WB_RULE) $(INSTALL_SPEEX_UB_RULE) $(INSTALL_CELT_RULE) $(INSTALL_ILBC_RULE) +uninstall-local: uninstall-libcodec_ulaw_so uninstall-libcodec_alaw_so uninstall-libcodec_g722_so uninstall-libcodec_gsm_so uninstall-libcodec_speex_nb_so uninstall-libcodec_speex_wb_so uninstall-libcodec_speex_ub_so uninstall-libcodec_celt_so install-libcodec_ulaw_so: libcodec_ulaw.so @@ -89,6 +97,8 @@ install-libcodec_speex_nb_so: libcodec_speex_nb.so $(INSTALL_PROGRAM) libcodec_speex_nb.so $(sflcodecdir) install-libcodec_speex_wb_so: libcodec_speex_wb.so $(INSTALL_PROGRAM) libcodec_speex_wb.so $(sflcodecdir) +install-libcodec_speex_ub_so: libcodec_speex_ub.so + $(INSTALL_PROGRAM) libcodec_speex_ub.so $(sflcodecdir) install-libcodec_celt_so: libcodec_celt.so $(INSTALL_PROGRAM) libcodec_celt.so $(sflcodecdir) install-libcodec_ilbc_so: libcodec_ilbc.so @@ -107,6 +117,8 @@ uninstall-libcodec_speex_nb_so: rm -f $(sflcodecdir)/libcodec_speex_nb.so uninstall-libcodec_speex_wb_so: rm -f $(sflcodecdir)/libcodec_speex_wb.so +uninstall-libcodec_speex_ub_so: + rm -f $(sflcodecdir)/libcodec_speex_ub.so rm -rf $(sflcodecdir) uninstall-libcodec_celt_so: libcodec_celt.so $(INSTALL_PROGRAM) libcodec_celt.so $(sflcodecdir) diff --git a/sflphone-common/src/audio/codecs/speexcodec_nb.cpp b/sflphone-common/src/audio/codecs/speexcodec_nb.cpp index 22089f0454c7f7654de0a4c3f57275c1056dfda4..96f7c63db46e2d3fe180a2c9ea51f95ffbaa9416 100644 --- a/sflphone-common/src/audio/codecs/speexcodec_nb.cpp +++ b/sflphone-common/src/audio/codecs/speexcodec_nb.cpp @@ -127,9 +127,11 @@ class Speex : public AudioCodec{ speex_preprocess_run(_preprocess_state, src); #endif + speex_encode_int(_speex_enc_state, src, &_speex_enc_bits); int nbBytes = speex_bits_write(&_speex_enc_bits, (char*)dst, size); + return nbBytes; } diff --git a/sflphone-common/src/audio/codecs/speexcodec_ub.cpp b/sflphone-common/src/audio/codecs/speexcodec_ub.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bce7e952e4ee37816e89d027d1ee9e72bcecffaf --- /dev/null +++ b/sflphone-common/src/audio/codecs/speexcodec_ub.cpp @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2007-2009 Savoir-Faire Linux inc. + * Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com> + * Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "audiocodec.h" +#include <cstdio> +#include <speex/speex.h> +#include <speex/speex_preprocess.h> + +class Speex : public AudioCodec{ + public: + Speex(int payload=0) + : AudioCodec(payload, "speex"), + _speexModePtr(NULL), + _speex_dec_bits(), + _speex_enc_bits(), + _speex_dec_state(), + _speex_enc_state(), + _speex_frame_size(), + _preprocess_state() + { + _clockRate = 32000; + _frameSize = 320; // 10 ms at 32 kHz + _channel = 1; + _bitrate = 0; + _bandwidth = 0; + initSpeex(); + } + + Speex( const Speex& ); + Speex& operator=(const Speex&); + + void initSpeex() { + + // int _samplingRate = 32000; + + // 8000 HZ --> Narrow-band mode + // TODO Manage the other modes + _speexModePtr = &speex_wb_mode; + // _speexModePtr = &speex_wb_mode; + + // Init the decoder struct + speex_bits_init(&_speex_dec_bits); + _speex_dec_state = speex_decoder_init(_speexModePtr); + + // Init the encoder struct + speex_bits_init(&_speex_enc_bits); + _speex_enc_state = speex_encoder_init(_speexModePtr); + + speex_encoder_ctl(_speex_enc_state,SPEEX_SET_SAMPLING_RATE,&_clockRate); + + speex_decoder_ctl(_speex_dec_state, SPEEX_GET_FRAME_SIZE, &_speex_frame_size); + +#ifdef HAVE_SPEEXDSP_LIB + + int enable = 1; + int quality = 10; + int complex = 10; + int attenuation = -10; + + speex_encoder_ctl(_speex_enc_state, SPEEX_SET_VAD, &enable); + speex_encoder_ctl(_speex_enc_state, SPEEX_SET_DTX, &enable); + // speex_encoder_ctl(_speex_enc_state, SPEEX_SET_VBR_QUALITY, &quality); + speex_encoder_ctl(_speex_enc_state, SPEEX_SET_COMPLEXITY, &complex); + + // Init the decoder struct + speex_decoder_ctl(_speex_dec_state, SPEEX_GET_FRAME_SIZE, &_speex_frame_size); + + // Init the preprocess struct + _preprocess_state = speex_preprocess_state_init(_speex_frame_size,_clockRate); + speex_preprocess_ctl(_preprocess_state, SPEEX_PREPROCESS_SET_DENOISE, &enable); + speex_preprocess_ctl(_preprocess_state, SPEEX_PREPROCESS_SET_NOISE_SUPPRESS, &attenuation); + speex_preprocess_ctl(_preprocess_state, SPEEX_PREPROCESS_SET_VAD, &enable); + speex_preprocess_ctl(_preprocess_state, SPEEX_PREPROCESS_SET_AGC, &enable); +#endif + + } + + ~Speex() + { + terminateSpeex(); + } + + void terminateSpeex() { + // Destroy the decoder struct + speex_bits_destroy(&_speex_dec_bits); + speex_decoder_destroy(_speex_dec_state); + _speex_dec_state = 0; + + // Destroy the encoder struct + speex_bits_destroy(&_speex_enc_bits); + speex_encoder_destroy(_speex_enc_state); + _speex_enc_state = 0; + } + + virtual int codecDecode (short *dst, unsigned char *src, unsigned int size) + { + + // int ratio = 320 / _speex_frame_size; + speex_bits_read_from(&_speex_dec_bits, (char*)src, size); + speex_decode_int(_speex_dec_state, &_speex_dec_bits, dst); + + // return the nuber of byte, not the number of sample + return _speex_frame_size * 2; + } + + virtual int codecEncode (unsigned char *dst, short *src, unsigned int size) + { + speex_bits_reset(&_speex_enc_bits); + +#ifdef HAVE_SPEEXDSP_LIB + + speex_preprocess_run(_preprocess_state, src); +#endif + + + speex_encode_int(_speex_enc_state, src, &_speex_enc_bits); + speex_bits_nbytes(&_speex_enc_bits); + int nbBytes = speex_bits_write(&_speex_enc_bits, (char*)dst, size); + + return nbBytes; + } + + private: + const SpeexMode* _speexModePtr; + SpeexBits _speex_dec_bits; + SpeexBits _speex_enc_bits; + void *_speex_dec_state; + void *_speex_enc_state; + int _speex_frame_size; + SpeexPreprocessState *_preprocess_state; +}; + +// the class factories +extern "C" AudioCodec* create() { + return new Speex(112); +} + +extern "C" void destroy(AudioCodec* a) { + delete a; +} + diff --git a/sflphone-common/src/audio/codecs/speexcodec_wb.cpp b/sflphone-common/src/audio/codecs/speexcodec_wb.cpp index 81d27bbcb0eebee7d7a75687bf82c0a8e410b9b6..dc93f39ec1a063732ef64b718d5fe48abf572f70 100644 --- a/sflphone-common/src/audio/codecs/speexcodec_wb.cpp +++ b/sflphone-common/src/audio/codecs/speexcodec_wb.cpp @@ -111,8 +111,9 @@ class Speex : public AudioCodec{ virtual int codecDecode (short *dst, unsigned char *src, unsigned int size) { - + int ratio = 320 / _speex_frame_size; + speex_bits_read_from(&_speex_dec_bits, (char*)src, size); speex_decode_int(_speex_dec_state, &_speex_dec_bits, dst); @@ -128,9 +129,10 @@ class Speex : public AudioCodec{ speex_preprocess_run(_preprocess_state, src); #endif + printf("Codec::codecEncode() size %i\n", size); speex_encode_int(_speex_enc_state, src, &_speex_enc_bits); int nbBytes = speex_bits_write(&_speex_enc_bits, (char*)dst, size); - printf("Codec::codecEncode() nbBytes: %i \n",nbBytes); + printf("Codec::codecEncode() nbBytes %i\n", nbBytes); return nbBytes; } diff --git a/sflphone-common/src/audio/pulselayer.cpp b/sflphone-common/src/audio/pulselayer.cpp index a5b07f277b2280da0b5fea1ad6131ae5849b73e8..c8410651b536ddddecb21dc5ce513700295430fd 100644 --- a/sflphone-common/src/audio/pulselayer.cpp +++ b/sflphone-common/src/audio/pulselayer.cpp @@ -166,12 +166,15 @@ bool PulseLayer::createStreams( pa_context* c ) pa_threaded_mainloop_signal(m , 0); + isCorked = true; + return true; } bool PulseLayer::openDevice(int indexIn UNUSED, int indexOut UNUSED, int sampleRate, int frameSize , int stream UNUSED, std::string plugin UNUSED) { + _debug("PulseLayer::openDevice \n"); _sampleRate = sampleRate; _frameSize = frameSize; @@ -225,35 +228,46 @@ int PulseLayer::getMic(void *buffer, int toCopy) void PulseLayer::startStream (void) { // flushMic(); + if (isCorked) { - _urgentRingBuffer.flush(); - _micRingBuffer.flush(); - _voiceRingBuffer.flush(); + _urgentRingBuffer.flush(); + _micRingBuffer.flush(); + _voiceRingBuffer.flush(); - _debug("PulseLayer::Start stream\n"); - pa_threaded_mainloop_lock(m); + _debug("PulseLayer::Start stream\n"); + pa_threaded_mainloop_lock(m); - pa_stream_cork( playback->pulseStream(), 0, NULL, NULL); - pa_stream_cork( record->pulseStream(), 0, NULL, NULL); + pa_stream_cork( playback->pulseStream(), 0, NULL, NULL); + pa_stream_cork( record->pulseStream(), 0, NULL, NULL); - pa_threaded_mainloop_unlock(m); + pa_threaded_mainloop_unlock(m); + + isCorked = false; + } } void PulseLayer::stopStream (void) { - _debug("PulseLayer::Stop stream\n"); - pa_stream_flush( playback->pulseStream(), NULL, NULL ); - pa_stream_flush( record->pulseStream(), NULL, NULL ); + + if (!isCorked) { + + _debug("PulseLayer::Stop stream\n"); + pa_stream_flush( playback->pulseStream(), NULL, NULL ); + pa_stream_flush( record->pulseStream(), NULL, NULL ); - flushMic(); - flushMain(); - flushUrgent(); + flushMic(); + flushMain(); + flushUrgent(); - pa_stream_cork( playback->pulseStream(), 1, NULL, NULL); - pa_stream_cork( record->pulseStream(), 1, NULL, NULL); + pa_stream_cork( playback->pulseStream(), 1, NULL, NULL); + pa_stream_cork( record->pulseStream(), 1, NULL, NULL); + isCorked = true; + + } + } diff --git a/sflphone-common/src/audio/pulselayer.h b/sflphone-common/src/audio/pulselayer.h index beae9eacc2b5b7400aca9ccd6d25a79b98dcd1c8..698cc9bf6b68b6ff7009b35efcccba3c664d2729 100644 --- a/sflphone-common/src/audio/pulselayer.h +++ b/sflphone-common/src/audio/pulselayer.h @@ -189,6 +189,8 @@ class PulseLayer : public AudioLayer { */ AudioStream* record; + bool isCorked; + int spkrVolume; int micVolume; diff --git a/sflphone-common/src/managerimpl.cpp b/sflphone-common/src/managerimpl.cpp index d4d67ad216c9c8164997206ec125a0bee50c00c1..5e01cd2d71683df845e1296c5818473a1a503f65 100644 --- a/sflphone-common/src/managerimpl.cpp +++ b/sflphone-common/src/managerimpl.cpp @@ -143,7 +143,7 @@ ManagerImpl::init() } if (audiolayer == 0) - audiolayer->stopStream(); + audiolayer->stopStream(); // Load the history @@ -326,7 +326,14 @@ ManagerImpl::hangupCall(const CallID& id) _debug("Stop audio stream\n"); audiolayer = getAudioDriver(); - audiolayer->stopStream(); + + int nbCalls = getCallList().size(); + + _debug("nbCalls %i \n", nbCalls); + + // stop stream + if (!(nbCalls > 1)) + audiolayer->stopStream(); /* Direct IP to IP call */ if (getConfigFromCall (id) == Call::IPtoIP) { @@ -952,11 +959,12 @@ void ManagerImpl::stopTone (bool stopAudio=true) hasToPlayTone = getConfigInt(SIGNALISATION, PLAY_TONES); if (!hasToPlayTone) return; - + if (stopAudio) { audiolayer = getAudioDriver(); if (audiolayer) audiolayer->stopStream(); } + _toneMutex.enterMutex(); if (_telephoneTone != 0) {