1 // Copyright 2018 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <stdio.h>
6 #include <gtest/gtest.h>
7
8 extern "C" {
9 #include "cras_apm_list.h"
10 #include "cras_audio_area.h"
11 #include "cras_dsp_pipeline.h"
12 #include "cras_iodev.h"
13 #include "cras_iodev_list.h"
14 #include "cras_types.h"
15 #include "float_buffer.h"
16 #include "webrtc_apm.h"
17 }
18
19 namespace {
20
21 static void *stream_ptr = reinterpret_cast<void *>(0x123);
22 static void *dev_ptr = reinterpret_cast<void *>(0x345);
23 static void *dev_ptr2 = reinterpret_cast<void *>(0x678);
24 static struct cras_apm_list *list;
25 static struct cras_audio_area fake_audio_area;
26 static unsigned int dsp_util_interleave_frames;
27 static unsigned int webrtc_apm_process_stream_f_called;
28 static unsigned int webrtc_apm_process_reverse_stream_f_called;
29 static device_enabled_callback_t device_enabled_callback_val;
30 static struct ext_dsp_module *ext_dsp_module_value;
31 static struct cras_iodev fake_iodev;
32
33
TEST(ApmList,ApmListCreate)34 TEST(ApmList, ApmListCreate) {
35 list = cras_apm_list_create(stream_ptr, 0);
36 EXPECT_EQ((void *)NULL, list);
37
38 list = cras_apm_list_create(stream_ptr, APM_ECHO_CANCELLATION);
39 EXPECT_NE((void *)NULL, list);
40 EXPECT_EQ(APM_ECHO_CANCELLATION, cras_apm_list_get_effects(list));
41
42 cras_apm_list_destroy(list);
43 }
44
TEST(ApmList,AddRemoveApm)45 TEST(ApmList, AddRemoveApm) {
46 struct cras_audio_format fmt;
47
48 fmt.num_channels = 2;
49 fmt.frame_rate = 48000;
50 fmt.format = SND_PCM_FORMAT_S16_LE;
51
52 list = cras_apm_list_create(stream_ptr, APM_ECHO_CANCELLATION);
53 EXPECT_NE((void *)NULL, list);
54
55 EXPECT_NE((void *)NULL, cras_apm_list_add(list, dev_ptr, &fmt));
56 EXPECT_EQ((void *)NULL, cras_apm_list_get(list, dev_ptr2));
57
58 EXPECT_NE((void *)NULL, cras_apm_list_add(list, dev_ptr2, &fmt));
59 EXPECT_NE((void *)NULL, cras_apm_list_get(list, dev_ptr));
60
61 cras_apm_list_remove(list, dev_ptr);
62 EXPECT_EQ((void *)NULL, cras_apm_list_get(list, dev_ptr));
63 EXPECT_NE((void *)NULL, cras_apm_list_get(list, dev_ptr2));
64
65 cras_apm_list_remove(list, dev_ptr2);
66 EXPECT_EQ((void *)NULL, cras_apm_list_get(list, dev_ptr2));
67
68 cras_apm_list_destroy(list);
69 }
70
TEST(ApmList,ApmProcessForwardBuffer)71 TEST(ApmList, ApmProcessForwardBuffer) {
72 struct cras_apm *apm;
73 struct cras_audio_format fmt;
74 struct cras_audio_area *area;
75 struct float_buffer *buf;
76
77 fmt.num_channels = 2;
78 fmt.frame_rate = 48000;
79 fmt.format = SND_PCM_FORMAT_S16_LE;
80
81 list = cras_apm_list_create(stream_ptr, APM_ECHO_CANCELLATION);
82 EXPECT_NE((void *)NULL, list);
83
84 apm = cras_apm_list_add(list, dev_ptr, &fmt);
85
86 buf = float_buffer_create(500, 2);
87 float_buffer_written(buf, 300);
88 webrtc_apm_process_stream_f_called = 0;
89 cras_apm_list_process(apm, buf, 0);
90 EXPECT_EQ(0, webrtc_apm_process_stream_f_called);
91
92 area = cras_apm_list_get_processed(apm);
93 EXPECT_EQ(0, area->frames);
94
95 float_buffer_reset(buf);
96 float_buffer_written(buf, 200);
97 cras_apm_list_process(apm, buf, 0);
98 area = cras_apm_list_get_processed(apm);
99 EXPECT_EQ(1, webrtc_apm_process_stream_f_called);
100 EXPECT_EQ(480, dsp_util_interleave_frames);
101 EXPECT_EQ(480, area->frames);
102
103 /* Put some processed frames. Another apm_list process will not call
104 * into webrtc_apm because the processed buffer is not yet empty.
105 */
106 cras_apm_list_put_processed(apm, 200);
107 float_buffer_reset(buf);
108 float_buffer_written(buf, 500);
109 cras_apm_list_process(apm, buf, 0);
110 EXPECT_EQ(1, webrtc_apm_process_stream_f_called);
111
112 /* Put another 280 processed frames, so it's now ready for webrtc_apm
113 * to process another chunk of 480 frames (10ms) data.
114 */
115 cras_apm_list_put_processed(apm, 280);
116 cras_apm_list_process(apm, buf, 0);
117 EXPECT_EQ(2, webrtc_apm_process_stream_f_called);
118
119 float_buffer_destroy(&buf);
120 cras_apm_list_destroy(list);
121 }
122
TEST(ApmList,ApmProcessReverseData)123 TEST(ApmList, ApmProcessReverseData) {
124 struct cras_apm *apm;
125 struct cras_audio_format fmt;
126 struct float_buffer *buf;
127 float *const *rp;
128 unsigned int nread;
129 struct cras_iodev fake_iodev;
130
131 fmt.num_channels = 2;
132 fmt.frame_rate = 48000;
133 fmt.format = SND_PCM_FORMAT_S16_LE;
134
135 fake_iodev.direction = CRAS_STREAM_OUTPUT;
136 device_enabled_callback_val = NULL;
137 ext_dsp_module_value = NULL;
138 webrtc_apm_process_reverse_stream_f_called = 0;
139
140 cras_apm_list_init("");
141 EXPECT_NE((void *)NULL, device_enabled_callback_val);
142
143 device_enabled_callback_val(&fake_iodev, NULL);
144 EXPECT_NE((void *)NULL, ext_dsp_module_value);
145 EXPECT_NE((void *)NULL, ext_dsp_module_value->ports);
146
147 buf = float_buffer_create(500, 2);
148 float_buffer_written(buf, 500);
149 nread = 500;
150 rp = float_buffer_read_pointer(buf, 0, &nread);
151
152 for (int i = 0; i < buf->num_channels; i++)
153 ext_dsp_module_value->ports[i] = rp[i];
154
155 ext_dsp_module_value->configure(ext_dsp_module_value,
156 800, 2, 48000);
157 ext_dsp_module_value->run(ext_dsp_module_value, 500);
158 EXPECT_EQ(0, webrtc_apm_process_reverse_stream_f_called);
159
160 list = cras_apm_list_create(stream_ptr, APM_ECHO_CANCELLATION);
161 EXPECT_NE((void *)NULL, list);
162
163 apm = cras_apm_list_add(list, dev_ptr, &fmt);
164
165 ext_dsp_module_value->run(ext_dsp_module_value, 250);
166 EXPECT_EQ(0, webrtc_apm_process_reverse_stream_f_called);
167
168 ext_dsp_module_value->run(ext_dsp_module_value, 250);
169 EXPECT_EQ(1, webrtc_apm_process_reverse_stream_f_called);
170
171 float_buffer_destroy(&buf);
172 cras_apm_list_deinit();
173 }
174
175 extern "C" {
cras_iodev_list_set_device_enabled_callback(device_enabled_callback_t enabled_cb,device_disabled_callback_t disabled_cb,void * cb_data)176 int cras_iodev_list_set_device_enabled_callback(
177 device_enabled_callback_t enabled_cb,
178 device_disabled_callback_t disabled_cb,
179 void *cb_data)
180 {
181 device_enabled_callback_val = enabled_cb;
182 return 0;
183 }
cras_iodev_list_get_first_enabled_iodev(enum CRAS_STREAM_DIRECTION direction)184 struct cras_iodev *cras_iodev_list_get_first_enabled_iodev(
185 enum CRAS_STREAM_DIRECTION direction)
186 {
187 return &fake_iodev;
188 }
cras_iodev_set_ext_dsp_module(struct cras_iodev * iodev,struct ext_dsp_module * ext)189 void cras_iodev_set_ext_dsp_module(struct cras_iodev *iodev,
190 struct ext_dsp_module *ext)
191 {
192 ext_dsp_module_value = ext;
193 }
cras_audio_area_create(int num_channels)194 struct cras_audio_area *cras_audio_area_create(int num_channels)
195 {
196 return &fake_audio_area;
197 }
198
cras_audio_area_destroy(struct cras_audio_area * area)199 void cras_audio_area_destroy(struct cras_audio_area *area)
200 {
201 }
cras_audio_area_config_channels(struct cras_audio_area * area,const struct cras_audio_format * fmt)202 void cras_audio_area_config_channels(struct cras_audio_area *area,
203 const struct cras_audio_format *fmt)
204 {
205 }
cras_audio_area_config_buf_pointers(struct cras_audio_area * area,const struct cras_audio_format * fmt,uint8_t * base_buffer)206 void cras_audio_area_config_buf_pointers(struct cras_audio_area *area,
207 const struct cras_audio_format *fmt,
208 uint8_t *base_buffer)
209 {
210 }
dsp_util_interleave(float * const * input,int16_t * output,int channels,snd_pcm_format_t format,int frames)211 void dsp_util_interleave(float *const *input, int16_t *output, int channels,
212 snd_pcm_format_t format, int frames)
213 {
214 dsp_util_interleave_frames = frames;
215 }
aec_config_get(const char * device_config_dir)216 struct aec_config *aec_config_get(const char *device_config_dir)
217 {
218 return NULL;
219 }
aec_config_dump(struct aec_config * config)220 void aec_config_dump(struct aec_config *config)
221 {
222 }
apm_config_get(const char * device_config_dir)223 struct apm_config *apm_config_get(const char *device_config_dir)
224 {
225 return NULL;
226 }
apm_config_dump(struct apm_config * config)227 void apm_config_dump(struct apm_config *config)
228 {
229 }
webrtc_apm_create(unsigned int num_channels,unsigned int frame_rate,struct aec_config * aec_config,struct apm_config * apm_config)230 webrtc_apm webrtc_apm_create(unsigned int num_channels,
231 unsigned int frame_rate,
232 struct aec_config *aec_config,
233 struct apm_config *apm_config)
234 {
235 return reinterpret_cast<webrtc_apm>(0x11);
236 }
webrtc_apm_destroy(webrtc_apm apm)237 void webrtc_apm_destroy(webrtc_apm apm)
238 {
239 return;
240 }
webrtc_apm_process_stream_f(webrtc_apm ptr,int num_channels,int rate,float * const * data)241 int webrtc_apm_process_stream_f(webrtc_apm ptr,
242 int num_channels,
243 int rate,
244 float *const *data)
245 {
246 webrtc_apm_process_stream_f_called++;
247 return 0;
248 }
249
webrtc_apm_process_reverse_stream_f(webrtc_apm ptr,int num_channels,int rate,float * const * data)250 int webrtc_apm_process_reverse_stream_f(
251 webrtc_apm ptr,
252 int num_channels, int rate,
253 float *const *data)
254 {
255 webrtc_apm_process_reverse_stream_f_called++;
256 return 0;
257 }
webrtc_apm_aec_dump(webrtc_apm ptr,void ** work_queue,int start,FILE * handle)258 int webrtc_apm_aec_dump(webrtc_apm ptr, void** work_queue,
259 int start, FILE *handle)
260 {
261 return 0;
262 }
263
264 } // extern "C"
265 } // namespace
266
267
main(int argc,char ** argv)268 int main(int argc, char **argv) {
269 ::testing::InitGoogleTest(&argc, argv);
270 return RUN_ALL_TESTS();
271 }
272