[pulseaudio-discuss] [PATCHv2 4/5] echo-cancel: Enable different blocksizes for sink and source

Stefan Huber s.huber at bct-electronic.com
Tue Dec 18 04:52:33 PST 2012


Hi Tanu,


again, I added your suggestions to the patch. Please see details below.


> > +    memcpy(out, rec, 256 * 2 );
> Extra space added after "256 * 2".

Fixed.

> u is not a pointer, this code will not compile. Same goes for the rest
> of the changes in this file.

Fixed. Patch 1/5 and 2/5 are related to this fix.

> > -        if (rlen && u->source_skip % u->blocksize) {
> > -            u->sink_skip += u->blocksize - (u->source_skip % u->blocksize);
> > -            u->source_skip -= (u->source_skip % u->blocksize);
> > +        if (rlen && u->source_skip % u->source_blocksize) {
> > +            u->sink_skip += u->source_blocksize - (u->source_skip % u->source_blocksize);
> Should this be
>     u->sink_skip += u->sink_blocksize - frames_to_sink_bytes(source_bytes_to_frames(u->source_skip % u->source_blocksize));
> ?

Yes, indeed, we need to consider different correspondences between usec
and bytes for source and sink. I fixed this by multiplying

   u->source_blocksize - (u->source_skip % u->source_blocksize)

with the factor u->sink_blocksize/u->source_blocksize, see below.


Best
Stefan

-- >8 --

In order to support different blocksizes for source and sink (e.g, for
4-to-1 beamforming/echo canceling which involves 4 record channels and 1
playback channel) the AEC API is altered:
The blocksize for source and sink may differ (due to different sample
specs) but the number of frames that are processed in one invokation of
the AEC implementation's run() function is the same for the playback and
the record stream. Consequently, the AEC implementation's init()
function initalizes 'nframes' instead of 'blocksize' and the source's
and sink's blocksizes are derived from 'nframes'. The old API also
caused code duplication in each AEC implementation's init function for
the compution of the blocksize, which is eliminated by the new API.

Signed-off-by: Stefan Huber <s.huber at bct-electronic.com>
Acked-by: Peter Meerwald <p.meerwald at bct-electronic.com>
---
 src/modules/echo-cancel/adrian.c             |   11 ++-
 src/modules/echo-cancel/echo-cancel.h        |   18 ++---
 src/modules/echo-cancel/module-echo-cancel.c |   98 +++++++++++++++-----------
 src/modules/echo-cancel/null.c               |    9 ++-
 src/modules/echo-cancel/speex.c              |   28 ++++----
 src/modules/echo-cancel/webrtc.cc            |    5 +-
 6 files changed, 89 insertions(+), 80 deletions(-)

diff --git a/src/modules/echo-cancel/adrian.c b/src/modules/echo-cancel/adrian.c
index ab3858a..8f779a6 100644
--- a/src/modules/echo-cancel/adrian.c
+++ b/src/modules/echo-cancel/adrian.c
@@ -57,9 +57,9 @@ static void pa_adrian_ec_fixate_spec(pa_sample_spec *source_ss, pa_channel_map *
 pa_bool_t pa_adrian_ec_init(pa_core *c, pa_echo_canceller *ec,
                            pa_sample_spec *source_ss, pa_channel_map *source_map,
                            pa_sample_spec *sink_ss, pa_channel_map *sink_map,
-                           uint32_t *blocksize, const char *args)
+                           uint32_t *nframes, const char *args)
 {
-    int framelen, rate, have_vector = 0;
+    int rate, have_vector = 0;
     uint32_t frame_size_ms;
     pa_modargs *ma;
 
@@ -77,11 +77,10 @@ pa_bool_t pa_adrian_ec_init(pa_core *c, pa_echo_canceller *ec,
     pa_adrian_ec_fixate_spec(source_ss, source_map, sink_ss, sink_map);
 
     rate = source_ss->rate;
-    framelen = (rate * frame_size_ms) / 1000;
+    *nframes = (rate * frame_size_ms) / 1000;
+    ec->params.priv.adrian.blocksize = (*nframes) * pa_frame_size (source_ss);
 
-    *blocksize = ec->params.priv.adrian.blocksize = framelen * pa_frame_size (source_ss);
-
-    pa_log_debug ("Using framelen %d, blocksize %u, channels %d, rate %d", framelen, ec->params.priv.adrian.blocksize, source_ss->channels, source_ss->rate);
+    pa_log_debug ("Using nframes %d, blocksize %u, channels %d, rate %d", *nframes, ec->params.priv.adrian.blocksize, source_ss->channels, source_ss->rate);
 
     /* For now we only support SSE */
     if (c->cpu_info.cpu_type == PA_CPU_X86 && (c->cpu_info.flags.x86 & PA_CPU_X86_SSE))
diff --git a/src/modules/echo-cancel/echo-cancel.h b/src/modules/echo-cancel/echo-cancel.h
index 9ca78ff..6e81681 100644
--- a/src/modules/echo-cancel/echo-cancel.h
+++ b/src/modules/echo-cancel/echo-cancel.h
@@ -86,7 +86,7 @@ struct pa_echo_canceller {
                                          pa_channel_map *source_map,
                                          pa_sample_spec *sink_ss,
                                          pa_channel_map *sink_map,
-                                         uint32_t *blocksize,
+                                         uint32_t *nframes,
                                          const char *args);
 
     /* You should have only one of play()+record() or run() set. The first
@@ -94,13 +94,13 @@ struct pa_echo_canceller {
      * samples yourself. If you set run(), module-echo-cancel will handle
      * synchronising the playback and record streams. */
 
-    /* Feed the engine 'blocksize' playback bytes.. */
+    /* Feed the engine 'nframes' playback frames.. */
     void        (*play)                 (pa_echo_canceller *ec, const uint8_t *play);
-    /* Feed the engine 'blocksize' record bytes. blocksize processed bytes are
+    /* Feed the engine 'nframes' record frames. nframes processed frames are
      * returned in out. */
     void        (*record)               (pa_echo_canceller *ec, const uint8_t *rec, uint8_t *out);
-    /* Feed the engine blocksize playback and record streams, with a reasonable
-     * effort at keeping the two in sync. blocksize processed bytes are
+    /* Feed the engine nframes playback and record frames, with a reasonable
+     * effort at keeping the two in sync. nframes processed frames are
      * returned in out. */
     void        (*run)                  (pa_echo_canceller *ec, const uint8_t *rec, const uint8_t *play, uint8_t *out);
 
@@ -132,7 +132,7 @@ void pa_echo_canceller_set_capture_volume(pa_echo_canceller *ec, pa_cvolume *v);
 pa_bool_t pa_null_ec_init(pa_core *c, pa_echo_canceller *ec,
                            pa_sample_spec *source_ss, pa_channel_map *source_map,
                            pa_sample_spec *sink_ss, pa_channel_map *sink_map,
-                           uint32_t *blocksize, const char *args);
+                           uint32_t *nframes, const char *args);
 void pa_null_ec_run(pa_echo_canceller *ec, const uint8_t *rec, const uint8_t *play, uint8_t *out);
 void pa_null_ec_done(pa_echo_canceller *ec);
 
@@ -141,7 +141,7 @@ void pa_null_ec_done(pa_echo_canceller *ec);
 pa_bool_t pa_speex_ec_init(pa_core *c, pa_echo_canceller *ec,
                            pa_sample_spec *source_ss, pa_channel_map *source_map,
                            pa_sample_spec *sink_ss, pa_channel_map *sink_map,
-                           uint32_t *blocksize, const char *args);
+                           uint32_t *nframes, const char *args);
 void pa_speex_ec_run(pa_echo_canceller *ec, const uint8_t *rec, const uint8_t *play, uint8_t *out);
 void pa_speex_ec_done(pa_echo_canceller *ec);
 #endif
@@ -151,7 +151,7 @@ void pa_speex_ec_done(pa_echo_canceller *ec);
 pa_bool_t pa_adrian_ec_init(pa_core *c, pa_echo_canceller *ec,
                            pa_sample_spec *source_ss, pa_channel_map *source_map,
                            pa_sample_spec *sink_ss, pa_channel_map *sink_map,
-                           uint32_t *blocksize, const char *args);
+                           uint32_t *nframes, const char *args);
 void pa_adrian_ec_run(pa_echo_canceller *ec, const uint8_t *rec, const uint8_t *play, uint8_t *out);
 void pa_adrian_ec_done(pa_echo_canceller *ec);
 #endif
@@ -162,7 +162,7 @@ PA_C_DECL_BEGIN
 pa_bool_t pa_webrtc_ec_init(pa_core *c, pa_echo_canceller *ec,
                             pa_sample_spec *source_ss, pa_channel_map *source_map,
                             pa_sample_spec *sink_ss, pa_channel_map *sink_map,
-                            uint32_t *blocksize, const char *args);
+                            uint32_t *nframes, const char *args);
 void pa_webrtc_ec_play(pa_echo_canceller *ec, const uint8_t *play);
 void pa_webrtc_ec_record(pa_echo_canceller *ec, const uint8_t *rec, uint8_t *out);
 void pa_webrtc_ec_set_drift(pa_echo_canceller *ec, float drift);
diff --git a/src/modules/echo-cancel/module-echo-cancel.c b/src/modules/echo-cancel/module-echo-cancel.c
index 103aef0..57b0d84 100644
--- a/src/modules/echo-cancel/module-echo-cancel.c
+++ b/src/modules/echo-cancel/module-echo-cancel.c
@@ -211,7 +211,8 @@ struct userdata {
     pa_bool_t save_aec;
 
     pa_echo_canceller *ec;
-    uint32_t blocksize;
+    uint32_t source_blocksize;
+    uint32_t sink_blocksize;
 
     pa_bool_t need_realign;
 
@@ -293,6 +294,7 @@ enum {
     ECHO_CANCELLER_MESSAGE_SET_VOLUME,
 };
 
+
 static int64_t calc_diff(struct userdata *u, struct snapshot *snapshot) {
     int64_t diff_time, buffer_latency;
     pa_usec_t plen, rlen, source_delay, sink_delay, recv_counter, send_counter;
@@ -417,7 +419,7 @@ static int source_process_msg_cb(pa_msgobject *o, int code, void *data, int64_t
                 /* Add the latency internal to our source output on top */
                 pa_bytes_to_usec(pa_memblockq_get_length(u->source_output->thread_info.delay_memblockq), &u->source_output->source->sample_spec) +
                 /* and the buffering we do on the source */
-                pa_bytes_to_usec(u->blocksize, &u->source_output->source->sample_spec);
+                pa_bytes_to_usec( u->source_blocksize, &u->source_output->source->sample_spec);
 
             return 0;
 
@@ -734,9 +736,11 @@ static void do_push_drift_comp(struct userdata *u) {
      * samples left from the last iteration (to avoid double counting
      * those remainder samples.
      */
+
+
     drift = ((float)(plen - u->sink_rem) - (rlen - u->source_rem)) / ((float)(rlen - u->source_rem));
-    u->sink_rem = plen % u->blocksize;
-    u->source_rem = rlen % u->blocksize;
+    u->sink_rem = plen % u->sink_blocksize;
+    u->source_rem = rlen % u->source_blocksize;
 
     /* Now let the canceller work its drift compensation magic */
     u->ec->set_drift(u->ec, drift);
@@ -747,8 +751,8 @@ static void do_push_drift_comp(struct userdata *u) {
     }
 
     /* Send in the playback samples first */
-    while (plen >= u->blocksize) {
-        pa_memblockq_peek_fixed_size(u->sink_memblockq, u->blocksize, &pchunk);
+    while (plen >= u->sink_blocksize) {
+        pa_memblockq_peek_fixed_size(u->sink_memblockq, u->sink_blocksize, &pchunk);
         pdata = pa_memblock_acquire(pchunk.memblock);
         pdata += pchunk.index;
 
@@ -756,27 +760,27 @@ static void do_push_drift_comp(struct userdata *u) {
 
         if (u->save_aec) {
             if (u->drift_file)
-                fprintf(u->drift_file, "p %d\n", u->blocksize);
+                fprintf(u->drift_file, "p %d\n", u->sink_blocksize);
             if (u->played_file)
-                unused = fwrite(pdata, 1, u->blocksize, u->played_file);
+                unused = fwrite(pdata, 1, u->sink_blocksize, u->played_file);
         }
 
         pa_memblock_release(pchunk.memblock);
-        pa_memblockq_drop(u->sink_memblockq, u->blocksize);
+        pa_memblockq_drop(u->sink_memblockq, u->sink_blocksize);
         pa_memblock_unref(pchunk.memblock);
 
-        plen -= u->blocksize;
+        plen -= u->sink_blocksize;
     }
 
     /* And now the capture samples */
-    while (rlen >= u->blocksize) {
-        pa_memblockq_peek_fixed_size(u->source_memblockq, u->blocksize, &rchunk);
+    while (rlen >= u->source_blocksize) {
+        pa_memblockq_peek_fixed_size(u->source_memblockq, u->source_blocksize, &rchunk);
 
         rdata = pa_memblock_acquire(rchunk.memblock);
         rdata += rchunk.index;
 
         cchunk.index = 0;
-        cchunk.length = u->blocksize;
+        cchunk.length = u->source_blocksize;
         cchunk.memblock = pa_memblock_new(u->source->core->mempool, cchunk.length);
         cdata = pa_memblock_acquire(cchunk.memblock);
 
@@ -784,11 +788,11 @@ static void do_push_drift_comp(struct userdata *u) {
 
         if (u->save_aec) {
             if (u->drift_file)
-                fprintf(u->drift_file, "c %d\n", u->blocksize);
+                fprintf(u->drift_file, "c %d\n", u->source_blocksize);
             if (u->captured_file)
-                unused = fwrite(rdata, 1, u->blocksize, u->captured_file);
+                unused = fwrite(rdata, 1, u->source_blocksize, u->captured_file);
             if (u->canceled_file)
-                unused = fwrite(cdata, 1, u->blocksize, u->canceled_file);
+                unused = fwrite(cdata, 1, u->source_blocksize, u->canceled_file);
         }
 
         pa_memblock_release(cchunk.memblock);
@@ -799,8 +803,8 @@ static void do_push_drift_comp(struct userdata *u) {
         pa_source_post(u->source, &cchunk);
         pa_memblock_unref(cchunk.memblock);
 
-        pa_memblockq_drop(u->source_memblockq, u->blocksize);
-        rlen -= u->blocksize;
+        pa_memblockq_drop(u->source_memblockq, u->source_blocksize);
+        rlen -= u->source_blocksize;
     }
 }
 
@@ -818,13 +822,13 @@ static void do_push(struct userdata *u) {
     rlen = pa_memblockq_get_length(u->source_memblockq);
     plen = pa_memblockq_get_length(u->sink_memblockq);
 
-    while (rlen >= u->blocksize) {
+    while (rlen >= u->source_blocksize) {
         /* take fixed block from recorded samples */
-        pa_memblockq_peek_fixed_size(u->source_memblockq, u->blocksize, &rchunk);
+        pa_memblockq_peek_fixed_size(u->source_memblockq, u->source_blocksize, &rchunk);
 
-        if (plen >= u->blocksize) {
+        if (plen >= u->sink_blocksize) {
             /* take fixed block from played samples */
-            pa_memblockq_peek_fixed_size(u->sink_memblockq, u->blocksize, &pchunk);
+            pa_memblockq_peek_fixed_size(u->sink_memblockq, u->sink_blocksize, &pchunk);
 
             rdata = pa_memblock_acquire(rchunk.memblock);
             rdata += rchunk.index;
@@ -832,15 +836,15 @@ static void do_push(struct userdata *u) {
             pdata += pchunk.index;
 
             cchunk.index = 0;
-            cchunk.length = u->blocksize;
+            cchunk.length = u->source_blocksize;
             cchunk.memblock = pa_memblock_new(u->source->core->mempool, cchunk.length);
             cdata = pa_memblock_acquire(cchunk.memblock);
 
             if (u->save_aec) {
                 if (u->captured_file)
-                    unused = fwrite(rdata, 1, u->blocksize, u->captured_file);
+                    unused = fwrite(rdata, 1, u->source_blocksize, u->captured_file);
                 if (u->played_file)
-                    unused = fwrite(pdata, 1, u->blocksize, u->played_file);
+                    unused = fwrite(pdata, 1, u->sink_blocksize, u->played_file);
             }
 
             /* perform echo cancellation */
@@ -848,7 +852,7 @@ static void do_push(struct userdata *u) {
 
             if (u->save_aec) {
                 if (u->canceled_file)
-                    unused = fwrite(cdata, 1, u->blocksize, u->canceled_file);
+                    unused = fwrite(cdata, 1, u->source_blocksize, u->canceled_file);
             }
 
             pa_memblock_release(cchunk.memblock);
@@ -856,7 +860,7 @@ static void do_push(struct userdata *u) {
             pa_memblock_release(rchunk.memblock);
 
             /* drop consumed sink samples */
-            pa_memblockq_drop(u->sink_memblockq, u->blocksize);
+            pa_memblockq_drop(u->sink_memblockq, u->sink_blocksize);
             pa_memblock_unref(pchunk.memblock);
 
             pa_memblock_unref(rchunk.memblock);
@@ -864,15 +868,15 @@ static void do_push(struct userdata *u) {
              * source */
             rchunk = cchunk;
 
-            plen -= u->blocksize;
+            plen -= u->sink_blocksize;
         }
 
         /* forward the (echo-canceled) data to the virtual source */
         pa_source_post(u->source, &rchunk);
         pa_memblock_unref(rchunk.memblock);
 
-        pa_memblockq_drop(u->source_memblockq, u->blocksize);
-        rlen -= u->blocksize;
+        pa_memblockq_drop(u->source_memblockq, u->source_blocksize);
+        rlen -= u->source_blocksize;
     }
 }
 
@@ -907,7 +911,7 @@ static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk)
     plen = pa_memblockq_get_length(u->sink_memblockq);
 
     /* Let's not do anything else till we have enough data to process */
-    if (rlen < u->blocksize)
+    if (rlen < u->source_blocksize)
         return;
 
     /* See if we need to drop samples in order to sync */
@@ -923,7 +927,7 @@ static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk)
          * means the only way to try to catch up is drop sink samples and let
          * the canceller cope up with this. */
         to_skip = rlen >= u->source_skip ? u->source_skip : rlen;
-        to_skip -= to_skip % u->blocksize;
+        to_skip -= to_skip % u->source_blocksize;
 
         if (to_skip) {
             pa_memblockq_peek_fixed_size(u->source_memblockq, to_skip, &rchunk);
@@ -936,9 +940,9 @@ static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk)
             u->source_skip -= to_skip;
         }
 
-        if (rlen && u->source_skip % u->blocksize) {
-            u->sink_skip += u->blocksize - (u->source_skip % u->blocksize);
-            u->source_skip -= (u->source_skip % u->blocksize);
+        if (rlen && u->source_skip % u->source_blocksize) {
+            u->sink_skip += (u->source_blocksize - (u->source_skip % u->source_blocksize)) * u->sink_blocksize / u->source_blocksize;
+            u->source_skip -= (u->source_skip % u->source_blocksize);
         }
     }
 
@@ -1730,10 +1734,14 @@ int pa__init(pa_module*m) {
     u->need_realign = TRUE;
 
     if (u->ec->init) {
-        if (!u->ec->init(u->core, u->ec, &source_ss, &source_map, &sink_ss, &sink_map, &u->blocksize, pa_modargs_get_value(ma, "aec_args", NULL))) {
+        uint32_t nframes = 0;
+        if (!u->ec->init(u->core, u->ec, &source_ss, &source_map, &sink_ss, &sink_map, &nframes, pa_modargs_get_value(ma, "aec_args", NULL))) {
             pa_log("Failed to init AEC engine");
             goto fail;
         }
+
+        u->source_blocksize = nframes * pa_frame_size(&source_ss);
+        u->sink_blocksize = nframes * pa_frame_size(&sink_ss);
     }
 
     if (u->ec->params.drift_compensation)
@@ -2071,6 +2079,7 @@ int main(int argc, char* argv[]) {
     int ret = 0, i;
     char c;
     float drift;
+    uint32_t nframes;
 
     pa_memzero(&u, sizeof(u));
 
@@ -2116,11 +2125,14 @@ int main(int argc, char* argv[]) {
     if (init_common(ma, &u, &source_ss, &source_map) < 0)
         goto fail;
 
-    if (!u.ec->init(u.core, u.ec, &source_ss, &source_map, &sink_ss, &sink_map, &u.blocksize,
+
+    if (!u.ec->init(u.core, u.ec, &source_ss, &source_map, &sink_ss, &sink_map, &nframes,
                      (argc > 5) ? argv[5] : NULL )) {
         pa_log("Failed to init AEC engine");
         goto fail;
     }
+    u.source_blocksize = nframes * pa_frame_size(&source_ss);
+    u.sink_blocksize = nframes * pa_frame_size(&sink_ss);
 
     if (u.ec->params.drift_compensation) {
         if (argc < 7) {
@@ -2136,20 +2148,20 @@ int main(int argc, char* argv[]) {
         }
     }
 
-    rdata = pa_xmalloc(u.blocksize);
-    pdata = pa_xmalloc(u.blocksize);
-    cdata = pa_xmalloc(u.blocksize);
+    rdata = pa_xmalloc(u.source_blocksize);
+    pdata = pa_xmalloc(u.sink_blocksize);
+    cdata = pa_xmalloc(u.source_blocksize);
 
     if (!u.ec->params.drift_compensation) {
-        while (fread(rdata, u.blocksize, 1, u.captured_file) > 0) {
-            if (fread(pdata, u.blocksize, 1, u.played_file) == 0) {
+        while (fread(rdata, u.source_blocksize, 1, u.captured_file) > 0) {
+            if (fread(pdata, u.sink_blocksize, 1, u.played_file) == 0) {
                 perror("Played file ended before captured file");
                 goto fail;
             }
 
             u.ec->run(u.ec, rdata, pdata, cdata);
 
-            unused = fwrite(cdata, u.blocksize, 1, u.canceled_file);
+            unused = fwrite(cdata, u.source_blocksize, 1, u.canceled_file);
         }
     } else {
         while (fscanf(u.drift_file, "%c", &c) > 0) {
diff --git a/src/modules/echo-cancel/null.c b/src/modules/echo-cancel/null.c
index 1820661..bfd6c30 100644
--- a/src/modules/echo-cancel/null.c
+++ b/src/modules/echo-cancel/null.c
@@ -28,8 +28,8 @@ PA_C_DECL_END
 pa_bool_t pa_null_ec_init(pa_core *c, pa_echo_canceller *ec,
                            pa_sample_spec *source_ss, pa_channel_map *source_map,
                            pa_sample_spec *sink_ss, pa_channel_map *sink_map,
-                           uint32_t *blocksize, const char *args) {
-    unsigned framelen = 256;
+                           uint32_t *nframes, const char *args) {
+    *nframes = 256;
 
     source_ss->format = PA_SAMPLE_S16NE;
     source_ss->channels = 1;
@@ -37,14 +37,13 @@ pa_bool_t pa_null_ec_init(pa_core *c, pa_echo_canceller *ec,
     *sink_ss = *source_ss;
     *sink_map = *source_map;
 
-    *blocksize = framelen * pa_frame_size(source_ss);
-
-    pa_log_debug("null AEC: framelen %u, blocksize %u, channels %d, rate %d", framelen, *blocksize, source_ss->channels, source_ss->rate);
+    pa_log_debug("null AEC: nframes %u, channels %d, rate %d", *nframes, source_ss->channels, source_ss->rate);
 
     return TRUE;
 }
 
 void pa_null_ec_run(pa_echo_canceller *ec, const uint8_t *rec, const uint8_t *play, uint8_t *out) {
+    // blocksize is nframes * frame-size
     memcpy(out, rec, 256 * 2);
 }
 
diff --git a/src/modules/echo-cancel/speex.c b/src/modules/echo-cancel/speex.c
index d6331fc..5ebd0b3 100644
--- a/src/modules/echo-cancel/speex.c
+++ b/src/modules/echo-cancel/speex.c
@@ -58,7 +58,7 @@ static void pa_speex_ec_fixate_spec(pa_sample_spec *source_ss, pa_channel_map *s
     *sink_map = *source_map;
 }
 
-static pa_bool_t pa_speex_ec_preprocessor_init(pa_echo_canceller *ec, pa_sample_spec *source_ss, uint32_t blocksize, pa_modargs *ma) {
+static pa_bool_t pa_speex_ec_preprocessor_init(pa_echo_canceller *ec, pa_sample_spec *source_ss, uint32_t nframes, pa_modargs *ma) {
     pa_bool_t agc;
     pa_bool_t denoise;
     pa_bool_t echo_suppress;
@@ -111,7 +111,7 @@ static pa_bool_t pa_speex_ec_preprocessor_init(pa_echo_canceller *ec, pa_sample_
             goto fail;
         }
 
-        ec->params.priv.speex.pp_state = speex_preprocess_state_init(blocksize / pa_frame_size(source_ss), source_ss->rate);
+        ec->params.priv.speex.pp_state = speex_preprocess_state_init(nframes, source_ss->rate);
 
         tmp = agc;
         speex_preprocess_ctl(ec->params.priv.speex.pp_state, SPEEX_PREPROCESS_SET_AGC, &tmp);
@@ -148,10 +148,10 @@ fail:
 pa_bool_t pa_speex_ec_init(pa_core *c, pa_echo_canceller *ec,
                            pa_sample_spec *source_ss, pa_channel_map *source_map,
                            pa_sample_spec *sink_ss, pa_channel_map *sink_map,
-                           uint32_t *blocksize, const char *args)
+                           uint32_t *nframes, const char *args)
 {
-    int framelen, y, rate;
-    uint32_t frame_size_ms, filter_size_ms;
+    int rate;
+    uint32_t y, frame_size_ms, filter_size_ms;
     pa_modargs *ma;
 
     if (!(ma = pa_modargs_new(args, valid_modargs))) {
@@ -174,25 +174,23 @@ pa_bool_t pa_speex_ec_init(pa_core *c, pa_echo_canceller *ec,
     pa_speex_ec_fixate_spec(source_ss, source_map, sink_ss, sink_map);
 
     rate = source_ss->rate;
-    framelen = (rate * frame_size_ms) / 1000;
-    /* framelen should be a power of 2, round down to nearest power of two */
-    y = 1 << ((8 * sizeof (int)) - 2);
-    while (y > framelen)
+    *nframes = (rate * frame_size_ms) / 1000;
+    /* nframes should be a power of 2, round down to nearest power of two */
+    y = 1 << ((8 * sizeof (uint32_t)) - 2);
+    while (y > *nframes)
       y >>= 1;
-    framelen = y;
+    *nframes = y;
 
-    *blocksize = framelen * pa_frame_size (source_ss);
+    pa_log_debug ("Using nframes %d, channels %d, rate %d", *nframes, source_ss->channels, source_ss->rate);
 
-    pa_log_debug ("Using framelen %d, blocksize %u, channels %d, rate %d", framelen, *blocksize, source_ss->channels, source_ss->rate);
-
-    ec->params.priv.speex.state = speex_echo_state_init_mc (framelen, (rate * filter_size_ms) / 1000, source_ss->channels, source_ss->channels);
+    ec->params.priv.speex.state = speex_echo_state_init_mc (*nframes, (rate * filter_size_ms) / 1000, source_ss->channels, source_ss->channels);
 
     if (!ec->params.priv.speex.state)
         goto fail;
 
     speex_echo_ctl(ec->params.priv.speex.state, SPEEX_ECHO_SET_SAMPLING_RATE, &rate);
 
-    if (!pa_speex_ec_preprocessor_init(ec, source_ss, *blocksize, ma))
+    if (!pa_speex_ec_preprocessor_init(ec, source_ss, *nframes, ma))
         goto fail;
 
     pa_modargs_free(ma);
diff --git a/src/modules/echo-cancel/webrtc.cc b/src/modules/echo-cancel/webrtc.cc
index 633b723..6ced28c 100644
--- a/src/modules/echo-cancel/webrtc.cc
+++ b/src/modules/echo-cancel/webrtc.cc
@@ -79,7 +79,7 @@ static int routing_mode_from_string(const char *rmode) {
 pa_bool_t pa_webrtc_ec_init(pa_core *c, pa_echo_canceller *ec,
                             pa_sample_spec *source_ss, pa_channel_map *source_map,
                             pa_sample_spec *sink_ss, pa_channel_map *sink_map,
-                            uint32_t *blocksize, const char *args)
+                            uint32_t *nframes, const char *args)
 {
     webrtc::AudioProcessing *apm = NULL;
     pa_bool_t hpf, ns, agc, dgc, mobile, cn;
@@ -216,7 +216,8 @@ pa_bool_t pa_webrtc_ec_init(pa_core *c, pa_echo_canceller *ec,
 
     ec->params.priv.webrtc.apm = apm;
     ec->params.priv.webrtc.sample_spec = *source_ss;
-    ec->params.priv.webrtc.blocksize = *blocksize = (uint64_t)pa_bytes_per_second(source_ss) * BLOCK_SIZE_US / PA_USEC_PER_SEC;
+    ec->params.priv.webrtc.blocksize = (uint64_t)pa_bytes_per_second(source_ss) * BLOCK_SIZE_US / PA_USEC_PER_SEC;
+    *nframes = ec->params.priv.webrtc.blocksize / pa_frame_size(source_ss);
 
     pa_modargs_free(ma);
     return TRUE;
-- 
1.7.9.5



More information about the pulseaudio-discuss mailing list