diff --git a/src/audio/CodecSpeex.cpp b/src/audio/CodecSpeex.cpp index 48cbad39136e721ece409ad96ecb1fa20a2e6755..8200b3ee246bd53f192c83edfbcd722286534fa2 100644 --- a/src/audio/CodecSpeex.cpp +++ b/src/audio/CodecSpeex.cpp @@ -18,78 +18,99 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "CodecSpeex.h" - -CodecSpeex::CodecSpeex(int payload) - : AudioCodec(payload, "speex") -{ - _description = "Speex"; - - _clockRate = 8000; - _channel = 1; - initSpeex(); -} - -void -CodecSpeex::initSpeex() { - if (_clockRate < 16000 ) { - _speexModePtr = &speex_nb_mode; - } else if (_clockRate < 32000) { - _speexModePtr = &speex_wb_mode; - } else { - _speexModePtr = &speex_uwb_mode; - } - - speex_bits_init(&_speex_dec_bits); - _speex_dec_state = speex_decoder_init(_speexModePtr); - - speex_bits_init(&_speex_enc_bits); - _speex_enc_state = speex_encoder_init(_speexModePtr); - - speex_decoder_ctl(_speex_dec_state, SPEEX_GET_FRAME_SIZE, &_speex_frame_size); -} - -CodecSpeex::~CodecSpeex() -{ - terminateSpeex(); -} - -void -CodecSpeex::terminateSpeex() { - speex_bits_destroy(&_speex_dec_bits); - speex_decoder_destroy(_speex_dec_state); - _speex_dec_state = 0; - - speex_bits_destroy(&_speex_enc_bits); - speex_encoder_destroy(_speex_enc_state); - _speex_enc_state = 0; -} - -int -CodecSpeex::codecDecode (short *dst, unsigned char *src, unsigned int size) -{ +#include "audiocodec.h" +#include <speex/speex.h> + + +class CodecSpeex : public AudioCodec{ +public: + CodecSpeex(int payload=0) + : AudioCodec(payload, "speex") + { + _clockRate = 8000; + _channel = 1; + initSpeex(); + } + + int getFrameSize(){ return _speex_frame_size; } + + void initSpeex() { + if (_clockRate < 16000 ) { + _speexModePtr = &speex_nb_mode; + } else if (_clockRate < 32000) { + _speexModePtr = &speex_wb_mode; + } else { + _speexModePtr = &speex_uwb_mode; + } + + speex_bits_init(&_speex_dec_bits); + _speex_dec_state = speex_decoder_init(_speexModePtr); + + speex_bits_init(&_speex_enc_bits); + _speex_enc_state = speex_encoder_init(_speexModePtr); + + speex_decoder_ctl(_speex_dec_state, SPEEX_GET_FRAME_SIZE, &_speex_frame_size); + } + + ~CodecSpeex() + { + terminateSpeex(); + } + + void terminateSpeex() { + speex_bits_destroy(&_speex_dec_bits); + speex_decoder_destroy(_speex_dec_state); + _speex_dec_state = 0; + + 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) + { // void *enh; speex_decoder_ctl(dec_state, SPEEX_SET_ENH, &enh); // decoding speex_bits_read_from(&_speex_dec_bits, (char*)src, size); - int return_status = speex_decode_int(_speex_dec_state, &_speex_dec_bits, dst); + //int return_status = speex_decode_int(_speex_dec_state, &_speex_dec_bits, dst); // 0 = no error // -1 = end of stream // -2 = other + speex_decode_int(_speex_dec_state, &_speex_dec_bits, dst); return _speex_frame_size; -} + } -int -CodecSpeex::codecEncode (unsigned char *dst, short *src, unsigned int size) -{ + virtual int codecEncode (unsigned char *dst, short *src, unsigned int size) + { speex_bits_reset(&_speex_enc_bits); speex_encoder_ctl(_speex_enc_state,SPEEX_SET_SAMPLING_RATE,&_clockRate); speex_encode_int(_speex_enc_state, src, &_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; + + + +}; + +//the class factories +extern "C" AudioCodec* create(){ + return new CodecSpeex(110); } +extern "C" void destroy(AudioCodec* a){ + delete a; +} /* * Speex example diff --git a/src/audio/Makefile.am b/src/audio/Makefile.am index 5621175377d55490fe5bb48a6c6a13ad3fcc4e25..af2ee76b5841f10d1e4791fecf0f41bd4dc691d3 100644 --- a/src/audio/Makefile.am +++ b/src/audio/Makefile.am @@ -1,19 +1,23 @@ sflcodecdir = $(libdir)/sflphone/codecs/ noinst_LTLIBRARIES = libaudio.la -noinst_PROGRAMS = libcodec_ulaw.so libcodec_alaw.so libcodec_gsm.so +noinst_PROGRAMS = libcodec_ulaw.so libcodec_alaw.so libcodec_gsm.so libcodec_speex.so libcodec_ulaw_so_SOURCES = ulaw.cpp libcodec_ulaw_so_CFLAGS = -fPIC -g -Wall -libcodec_ulaw_so_LDFLAGS = -shared +libcodec_ulaw_so_LDFLAGS = -shared -lc libcodec_alaw_so_SOURCES = alaw.cpp libcodec_alaw_so_CFLAGS = -fPIC -g -Wall -libcodec_alaw_so_LDFLAGS = -shared +libcodec_alaw_so_LDFLAGS = -shared -lc libcodec_gsm_so_SOURCES = gsmcodec.cpp libcodec_gsm_so_CFLAGS = -fPIC -g -Wall -libcodec_gsm_so_LDFLAGS = -shared -lgsm +libcodec_gsm_so_LDFLAGS = -shared -lc -lgsm + +libcodec_speex_so_SOURCES = CodecSpeex.cpp +libcodec_speex_so_CFLAGS = -fPIC -g -Wall +libcodec_speex_so_LDFLAGS = -shared -lc -lspeex if USE_SPEEX SPEEX_SOURCES_CPP=CodecSpeex.cpp @@ -25,6 +29,8 @@ SPEEX_FLAG= SPEEX_LIB= endif +SUBDIRS = ilbc + libaudio_la_SOURCES = audiofile.cpp tonelist.cpp \ audiortp.cpp dtmf.cpp tone.cpp audiolayer.cpp audiodevice.cpp dtmfgenerator.cpp \ tonegenerator.cpp codecDescriptor.cpp \ @@ -40,8 +46,8 @@ noinst_HEADERS = audioloop.h common.h ringbuffer.h audiofile.h codecDescriptor.h dtmf.h tone.h \ CodecSpeex.h -install-exec-local: install-libcodec_ulaw_so install-libcodec_alaw_so install-libcodec_gsm_so -uninstall-local: uninstall-libcodec_ulaw_so uninstall-libcodec_alaw_so uninstall-libcodec_gsm_so +install-exec-local: install-libcodec_ulaw_so install-libcodec_alaw_so install-libcodec_gsm_so install-libcodec_speex_so +uninstall-local: uninstall-libcodec_ulaw_so uninstall-libcodec_alaw_so uninstall-libcodec_gsm_so uninstall-libcodec_speex_so install-libcodec_ulaw_so: libcodec_ulaw.so mkdir -p $(sflcodecdir) @@ -50,6 +56,8 @@ install-libcodec_alaw_so: libcodec_alaw.so $(INSTALL_PROGRAM) libcodec_alaw.so $(sflcodecdir) install-libcodec_gsm_so: libcodec_gsm.so $(INSTALL_PROGRAM) libcodec_gsm.so $(sflcodecdir) +install-libcodec_speex_so: libcodec_speex.so + $(INSTALL_PROGRAM) libcodec_speex.so $(sflcodecdir) uninstall-libcodec_ulaw_so: rm -f $(sflcodecdir)/libcodec_ulaw.so @@ -57,4 +65,6 @@ uninstall-libcodec_alaw_so: rm -f $(sflcodecdir)/libcodec_alaw.so uninstall-libcodec_gsm_so: rm -f $(sflcodecdir)/libcodec_gsm.so +uninstall-libcodec_speex_so: + rm -f $(sflcodecdir)/libcodec_speex.so rm -rf $(sflcodecdir) diff --git a/src/audio/audiortp.cpp b/src/audio/audiortp.cpp index 13c787961de894b357fe694c2a480ee62e8f5c87..4bbc93508d04380e97f5d14e928da885020cce52 100644 --- a/src/audio/audiortp.cpp +++ b/src/audio/audiortp.cpp @@ -1,4 +1,5 @@ /* + * * Copyright (C) 2004-2007 Savoir-Faire Linux inc. * Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com> * Author: Alexandre Bourget <alexandre.bourget@savoirfairelinux.com> @@ -26,8 +27,6 @@ #include <assert.h> #include <string> #include <cstring> -//#include <fstream> // fstream + iostream pour fstream debugging.. -//#include <iostream> // removeable... #include <math.h> #include <dlfcn.h> #include <iostream> @@ -98,17 +97,17 @@ AudioRtp::closeRtpSession () { // AudioRtpRTX Class // //////////////////////////////////////////////////////////////////////////////// AudioRtpRTX::AudioRtpRTX (SIPCall *sipcall, bool sym) - // : _fstream("/tmp/audio.dat", std::ofstream::binary) + : //_fstream("/tmp/audio.dat", std::ofstream::binary|std::ios::out|std::ios::app) { setCancel(cancelDeferred); time = new ost::Time(); _ca = sipcall; _sym = sym; + //std::string s = "snd.dat"; // AudioRtpRTX should be close if we change sample rate //_codecSampleRate = _ca->getAudioCodec()->getClockRate(); - // TODO: Change bind address according to user settings. // TODO: this should be the local ip not the external (router) IP std::string localipConfig = _ca->getLocalIp(); // _ca->getLocalIp(); @@ -142,7 +141,7 @@ AudioRtpRTX::~AudioRtpRTX () { } //_debug("terminate audiortprtx ended...\n"); _ca = 0; - + //fd = fopen("snd_data", "wa"); if (!_sym) { delete _sessionRecv; _sessionRecv = NULL; delete _sessionSend; _sessionSend = NULL; @@ -185,7 +184,6 @@ AudioRtpRTX::initAudioRtpSession (void) try { if (_ca == 0) { return; } - _debug("AUDIOCODEC=%i\n", _ca->getAudioCodec()); AudioCodec* audiocodec = loadCodec(_ca->getAudioCodec()); _codecSampleRate = audiocodec->getClockRate(); @@ -270,6 +268,9 @@ AudioRtpRTX::loadCodec(int payload) case 97: handle_codec = dlopen(CODECS_DIR "/libcodec_ilbc.so", RTLD_LAZY); break; + case 110: + handle_codec = dlopen(CODECS_DIR "/libcodec_speex.so", RTLD_LAZY); + break; } if(!handle_codec){ @@ -302,7 +303,6 @@ void AudioRtpRTX::sendSessionFromMic(int timestamp) { AudioCodec* audiocodec = loadCodec(_ca->getAudioCodec()); - // STEP: // 1. get data from mic // 2. convert it to int16 - good sample, good rate @@ -327,11 +327,12 @@ try { // take the lowest int bytesAvail = (availBytesFromMic < maxBytesToGet) ? availBytesFromMic : maxBytesToGet; - + //printf("clock rate = %i\n", audiocodec->getClockRate()); // Get bytes from micRingBuffer to data_from_mic int nbSample = audiolayer->getMic(_dataAudioLayer, bytesAvail) / sizeof(SFLDataFormat); int nb_sample_up = nbSample; int nbSamplesMax = _layerFrameSize * audiocodec->getClockRate() / 1000; + //_fstream.write((char*) _dataAudioLayer, nbSample); nbSample = reSampleData(audiocodec->getClockRate(), nb_sample_up, DOWN_SAMPLING); @@ -343,11 +344,12 @@ try { memset(toSIP + nbSample, 0, (nbSamplesMax-nbSample)*sizeof(int16)); nbSample = nbSamplesMax; } - //_debug("AR: Nb sample: %d int, [0]=%d [1]=%d [2]=%d\n", nbSample, toSIP[0], toSIP[1], toSIP[2]); - + // debug - dump sound in a file +//_debug("AR: Nb sample: %d int, [0]=%d [1]=%d [2]=%d\n", nbSample, toSIP[0], toSIP[1], toSIP[2]); // for the mono: range = 0 to RTP_FRAME2SEND * sizeof(int16) // codecEncode(char *dest, int16* src, size in bytes of the src) int compSize = audiocodec->codecEncode(_sendDataEncoded, toSIP, nbSample*sizeof(int16)); + //printf("jusqu'ici tout vas bien\n"); // encode divise by two // Send encoded audio sample over the network @@ -393,8 +395,9 @@ try { int payload = adu->getType(); // codec type unsigned char* data = (unsigned char*)adu->getData(); // data in char - unsigned int size = adu->getSize(); // size in char + unsigned int size = adu->getSize(); // size in char + //_fstream.write((char*) data, size); audiocodec = loadCodec(payload); // Decode data with relevant codec _codecSampleRate = audiocodec->getClockRate(); @@ -405,7 +408,8 @@ try { _debug("The packet size has been cropped\n"); size=max; } - + + //printf("size = %i\n", size); if (audiocodec != NULL) { int expandedSize = audiocodec->codecDecode(_receiveDataDecoded, data, size); @@ -565,6 +569,7 @@ try { Thread::sleep(TimerPort::getTimer()); TimerPort::incTimer(_layerFrameSize); // 'frameSize' ms } + //_fstream.close(); //_debug("stop stream for audiortp loop\n"); audiolayer->stopStream(); } catch(std::exception &e) { diff --git a/src/audio/codecDescriptor.cpp b/src/audio/codecDescriptor.cpp index fdb4dd39d2d7e78a22c9943ea3e69a6ecd9938cd..a00720cda87dead0037694b4c5e42c8c521197f7 100644 --- a/src/audio/codecDescriptor.cpp +++ b/src/audio/codecDescriptor.cpp @@ -52,11 +52,9 @@ void CodecDescriptor::setDefaultOrder() { _codecOrder.clear(); - //_codecOrder.push_back(PAYLOAD_CODEC_ILBC_20); _codecOrder.push_back(PAYLOAD_CODEC_ULAW); _codecOrder.push_back(PAYLOAD_CODEC_ALAW); _codecOrder.push_back(PAYLOAD_CODEC_GSM); - //_codecOrder.push_back(PAYLOAD_CODEC_SPEEX_8000); } std::string& @@ -121,7 +119,7 @@ CodecDescriptor::getBitRate(CodecType payload) return 15.2; } - return -1; + return 0.0; } double @@ -137,7 +135,7 @@ CodecDescriptor::getBandwidthPerCall(CodecType payload) case PAYLOAD_CODEC_ILBC_20: return 30.8; } - return -1; + return 0.0; } diff --git a/src/audio/codecDescriptor.h b/src/audio/codecDescriptor.h index 4cb9be9a5c03c88ef58b6c653ce77958b7aa7053..77da6e81dc02b74eaa253bd82b4a020ff05ee42d 100644 --- a/src/audio/codecDescriptor.h +++ b/src/audio/codecDescriptor.h @@ -45,7 +45,9 @@ typedef enum { // 97 speex/8000 // http://support.xten.com/viewtopic.php?p=8684&sid=3367a83d01fdcad16c7459a79859b08e // 100 speex/16000 - PAYLOAD_CODEC_SPEEX = 110 + PAYLOAD_CODEC_SPEEX_8000 = 110, + PAYLOAD_CODEC_SPEEX_16000 = 111, + PAYLOAD_CODEC_SPEEX_32000 = 112 } CodecType; #include "audiocodec.h" diff --git a/src/iaxcall.cpp b/src/iaxcall.cpp index e522e028a1466e9c785e3d04f8d51a38a238e1ef..9ffc3808568ca1aef9ca6856f5665fa73a899b91 100644 --- a/src/iaxcall.cpp +++ b/src/iaxcall.cpp @@ -44,7 +44,7 @@ IAXCall::setFormat(int format) case AST_FORMAT_ILBC: setAudioCodec(_codecMap.getCodec(PAYLOAD_CODEC_ILBC_20)); break; case AST_FORMAT_SPEEX: - setAudioCodec(_codecMap.getCodec(PAYLOAD_CODEC_SPEEX)); break;*/ + setAudioCodec(_codecMap.getCodec(PAYLOAD_CODEC_SPEEX_8000)); break;*/ case AST_FORMAT_ULAW: setAudioCodec(PAYLOAD_CODEC_ULAW); break; case AST_FORMAT_GSM: @@ -54,7 +54,7 @@ IAXCall::setFormat(int format) case AST_FORMAT_ILBC: setAudioCodec(PAYLOAD_CODEC_ILBC_20); break; case AST_FORMAT_SPEEX: - setAudioCodec(PAYLOAD_CODEC_SPEEX); break; + setAudioCodec(PAYLOAD_CODEC_SPEEX_8000); break; default: setAudioCodec((CodecType) -1); break; @@ -79,7 +79,7 @@ IAXCall::getSupportedFormat() format |= AST_FORMAT_ALAW; break; case PAYLOAD_CODEC_ILBC_20: format |= AST_FORMAT_ILBC; break; - case PAYLOAD_CODEC_SPEEX: + case PAYLOAD_CODEC_SPEEX_8000: format |= AST_FORMAT_SPEEX; break; default: break; @@ -107,7 +107,7 @@ IAXCall::getFirstMatchingFormat(int needles) format = AST_FORMAT_ALAW; break; case PAYLOAD_CODEC_ILBC_20: format = AST_FORMAT_ILBC; break; - case PAYLOAD_CODEC_SPEEX: + case PAYLOAD_CODEC_SPEEX_8000: format = AST_FORMAT_SPEEX; break; default: break; diff --git a/src/iaxvoiplink.cpp b/src/iaxvoiplink.cpp index 4e4738deb1d51cee566c0b46c6161c1e03d86c2b..43970a6a830c772714f9d0e8860fec8048d5a9f2 100644 --- a/src/iaxvoiplink.cpp +++ b/src/iaxvoiplink.cpp @@ -247,6 +247,9 @@ IAXVoIPLink::loadCodec(int payload) case 97: handle_codec = dlopen(CODECS_DIR "/libcodec_ilbc.so", RTLD_LAZY); break; + case 110: + handle_codec = dlopen(CODECS_DIR "/libcodec_speex.so", RTLD_LAZY); + break; } if(!handle_codec){ cerr<<"cannot load library: "<< dlerror() <<'\n';