153a5a1b3Sopenharmony_ci/***
253a5a1b3Sopenharmony_ci    This file is part of PulseAudio.
353a5a1b3Sopenharmony_ci
453a5a1b3Sopenharmony_ci    Copyright 2010 Arun Raghavan <arun.raghavan@collabora.co.uk>
553a5a1b3Sopenharmony_ci
653a5a1b3Sopenharmony_ci    PulseAudio is free software; you can redistribute it and/or modify
753a5a1b3Sopenharmony_ci    it under the terms of the GNU Lesser General Public License as published
853a5a1b3Sopenharmony_ci    by the Free Software Foundation; either version 2.1 of the License,
953a5a1b3Sopenharmony_ci    or (at your option) any later version.
1053a5a1b3Sopenharmony_ci
1153a5a1b3Sopenharmony_ci    PulseAudio is distributed in the hope that it will be useful, but
1253a5a1b3Sopenharmony_ci    WITHOUT ANY WARRANTY; without even the implied warranty of
1353a5a1b3Sopenharmony_ci    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1453a5a1b3Sopenharmony_ci    General Public License for more details.
1553a5a1b3Sopenharmony_ci
1653a5a1b3Sopenharmony_ci    You should have received a copy of the GNU Lesser General Public License
1753a5a1b3Sopenharmony_ci    along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
1853a5a1b3Sopenharmony_ci***/
1953a5a1b3Sopenharmony_ci
2053a5a1b3Sopenharmony_ci#ifndef fooechocancelhfoo
2153a5a1b3Sopenharmony_ci#define fooechocancelhfoo
2253a5a1b3Sopenharmony_ci
2353a5a1b3Sopenharmony_ci#ifdef HAVE_CONFIG_H
2453a5a1b3Sopenharmony_ci#include <config.h>
2553a5a1b3Sopenharmony_ci#endif
2653a5a1b3Sopenharmony_ci
2753a5a1b3Sopenharmony_ci#include <pulse/sample.h>
2853a5a1b3Sopenharmony_ci#include <pulse/channelmap.h>
2953a5a1b3Sopenharmony_ci#include <pulsecore/core.h>
3053a5a1b3Sopenharmony_ci#include <pulsecore/macro.h>
3153a5a1b3Sopenharmony_ci
3253a5a1b3Sopenharmony_ci#ifdef HAVE_SPEEX
3353a5a1b3Sopenharmony_ci#include <speex/speex_echo.h>
3453a5a1b3Sopenharmony_ci#include <speex/speex_preprocess.h>
3553a5a1b3Sopenharmony_ci#endif
3653a5a1b3Sopenharmony_ci
3753a5a1b3Sopenharmony_ci#include "adrian.h"
3853a5a1b3Sopenharmony_ci
3953a5a1b3Sopenharmony_ci/* Common data structures */
4053a5a1b3Sopenharmony_ci
4153a5a1b3Sopenharmony_citypedef struct pa_echo_canceller_msg pa_echo_canceller_msg;
4253a5a1b3Sopenharmony_ci
4353a5a1b3Sopenharmony_citypedef struct pa_echo_canceller_params pa_echo_canceller_params;
4453a5a1b3Sopenharmony_ci
4553a5a1b3Sopenharmony_cistruct pa_echo_canceller_params {
4653a5a1b3Sopenharmony_ci    union {
4753a5a1b3Sopenharmony_ci        struct {
4853a5a1b3Sopenharmony_ci            pa_sample_spec out_ss;
4953a5a1b3Sopenharmony_ci        } null;
5053a5a1b3Sopenharmony_ci#ifdef HAVE_SPEEX
5153a5a1b3Sopenharmony_ci        struct {
5253a5a1b3Sopenharmony_ci            SpeexEchoState *state;
5353a5a1b3Sopenharmony_ci            SpeexPreprocessState *pp_state;
5453a5a1b3Sopenharmony_ci        } speex;
5553a5a1b3Sopenharmony_ci#endif
5653a5a1b3Sopenharmony_ci#ifdef HAVE_ADRIAN_EC
5753a5a1b3Sopenharmony_ci        struct {
5853a5a1b3Sopenharmony_ci            uint32_t blocksize;
5953a5a1b3Sopenharmony_ci            AEC *aec;
6053a5a1b3Sopenharmony_ci        } adrian;
6153a5a1b3Sopenharmony_ci#endif
6253a5a1b3Sopenharmony_ci#ifdef HAVE_WEBRTC
6353a5a1b3Sopenharmony_ci        struct {
6453a5a1b3Sopenharmony_ci            /* This is a void* so that we don't have to convert this whole file
6553a5a1b3Sopenharmony_ci             * to C++ linkage. apm is a pointer to an AudioProcessing object */
6653a5a1b3Sopenharmony_ci            void *apm;
6753a5a1b3Sopenharmony_ci            unsigned int blocksize; /* in frames */
6853a5a1b3Sopenharmony_ci            pa_sample_spec rec_ss, play_ss, out_ss;
6953a5a1b3Sopenharmony_ci            float *rec_buffer[PA_CHANNELS_MAX], *play_buffer[PA_CHANNELS_MAX]; /* for deinterleaved buffers */
7053a5a1b3Sopenharmony_ci            void *trace_callback;
7153a5a1b3Sopenharmony_ci            bool agc;
7253a5a1b3Sopenharmony_ci            bool first;
7353a5a1b3Sopenharmony_ci            unsigned int agc_start_volume;
7453a5a1b3Sopenharmony_ci        } webrtc;
7553a5a1b3Sopenharmony_ci#endif
7653a5a1b3Sopenharmony_ci        /* each canceller-specific structure goes here */
7753a5a1b3Sopenharmony_ci    };
7853a5a1b3Sopenharmony_ci
7953a5a1b3Sopenharmony_ci    /* Set this if canceller can do drift compensation. Also see set_drift()
8053a5a1b3Sopenharmony_ci     * below */
8153a5a1b3Sopenharmony_ci    bool drift_compensation;
8253a5a1b3Sopenharmony_ci};
8353a5a1b3Sopenharmony_ci
8453a5a1b3Sopenharmony_citypedef struct pa_echo_canceller pa_echo_canceller;
8553a5a1b3Sopenharmony_ci
8653a5a1b3Sopenharmony_cistruct pa_echo_canceller {
8753a5a1b3Sopenharmony_ci    /* Initialise canceller engine. */
8853a5a1b3Sopenharmony_ci    bool   (*init)                      (pa_core *c,
8953a5a1b3Sopenharmony_ci                                         pa_echo_canceller *ec,
9053a5a1b3Sopenharmony_ci                                         pa_sample_spec *rec_ss,
9153a5a1b3Sopenharmony_ci                                         pa_channel_map *rec_map,
9253a5a1b3Sopenharmony_ci                                         pa_sample_spec *play_ss,
9353a5a1b3Sopenharmony_ci                                         pa_channel_map *play_map,
9453a5a1b3Sopenharmony_ci                                         pa_sample_spec *out_ss,
9553a5a1b3Sopenharmony_ci                                         pa_channel_map *out_map,
9653a5a1b3Sopenharmony_ci                                         uint32_t *nframes,
9753a5a1b3Sopenharmony_ci                                         const char *args);
9853a5a1b3Sopenharmony_ci
9953a5a1b3Sopenharmony_ci    /* You should have only one of play()+record() or run() set. The first
10053a5a1b3Sopenharmony_ci     * works under the assumption that you'll handle buffering and matching up
10153a5a1b3Sopenharmony_ci     * samples yourself. If you set run(), module-echo-cancel will handle
10253a5a1b3Sopenharmony_ci     * synchronising the playback and record streams. */
10353a5a1b3Sopenharmony_ci
10453a5a1b3Sopenharmony_ci    /* Feed the engine 'nframes' playback frames. */
10553a5a1b3Sopenharmony_ci    void        (*play)                 (pa_echo_canceller *ec, const uint8_t *play);
10653a5a1b3Sopenharmony_ci    /* Feed the engine 'nframes' record frames. nframes processed frames are
10753a5a1b3Sopenharmony_ci     * returned in out. */
10853a5a1b3Sopenharmony_ci    void        (*record)               (pa_echo_canceller *ec, const uint8_t *rec, uint8_t *out);
10953a5a1b3Sopenharmony_ci    /* Feed the engine nframes playback and record frames, with a reasonable
11053a5a1b3Sopenharmony_ci     * effort at keeping the two in sync. nframes processed frames are
11153a5a1b3Sopenharmony_ci     * returned in out. */
11253a5a1b3Sopenharmony_ci    void        (*run)                  (pa_echo_canceller *ec, const uint8_t *rec, const uint8_t *play, uint8_t *out);
11353a5a1b3Sopenharmony_ci
11453a5a1b3Sopenharmony_ci    /* Optional callback to set the drift, expressed as the ratio of the
11553a5a1b3Sopenharmony_ci     * difference in number of playback and capture samples to the number of
11653a5a1b3Sopenharmony_ci     * capture samples, for some instant of time. This is used only if the
11753a5a1b3Sopenharmony_ci     * canceller signals that it supports drift compensation, and is called
11853a5a1b3Sopenharmony_ci     * before record(). The actual implementation needs to derive drift based
11953a5a1b3Sopenharmony_ci     * on point samples -- the individual values are not accurate enough to use
12053a5a1b3Sopenharmony_ci     * as-is. */
12153a5a1b3Sopenharmony_ci    /* NOTE: the semantics of this function might change in the future. */
12253a5a1b3Sopenharmony_ci    void        (*set_drift)            (pa_echo_canceller *ec, float drift);
12353a5a1b3Sopenharmony_ci
12453a5a1b3Sopenharmony_ci    /* Free up resources. */
12553a5a1b3Sopenharmony_ci    void        (*done)                 (pa_echo_canceller *ec);
12653a5a1b3Sopenharmony_ci
12753a5a1b3Sopenharmony_ci    /* Structure with common and engine-specific canceller parameters. */
12853a5a1b3Sopenharmony_ci    pa_echo_canceller_params params;
12953a5a1b3Sopenharmony_ci
13053a5a1b3Sopenharmony_ci    /* msgobject that can be used to send messages back to the main thread */
13153a5a1b3Sopenharmony_ci    pa_echo_canceller_msg *msg;
13253a5a1b3Sopenharmony_ci};
13353a5a1b3Sopenharmony_ci
13453a5a1b3Sopenharmony_ci/* Functions to be used by the canceller analog gain control routines */
13553a5a1b3Sopenharmony_cipa_volume_t pa_echo_canceller_get_capture_volume(pa_echo_canceller *ec);
13653a5a1b3Sopenharmony_civoid pa_echo_canceller_set_capture_volume(pa_echo_canceller *ec, pa_volume_t volume);
13753a5a1b3Sopenharmony_ci
13853a5a1b3Sopenharmony_ci/* Computes EC block size in frames (rounded down to nearest power-of-2) based
13953a5a1b3Sopenharmony_ci * on sample rate and milliseconds. */
14053a5a1b3Sopenharmony_ciuint32_t pa_echo_canceller_blocksize_power2(unsigned rate, unsigned ms);
14153a5a1b3Sopenharmony_ci
14253a5a1b3Sopenharmony_ci/* Null canceller functions */
14353a5a1b3Sopenharmony_cibool pa_null_ec_init(pa_core *c, pa_echo_canceller *ec,
14453a5a1b3Sopenharmony_ci                     pa_sample_spec *rec_ss, pa_channel_map *rec_map,
14553a5a1b3Sopenharmony_ci                     pa_sample_spec *play_ss, pa_channel_map *play_map,
14653a5a1b3Sopenharmony_ci                     pa_sample_spec *out_ss, pa_channel_map *out_map,
14753a5a1b3Sopenharmony_ci                     uint32_t *nframes, const char *args);
14853a5a1b3Sopenharmony_civoid pa_null_ec_run(pa_echo_canceller *ec, const uint8_t *rec, const uint8_t *play, uint8_t *out);
14953a5a1b3Sopenharmony_civoid pa_null_ec_done(pa_echo_canceller *ec);
15053a5a1b3Sopenharmony_ci
15153a5a1b3Sopenharmony_ci#ifdef HAVE_SPEEX
15253a5a1b3Sopenharmony_ci/* Speex canceller functions */
15353a5a1b3Sopenharmony_cibool pa_speex_ec_init(pa_core *c, pa_echo_canceller *ec,
15453a5a1b3Sopenharmony_ci                      pa_sample_spec *rec_ss, pa_channel_map *rec_map,
15553a5a1b3Sopenharmony_ci                      pa_sample_spec *play_ss, pa_channel_map *play_map,
15653a5a1b3Sopenharmony_ci                      pa_sample_spec *out_ss, pa_channel_map *out_map,
15753a5a1b3Sopenharmony_ci                      uint32_t *nframes, const char *args);
15853a5a1b3Sopenharmony_civoid pa_speex_ec_run(pa_echo_canceller *ec, const uint8_t *rec, const uint8_t *play, uint8_t *out);
15953a5a1b3Sopenharmony_civoid pa_speex_ec_done(pa_echo_canceller *ec);
16053a5a1b3Sopenharmony_ci#endif
16153a5a1b3Sopenharmony_ci
16253a5a1b3Sopenharmony_ci#ifdef HAVE_ADRIAN_EC
16353a5a1b3Sopenharmony_ci/* Adrian Andre's echo canceller */
16453a5a1b3Sopenharmony_cibool pa_adrian_ec_init(pa_core *c, pa_echo_canceller *ec,
16553a5a1b3Sopenharmony_ci                       pa_sample_spec *rec_ss, pa_channel_map *rec_map,
16653a5a1b3Sopenharmony_ci                       pa_sample_spec *play_ss, pa_channel_map *play_map,
16753a5a1b3Sopenharmony_ci                       pa_sample_spec *out_ss, pa_channel_map *out_map,
16853a5a1b3Sopenharmony_ci                       uint32_t *nframes, const char *args);
16953a5a1b3Sopenharmony_civoid pa_adrian_ec_run(pa_echo_canceller *ec, const uint8_t *rec, const uint8_t *play, uint8_t *out);
17053a5a1b3Sopenharmony_civoid pa_adrian_ec_done(pa_echo_canceller *ec);
17153a5a1b3Sopenharmony_ci#endif
17253a5a1b3Sopenharmony_ci
17353a5a1b3Sopenharmony_ci#ifdef HAVE_WEBRTC
17453a5a1b3Sopenharmony_ci/* WebRTC canceller functions */
17553a5a1b3Sopenharmony_ciPA_C_DECL_BEGIN
17653a5a1b3Sopenharmony_cibool pa_webrtc_ec_init(pa_core *c, pa_echo_canceller *ec,
17753a5a1b3Sopenharmony_ci                       pa_sample_spec *rec_ss, pa_channel_map *rec_map,
17853a5a1b3Sopenharmony_ci                       pa_sample_spec *play_ss, pa_channel_map *play_map,
17953a5a1b3Sopenharmony_ci                       pa_sample_spec *out_ss, pa_channel_map *out_map,
18053a5a1b3Sopenharmony_ci                       uint32_t *nframes, const char *args);
18153a5a1b3Sopenharmony_civoid pa_webrtc_ec_play(pa_echo_canceller *ec, const uint8_t *play);
18253a5a1b3Sopenharmony_civoid pa_webrtc_ec_record(pa_echo_canceller *ec, const uint8_t *rec, uint8_t *out);
18353a5a1b3Sopenharmony_civoid pa_webrtc_ec_set_drift(pa_echo_canceller *ec, float drift);
18453a5a1b3Sopenharmony_civoid pa_webrtc_ec_run(pa_echo_canceller *ec, const uint8_t *rec, const uint8_t *play, uint8_t *out);
18553a5a1b3Sopenharmony_civoid pa_webrtc_ec_done(pa_echo_canceller *ec);
18653a5a1b3Sopenharmony_ciPA_C_DECL_END
18753a5a1b3Sopenharmony_ci#endif
18853a5a1b3Sopenharmony_ci
18953a5a1b3Sopenharmony_ci#endif /* fooechocancelhfoo */
190