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 <gtest/gtest.h>
6 #include <stdio.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 static int webrtc_apm_create_called;
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, 800, 2, 48000);
156 ext_dsp_module_value->run(ext_dsp_module_value, 500);
157 EXPECT_EQ(0, webrtc_apm_process_reverse_stream_f_called);
158
159 list = cras_apm_list_create(stream_ptr, APM_ECHO_CANCELLATION);
160 EXPECT_NE((void*)NULL, list);
161
162 apm = cras_apm_list_add(list, dev_ptr, &fmt);
163
164 ext_dsp_module_value->run(ext_dsp_module_value, 250);
165 EXPECT_EQ(0, webrtc_apm_process_reverse_stream_f_called);
166
167 ext_dsp_module_value->run(ext_dsp_module_value, 250);
168 EXPECT_EQ(1, webrtc_apm_process_reverse_stream_f_called);
169
170 float_buffer_destroy(&buf);
171 cras_apm_list_destroy(list);
172 cras_apm_list_deinit();
173 }
174
TEST(ApmList,StreamAddToAlreadyOpenedDev)175 TEST(ApmList, StreamAddToAlreadyOpenedDev) {
176 struct cras_audio_format fmt;
177 struct cras_apm *apm1, *apm2;
178
179 fmt.num_channels = 2;
180 fmt.frame_rate = 48000;
181 fmt.format = SND_PCM_FORMAT_S16_LE;
182
183 webrtc_apm_create_called = 0;
184 list = cras_apm_list_create(stream_ptr, APM_ECHO_CANCELLATION);
185 EXPECT_NE((void*)NULL, list);
186
187 apm1 = cras_apm_list_add(list, dev_ptr, &fmt);
188 EXPECT_EQ(1, webrtc_apm_create_called);
189 EXPECT_NE((void*)NULL, apm1);
190
191 apm2 = cras_apm_list_add(list, dev_ptr, &fmt);
192 EXPECT_EQ(1, webrtc_apm_create_called);
193 EXPECT_EQ(apm1, apm2);
194
195 cras_apm_list_destroy(list);
196 }
197
198 extern "C" {
cras_iodev_list_set_device_enabled_callback(device_enabled_callback_t enabled_cb,device_disabled_callback_t disabled_cb,void * cb_data)199 int cras_iodev_list_set_device_enabled_callback(
200 device_enabled_callback_t enabled_cb,
201 device_disabled_callback_t disabled_cb,
202 void* cb_data) {
203 device_enabled_callback_val = enabled_cb;
204 return 0;
205 }
cras_iodev_list_get_first_enabled_iodev(enum CRAS_STREAM_DIRECTION direction)206 struct cras_iodev* cras_iodev_list_get_first_enabled_iodev(
207 enum CRAS_STREAM_DIRECTION direction) {
208 return &fake_iodev;
209 }
cras_iodev_set_ext_dsp_module(struct cras_iodev * iodev,struct ext_dsp_module * ext)210 void cras_iodev_set_ext_dsp_module(struct cras_iodev* iodev,
211 struct ext_dsp_module* ext) {
212 ext_dsp_module_value = ext;
213 }
cras_audio_area_create(int num_channels)214 struct cras_audio_area* cras_audio_area_create(int num_channels) {
215 return &fake_audio_area;
216 }
217
cras_audio_area_destroy(struct cras_audio_area * area)218 void cras_audio_area_destroy(struct cras_audio_area* area) {}
cras_audio_area_config_channels(struct cras_audio_area * area,const struct cras_audio_format * fmt)219 void cras_audio_area_config_channels(struct cras_audio_area* area,
220 const struct cras_audio_format* fmt) {}
cras_audio_area_config_buf_pointers(struct cras_audio_area * area,const struct cras_audio_format * fmt,uint8_t * base_buffer)221 void cras_audio_area_config_buf_pointers(struct cras_audio_area* area,
222 const struct cras_audio_format* fmt,
223 uint8_t* base_buffer) {}
dsp_util_interleave(float * const * input,int16_t * output,int channels,snd_pcm_format_t format,int frames)224 void dsp_util_interleave(float* const* input,
225 int16_t* output,
226 int channels,
227 snd_pcm_format_t format,
228 int frames) {
229 dsp_util_interleave_frames = frames;
230 }
aec_config_get(const char * device_config_dir)231 struct aec_config* aec_config_get(const char* device_config_dir) {
232 return NULL;
233 }
aec_config_dump(struct aec_config * config)234 void aec_config_dump(struct aec_config* config) {}
apm_config_get(const char * device_config_dir)235 struct apm_config* apm_config_get(const char* device_config_dir) {
236 return NULL;
237 }
apm_config_dump(struct apm_config * config)238 void apm_config_dump(struct apm_config* config) {}
webrtc_apm_create(unsigned int num_channels,unsigned int frame_rate,dictionary * aec_ini,dictionary * apm_ini)239 webrtc_apm webrtc_apm_create(unsigned int num_channels,
240 unsigned int frame_rate,
241 dictionary* aec_ini,
242 dictionary* apm_ini) {
243 webrtc_apm_create_called++;
244 return reinterpret_cast<webrtc_apm>(0x11);
245 }
webrtc_apm_dump_configs(dictionary * aec_ini,dictionary * apm_ini)246 void webrtc_apm_dump_configs(dictionary* aec_ini, dictionary* apm_ini) {}
webrtc_apm_destroy(webrtc_apm apm)247 void webrtc_apm_destroy(webrtc_apm apm) {
248 return;
249 }
webrtc_apm_process_stream_f(webrtc_apm ptr,int num_channels,int rate,float * const * data)250 int webrtc_apm_process_stream_f(webrtc_apm ptr,
251 int num_channels,
252 int rate,
253 float* const* data) {
254 webrtc_apm_process_stream_f_called++;
255 return 0;
256 }
257
webrtc_apm_process_reverse_stream_f(webrtc_apm ptr,int num_channels,int rate,float * const * data)258 int webrtc_apm_process_reverse_stream_f(webrtc_apm ptr,
259 int num_channels,
260 int rate,
261 float* const* data) {
262 webrtc_apm_process_reverse_stream_f_called++;
263 return 0;
264 }
webrtc_apm_aec_dump(webrtc_apm ptr,void ** work_queue,int start,FILE * handle)265 int webrtc_apm_aec_dump(webrtc_apm ptr,
266 void** work_queue,
267 int start,
268 FILE* handle) {
269 return 0;
270 }
271
272 } // extern "C"
273 } // namespace
274
main(int argc,char ** argv)275 int main(int argc, char** argv) {
276 ::testing::InitGoogleTest(&argc, argv);
277 return RUN_ALL_TESTS();
278 }
279