mirror of
				https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
				synced 2025-11-03 09:01:50 -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
							
								
									57c5983937
								
							
						
					
					
						commit
						668f4e49b6
					
				
					 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;
 | 
			
		||||
 | 
			
		||||
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        (*done)                 (pa_echo_canceller *ec);
 | 
			
		||||
    uint32_t    (*get_block_size)       (pa_echo_canceller *ec);
 | 
			
		||||
| 
						 | 
				
			
			@ -55,7 +55,7 @@ struct pa_echo_canceller {
 | 
			
		|||
};
 | 
			
		||||
 | 
			
		||||
/* 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_done(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_properties=<properties for the sink> "
 | 
			
		||||
          "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> "
 | 
			
		||||
          "format=<sample format> "
 | 
			
		||||
          "rate=<sample rate> "
 | 
			
		||||
          "channels=<number of channels> "
 | 
			
		||||
          "channel_map=<channel map> "
 | 
			
		||||
          "aec_args=<parameters for the AEC engine> "
 | 
			
		||||
          "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_SAVE_AEC 0
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -154,7 +148,6 @@ struct userdata {
 | 
			
		|||
    pa_core *core;
 | 
			
		||||
    pa_module *module;
 | 
			
		||||
 | 
			
		||||
    uint32_t frame_size_ms;
 | 
			
		||||
    uint32_t save_aec;
 | 
			
		||||
 | 
			
		||||
    pa_echo_canceller *ec;
 | 
			
		||||
| 
						 | 
				
			
			@ -199,13 +192,12 @@ static const char* const valid_modargs[] = {
 | 
			
		|||
    "sink_name",
 | 
			
		||||
    "sink_properties",
 | 
			
		||||
    "sink_master",
 | 
			
		||||
    "frame_size_ms",
 | 
			
		||||
    "filter_size_ms",
 | 
			
		||||
    "adjust_time",
 | 
			
		||||
    "format",
 | 
			
		||||
    "rate",
 | 
			
		||||
    "channels",
 | 
			
		||||
    "channel_map",
 | 
			
		||||
    "aec_args",
 | 
			
		||||
    "save_aec",
 | 
			
		||||
    NULL
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -1287,7 +1279,6 @@ int pa__init(pa_module*m) {
 | 
			
		|||
    pa_source_new_data source_data;
 | 
			
		||||
    pa_sink_new_data sink_data;
 | 
			
		||||
    pa_memchunk silence;
 | 
			
		||||
    uint32_t frame_size_ms, filter_size_ms;
 | 
			
		||||
    uint32_t adjust_time_sec;
 | 
			
		||||
 | 
			
		||||
    pa_assert(m);
 | 
			
		||||
| 
						 | 
				
			
			@ -1309,18 +1300,6 @@ int pa__init(pa_module*m) {
 | 
			
		|||
    }
 | 
			
		||||
    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.format = PA_SAMPLE_S16LE;
 | 
			
		||||
    map = source_master->channel_map;
 | 
			
		||||
| 
						 | 
				
			
			@ -1337,7 +1316,6 @@ int pa__init(pa_module*m) {
 | 
			
		|||
    u->core = m->core;
 | 
			
		||||
    u->module = m;
 | 
			
		||||
    m->userdata = u;
 | 
			
		||||
    u->frame_size_ms = frame_size_ms;
 | 
			
		||||
 | 
			
		||||
    u->ec = pa_xnew0(pa_echo_canceller, 1);
 | 
			
		||||
    if (!u->ec) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1369,7 +1347,7 @@ 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->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");
 | 
			
		||||
            goto fail;
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,11 +21,46 @@
 | 
			
		|||
    USA.
 | 
			
		||||
***/
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_CONFIG_H
 | 
			
		||||
#include <config.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <pulsecore/modargs.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;
 | 
			
		||||
    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 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);
 | 
			
		||||
 | 
			
		||||
    if (ec->params.priv.speex.state) {
 | 
			
		||||
	speex_echo_ctl(ec->params.priv.speex.state, SPEEX_ECHO_SET_SAMPLING_RATE, &rate);
 | 
			
		||||
	return TRUE;
 | 
			
		||||
    } else
 | 
			
		||||
	return FALSE;
 | 
			
		||||
    if (!ec->params.priv.speex.state)
 | 
			
		||||
	goto fail;
 | 
			
		||||
 | 
			
		||||
    speex_echo_ctl(ec->params.priv.speex.state, SPEEX_ECHO_SET_SAMPLING_RATE, &rate);
 | 
			
		||||
 | 
			
		||||
    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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue