1 /*
2 * Copyright (C) 2015-2020 Alibaba Group Holding Limited
3 *
4 */
5
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <stdint.h>
9 #include <string.h>
10
11 #include "uvoice_os.h"
12 #include "uvoice_audio.h"
13 #include "uvoice_common.h"
14 #include "audio_common.h"
15 #include "audio_stream.h"
16 #include "audio_aec.h"
17
18 #include "opensource/webrtc/modules/audio_processing/aec/include/echo_cancellation.h"
19
20
21 typedef struct {
22 int16_t *out;
23 int16_t *far;
24 int16_t *near;
25 int samples;
26 int band_samples;
27 int band_num;
28 void *inst;
29 } webrtc_aec_t;
30
aec_buffer_alloc(webrtc_aec_t * webrtc_aec)31 static int aec_buffer_alloc(webrtc_aec_t *webrtc_aec)
32 {
33 if (!webrtc_aec) {
34 snd_err("webrtc_aec null !\n");
35 return -1;
36 }
37
38 webrtc_aec->out = snd_zalloc(
39 webrtc_aec->samples * sizeof(int16_t), AFM_MAIN);
40 if (!webrtc_aec->out) {
41 snd_err("alloc out buffer failed !\n");
42 return -1;
43 }
44
45 webrtc_aec->far = snd_zalloc(
46 webrtc_aec->samples * sizeof(int16_t), AFM_MAIN);
47 if (!webrtc_aec->far) {
48 snd_err("alloc far buffer failed !\n");
49 return -1;
50 }
51
52 webrtc_aec->near = snd_zalloc(
53 webrtc_aec->samples * sizeof(int16_t), AFM_MAIN);
54 if (!webrtc_aec->near) {
55 snd_err("alloc near buffer failed !\n");
56 return -1;
57 }
58
59 return 0;
60 }
61
aec_buffer_free(webrtc_aec_t * webrtc_aec)62 static int aec_buffer_free(webrtc_aec_t *webrtc_aec)
63 {
64 if (!webrtc_aec) {
65 snd_err("webrtc_aec null !\n");
66 return -1;
67 }
68
69 if (webrtc_aec->near) {
70 snd_free(webrtc_aec->near);
71 webrtc_aec->near = NULL;
72 }
73
74 if (webrtc_aec->far) {
75 snd_free(webrtc_aec->far);
76 webrtc_aec->far = NULL;
77 }
78
79 if (webrtc_aec->out) {
80 snd_free(webrtc_aec->out);
81 webrtc_aec->out = NULL;
82 }
83
84 return 0;
85 }
86
echo_cancellation_process(struct aec_handler * ec,uint8_t * near,uint8_t * far,int nbytes)87 int echo_cancellation_process(struct aec_handler *ec,
88 uint8_t *near, uint8_t *far, int nbytes)
89 {
90 webrtc_aec_t *webrtc_aec;
91 int proc_size;
92 int ret;
93 int i;
94
95 if (!ec) {
96 snd_err("ec null !\n");
97 return -1;
98 }
99
100 webrtc_aec = ec->aec_inst;
101 if (!webrtc_aec) {
102 snd_err("webrtc_aec null !\n");
103 return -1;
104 }
105
106 proc_size = webrtc_aec->samples * sizeof(int16_t);
107
108 if (nbytes % proc_size != 0) {
109 snd_err("invalid input size !\n");
110 return -1;
111 }
112
113 for (i = 0; i < nbytes; i += proc_size) {
114 memcpy(webrtc_aec->far, far + i, proc_size);
115 WebRtcAec_BufferFarend(webrtc_aec->inst,
116 webrtc_aec->far,
117 webrtc_aec->samples);
118
119 memcpy(webrtc_aec->near, near + i, proc_size);
120 WebRtcAec_Process(webrtc_aec->inst,
121 webrtc_aec->near,
122 NULL,
123 webrtc_aec->out,
124 NULL,
125 webrtc_aec->samples,
126 10,
127 0);
128 memcpy(near + i, webrtc_aec->out, proc_size);
129 }
130
131 return 0;
132 }
133
echo_cancellation_create(struct aec_handler * aec,int rate,int bits,int samples)134 int echo_cancellation_create(struct aec_handler *aec,
135 int rate, int bits, int samples)
136 {
137 webrtc_aec_t *webrtc_aec;
138 int ret;
139
140 if (!aec) {
141 snd_err("aec null !\n");
142 return -1;
143 }
144
145 if (bits != 16) {
146 snd_err("bits %d ns not support !\n", bits);
147 return -1;
148 }
149
150 if (samples % (rate / 100) != 0) {
151 snd_err("samples and rate not mulitple !\n");
152 return -1;
153 }
154
155 webrtc_aec = snd_zalloc(sizeof(webrtc_aec_t), AFM_EXTN);
156 if (!webrtc_aec) {
157 snd_err("alloc webrtc ns failed !\n");
158 return -1;
159 }
160
161 webrtc_aec->samples = rate / 100;
162
163 if (aec_buffer_alloc(webrtc_aec)) {
164 snd_err("alloc buffer failed !\n");
165 snd_free(webrtc_aec);
166 return -1;
167 }
168
169 ret = WebRtcAec_Create(&webrtc_aec->inst);
170 if (ret) {
171 snd_err("create webrtc aec failed %d!\n", ret);
172 snd_free(webrtc_aec);
173 return -1;
174 }
175
176 ret = WebRtcAec_Init(webrtc_aec->inst, rate, rate);
177 if (ret) {
178 snd_err("init webrtc aec failed !\n");
179 WebRtcAec_Free(webrtc_aec->inst);
180 aec_buffer_free(webrtc_aec);
181 snd_free(webrtc_aec);
182 return -1;
183 }
184
185 snd_info("echo cancellation create\n");
186 aec->aec_inst = webrtc_aec;
187 return 0;
188 }
189
echo_cancellation_release(struct aec_handler * aec)190 int echo_cancellation_release(struct aec_handler *aec)
191 {
192 webrtc_aec_t *webrtc_aec;
193
194 if (!aec) {
195 snd_err("aec null !\n");
196 return -1;
197 }
198
199 webrtc_aec = aec->aec_inst;
200 if (!webrtc_aec) {
201 snd_err("webrtc_aec null !\n");
202 return -1;
203 }
204
205 aec_buffer_free(webrtc_aec);
206 WebRtcAec_Free(webrtc_aec->inst);
207 snd_free(webrtc_aec);
208 aec->aec_inst = NULL;
209
210 snd_info("echo cancellation release\n");
211 return 0;
212 }
213
214