mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-11-04 13:29:59 -05:00
echo-cancel: Pass arguments to the specific canceller module
This allows us to tweak module parameters for whichever AEC module is chosen.
This commit is contained in:
parent
e7177680d1
commit
21001f49a4
3 changed files with 53 additions and 33 deletions
|
|
@ -46,7 +46,7 @@ struct pa_echo_canceller_params {
|
||||||
typedef struct pa_echo_canceller pa_echo_canceller;
|
typedef struct pa_echo_canceller pa_echo_canceller;
|
||||||
|
|
||||||
struct pa_echo_canceller {
|
struct pa_echo_canceller {
|
||||||
pa_bool_t (*init) (pa_echo_canceller *ec, pa_sample_spec ss, pa_channel_map map, uint32_t filter_size_ms, uint32_t frame_size_ms);
|
pa_bool_t (*init) (pa_echo_canceller *ec, pa_sample_spec ss, pa_channel_map map, const char *args);
|
||||||
void (*run) (pa_echo_canceller *ec, uint8_t *rec, uint8_t *play, uint8_t *out);
|
void (*run) (pa_echo_canceller *ec, uint8_t *rec, uint8_t *play, uint8_t *out);
|
||||||
void (*done) (pa_echo_canceller *ec);
|
void (*done) (pa_echo_canceller *ec);
|
||||||
uint32_t (*get_block_size) (pa_echo_canceller *ec);
|
uint32_t (*get_block_size) (pa_echo_canceller *ec);
|
||||||
|
|
@ -55,7 +55,7 @@ struct pa_echo_canceller {
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Speex canceller functions */
|
/* Speex canceller functions */
|
||||||
pa_bool_t pa_speex_ec_init(pa_echo_canceller *ec, pa_sample_spec ss, pa_channel_map map, uint32_t filter_size_ms, uint32_t frame_size_ms);
|
pa_bool_t pa_speex_ec_init(pa_echo_canceller *ec, pa_sample_spec ss, pa_channel_map map, const char *args);
|
||||||
void pa_speex_ec_run(pa_echo_canceller *ec, uint8_t *rec, uint8_t *play, uint8_t *out);
|
void pa_speex_ec_run(pa_echo_canceller *ec, uint8_t *rec, uint8_t *play, uint8_t *out);
|
||||||
void pa_speex_ec_done(pa_echo_canceller *ec);
|
void pa_speex_ec_done(pa_echo_canceller *ec);
|
||||||
uint32_t pa_speex_ec_get_block_size(pa_echo_canceller *ec);
|
uint32_t pa_speex_ec_get_block_size(pa_echo_canceller *ec);
|
||||||
|
|
|
||||||
|
|
@ -70,13 +70,12 @@ PA_MODULE_USAGE(
|
||||||
"sink_name=<name for the sink> "
|
"sink_name=<name for the sink> "
|
||||||
"sink_properties=<properties for the sink> "
|
"sink_properties=<properties for the sink> "
|
||||||
"sink_master=<name of sink to filter> "
|
"sink_master=<name of sink to filter> "
|
||||||
"frame_size_ms=<amount of data to process at one time> "
|
|
||||||
"filter_size_ms=<amount of echo to cancel> "
|
|
||||||
"adjust_time=<how often to readjust rates in s> "
|
"adjust_time=<how often to readjust rates in s> "
|
||||||
"format=<sample format> "
|
"format=<sample format> "
|
||||||
"rate=<sample rate> "
|
"rate=<sample rate> "
|
||||||
"channels=<number of channels> "
|
"channels=<number of channels> "
|
||||||
"channel_map=<channel map> "
|
"channel_map=<channel map> "
|
||||||
|
"aec_args=<parameters for the AEC engine> "
|
||||||
"save_aec=<save AEC data in /tmp> "
|
"save_aec=<save AEC data in /tmp> "
|
||||||
));
|
));
|
||||||
|
|
||||||
|
|
@ -97,11 +96,6 @@ static const pa_echo_canceller ec_table[] = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/* should be between 10-20 ms */
|
|
||||||
#define DEFAULT_FRAME_SIZE_MS 20
|
|
||||||
/* should be between 100-500 ms */
|
|
||||||
#define DEFAULT_FILTER_SIZE_MS 200
|
|
||||||
|
|
||||||
#define DEFAULT_ADJUST_TIME_USEC (1*PA_USEC_PER_SEC)
|
#define DEFAULT_ADJUST_TIME_USEC (1*PA_USEC_PER_SEC)
|
||||||
#define DEFAULT_SAVE_AEC 0
|
#define DEFAULT_SAVE_AEC 0
|
||||||
|
|
||||||
|
|
@ -154,7 +148,6 @@ struct userdata {
|
||||||
pa_core *core;
|
pa_core *core;
|
||||||
pa_module *module;
|
pa_module *module;
|
||||||
|
|
||||||
uint32_t frame_size_ms;
|
|
||||||
uint32_t save_aec;
|
uint32_t save_aec;
|
||||||
|
|
||||||
pa_echo_canceller *ec;
|
pa_echo_canceller *ec;
|
||||||
|
|
@ -199,13 +192,12 @@ static const char* const valid_modargs[] = {
|
||||||
"sink_name",
|
"sink_name",
|
||||||
"sink_properties",
|
"sink_properties",
|
||||||
"sink_master",
|
"sink_master",
|
||||||
"frame_size_ms",
|
|
||||||
"filter_size_ms",
|
|
||||||
"adjust_time",
|
"adjust_time",
|
||||||
"format",
|
"format",
|
||||||
"rate",
|
"rate",
|
||||||
"channels",
|
"channels",
|
||||||
"channel_map",
|
"channel_map",
|
||||||
|
"aec_args",
|
||||||
"save_aec",
|
"save_aec",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
@ -1287,7 +1279,6 @@ int pa__init(pa_module*m) {
|
||||||
pa_source_new_data source_data;
|
pa_source_new_data source_data;
|
||||||
pa_sink_new_data sink_data;
|
pa_sink_new_data sink_data;
|
||||||
pa_memchunk silence;
|
pa_memchunk silence;
|
||||||
uint32_t frame_size_ms, filter_size_ms;
|
|
||||||
uint32_t adjust_time_sec;
|
uint32_t adjust_time_sec;
|
||||||
|
|
||||||
pa_assert(m);
|
pa_assert(m);
|
||||||
|
|
@ -1309,18 +1300,6 @@ int pa__init(pa_module*m) {
|
||||||
}
|
}
|
||||||
pa_assert(sink_master);
|
pa_assert(sink_master);
|
||||||
|
|
||||||
frame_size_ms = DEFAULT_FRAME_SIZE_MS;
|
|
||||||
if (pa_modargs_get_value_u32(ma, "frame_size_ms", &frame_size_ms) < 0 || frame_size_ms < 1 || frame_size_ms > 200) {
|
|
||||||
pa_log("Invalid frame_size_ms specification");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
filter_size_ms = DEFAULT_FILTER_SIZE_MS;
|
|
||||||
if (pa_modargs_get_value_u32(ma, "filter_size_ms", &filter_size_ms) < 0 || filter_size_ms < 1 || filter_size_ms > 2000) {
|
|
||||||
pa_log("Invalid filter_size_ms specification");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
ss = source_master->sample_spec;
|
ss = source_master->sample_spec;
|
||||||
ss.format = PA_SAMPLE_S16LE;
|
ss.format = PA_SAMPLE_S16LE;
|
||||||
map = source_master->channel_map;
|
map = source_master->channel_map;
|
||||||
|
|
@ -1337,7 +1316,6 @@ int pa__init(pa_module*m) {
|
||||||
u->core = m->core;
|
u->core = m->core;
|
||||||
u->module = m;
|
u->module = m;
|
||||||
m->userdata = u;
|
m->userdata = u;
|
||||||
u->frame_size_ms = frame_size_ms;
|
|
||||||
|
|
||||||
u->ec = pa_xnew0(pa_echo_canceller, 1);
|
u->ec = pa_xnew0(pa_echo_canceller, 1);
|
||||||
if (!u->ec) {
|
if (!u->ec) {
|
||||||
|
|
@ -1369,7 +1347,7 @@ int pa__init(pa_module*m) {
|
||||||
u->asyncmsgq = pa_asyncmsgq_new(0);
|
u->asyncmsgq = pa_asyncmsgq_new(0);
|
||||||
u->need_realign = TRUE;
|
u->need_realign = TRUE;
|
||||||
if (u->ec->init) {
|
if (u->ec->init) {
|
||||||
if (!u->ec->init(u->ec, ss, map, filter_size_ms, frame_size_ms)) {
|
if (!u->ec->init(u->ec, ss, map, pa_modargs_get_value(ma, "aec_args", NULL))) {
|
||||||
pa_log("Failed to init AEC engine");
|
pa_log("Failed to init AEC engine");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,11 +21,46 @@
|
||||||
USA.
|
USA.
|
||||||
***/
|
***/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <pulsecore/modargs.h>
|
||||||
#include "echo-cancel.h"
|
#include "echo-cancel.h"
|
||||||
|
|
||||||
pa_bool_t pa_speex_ec_init(pa_echo_canceller *ec, pa_sample_spec ss, pa_channel_map map, uint32_t filter_size_ms, uint32_t frame_size_ms)
|
/* should be between 10-20 ms */
|
||||||
|
#define DEFAULT_FRAME_SIZE_MS 20
|
||||||
|
/* should be between 100-500 ms */
|
||||||
|
#define DEFAULT_FILTER_SIZE_MS 200
|
||||||
|
|
||||||
|
static const char* const valid_modargs[] = {
|
||||||
|
"frame_size_ms",
|
||||||
|
"filter_size_ms",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
pa_bool_t pa_speex_ec_init(pa_echo_canceller *ec, pa_sample_spec ss, pa_channel_map map, const char *args)
|
||||||
{
|
{
|
||||||
int framelen, y, rate = ss.rate;
|
int framelen, y, rate = ss.rate;
|
||||||
|
uint32_t frame_size_ms, filter_size_ms;
|
||||||
|
pa_modargs *ma;
|
||||||
|
|
||||||
|
if (!(ma = pa_modargs_new(args, valid_modargs))) {
|
||||||
|
pa_log("Failed to parse submodule arguments.");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
filter_size_ms = DEFAULT_FILTER_SIZE_MS;
|
||||||
|
if (pa_modargs_get_value_u32(ma, "filter_size_ms", &filter_size_ms) < 0 || filter_size_ms < 1 || filter_size_ms > 2000) {
|
||||||
|
pa_log("Invalid filter_size_ms specification");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
frame_size_ms = DEFAULT_FRAME_SIZE_MS;
|
||||||
|
if (pa_modargs_get_value_u32(ma, "frame_size_ms", &frame_size_ms) < 0 || frame_size_ms < 1 || frame_size_ms > 200) {
|
||||||
|
pa_log("Invalid frame_size_ms specification");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
framelen = (rate * frame_size_ms) / 1000;
|
framelen = (rate * frame_size_ms) / 1000;
|
||||||
/* framelen should be a power of 2, round down to nearest power of two */
|
/* framelen should be a power of 2, round down to nearest power of two */
|
||||||
|
|
@ -40,11 +75,18 @@ pa_bool_t pa_speex_ec_init(pa_echo_canceller *ec, pa_sample_spec ss, pa_channel_
|
||||||
|
|
||||||
ec->params.priv.speex.state = speex_echo_state_init_mc (framelen, (rate * filter_size_ms) / 1000, ss.channels, ss.channels);
|
ec->params.priv.speex.state = speex_echo_state_init_mc (framelen, (rate * filter_size_ms) / 1000, ss.channels, ss.channels);
|
||||||
|
|
||||||
if (ec->params.priv.speex.state) {
|
if (!ec->params.priv.speex.state)
|
||||||
speex_echo_ctl(ec->params.priv.speex.state, SPEEX_ECHO_SET_SAMPLING_RATE, &rate);
|
goto fail;
|
||||||
return TRUE;
|
|
||||||
} else
|
speex_echo_ctl(ec->params.priv.speex.state, SPEEX_ECHO_SET_SAMPLING_RATE, &rate);
|
||||||
return FALSE;
|
|
||||||
|
pa_modargs_free(ma);
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
if (ma)
|
||||||
|
pa_modargs_free(ma);
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pa_speex_ec_run(pa_echo_canceller *ec, uint8_t *rec, uint8_t *play, uint8_t *out)
|
void pa_speex_ec_run(pa_echo_canceller *ec, uint8_t *rec, uint8_t *play, uint8_t *out)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue