• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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