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