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 "audio_common.h"
14 #include "audio_stream.h"
15 
16 #include "opensource/webrtc/modules/audio_processing/ns/noise_suppression_x.h"
17 
18 
19 typedef struct {
20 	short *in[2];
21 	short *out[2];
22 	int32_t *filter_state[4];
23 	int samples;
24 	int band_samples;
25 	int band_num;
26 	NsxHandle *inst;
27 } webrtc_ns_t;
28 
29 
ns_buffer_alloc(webrtc_ns_t * webrtc_ns)30 static int ns_buffer_alloc(webrtc_ns_t *webrtc_ns)
31 {
32 	int i;
33 
34 	if (!webrtc_ns) {
35 		snd_err("webrtc_ns null !\n");
36 		return -1;
37 	}
38 
39 	for (i = 0; i < webrtc_ns->band_num; i++) {
40 		webrtc_ns->in[i] = snd_zalloc(
41 			webrtc_ns->band_samples * sizeof(short), AFM_MAIN);
42 		if (!webrtc_ns->in) {
43 			snd_err("alloc in buffer failed !\n");
44 			return -1;
45 		}
46 
47 		webrtc_ns->out[i] = snd_zalloc(
48 			webrtc_ns->band_samples * sizeof(short), AFM_MAIN);
49 		if (!webrtc_ns->out) {
50 			snd_err("alloc out buffer failed !\n");
51 			return -1;
52 		}
53 	}
54 
55 	if (webrtc_ns->band_num == 2) {
56 		for (i = 0; i < 4; i++) {
57 			webrtc_ns->filter_state[i] = snd_zalloc(
58 				6 * sizeof(int32_t), AFM_MAIN);
59 			if (!webrtc_ns->filter_state[i]) {
60 				snd_err("alloc filter state failed !\n");
61 				return -1;
62 			}
63 		}
64 	}
65 
66 	return 0;
67 }
68 
ns_buffer_free(webrtc_ns_t * webrtc_ns)69 static int ns_buffer_free(webrtc_ns_t *webrtc_ns)
70 {
71 	int i;
72 
73 	if (!webrtc_ns) {
74 		snd_err("webrtc_ns null !\n");
75 		return -1;
76 	}
77 
78 	for (i = 0; i < 4; i++) {
79 		if (webrtc_ns->filter_state[i]) {
80 			snd_free(webrtc_ns->filter_state[i]);
81 			webrtc_ns->filter_state[i] = NULL;
82 		}
83 	}
84 
85 	for (i = 0; i < webrtc_ns->band_num; i++) {
86 		if (webrtc_ns->in[i]) {
87 			snd_free(webrtc_ns->in[i]);
88 			webrtc_ns->in[i] = NULL;
89 		}
90 
91 		if (webrtc_ns->out[i]) {
92 			snd_free(webrtc_ns->out[i]);
93 			webrtc_ns->out[i] = NULL;
94 		}
95 	}
96 
97 	return 0;
98 }
99 
noise_suppression_process(struct noise_suppression * ns,uint8_t * buffer,int nbytes)100 int noise_suppression_process(struct noise_suppression *ns,
101 	uint8_t *buffer, int nbytes)
102 {
103 	webrtc_ns_t *webrtc_ns;
104 	int proc_size;
105 	int ret;
106 	int i;
107 
108 	if (!ns) {
109 		snd_err("ns null !\n");
110 		return -1;
111 	}
112 
113 	webrtc_ns = ns->handler;
114 	if (!webrtc_ns) {
115 		snd_err("webrtc_ns null !\n");
116 		return -1;
117 	}
118 
119 	proc_size = webrtc_ns->samples * sizeof(short);
120 
121 	if (nbytes % proc_size != 0) {
122 		snd_err("invalid input size !\n");
123 		return -1;
124 	}
125 
126 	if (webrtc_ns->band_num == 1) {
127 		for (i = 0; i < nbytes; i += proc_size) {
128 			memcpy(webrtc_ns->in[0], buffer + i, proc_size);
129 			WebRtcNsx_Process(webrtc_ns->inst,
130 				webrtc_ns->in, 1, webrtc_ns->out);
131 			memcpy(buffer + i, webrtc_ns->out[0], proc_size);
132 		}
133 	} else if (webrtc_ns->band_num == 2) {
134 		for (i = 0; i < nbytes; i += proc_size) {
135 			WebRtcSpl_AnalysisQMF(buffer + i,
136 				webrtc_ns->samples,
137 				webrtc_ns->in[0],
138 				webrtc_ns->in[1],
139   				webrtc_ns->filter_state[0],
140   				webrtc_ns->filter_state[1]);
141 
142 			WebRtcNsx_Process(webrtc_ns->inst,
143 				webrtc_ns->in, 2, webrtc_ns->out);
144 
145 			WebRtcSpl_SynthesisQMF(webrtc_ns->out[0],
146 				webrtc_ns->out[1],
147 				webrtc_ns->band_samples,
148 				buffer + i,
149   				webrtc_ns->filter_state[2],
150   				webrtc_ns->filter_state[3]);
151 		}
152 	}
153 
154 	return 0;
155 }
156 
noise_suppression_create(struct noise_suppression * ns,int rate,int bits,int samples,int mode)157 int noise_suppression_create(struct noise_suppression *ns,
158 	int rate, int bits, int samples, int mode)
159 {
160 	webrtc_ns_t *webrtc_ns;
161 	int ret;
162 
163 	if (!ns) {
164 		snd_err("ns null !\n");
165 		return -1;
166 	}
167 
168 	if (bits != 16) {
169 		snd_err("bits %d ns not support !\n", bits);
170 		return -1;
171 	}
172 
173 	if (samples % (rate / 100) != 0) {
174 		snd_err("samples and rate not mulitple !\n");
175 		return -1;
176 	}
177 
178 	webrtc_ns = snd_zalloc(sizeof(webrtc_ns_t), AFM_EXTN);
179 	if (!webrtc_ns) {
180 		snd_err("alloc webrtc ns failed !\n");
181 		return -1;
182 	}
183 
184 	webrtc_ns->inst = WebRtcNsx_Create();
185 	if (!webrtc_ns->inst) {
186 		snd_err("create webrtc nsx failed !\n");
187 		snd_free(webrtc_ns);
188 		return -1;
189 	}
190 
191 	ret = WebRtcNsx_Init(webrtc_ns->inst, rate);
192 	if (ret) {
193 		snd_err("init webrtc nsx failed !\n");
194 		WebRtcNsx_Free(webrtc_ns->inst);
195 		snd_free(webrtc_ns);
196 		return -1;
197 	}
198 
199 	webrtc_ns->samples = rate / 100;
200 	if (rate == 48000 || rate == 32000) {
201 		webrtc_ns->band_num = 2;
202 		webrtc_ns->band_samples = webrtc_ns->samples / 2;
203 	} else {
204 		webrtc_ns->band_num = 1;
205 		webrtc_ns->band_samples = webrtc_ns->samples;
206 	}
207 
208 	ret = WebRtcNsx_set_policy(webrtc_ns->inst, mode);
209 	if (ret) {
210 		snd_err("set webrtc policy failed %d!\n", ret);
211 		WebRtcNsx_Free(webrtc_ns->inst);
212 		snd_free(webrtc_ns);
213 		return -1;
214 	}
215 
216 	if (ns_buffer_alloc(webrtc_ns)) {
217 		snd_err("alloc ns buffer failed !\n");
218 		ns_buffer_free(webrtc_ns);
219 		WebRtcNsx_Free(webrtc_ns->inst);
220 		snd_free(webrtc_ns);
221 		return -1;
222 	}
223 
224 	snd_info("noise suppression create\n");
225 	ns->handler = webrtc_ns;
226 	return 0;
227 }
228 
noise_suppression_release(struct noise_suppression * ns)229 int noise_suppression_release(struct noise_suppression *ns)
230 {
231 	webrtc_ns_t *webrtc_ns;
232 
233 	if (!ns) {
234 		snd_err("ns null !\n");
235 		return -1;
236 	}
237 
238 	webrtc_ns = ns->handler;
239 	if (!webrtc_ns) {
240 		snd_err("webrtc_ns null !\n");
241 		return -1;
242 	}
243 
244 	ns_buffer_free(webrtc_ns);
245 
246 	WebRtcNsx_Free(webrtc_ns->inst);
247 	snd_free(webrtc_ns);
248 	ns->handler = NULL;
249 
250 	snd_info("noise suppression release\n");
251 	return 0;
252 }
253 
254