[pulseaudio-commits] [SCM] PulseAudio Sound Server branch, master, updated. v1.0-dev-358-g0ecf511

Colin Guthrie gitmailer-noreply at 0pointer.de
Tue May 24 01:31:57 PDT 2011


This is an automated email from the git hooks/post-receive script. It was
generated because of a push to the "PulseAudio Sound Server" repository.

The master branch has been updated
      from  117c7145944fb227703d72dd2f03e88d439c187d (commit)

- Log -----------------------------------------------------------------
0ecf511 echo-cancel: Add speex preprocessing
-----------------------------------------------------------------------

Summary of changes:
 src/modules/echo-cancel/echo-cancel.h        |    6 +++
 src/modules/echo-cancel/module-echo-cancel.c |   61 ++++++++++++++++++++++++-
 2 files changed, 64 insertions(+), 3 deletions(-)

-----------------------------------------------------------------------

commit 0ecf51119a349e51daeea0437eba9a14d69ce533
Author: Arun Raghavan <arun.raghavan at collabora.co.uk>
Date:   Thu May 19 13:29:49 2011 +0530

    echo-cancel: Add speex preprocessing
    
    This allows the selective enabling of speex' preprocessing algorithms
    before running the echo-canceller -- for now this includes automatic
    gain control, noise suppression and echo suppression. It's all off by
    default for now, though at some point in the near future we might want
    to enable at least denoising by default.
    
    The denoising works pretty well, though we might want to add a way to
    tweak the noise-suppression knob that libspeex provides.
    
    The AGC option is just a stop-gap -- we need a real AGC mechanism that
    tweaks the source volume rather than doing this in software.
    
    The speex documentation mentions VAD and dereverb, but it appears that
    these are not complete yet.
    
    We don't do all this in a separate module from module-echo-cancel to
    avoid the overhead of adding another virtual source. It makes more sense
    to make a separate virtual source module that can be used for cases
    where preprocessing is useful but AEC is not (for e.g. noise suppression
    for fan noise in a recording application).
    
    Another reason to keep this integrated with the AEC module is that the
    echo suppression bits use the speex echo canceller state. This does leak
    some information about the AEC implementation into module-echo-cancel,
    but this is unavoidable.

diff --git a/src/modules/echo-cancel/echo-cancel.h b/src/modules/echo-cancel/echo-cancel.h
index 5f6adbc..5f18053 100644
--- a/src/modules/echo-cancel/echo-cancel.h
+++ b/src/modules/echo-cancel/echo-cancel.h
@@ -29,6 +29,7 @@
 #include <pulsecore/macro.h>
 
 #include <speex/speex_echo.h>
+#include <speex/speex_preprocess.h>
 #include "adrian.h"
 
 /* Common data structures */
@@ -63,6 +64,11 @@ struct pa_echo_canceller {
     void        (*done)                 (pa_echo_canceller *ec);
 
     pa_echo_canceller_params params;
+
+    pa_bool_t agc;
+    pa_bool_t denoise;
+    pa_bool_t echo_suppress;
+    SpeexPreprocessState *pp_state;
 };
 
 /* Speex canceller functions */
diff --git a/src/modules/echo-cancel/module-echo-cancel.c b/src/modules/echo-cancel/module-echo-cancel.c
index b0d3c68..e83839a 100644
--- a/src/modules/echo-cancel/module-echo-cancel.c
+++ b/src/modules/echo-cancel/module-echo-cancel.c
@@ -77,6 +77,9 @@ PA_MODULE_USAGE(
           "channel_map=<channel map> "
           "aec_method=<implementation to use> "
           "aec_args=<parameters for the AEC engine> "
+          "agc=<perform automagic gain control?> "
+          "denoise=<apply denoising?> "
+          "echo_suppress=<perform echo suppression? (only with the speex canceller)> "
           "save_aec=<save AEC data in /tmp> "
           "autoloaded=<set if this module is being loaded automatically> "
         ));
@@ -106,6 +109,9 @@ static const pa_echo_canceller ec_table[] = {
 };
 
 #define DEFAULT_ADJUST_TIME_USEC (1*PA_USEC_PER_SEC)
+#define DEFAULT_AGC_ENABLED FALSE
+#define DEFAULT_DENOISE_ENABLED FALSE
+#define DEFAULT_ECHO_SUPPRESS_ENABLED FALSE
 #define DEFAULT_SAVE_AEC 0
 #define DEFAULT_AUTOLOADED FALSE
 
@@ -212,6 +218,9 @@ static const char* const valid_modargs[] = {
     "channel_map",
     "aec_method",
     "aec_args",
+    "agc",
+    "denoise",
+    "echo_suppress",
     "save_aec",
     "autoloaded",
     NULL
@@ -710,14 +719,20 @@ static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk)
                 cchunk.memblock = pa_memblock_new(u->source->core->mempool, cchunk.length);
                 cdata = pa_memblock_acquire(cchunk.memblock);
 
-                /* perform echo cancelation */
-                u->ec->run(u->ec, rdata, pdata, cdata);
-
                 if (u->save_aec) {
                     if (u->captured_file)
                         fwrite(rdata, 1, u->blocksize, u->captured_file);
                     if (u->played_file)
                         fwrite(pdata, 1, u->blocksize, u->played_file);
+                }
+
+                if (u->ec->pp_state)
+                    speex_preprocess_run(u->ec->pp_state, (spx_int16_t *) rdata);
+
+                /* perform echo cancelation */
+                u->ec->run(u->ec, rdata, pdata, cdata);
+
+                if (u->save_aec) {
                     if (u->canceled_file)
                         fwrite(cdata, 1, u->blocksize, u->canceled_file);
                 }
@@ -1391,6 +1406,28 @@ int pa__init(pa_module*m) {
     else
         u->adjust_time = DEFAULT_ADJUST_TIME_USEC;
 
+    u->ec->agc = DEFAULT_AGC_ENABLED;
+    if (pa_modargs_get_value_boolean(ma, "agc", &u->ec->agc) < 0) {
+        pa_log("Failed to parse agc value");
+        goto fail;
+    }
+
+    u->ec->denoise = DEFAULT_DENOISE_ENABLED;
+    if (pa_modargs_get_value_boolean(ma, "denoise", &u->ec->denoise) < 0) {
+        pa_log("Failed to parse denoise value");
+        goto fail;
+    }
+
+    u->ec->echo_suppress = DEFAULT_ECHO_SUPPRESS_ENABLED;
+    if (pa_modargs_get_value_boolean(ma, "echo_suppress", &u->ec->echo_suppress) < 0) {
+        pa_log("Failed to parse echo_suppress value");
+        goto fail;
+    }
+    if (u->ec->echo_suppress && ec_method != PA_ECHO_CANCELLER_SPEEX) {
+        pa_log("Echo suppression is only useful with the speex canceller");
+        goto fail;
+    }
+
     u->save_aec = DEFAULT_SAVE_AEC;
     if (pa_modargs_get_value_u32(ma, "save_aec", &u->save_aec) < 0) {
         pa_log("Failed to parse save_aec value");
@@ -1412,6 +1449,21 @@ int pa__init(pa_module*m) {
         }
     }
 
+    if (u->ec->agc || u->ec->denoise || u->ec->echo_suppress) {
+        if (source_ss.channels != 1) {
+            pa_log("AGC, denoising and echo suppression only work with channels=1");
+            goto fail;
+        }
+
+        u->ec->pp_state = speex_preprocess_state_init(u->blocksize, source_ss.rate);
+
+        speex_preprocess_ctl(u->ec->pp_state, SPEEX_PREPROCESS_SET_AGC, &u->ec->agc);
+        speex_preprocess_ctl(u->ec->pp_state, SPEEX_PREPROCESS_SET_DENOISE, &u->ec->denoise);
+        speex_preprocess_ctl(u->ec->pp_state, SPEEX_PREPROCESS_SET_ECHO_SUPPRESS, &u->ec->echo_suppress);
+        if (u->ec->echo_suppress)
+            speex_preprocess_ctl(u->ec->pp_state, SPEEX_PREPROCESS_SET_ECHO_STATE, u->ec->params.priv.speex.state);
+    }
+
     /* Create source */
     pa_source_new_data_init(&source_data);
     source_data.driver = __FILE__;
@@ -1682,6 +1734,9 @@ void pa__done(pa_module*m) {
     if (u->sink_memblockq)
         pa_memblockq_free(u->sink_memblockq);
 
+    if (u->ec->pp_state)
+        speex_preprocess_state_destroy(u->ec->pp_state);
+
     if (u->ec) {
         if (u->ec->done)
             u->ec->done(u->ec);

-- 
hooks/post-receive
PulseAudio Sound Server



More information about the pulseaudio-commits mailing list