• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /***
2     This file is part of PulseAudio.
3 
4     Copyright 2010 Arun Raghavan <arun.raghavan@collabora.co.uk>
5 
6     PulseAudio is free software; you can redistribute it and/or modify
7     it under the terms of the GNU Lesser General Public License as published
8     by the Free Software Foundation; either version 2.1 of the License,
9     or (at your option) any later version.
10 
11     PulseAudio is distributed in the hope that it will be useful, but
12     WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14     General Public License for more details.
15 
16     You should have received a copy of the GNU Lesser General Public License
17     along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
18 ***/
19 
20 #ifndef fooechocancelhfoo
21 #define fooechocancelhfoo
22 
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26 
27 #include <pulse/sample.h>
28 #include <pulse/channelmap.h>
29 #include <pulsecore/core.h>
30 #include <pulsecore/macro.h>
31 
32 #ifdef HAVE_SPEEX
33 #include <speex/speex_echo.h>
34 #include <speex/speex_preprocess.h>
35 #endif
36 
37 #include "adrian.h"
38 
39 /* Common data structures */
40 
41 typedef struct pa_echo_canceller_msg pa_echo_canceller_msg;
42 
43 typedef struct pa_echo_canceller_params pa_echo_canceller_params;
44 
45 struct pa_echo_canceller_params {
46     union {
47         struct {
48             pa_sample_spec out_ss;
49         } null;
50 #ifdef HAVE_SPEEX
51         struct {
52             SpeexEchoState *state;
53             SpeexPreprocessState *pp_state;
54         } speex;
55 #endif
56 #ifdef HAVE_ADRIAN_EC
57         struct {
58             uint32_t blocksize;
59             AEC *aec;
60         } adrian;
61 #endif
62 #ifdef HAVE_WEBRTC
63         struct {
64             /* This is a void* so that we don't have to convert this whole file
65              * to C++ linkage. apm is a pointer to an AudioProcessing object */
66             void *apm;
67             unsigned int blocksize; /* in frames */
68             pa_sample_spec rec_ss, play_ss, out_ss;
69             float *rec_buffer[PA_CHANNELS_MAX], *play_buffer[PA_CHANNELS_MAX]; /* for deinterleaved buffers */
70             void *trace_callback;
71             bool agc;
72             bool first;
73             unsigned int agc_start_volume;
74         } webrtc;
75 #endif
76         /* each canceller-specific structure goes here */
77     };
78 
79     /* Set this if canceller can do drift compensation. Also see set_drift()
80      * below */
81     bool drift_compensation;
82 };
83 
84 typedef struct pa_echo_canceller pa_echo_canceller;
85 
86 struct pa_echo_canceller {
87     /* Initialise canceller engine. */
88     bool   (*init)                      (pa_core *c,
89                                          pa_echo_canceller *ec,
90                                          pa_sample_spec *rec_ss,
91                                          pa_channel_map *rec_map,
92                                          pa_sample_spec *play_ss,
93                                          pa_channel_map *play_map,
94                                          pa_sample_spec *out_ss,
95                                          pa_channel_map *out_map,
96                                          uint32_t *nframes,
97                                          const char *args);
98 
99     /* You should have only one of play()+record() or run() set. The first
100      * works under the assumption that you'll handle buffering and matching up
101      * samples yourself. If you set run(), module-echo-cancel will handle
102      * synchronising the playback and record streams. */
103 
104     /* Feed the engine 'nframes' playback frames. */
105     void        (*play)                 (pa_echo_canceller *ec, const uint8_t *play);
106     /* Feed the engine 'nframes' record frames. nframes processed frames are
107      * returned in out. */
108     void        (*record)               (pa_echo_canceller *ec, const uint8_t *rec, uint8_t *out);
109     /* Feed the engine nframes playback and record frames, with a reasonable
110      * effort at keeping the two in sync. nframes processed frames are
111      * returned in out. */
112     void        (*run)                  (pa_echo_canceller *ec, const uint8_t *rec, const uint8_t *play, uint8_t *out);
113 
114     /* Optional callback to set the drift, expressed as the ratio of the
115      * difference in number of playback and capture samples to the number of
116      * capture samples, for some instant of time. This is used only if the
117      * canceller signals that it supports drift compensation, and is called
118      * before record(). The actual implementation needs to derive drift based
119      * on point samples -- the individual values are not accurate enough to use
120      * as-is. */
121     /* NOTE: the semantics of this function might change in the future. */
122     void        (*set_drift)            (pa_echo_canceller *ec, float drift);
123 
124     /* Free up resources. */
125     void        (*done)                 (pa_echo_canceller *ec);
126 
127     /* Structure with common and engine-specific canceller parameters. */
128     pa_echo_canceller_params params;
129 
130     /* msgobject that can be used to send messages back to the main thread */
131     pa_echo_canceller_msg *msg;
132 };
133 
134 /* Functions to be used by the canceller analog gain control routines */
135 pa_volume_t pa_echo_canceller_get_capture_volume(pa_echo_canceller *ec);
136 void pa_echo_canceller_set_capture_volume(pa_echo_canceller *ec, pa_volume_t volume);
137 
138 /* Computes EC block size in frames (rounded down to nearest power-of-2) based
139  * on sample rate and milliseconds. */
140 uint32_t pa_echo_canceller_blocksize_power2(unsigned rate, unsigned ms);
141 
142 /* Null canceller functions */
143 bool pa_null_ec_init(pa_core *c, pa_echo_canceller *ec,
144                      pa_sample_spec *rec_ss, pa_channel_map *rec_map,
145                      pa_sample_spec *play_ss, pa_channel_map *play_map,
146                      pa_sample_spec *out_ss, pa_channel_map *out_map,
147                      uint32_t *nframes, const char *args);
148 void pa_null_ec_run(pa_echo_canceller *ec, const uint8_t *rec, const uint8_t *play, uint8_t *out);
149 void pa_null_ec_done(pa_echo_canceller *ec);
150 
151 #ifdef HAVE_SPEEX
152 /* Speex canceller functions */
153 bool pa_speex_ec_init(pa_core *c, pa_echo_canceller *ec,
154                       pa_sample_spec *rec_ss, pa_channel_map *rec_map,
155                       pa_sample_spec *play_ss, pa_channel_map *play_map,
156                       pa_sample_spec *out_ss, pa_channel_map *out_map,
157                       uint32_t *nframes, const char *args);
158 void pa_speex_ec_run(pa_echo_canceller *ec, const uint8_t *rec, const uint8_t *play, uint8_t *out);
159 void pa_speex_ec_done(pa_echo_canceller *ec);
160 #endif
161 
162 #ifdef HAVE_ADRIAN_EC
163 /* Adrian Andre's echo canceller */
164 bool pa_adrian_ec_init(pa_core *c, pa_echo_canceller *ec,
165                        pa_sample_spec *rec_ss, pa_channel_map *rec_map,
166                        pa_sample_spec *play_ss, pa_channel_map *play_map,
167                        pa_sample_spec *out_ss, pa_channel_map *out_map,
168                        uint32_t *nframes, const char *args);
169 void pa_adrian_ec_run(pa_echo_canceller *ec, const uint8_t *rec, const uint8_t *play, uint8_t *out);
170 void pa_adrian_ec_done(pa_echo_canceller *ec);
171 #endif
172 
173 #ifdef HAVE_WEBRTC
174 /* WebRTC canceller functions */
175 PA_C_DECL_BEGIN
176 bool pa_webrtc_ec_init(pa_core *c, pa_echo_canceller *ec,
177                        pa_sample_spec *rec_ss, pa_channel_map *rec_map,
178                        pa_sample_spec *play_ss, pa_channel_map *play_map,
179                        pa_sample_spec *out_ss, pa_channel_map *out_map,
180                        uint32_t *nframes, const char *args);
181 void pa_webrtc_ec_play(pa_echo_canceller *ec, const uint8_t *play);
182 void pa_webrtc_ec_record(pa_echo_canceller *ec, const uint8_t *rec, uint8_t *out);
183 void pa_webrtc_ec_set_drift(pa_echo_canceller *ec, float drift);
184 void pa_webrtc_ec_run(pa_echo_canceller *ec, const uint8_t *rec, const uint8_t *play, uint8_t *out);
185 void pa_webrtc_ec_done(pa_echo_canceller *ec);
186 PA_C_DECL_END
187 #endif
188 
189 #endif /* fooechocancelhfoo */
190