[alsa-devel] ALSA 1.0.20 Speex PCM Plugin
Robert Krakora
rob.krakora at messagenetsystems.com
Wed Jun 10 23:36:20 CEST 2009
On Tue, Jun 9, 2009 at 4:07 AM, Takashi Iwai<tiwai at suse.de> wrote:
> At Mon, 8 Jun 2009 15:56:38 -0400,
> Robert Krakora wrote:
>>
>> Takashi:
>>
>> I applied your Speex echo cancellation patch. I had to modify it
>> since the 'buf_out' buffer was not being malloc'd. Attached are the
>> files affected by your patch. The echo cancellation seems to work
>> pretty well. However, turning on 'denoise' seems to cause audio to
>> drop in and out at a very periodic rate. Do you have any example of
>> how to set up all of the parameters? A tutorial or something? Thanks
>> again.
>
> No idea, I just wrote it up blindly :)
> Can the preprocessor be dropped, possibly, like the patch below?
>
>
> Takashi
>
> ---
> diff --git a/doc/speexdsp.txt b/doc/speexdsp.txt
> index 875fc19..5b5e5a0 100644
> --- a/doc/speexdsp.txt
> +++ b/doc/speexdsp.txt
> @@ -12,7 +12,7 @@ using libspeex DSP API. You can use the plugin with the plugin type
>
> Then record like
>
> - % arecord -fdat -c1 -Dplug:speex foo.wav
> + % arecord -fdat -c1 -Dplug:my_pcm foo.wav
>
> so that you'll get 48kHz mono stream with the denoising effect.
>
> @@ -44,6 +44,15 @@ The following parameters can be set optionally:
>
> A boolean value to enable/disable dereverb function. Default is no.
>
> +* echo
> +
> + A boolean value to enable/disable echo-cancellation function.
> + Default is no.
> +
> +* filter_length
> +
> + Number of samples of echo to cancel. As default it's 256.
> +
> For example, you can enable agc like
>
> pcm.my_pcm {
> diff --git a/speex/pcm_speex.c b/speex/pcm_speex.c
> index 7bb9213..757a400 100644
> --- a/speex/pcm_speex.c
> +++ b/speex/pcm_speex.c
> @@ -1,5 +1,5 @@
> /*
> - * Speex preprocess plugin
> + * Speex DSP plugin
> *
> * Copyright (c) 2009 by Takashi Iwai <tiwai at suse.de>
> *
> @@ -21,12 +21,15 @@
> #include <alsa/asoundlib.h>
> #include <alsa/pcm_external.h>
> #include <speex/speex_preprocess.h>
> +#include <speex/speex_echo.h>
>
> -/* preprocessing parameters */
> +/* DSP parameters */
> struct spx_parms {
> int frames;
> int denoise;
> int agc;
> + int echo;
> + int filter_length;
> float agc_level;
> int dereverb;
> float dereverb_decay;
> @@ -38,7 +41,9 @@ typedef struct {
> struct spx_parms parms;
> /* instance and intermedate buffer */
> SpeexPreprocessState *state;
> + SpeexEchoState *echo_state;
> short *buf;
> + short *outbuf;
> /* running states */
> unsigned int filled;
> unsigned int processed;
> @@ -64,6 +69,18 @@ spx_transfer(snd_pcm_extplug_t *ext,
> short *src = area_addr(src_areas, src_offset);
> short *dst = area_addr(dst_areas, dst_offset);
> unsigned int count = size;
> + short *databuf;
> +
> + if (!spx->state && !spx->echo_state) {
> + /* no DSP processing */
> + memcpy(dst, src, count * 2);
> + return size;
> + }
> +
> + if (spx->echo_state)
> + databuf = spx->outbuf;
> + else
> + databuf = spx->buf;
>
> while (count > 0) {
> unsigned int chunk;
> @@ -72,14 +89,20 @@ spx_transfer(snd_pcm_extplug_t *ext,
> else
> chunk = count;
> if (spx->processed)
> - memcpy(dst, spx->buf + spx->filled, chunk * 2);
> + memcpy(dst, databuf + spx->filled, chunk * 2);
> else
> memset(dst, 0, chunk * 2);
> dst += chunk;
> memcpy(spx->buf + spx->filled, src, chunk * 2);
> spx->filled += chunk;
> if (spx->filled == spx->parms.frames) {
> - speex_preprocess_run(spx->state, spx->buf);
> + if (spx->echo_state)
> + speex_echo_capture(spx->echo_state, spx->buf,
> + spx->outbuf);
> + if (spx->state)
> + speex_preprocess_run(spx->state, databuf);
> + if (spx->echo_state)
> + speex_echo_playback(spx->echo_state, databuf);
> spx->processed = 1;
> spx->filled = 0;
> }
> @@ -94,6 +117,9 @@ static int spx_init(snd_pcm_extplug_t *ext)
> {
> snd_pcm_speex_t *spx = (snd_pcm_speex_t *)ext;
>
> + spx->filled = 0;
> + spx->processed = 0;
> +
> if (!spx->buf) {
> spx->buf = malloc(spx->parms.frames * 2);
> if (!spx->buf)
> @@ -101,12 +127,43 @@ static int spx_init(snd_pcm_extplug_t *ext)
> }
> memset(spx->buf, 0, spx->parms.frames * 2);
>
> - if (spx->state)
> + if (!spx->outbuf) {
> + spx->outbuf = malloc(spx->parms.frames * 2);
> + if (!spx->outbuf)
> + return -ENOMEM;
> + }
> + memset(spx->outbuf, 0, spx->parms.frames * 2);
> +
> + if (spx->state) {
> speex_preprocess_state_destroy(spx->state);
> + spx->state = NULL;
> + }
> + if (spx->echo_state) {
> + speex_echo_state_destroy(spx->echo_state);
> + spx->echo_state = NULL;
> + }
> +
> + if (spx->parms.echo) {
> + spx->echo_state = speex_echo_state_init(spx->parms.frames,
> + spx->parms.filter_length);
> + if (!spx->echo_state)
> + return -EIO;
> + speex_echo_ctl(spx->echo_state, SPEEX_ECHO_SET_SAMPLING_RATE,
> + &spx->ext.rate);
> + }
> +
> + /* no preprocessor? */
> + if (!spx->parms.denoise && !spx->parms.agc && !spx->parms.dereverb)
> + return 0;
> +
> spx->state = speex_preprocess_state_init(spx->parms.frames,
> spx->ext.rate);
> if (!spx->state)
> return -EIO;
> + if (spx->echo_state)
> + speex_preprocess_ctl(spx->state,
> + SPEEX_PREPROCESS_SET_ECHO_STATE,
> + spx->echo_state);
>
> speex_preprocess_ctl(spx->state, SPEEX_PREPROCESS_SET_DENOISE,
> &spx->parms.denoise);
> @@ -120,18 +177,18 @@ static int spx_init(snd_pcm_extplug_t *ext)
> &spx->parms.dereverb_decay);
> speex_preprocess_ctl(spx->state, SPEEX_PREPROCESS_SET_DEREVERB_LEVEL,
> &spx->parms.dereverb_level);
> -
> - spx->filled = 0;
> - spx->processed = 0;
> return 0;
> }
>
> static int spx_close(snd_pcm_extplug_t *ext)
> {
> snd_pcm_speex_t *spx = (snd_pcm_speex_t *)ext;
> + free(spx->outbuf);
> free(spx->buf);
> if (spx->state)
> speex_preprocess_state_destroy(spx->state);
> + if (spx->echo_state)
> + speex_echo_state_destroy(spx->echo_state);
> return 0;
> }
>
> @@ -205,6 +262,8 @@ SND_PCM_PLUGIN_DEFINE_FUNC(speex)
> .dereverb = 0,
> .dereverb_decay = 0,
> .dereverb_level = 0,
> + .echo = 0,
> + .filter_length = 256,
> };
>
> snd_config_for_each(i, next, conf) {
> @@ -242,6 +301,13 @@ SND_PCM_PLUGIN_DEFINE_FUNC(speex)
> &parms.dereverb_level);
> if (err)
> goto ok;
> + err = get_bool_parm(n, id, "echo", &parms.echo);
> + if (err)
> + goto ok;
> + err = get_int_parm(n, id, "filter_length",
> + &parms.filter_length);
> + if (err)
> + goto ok;
> SNDERR("Unknown field %s", id);
> err = -EINVAL;
> ok:
> @@ -259,7 +325,7 @@ SND_PCM_PLUGIN_DEFINE_FUNC(speex)
> return -ENOMEM;
>
> spx->ext.version = SND_PCM_EXTPLUG_VERSION;
> - spx->ext.name = "Speex Denoise Plugin";
> + spx->ext.name = "Speex DSP Plugin";
> spx->ext.callback = &speex_callback;
> spx->ext.private_data = spx;
> spx->parms = parms;
>
>
Takashi:
Finally, I have your patch applied successfully and all seems to be
working well. See the attached files.
Best Regards,
--
Rob Krakora
Senior Software Engineer
MessageNet Systems
101 East Carmel Dr. Suite 105
Carmel, IN 46032
(317)566-1677 Ext. 206
(317)663-0808 Fax
-------------- next part --------------
A non-text attachment was scrubbed...
Name: chan_alsa.c
Type: text/x-csrc
Size: 35531 bytes
Desc: not available
Url : http://mailman.alsa-project.org/pipermail/alsa-devel/attachments/20090610/5203fe0c/attachment-0001.c
-------------- next part --------------
A non-text attachment was scrubbed...
Name: asound.conf
Type: application/octet-stream
Size: 1184 bytes
Desc: not available
Url : http://mailman.alsa-project.org/pipermail/alsa-devel/attachments/20090610/5203fe0c/attachment-0001.dll
More information about the Alsa-devel
mailing list