1 // Copyright (c) 2014 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_audio_format.h"
10 #include "cras_audio_area.h"
11 }
12 
13 static const int8_t stereo[CRAS_CH_MAX] = {
14   0, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
15 };
16 static const int8_t mono[CRAS_CH_MAX] = {
17   -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1,
18 };
19 static const int8_t kb_mic[CRAS_CH_MAX] = {
20   0, 1, -1, -1, 2, -1, -1, -1, -1, -1, -1,
21 };
22 
23 static uint16_t buf1[32];
24 static uint16_t buf2[32];
25 struct cras_audio_area *a1;
26 struct cras_audio_area *a2;
27 
28 namespace {
29 
TEST(AudioArea,CopyAudioArea)30 TEST(AudioArea, CopyAudioArea) {
31   struct cras_audio_format fmt;
32   int i;
33 
34   fmt.num_channels = 2;
35   fmt.format = SND_PCM_FORMAT_S16_LE;
36   for (i = 0; i < CRAS_CH_MAX; i++)
37     fmt.channel_layout[i] = stereo[i];
38 
39   a1 = cras_audio_area_create(2);
40   a2 = cras_audio_area_create(2);
41   cras_audio_area_config_channels(a1, &fmt);
42   cras_audio_area_config_channels(a2, &fmt);
43   cras_audio_area_config_buf_pointers(a1, &fmt, (uint8_t *)buf1);
44   cras_audio_area_config_buf_pointers(a2, &fmt, (uint8_t *)buf2);
45   a1->frames = 16;
46   a2->frames = 16;
47 
48   memset(buf1, 0, 32 * 2);
49   for (i = 0; i < 32; i++)
50     buf2[i] = rand();
51   cras_audio_area_copy(a1, 0, &fmt, a2, 0, 1.0);
52   for (i = 0; i < 32; i++)
53     EXPECT_EQ(buf1[i], buf2[i]);
54 
55   cras_audio_area_destroy(a1);
56   cras_audio_area_destroy(a2);
57 }
58 
TEST(AudioArea,CopyAudioAreaWithGain)59 TEST(AudioArea, CopyAudioAreaWithGain) {
60   struct cras_audio_format fmt;
61   int i;
62   /* Check a gain of 10x can be applied. */
63   float gain_scaler = 10.0f;
64 
65   fmt.num_channels = 2;
66   fmt.format = SND_PCM_FORMAT_S16_LE;
67   for (i = 0; i < CRAS_CH_MAX; i++)
68     fmt.channel_layout[i] = stereo[i];
69 
70   a1 = cras_audio_area_create(2);
71   a2 = cras_audio_area_create(2);
72   cras_audio_area_config_channels(a1, &fmt);
73   cras_audio_area_config_channels(a2, &fmt);
74   cras_audio_area_config_buf_pointers(a1, &fmt, (uint8_t *)buf1);
75   cras_audio_area_config_buf_pointers(a2, &fmt, (uint8_t *)buf2);
76   a1->frames = 16;
77   a2->frames = 16;
78 
79   memset(buf1, 0, 32 * 2);
80   /* Let src has some samples smaller than 32768/10 and some samples larger than
81    * 32768/10 to test clipping. */
82   for (i = 0; i < 16; i++)
83     buf2[i] = rand() % 3270;
84   for (i = 17; i < 32; i++)
85     buf2[i] = 3280 + rand() % 3200;
86   cras_audio_area_copy(a1, 0, &fmt, a2, 0, gain_scaler);
87   for (i = 0; i < 32; i++) {
88     int32_t expected_value = buf2[i] * gain_scaler;
89     if (expected_value > INT16_MAX)
90       expected_value = INT16_MAX;
91     EXPECT_EQ(buf1[i], expected_value);
92   }
93 
94   cras_audio_area_destroy(a1);
95   cras_audio_area_destroy(a2);
96 }
TEST(AudioArea,CopyAudioAreaOffset)97 TEST(AudioArea, CopyAudioAreaOffset) {
98   struct cras_audio_format fmt;
99   int i;
100 
101   fmt.num_channels = 2;
102   fmt.format = SND_PCM_FORMAT_S16_LE;
103   for (i = 0; i < CRAS_CH_MAX; i++)
104     fmt.channel_layout[i] = stereo[i];
105 
106   a1 = cras_audio_area_create(2);
107   a2 = cras_audio_area_create(2);
108   cras_audio_area_config_channels(a1, &fmt);
109   cras_audio_area_config_channels(a2, &fmt);
110   cras_audio_area_config_buf_pointers(a1, &fmt, (uint8_t *)buf1);
111   cras_audio_area_config_buf_pointers(a2, &fmt, (uint8_t *)buf2);
112   a1->frames = 16;
113   a2->frames = 14;
114 
115   memset(buf1, 0, 32 * 2);
116   for (i = 0; i < 32; i++)
117     buf2[i] = rand();
118   cras_audio_area_copy(a1, 2, &fmt, a2, 0, 1.0);
119   EXPECT_EQ(buf1[0], 0);
120   EXPECT_EQ(buf1[1], 0);
121   EXPECT_EQ(buf1[2], 0);
122   EXPECT_EQ(buf1[3], 0);
123   for (i = 4; i < 32; i++)
124     EXPECT_EQ(buf1[i], buf2[i-4]);
125 
126   cras_audio_area_destroy(a1);
127   cras_audio_area_destroy(a2);
128 }
129 
TEST(AudioArea,CopyAudioAreaOffsetLimit)130 TEST(AudioArea, CopyAudioAreaOffsetLimit) {
131   struct cras_audio_format fmt;
132   int i;
133 
134   fmt.num_channels = 2;
135   fmt.format = SND_PCM_FORMAT_S16_LE;
136   for (i = 0; i < CRAS_CH_MAX; i++)
137     fmt.channel_layout[i] = stereo[i];
138 
139   a1 = cras_audio_area_create(2);
140   a2 = cras_audio_area_create(2);
141   cras_audio_area_config_channels(a1, &fmt);
142   cras_audio_area_config_channels(a2, &fmt);
143   cras_audio_area_config_buf_pointers(a1, &fmt, (uint8_t *)buf1);
144   cras_audio_area_config_buf_pointers(a2, &fmt, (uint8_t *)buf2);
145   a1->frames = 14;
146   a2->frames = 14;
147 
148   memset(buf1, 0, 32 * 2);
149   for (i = 0; i < 32; i++)
150     buf2[i] = rand();
151   cras_audio_area_copy(a1, 2, &fmt, a2, 0, 1.0);
152   EXPECT_EQ(buf1[0], 0);
153   EXPECT_EQ(buf1[1], 0);
154   EXPECT_EQ(buf1[2], 0);
155   EXPECT_EQ(buf1[3], 0);
156   for (i = 4; i < 28; i++)
157     EXPECT_EQ(buf1[i], buf2[i-4]);
158   EXPECT_EQ(buf1[28], 0);
159   EXPECT_EQ(buf1[29], 0);
160   EXPECT_EQ(buf1[30], 0);
161   EXPECT_EQ(buf1[31], 0);
162 
163   cras_audio_area_destroy(a1);
164   cras_audio_area_destroy(a2);
165 }
166 
TEST(AudioArea,CopyMonoToStereo)167 TEST(AudioArea, CopyMonoToStereo) {
168   struct cras_audio_format dst_fmt;
169   struct cras_audio_format src_fmt;
170   int i;
171 
172   dst_fmt.num_channels = 2;
173   dst_fmt.format = SND_PCM_FORMAT_S16_LE;
174   for (i = 0; i < CRAS_CH_MAX; i++)
175     dst_fmt.channel_layout[i] = stereo[i];
176   a1 = cras_audio_area_create(2);
177   a1->frames = 16;
178   cras_audio_area_config_channels(a1, &dst_fmt);
179   cras_audio_area_config_buf_pointers(a1, &dst_fmt, (uint8_t *)buf1);
180 
181   src_fmt.num_channels = 1;
182   src_fmt.format = SND_PCM_FORMAT_S16_LE;
183   for (i = 0; i < CRAS_CH_MAX; i++)
184     src_fmt.channel_layout[i] = mono[i];
185   a2 = cras_audio_area_create(1);
186   a2->frames = 16;
187   cras_audio_area_config_channels(a2, &src_fmt);
188   cras_audio_area_config_buf_pointers(a2, &src_fmt, (uint8_t *)buf2);
189 
190   memset(buf1, 0, 32 * 2);
191   for (i = 0; i < 32; i++)
192     buf2[i] = rand();
193   cras_audio_area_copy(a1, 0, &dst_fmt, a2, 0, 1.0);
194   for (i = 0; i < 16; i++) {
195     EXPECT_EQ(buf1[i * 2], buf2[i]);
196     EXPECT_EQ(buf1[i * 2 + 1], buf2[i]);
197   }
198 
199   cras_audio_area_destroy(a1);
200   cras_audio_area_destroy(a2);
201 }
202 
TEST(AudioArea,CopyStereoToMono)203 TEST(AudioArea, CopyStereoToMono) {
204   struct cras_audio_format fmt;
205   int i;
206 
207   fmt.num_channels = 1;
208   fmt.format = SND_PCM_FORMAT_S16_LE;
209   for (i = 0; i < CRAS_CH_MAX; i++)
210     fmt.channel_layout[i] = mono[i];
211   a1 = cras_audio_area_create(1);
212   a1->frames = 16;
213   cras_audio_area_config_channels(a1, &fmt);
214   cras_audio_area_config_buf_pointers(a1, &fmt, (uint8_t *)buf1);
215 
216   fmt.num_channels = 2;
217   for (i = 0; i < CRAS_CH_MAX; i++)
218     fmt.channel_layout[i] = stereo[i];
219   a2 = cras_audio_area_create(2);
220   a2->frames = 16;
221   cras_audio_area_config_channels(a2, &fmt);
222   cras_audio_area_config_buf_pointers(a2, &fmt, (uint8_t *)buf2);
223 
224   memset(buf1, 0, 32 * 2);
225   for (i = 0; i < 32; i++)
226     buf2[i] = rand() % 10000;
227   cras_audio_area_copy(a1, 0, &fmt, a2, 0, 1.0);
228   for (i = 0; i < 16; i++)
229     EXPECT_EQ(buf1[i], buf2[i * 2] + buf2[i * 2 + 1]);
230 
231   cras_audio_area_destroy(a1);
232   cras_audio_area_destroy(a2);
233 }
234 
TEST(AudioArea,KeyboardMicCopyStereo)235 TEST(AudioArea, KeyboardMicCopyStereo) {
236   struct cras_audio_format fmt;
237   int i;
238 
239   fmt.num_channels = 3;
240   fmt.format = SND_PCM_FORMAT_S16_LE;
241   for (i = 0; i < CRAS_CH_MAX; i++)
242     fmt.channel_layout[i] = kb_mic[i];
243   a1 = cras_audio_area_create(3);
244   a1->frames = 10;
245   cras_audio_area_config_channels(a1, &fmt);
246   cras_audio_area_config_buf_pointers(a1, &fmt, (uint8_t *)buf1);
247 
248   fmt.num_channels = 2;
249   for (i = 0; i < CRAS_CH_MAX; i++)
250     fmt.channel_layout[i] = stereo[i];
251   a2 = cras_audio_area_create(2);
252   a2->frames = 10;
253   cras_audio_area_config_channels(a2, &fmt);
254   cras_audio_area_config_buf_pointers(a2, &fmt, (uint8_t *)buf2);
255 
256   memset(buf1, 0, 32 * 2);
257   for (i = 0; i < 32; i++)
258     buf2[i] = rand();
259   cras_audio_area_copy(a1, 0, &fmt, a2, 0, 1.0);
260   for (i = 0; i < 10; i++) {
261     EXPECT_EQ(buf1[i * 3], buf2[i * 2]);
262     EXPECT_EQ(buf1[i * 3 + 1], buf2[i * 2 + 1]);
263     EXPECT_EQ(buf1[i * 3 + 2], 0);
264   }
265 
266   cras_audio_area_destroy(a1);
267   cras_audio_area_destroy(a2);
268 }
269 
TEST(AudioArea,KeyboardMicCopyFrontCenter)270 TEST(AudioArea, KeyboardMicCopyFrontCenter) {
271   struct cras_audio_format dst_fmt;
272   struct cras_audio_format src_fmt;
273   int i;
274 
275   dst_fmt.num_channels = 3;
276   dst_fmt.format = SND_PCM_FORMAT_S16_LE;
277   for (i = 0; i < CRAS_CH_MAX; i++)
278     dst_fmt.channel_layout[i] = kb_mic[i];
279   a1 = cras_audio_area_create(3);
280   a1->frames = 10;
281   cras_audio_area_config_channels(a1, &dst_fmt);
282   cras_audio_area_config_buf_pointers(a1, &dst_fmt, (uint8_t *)buf1);
283 
284   /* Test 2 channels area with only front center in layout. */
285   src_fmt.num_channels = 2;
286   src_fmt.format = SND_PCM_FORMAT_S16_LE;
287   for (i = 0; i < CRAS_CH_MAX; i++)
288     src_fmt.channel_layout[i] = -1;
289   src_fmt.channel_layout[CRAS_CH_FC] = 0;
290   a2 = cras_audio_area_create(2);
291   a2->frames = 10;
292   cras_audio_area_config_channels(a2, &src_fmt);
293   cras_audio_area_config_buf_pointers(a2, &src_fmt, (uint8_t *)buf2);
294 
295   memset(buf1, 0, 32 * 2);
296   for (i = 0; i < 32; i++)
297     buf2[i] = rand();
298   cras_audio_area_copy(a1, 0, &dst_fmt, a2, 0, 1.0);
299   for (i = 0; i < 10; i++) {
300     EXPECT_EQ(buf1[i * 3], 0);
301     EXPECT_EQ(buf1[i * 3 + 1], 0);
302     EXPECT_EQ(buf1[i * 3 + 2], buf2[i * 2]);
303   }
304 
305   cras_audio_area_destroy(a1);
306   cras_audio_area_destroy(a2);
307 }
308 
309 }  //  namespace
310 
311 extern "C" {
312 
cras_mix_add_scale_stride(snd_pcm_format_t fmt,uint8_t * dst,uint8_t * src,unsigned int count,unsigned int dst_stride,unsigned int src_stride,float scaler)313 void cras_mix_add_scale_stride(snd_pcm_format_t fmt, uint8_t *dst, uint8_t *src,
314 			 unsigned int count, unsigned int dst_stride,
315 			 unsigned int src_stride, float scaler)
316 {
317 	unsigned int i;
318 
319 	for (i = 0; i < count; i++) {
320 		int32_t sum;
321 		sum = *(int16_t *)dst + *(int16_t *)src * scaler;
322 		if (sum > INT16_MAX)
323 			sum = INT16_MAX;
324 		else if (sum < INT16_MIN)
325 			sum = INT16_MIN;
326 		*(int16_t*)dst = sum;
327 		dst += dst_stride;
328 		src += src_stride;
329 	}
330 }
331 
332 }  //  extern "C"
333 
main(int argc,char ** argv)334 int main(int argc, char **argv) {
335   ::testing::InitGoogleTest(&argc, argv);
336   return RUN_ALL_TESTS();
337 }
338