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