]>
code.delx.au - pulseaudio/blob - src/modules/echo-cancel/adrian.c
2 This file is part of PulseAudio.
4 Copyright 2010 Arun Raghavan <arun.raghavan@collabora.co.uk>
6 Contributor: Wim Taymans <wim.taymans@gmail.com>
8 The actual implementation is taken from the sources at
9 http://andreadrian.de/intercom/ - for the license, look for
10 adrian-license.txt in the same directory as this file.
12 PulseAudio is free software; you can redistribute it and/or modify
13 it under the terms of the GNU Lesser General Public License as published
14 by the Free Software Foundation; either version 2.1 of the License,
15 or (at your option) any later version.
17 PulseAudio is distributed in the hope that it will be useful, but
18 WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 General Public License for more details.
22 You should have received a copy of the GNU Lesser General Public License
23 along with PulseAudio; if not, write to the Free Software
24 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
32 #include <pulsecore/modargs.h>
33 #include "echo-cancel.h"
35 /* should be between 10-20 ms */
36 #define DEFAULT_FRAME_SIZE_MS 20
38 static const char* const valid_modargs
[] = {
43 static void pa_adrian_ec_fixate_spec(pa_sample_spec
*source_ss
, pa_channel_map
*source_map
,
44 pa_sample_spec
*sink_ss
, pa_channel_map
*sink_map
)
46 source_ss
->format
= PA_SAMPLE_S16LE
;
47 source_ss
->channels
= 1;
48 pa_channel_map_init_mono(source_map
);
50 *sink_ss
= *source_ss
;
51 *sink_map
= *source_map
;
54 pa_bool_t
pa_adrian_ec_init(pa_echo_canceller
*ec
,
55 pa_sample_spec
*source_ss
, pa_channel_map
*source_map
,
56 pa_sample_spec
*sink_ss
, pa_channel_map
*sink_map
,
60 uint32_t frame_size_ms
;
63 if (!(ma
= pa_modargs_new(args
, valid_modargs
))) {
64 pa_log("Failed to parse submodule arguments.");
68 frame_size_ms
= DEFAULT_FRAME_SIZE_MS
;
69 if (pa_modargs_get_value_u32(ma
, "frame_size_ms", &frame_size_ms
) < 0 || frame_size_ms
< 1 || frame_size_ms
> 200) {
70 pa_log("Invalid frame_size_ms specification");
74 pa_adrian_ec_fixate_spec(source_ss
, source_map
, sink_ss
, sink_map
);
76 rate
= source_ss
->rate
;
77 framelen
= (rate
* frame_size_ms
) / 1000;
79 ec
->params
.priv
.adrian
.blocksize
= framelen
* pa_frame_size (source_ss
);
81 pa_log_debug ("Using framelen %d, blocksize %lld, channels %d, rate %d", framelen
, (long long) ec
->params
.priv
.adrian
.blocksize
, source_ss
->channels
, source_ss
->rate
);
83 ec
->params
.priv
.adrian
.aec
= AEC_init(rate
);
84 if (!ec
->params
.priv
.adrian
.aec
)
96 void pa_adrian_ec_run(pa_echo_canceller
*ec
, uint8_t *rec
, uint8_t *play
, uint8_t *out
)
100 for (i
= 0; i
< ec
->params
.priv
.adrian
.blocksize
; i
+= 2) {
101 /* We know it's S16LE mono data */
102 int r
= (((int8_t) rec
[i
+ 1]) << 8) | rec
[i
];
103 int p
= (((int8_t) play
[i
+ 1]) << 8) | play
[i
];
106 res
= AEC_doAEC(ec
->params
.priv
.adrian
.aec
, r
, p
);
107 out
[i
] = (uint8_t) (res
& 0xff);
108 out
[i
+ 1] = (uint8_t) ((res
>> 8) & 0xff);
112 void pa_adrian_ec_done(pa_echo_canceller
*ec
)
114 pa_xfree(ec
->params
.priv
.adrian
.aec
);
115 ec
->params
.priv
.adrian
.aec
= NULL
;
118 uint32_t pa_adrian_ec_get_block_size(pa_echo_canceller
*ec
)
120 return ec
->params
.priv
.adrian
.blocksize
;