summaryrefslogtreecommitdiffstats
path: root/audio/audio_aec.h
blob: ac7a1dda97d5a80da6c8202f91361436cb32c497 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * Definitions and interface related to HAL implementations of Acoustic Echo Canceller (AEC).
 *
 * AEC cleans the microphone signal by removing from it audio data corresponding to loudspeaker
 * playback. Note that this process can be nonlinear.
 *
 */

#ifndef _AUDIO_AEC_H_
#define _AUDIO_AEC_H_

#include <stdint.h>
#include <pthread.h>
#include <sys/time.h>
#include <hardware/audio.h>
#include <audio_utils/resampler.h>
#include "audio_hw.h"
#include "fifo_wrapper.h"

struct aec_t {
    pthread_mutex_t lock;
    size_t num_reference_channels;
    bool mic_initialized;
    int32_t *mic_buf;
    size_t mic_num_channels;
    size_t mic_buf_size_bytes;
    size_t mic_frame_size_bytes;
    uint32_t mic_sampling_rate;
    struct aec_info last_mic_info;
    bool spk_initialized;
    int32_t *spk_buf;
    size_t spk_num_channels;
    size_t spk_buf_size_bytes;
    size_t spk_frame_size_bytes;
    uint32_t spk_sampling_rate;
    struct aec_info last_spk_info;
    int16_t *spk_buf_playback_format;
    int16_t *spk_buf_resampler_out;
    void *spk_fifo;
    void *ts_fifo;
    ssize_t read_write_diff_bytes;
    struct resampler_itfe *spk_resampler;
    bool spk_running;
    bool prev_spk_running;
};

/* Initialize AEC object.
 * This must be called when the audio device is opened.
 * ALSA device mutex must be held before calling this API.
 * Returns -EINVAL if AEC object fails to initialize, else returns 0. */
int init_aec (int sampling_rate, int num_reference_channels,
                int num_microphone_channels, struct aec_t **);

/* Release AEC object.
 * This must be called when the audio device is closed. */
void release_aec(struct aec_t* aec);

/* Initialize reference configuration for AEC.
 * Must be called when a new output stream is opened.
 * Returns -EINVAL if any processing block fails to initialize,
 * else returns 0. */
int init_aec_reference_config (struct aec_t *aec, struct alsa_stream_out *out);

/* Clear reference configuration for AEC.
 * Must be called when the output stream is closed. */
void destroy_aec_reference_config (struct aec_t *aec);

/* Initialize microphone configuration for AEC.
 * Must be called when a new input stream is opened.
 * Returns -EINVAL if any processing block fails to initialize,
 * else returns 0. */
int init_aec_mic_config(struct aec_t* aec, struct alsa_stream_in* in);

/* Clear microphone configuration for AEC.
 * Must be called when the input stream is closed. */
void destroy_aec_mic_config (struct aec_t *aec);

/* Used to communicate playback state (running or not) to AEC interface.
 * This is used by process_aec() to determine if AEC processing is to be run. */
void aec_set_spk_running (struct aec_t *aec, bool state);

/* Used to communicate playback state (running or not) to the caller. */
bool aec_get_spk_running(struct aec_t* aec);

/* Write audio samples to AEC reference FIFO for use in AEC.
 * Both audio samples and timestamps are added in FIFO fashion.
 * Must be called after every write to PCM.
 * Returns -ENOMEM if the write fails, else returns 0. */
int write_to_reference_fifo(struct aec_t* aec, void* buffer, struct aec_info* info);

/* Get reference audio samples + timestamp, in the format expected by AEC,
 * i.e. same sample rate and bit rate as microphone audio.
 * Timestamp is updated in field 'timestamp_usec', and not in 'timestamp'.
 * Returns:
 *  -EINVAL    if the AEC object is invalid.
 *  -ENOMEM    if the reference FIFO overflows or is corrupted.
 *  -ETIMEDOUT if we timed out waiting for the requested number of bytes
 *  0          otherwise */
int get_reference_samples(struct aec_t* aec, void* buffer, struct aec_info* info);

#ifdef AEC_HAL

/* Processing function call for AEC.
 * AEC output is updated at location pointed to by 'buffer'.
 * This function does not run AEC when there is no playback -
 * as communicated to this AEC interface using aec_set_spk_running().
 * Returns -EINVAL if processing fails, else returns 0. */
int process_aec(struct aec_t* aec, void* buffer, struct aec_info* info);

#else /* #ifdef AEC_HAL */

#define process_aec(...) ((int)0)

#endif /* #ifdef AEC_HAL */

#endif /* _AUDIO_AEC_H_ */