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 #include <stdarg.h>
11 #include <signal.h>
12 
13 #include "uvoice_types.h"
14 
15 #include "uvoice_os.h"
16 #include "uvoice_common.h"
17 #include "uvoice_audio.h"
18 #include "audio_common.h"
19 #include "audio_stream.h"
20 #include "audio_process.h"
21 #include "audio_aec.h"
22 
23 
24 #define AEC_REFER_DELAY_MS        10
25 
26 
audio_out_process(struct out_stream * out,uint8_t * buffer,int nbytes)27 int audio_out_process(struct out_stream *out, uint8_t *buffer, int nbytes)
28 {
29     if (!out) {
30         snd_err("out null !\n");
31         return -1;
32     }
33 
34 #ifdef UVOICE_EQ_ENABLE
35     equalizer_process(&out->pcm.config, buffer, nbytes);
36 #endif
37 
38     return 0;
39 }
40 
audio_out_process_init(struct audio_device * adev,struct out_stream * out)41 int audio_out_process_init(struct audio_device *adev, struct out_stream *out)
42 {
43 #ifdef UVOICE_EQ_ENABLE
44     struct pcm_config *config;
45     int period_size;
46     int bits;
47 
48     if (!adev || !out) {
49         snd_err("args null !\n");
50         return -1;
51     }
52 
53     config = &out->pcm.config;
54     bits = pcm_format_to_bits(config->format);
55     period_size = period_samples_to_bytes(config);
56 
57     if (adev->equalizer_enable && !out->eq) {
58         out->eq = equalizer_create(period_size,
59             config->rate, bits, config->channels);
60         if (!out->eq) {
61             snd_err("create equalizer failed !\n");
62             return -1;
63         }
64     }
65 #endif
66 
67     return 0;
68 }
69 
audio_out_process_deinit(struct out_stream * out)70 int audio_out_process_deinit(struct out_stream *out)
71 {
72 #ifdef UVOICE_EQ_ENABLE
73     if (!out) {
74         snd_err("out null !\n");
75         return -1;
76     }
77 
78     if (out->eq) {
79         equalizer_release(out->eq);
80         out->eq = NULL;
81     }
82 #endif
83     return 0;
84 }
85 
audio_out_conserve(struct audio_device * adev,uint8_t * buffer,int nbytes)86 int audio_out_conserve(struct audio_device *adev, uint8_t *buffer,
87     int nbytes)
88 {
89     struct in_stream *in;
90 
91     in = adev->in;
92     if (!in)
93         goto __exit;
94 
95 #ifdef UVOICE_AEC_ENABLE
96     if (in->state == STREAM_RUNNING) {
97         if (in->aec)
98             return audio_aec_refer_conserve(in->aec, buffer, nbytes);
99     }
100 #endif
101 
102 __exit:
103     return 0;
104 }
105 
audio_in_process(struct in_stream * in,uint8_t * buffer,int nbytes)106 int audio_in_process(struct in_stream *in, uint8_t *buffer, int nbytes)
107 {
108     if (!in) {
109         snd_err("stream null !\n");
110         return -1;
111     }
112 
113     if (!buffer) {
114         snd_err("buffer null !\n");
115         return -1;
116     }
117 
118 #ifdef UVOICE_AEC_ENABLE
119     if (in->aec) {
120         if (audio_aec_process(in->aec, buffer, nbytes)) {
121             snd_err("aec process failed !\n");
122             return -1;
123         }
124     }
125 #endif
126 
127 #ifdef UVOICE_ANC_ENABLE
128     if (in->ns) {
129         if (noise_suppression_process(in->ns, buffer, nbytes)) {
130             snd_err("ns process failed !\n");
131             return -1;
132         }
133     }
134 #endif
135 
136 #ifdef UVOICE_AGC_ENABLE
137     if (in->agc) {
138         if (auto_gain_control_process(in->agc, buffer, nbytes)) {
139             snd_err("agc process failed !\n");
140             return -1;
141         }
142     }
143 #endif
144 
145     return 0;
146 }
147 
audio_in_process_init(struct audio_device * adev,struct in_stream * in)148 int audio_in_process_init(struct audio_device *adev, struct in_stream *in)
149 {
150     struct pcm_config *config;
151     int bits;
152 
153     if (!adev || !in) {
154         snd_err("args null !\n");
155         return -1;
156     }
157 
158 #ifdef UVOICE_ANC_ENABLE
159     if (adev->noise_suppression) {
160         in->ns = snd_zalloc(sizeof(struct noise_suppression), AFM_EXTN);
161         if (!in->ns) {
162             snd_err("alloc noise supression struct failed !\n");
163             return -1;
164         }
165     }
166 #endif
167 
168 #ifdef UVOICE_AGC_ENABLE
169     if (adev->auto_gain_control) {
170         in->agc = snd_zalloc(sizeof(struct auto_gain_control), AFM_EXTN);
171         if (!in->agc) {
172             snd_err("alloc auto gain control struct failed !\n");
173             if (in->ns) {
174                 snd_free(in->ns);
175                 in->ns = NULL;
176             }
177             return -1;
178         }
179     }
180 #endif
181 
182     config = &in->pcm.config;
183     bits = pcm_format_to_bits(config->format);
184 
185 #ifdef UVOICE_ANC_ENABLE
186     if (in->ns) {
187         if (noise_suppression_create(in->ns,
188                 config->rate, bits, config->period_size, 3)) {
189             snd_err("create ns failed !\n");
190             audio_in_process_deinit(in);
191             return -1;
192         }
193     }
194 #endif
195 
196 #ifdef UVOICE_AGC_ENABLE
197     if (in->agc) {
198         if (auto_gain_control_create(in->agc,
199                 config->rate, bits, config->period_size)) {
200             snd_err("create agc failed !\n");
201             audio_in_process_deinit(in);
202             return -1;
203         }
204     }
205 #endif
206 
207 #ifdef UVOICE_AEC_ENABLE
208     if (adev->echo_cancellation) {
209         if (audio_aec_init(in)) {
210             snd_err("init audio aec failed !\n");
211             audio_in_process_deinit(in);
212             return -1;
213         }
214     }
215 #endif
216 
217     return 0;
218 }
219 
audio_in_process_deinit(struct in_stream * in)220 int audio_in_process_deinit(struct in_stream *in)
221 {
222     if (!in) {
223         snd_err("stream null !\n");
224         return -1;
225     }
226 
227 #ifdef UVOICE_AEC_ENABLE
228     if (in->aec)
229         audio_aec_deinit(in);
230 #endif
231 
232 #ifdef UVOICE_ANC_ENABLE
233     if (in->ns) {
234         noise_suppression_release(in->ns);
235         snd_free(in->ns);
236         in->ns = NULL;
237     }
238 #endif
239 
240 #ifdef UVOICE_AGC_ENABLE
241     if (in->agc) {
242         auto_gain_control_release(in->agc);
243         snd_free(in->agc);
244         in->agc = NULL;
245     }
246 #endif
247 
248     return 0;
249 }
250 
251