diff --git a/sflphone-common/libs/pjproject/pjmedia/src/pjmedia/delaybuf.c b/sflphone-common/libs/pjproject/pjmedia/src/pjmedia/delaybuf.c index 667bcdbe9ab90d1c58e124604711772a994a79af..3f26b76b7dbb5e613f204aaf6301bc0058a25b47 100644 --- a/sflphone-common/libs/pjproject/pjmedia/src/pjmedia/delaybuf.c +++ b/sflphone-common/libs/pjproject/pjmedia/src/pjmedia/delaybuf.c @@ -144,8 +144,8 @@ PJ_DEF(pj_status_t) pjmedia_delay_buf_create( pj_pool_t *pool, return status; /* Finally, create mutex */ - status = pj_lock_create_recursive_mutex(pool, b->obj_name, - &b->lock); +// status = pj_lock_create_recursive_mutex(pool, b->obj_name, +// &b->lock); if (status != PJ_SUCCESS) return status; @@ -162,15 +162,15 @@ PJ_DEF(pj_status_t) pjmedia_delay_buf_destroy(pjmedia_delay_buf *b) PJ_ASSERT_RETURN(b, PJ_EINVAL); - pj_lock_acquire(b->lock); +// pj_lock_acquire(b->lock); status = pjmedia_wsola_destroy(b->wsola); if (status == PJ_SUCCESS) b->wsola = NULL; - pj_lock_release(b->lock); +// pj_lock_release(b->lock); - pj_lock_destroy(b->lock); +// pj_lock_destroy(b->lock); b->lock = NULL; return status; @@ -273,13 +273,13 @@ PJ_DEF(pj_status_t) pjmedia_delay_buf_put(pjmedia_delay_buf *b, PJ_ASSERT_RETURN(b && frame, PJ_EINVAL); - pj_lock_acquire(b->lock); + // pj_lock_acquire(b->lock); update(b, OP_PUT); status = pjmedia_wsola_save(b->wsola, frame, PJ_FALSE); if (status != PJ_SUCCESS) { - pj_lock_release(b->lock); +// pj_lock_release(b->lock); return status; } @@ -316,7 +316,7 @@ PJ_DEF(pj_status_t) pjmedia_delay_buf_put(pjmedia_delay_buf *b, pjmedia_circ_buf_write(b->circ_buf, frame, b->samples_per_frame); - pj_lock_release(b->lock); + // pj_lock_release(b->lock); return PJ_SUCCESS; } @@ -327,7 +327,7 @@ PJ_DEF(pj_status_t) pjmedia_delay_buf_get( pjmedia_delay_buf *b, PJ_ASSERT_RETURN(b && frame, PJ_EINVAL); - pj_lock_acquire(b->lock); + // pj_lock_acquire(b->lock); update(b, OP_GET); @@ -342,7 +342,7 @@ PJ_DEF(pj_status_t) pjmedia_delay_buf_get( pjmedia_delay_buf *b, if (status == PJ_SUCCESS) { TRACE__((b->obj_name,"Successfully generate 1 frame")); if (pjmedia_circ_buf_get_len(b->circ_buf) == 0) { - pj_lock_release(b->lock); +// pj_lock_release(b->lock); return PJ_SUCCESS; } @@ -363,7 +363,7 @@ PJ_DEF(pj_status_t) pjmedia_delay_buf_get( pjmedia_delay_buf *b, /* The buffer is empty now, reset it */ pjmedia_circ_buf_reset(b->circ_buf); - pj_lock_release(b->lock); + // pj_lock_release(b->lock); return PJ_SUCCESS; } @@ -371,7 +371,7 @@ PJ_DEF(pj_status_t) pjmedia_delay_buf_get( pjmedia_delay_buf *b, pjmedia_circ_buf_read(b->circ_buf, frame, b->samples_per_frame); - pj_lock_release(b->lock); + //pj_lock_release(b->lock); return PJ_SUCCESS; } @@ -381,7 +381,7 @@ PJ_DEF(pj_status_t) pjmedia_delay_buf_reset(pjmedia_delay_buf *b) { PJ_ASSERT_RETURN(b, PJ_EINVAL); - pj_lock_acquire(b->lock); + // pj_lock_acquire(b->lock); b->recalc_timer = RECALC_TIME; @@ -391,7 +391,7 @@ PJ_DEF(pj_status_t) pjmedia_delay_buf_reset(pjmedia_delay_buf *b) /* Reset WSOLA */ pjmedia_wsola_reset(b->wsola, 0); - pj_lock_release(b->lock); + // pj_lock_release(b->lock); PJ_LOG(5,(b->obj_name,"Delay buffer is reset")); diff --git a/sflphone-common/src/audio/Makefile.am b/sflphone-common/src/audio/Makefile.am index 4fd2854e713a9a83f609b2c15b1ecef259210822..40b669fd1ff746004878992a3d7d208b2b4201de 100644 --- a/sflphone-common/src/audio/Makefile.am +++ b/sflphone-common/src/audio/Makefile.am @@ -20,6 +20,7 @@ libaudio_la_SOURCES = \ samplerateconverter.cpp \ delaydetection.cpp \ echocancel.cpp \ + echosuppress.cpp \ speexechocancel.cpp \ noisesuppress.cpp \ audioprocessing.cpp \ @@ -39,6 +40,7 @@ noinst_HEADERS = \ algorithm.h \ delaydetection.h \ echocancel.h \ + echosuppress.h \ speexechocancel.h \ noisesuppress.h \ audioprocessing.h \ diff --git a/sflphone-common/src/audio/audiortp/AudioRtpRecordHandler.cpp b/sflphone-common/src/audio/audiortp/AudioRtpRecordHandler.cpp index 201c2b22e0359cc653287e0e587050f04777c01d..2e69bdc1f1479e6cdca5061980d09ea01b9ec050 100644 --- a/sflphone-common/src/audio/audiortp/AudioRtpRecordHandler.cpp +++ b/sflphone-common/src/audio/audiortp/AudioRtpRecordHandler.cpp @@ -123,7 +123,7 @@ AudioRtpRecord::~AudioRtpRecord() } -AudioRtpRecordHandler::AudioRtpRecordHandler (SIPCall *ca) : _audioRtpRecord (), _ca (ca) {} +AudioRtpRecordHandler::AudioRtpRecordHandler (SIPCall *ca) : _audioRtpRecord (), _ca (ca), echoCanceller(ca->getMemoryPool()) {} AudioRtpRecordHandler::~AudioRtpRecordHandler() {} @@ -299,14 +299,16 @@ int AudioRtpRecordHandler::processDataEncode (void) _audioRtpRecord._audioProcess->processAudio (micDataConverted, nbSample * sizeof (SFLDataFormat)); } - echoCanceller.process(micDataConverted, micDataEchoCancelled, nbSample * sizeof(SFLDataFormat)); - + // echoCanceller.process(micDataConverted, micDataEchoCancelled, nbSample * sizeof(SFLDataFormat)); + if(Manager::instance().getEchoCancelState() != "enabled") { + echoCanceller.getData(micData); + } _audioRtpRecord.audioProcessMutex.leave(); _audioRtpRecord.audioCodecMutex.enter(); - compSize = _audioRtpRecord._audioCodec->encode (micDataEncoded, micDataEchoCancelled, nbSample * sizeof (SFLDataFormat)); + compSize = _audioRtpRecord._audioCodec->encode (micDataEncoded, micData, nbSample * sizeof (SFLDataFormat)); // compSize = _audioRtpRecord._audioCodec->encode (micDataEncoded, micDataConverted, nbSample * sizeof (SFLDataFormat)); _audioRtpRecord.audioCodecMutex.leave(); @@ -320,9 +322,14 @@ int AudioRtpRecordHandler::processDataEncode (void) // _audioRtpRecord._audioProcess->processAudio (micDataEchoCancelled, nbSample * sizeof (SFLDataFormat)); } - echoCanceller.process(micData, micDataEchoCancelled, nbSample * sizeof(SFLDataFormat)); + // echoCanceller.process(micData, micDataEchoCancelled, nbSample * sizeof(SFLDataFormat)); + // echoCanceller.process(micData, micDataEchoCancelled, nbSample * sizeof(SFLDataFormat)); + if(Manager::instance().getEchoCancelState() != "enabled") { + _debug("EchoCancel: -------------------------- getData"); + echoCanceller.getData(micData); + } - teststream.write(reinterpret_cast<char *>(micDataEchoCancelled), nbSample * sizeof(SFLDataFormat)); + teststream.write(reinterpret_cast<char *>(micData), nbSample * sizeof(SFLDataFormat)); _audioRtpRecord.audioProcessMutex.leave(); @@ -331,7 +338,7 @@ int AudioRtpRecordHandler::processDataEncode (void) // no resampling required // compSize = _audioRtpRecord._audioCodec->encode (micDataEncoded, micData, nbSample * sizeof (SFLDataFormat)); - compSize = _audioRtpRecord._audioCodec->encode (micDataEncoded, micDataEchoCancelled, nbSample * sizeof (SFLDataFormat)); + compSize = _audioRtpRecord._audioCodec->encode (micDataEncoded, micData, nbSample * sizeof (SFLDataFormat)); _audioRtpRecord.audioCodecMutex.leave(); } @@ -370,15 +377,19 @@ void AudioRtpRecordHandler::processDataDecode (unsigned char *spkrData, unsigned nbSample = _audioRtpRecord._converter->upsampleData (spkrDataDecoded, spkrDataConverted, codecSampleRate, mainBufferSampleRate, nbSampleDown); - echoCanceller.putData(spkrDataConverted, nbSample * sizeof(SFLDataFormat)); + if(Manager::instance().getEchoCancelState() != "enabled") { + echoCanceller.putData(spkrDataConverted, nbSample * sizeof(SFLDataFormat)); + } // put data in audio layer, size in byte Manager::instance().getMainBuffer()->putData (spkrDataConverted, nbSample * sizeof (SFLDataFormat), 100, _ca->getCallId()); } else { - echoCanceller.putData(spkrDataDecoded, expandedSize); - + if(Manager::instance().getEchoCancelState() != "enabled") { + _debug("EchoCancel: ------------------------ Put Data"); + echoCanceller.putData(spkrDataDecoded, expandedSize); + } // put data in audio layer, size in byte Manager::instance().getMainBuffer()->putData (spkrDataDecoded, expandedSize, 100, _ca->getCallId()); } diff --git a/sflphone-common/src/audio/audiortp/AudioRtpRecordHandler.h b/sflphone-common/src/audio/audiortp/AudioRtpRecordHandler.h index f08e512e0dd198e8e8788aae610698e810184314..96f733da2716016f1f3f7a0c45dee5ee04f96c34 100644 --- a/sflphone-common/src/audio/audiortp/AudioRtpRecordHandler.h +++ b/sflphone-common/src/audio/audiortp/AudioRtpRecordHandler.h @@ -36,6 +36,7 @@ #include "audio/audioprocessing.h" #include "audio/noisesuppress.h" #include "audio/speexechocancel.h" +#include "audio/echosuppress.h" #include "managerimpl.h" #include <ccrtp/rtp.h> @@ -227,7 +228,7 @@ class AudioRtpRecordHandler SIPCall *_ca; - SpeexEchoCancel echoCanceller; + EchoSuppress echoCanceller; }; } diff --git a/sflphone-common/src/audio/echosuppress.cpp b/sflphone-common/src/audio/echosuppress.cpp new file mode 100644 index 0000000000000000000000000000000000000000..46c9fd67377a411daef5948c35fa44a49d642c63 --- /dev/null +++ b/sflphone-common/src/audio/echosuppress.cpp @@ -0,0 +1,94 @@ +/* + * EchoSuppress.cpp + * + * Created on: 2011-05-18 + * Author: asavard + */ + +#include "echosuppress.h" +#include "pj/os.h" + +#define ECHO_CANCEL_MEM_SIZE 1000 + +EchoSuppress::EchoSuppress(pj_pool_t *pool) +{ + pj_status_t status; + + _debug("********************************************************************** Init echo suppress"); + + // pj_thread_register + + pj_thread_desc aPJThreadDesc; + pj_thread_t *pjThread; + _debug("EchoCancel: Thread not yet registered to pjsip, registering"); + status = pj_thread_register("EchoCanceller", aPJThreadDesc, &pjThread); + if (status != PJ_SUCCESS) { + _error("EchoCancel: Error: Could not register new thread"); + } +// if (!pj_thread_is_registered()) { +// } + + if (!pj_thread_is_registered()) { + _warn("EchoCancel: Thread not registered..."); + } + + // pj_thread_register(); + +// status = pj_init(); +// if(status != PJ_SUCCESS) { +// _error("EchoCancel: Error: could not init pj"); +// } +// +// pj_caching_pool_init(&echoCachingPool, &pj_pool_factory_default_policy, ECHO_CANCEL_MEM_SIZE); + + // echoCancelPool = pj_pool_create_int(&echoCachingPool.factory, "EchoCancelPool", 1000, 1000, NULL); + echoCancelPool = pool; + + status = pjmedia_echo_create(echoCancelPool, 8000, 160, 250, 0, PJMEDIA_ECHO_SIMPLE, &echoState); + if(status != PJ_SUCCESS) { + _error("EchoCancel: Error: Could not create echo canceller"); + } +} + +EchoSuppress::~EchoSuppress() +{ +// pjmedia_echo_destroy(echoState); + + // pj_pool_destroy(echoCancelPool); + + //pj_caching_pool_destroy(&echoCachingPool); +} + +void EchoSuppress::reset() +{ + +} + +void EchoSuppress::putData (SFLDataFormat *inputData, int nbBytes) +{ + pj_status_t status; + + status = pjmedia_echo_playback(echoState, reinterpret_cast<pj_int16_t *>(inputData)); + + if(status != PJ_SUCCESS) { + _warn("EchoCancel: Warning: Problem while putting input data"); + } +} + +int EchoSuppress::getData(SFLDataFormat *outputData) +{ + pj_status_t status; + + status = pjmedia_echo_capture(echoState, reinterpret_cast<pj_int16_t *>(outputData), 0); + if(status != PJ_SUCCESS) { + _warn("EchoCancel: Warning: Problem while getting output data"); + } + + return 0; +} + +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 new file mode 100644 index 0000000000000000000000000000000000000000..f4bba4c688a957053583f053f7ecc65d6d4c7aa0 --- /dev/null +++ b/sflphone-common/src/audio/echosuppress.h @@ -0,0 +1,66 @@ +/* + * EchoSuppress.h + * + * Created on: 2011-05-18 + * Author: asavard + */ + +#ifndef ECHOSUPPRESS_H_ +#define ECHOSUPPRESS_H_ + +#include "pjmedia/echo.h" +#include "pj/pool.h" + +#include "audioprocessing.h" + +class EchoSuppress: public Algorithm { +public: + EchoSuppress(pj_pool_t *pool); + + virtual ~EchoSuppress(); + + virtual void reset (void); + + /** + * Add speaker data into internal buffer + * \param inputData containing far-end voice data to be sent to speakers + */ + virtual void putData (SFLDataFormat *, int); + + virtual int getData(SFLDataFormat *); + + /** + * Unused + */ + virtual void process (SFLDataFormat *, int); + + /** + * Perform echo cancellation using internal buffers + * \param inputData containing mixed echo and voice data + * \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: + + /** + * Memory pool for echo cancellation + */ + pj_pool_t *echoCancelPool; + + /** + * The internal state of the echo canceller + */ + pjmedia_echo_state *echoState; +}; + +#endif /* ECHOSUPPRESS_H_ */