[pulseaudio-discuss] [PATCHv4 1/2] echo-cancel: Enable different blocksizes for sink and source
Stefan Huber
s.huber at bct-electronic.com
Thu Dec 20 02:33:04 PST 2012
Hi Tanu,
thanks for applying the first three patches. I incorporated your
suggestions and a bit more, see details below. The following two updated
patches apply against mainline/master.
Changes to "[PATCHv3 3/5] echo-cancel: Enable different blocksizes for
sink and source":
On Thu 20.12.12 10:59, Tanu Kaskinen wrote:
> On Wed, 2012-12-19 at 13:08 +0100, Stefan Huber wrote:
> >
> > +
>
> Extra empty line added.
Fixed.
> > - 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);
>
> Extra space added
Fixed.
> > +
> > +
>
> We don't use double empty lines. One is enough. And in this case, in my
> opinion the original of zero empty lines is best, because the comment
> applies only to the drift calculation, not anything after that (an empty
> line would be appropriate if the comment would apply to more than only
> the immediately following group of code).
Fixed.
> > - 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;
>
> Is the multiplication totally safe? It doesn't seem unconceivable that
> multiplying two blocksizes could some day overflow the 32-bit space. A
> cast to uint64_t should probably be added.
Good point. Added a cast to (uint64_t) in order to support blocksizes up
to 2^32-1 instead of 2^16-1.
In addition, I fixed:
- an added newline introduced by the previous patch version and
- a ".." in a comment in the original code basis (@@ -94)
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 | 101 ++++++++++++++------------
src/modules/echo-cancel/null.c | 9 +--
src/modules/echo-cancel/speex.c | 28 ++++---
src/modules/echo-cancel/webrtc.cc | 5 +-
6 files changed, 88 insertions(+), 84 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..9f14ade 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..adac66e 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;
@@ -417,7 +418,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;
@@ -735,8 +736,8 @@ static void do_push_drift_comp(struct userdata *u) {
* 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 +748,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 +757,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 +785,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 +800,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 +819,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 +833,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 +849,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 +857,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 +865,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 +908,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 +924,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 +937,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 += (uint64_t)(u->source_blocksize - (u->source_skip % u->source_blocksize)) * u->sink_blocksize / u->source_blocksize;
+ u->source_skip -= (u->source_skip % u->source_blocksize);
}
}
@@ -1640,6 +1641,7 @@ int pa__init(pa_module*m) {
pa_sink_new_data sink_data;
pa_memchunk silence;
uint32_t temp;
+ uint32_t nframes=0;
pa_assert(m);
@@ -1729,13 +1731,15 @@ int pa__init(pa_module*m) {
u->asyncmsgq = pa_asyncmsgq_new(0);
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))) {
- pa_log("Failed to init AEC engine");
- goto fail;
- }
+ pa_assert(u->ec->init);
+ 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)
pa_assert(u->ec->set_drift);
@@ -2071,6 +2075,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 +2121,13 @@ 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 +2143,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