1 /* Copyright 2019 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 <stdint.h>
6 #include <limits.h>
7 #include <string.h>
8
9 #include "cras_fmt_conv_ops.h"
10
11 #define MAX(a, b) \
12 ({ \
13 __typeof__(a) _a = (a); \
14 __typeof__(b) _b = (b); \
15 _a > _b ? _a : _b; \
16 })
17 #define MIN(a, b) \
18 ({ \
19 __typeof__(a) _a = (a); \
20 __typeof__(b) _b = (b); \
21 _a < _b ? _a : _b; \
22 })
23
24 /*
25 * Add and clip.
26 */
s16_add_and_clip(int16_t a,int16_t b)27 static int16_t s16_add_and_clip(int16_t a, int16_t b)
28 {
29 int32_t sum;
30
31 a = htole16(a);
32 b = htole16(b);
33 sum = (int32_t)a + (int32_t)b;
34 sum = MAX(sum, SHRT_MIN);
35 sum = MIN(sum, SHRT_MAX);
36 return (int16_t)le16toh(sum);
37 }
38
39 /*
40 * Format converter.
41 */
convert_u8_to_s16le(const uint8_t * in,size_t in_samples,uint8_t * out)42 void convert_u8_to_s16le(const uint8_t *in, size_t in_samples, uint8_t *out)
43 {
44 size_t i;
45 uint16_t *_out = (uint16_t *)out;
46
47 for (i = 0; i < in_samples; i++, in++, _out++)
48 *_out = (uint16_t)((int16_t)*in - 0x80) << 8;
49 }
50
convert_s243le_to_s16le(const uint8_t * in,size_t in_samples,uint8_t * out)51 void convert_s243le_to_s16le(const uint8_t *in, size_t in_samples, uint8_t *out)
52 {
53 /* find how to calculate in and out size, implement the conversion
54 * between S24_3LE and S16 */
55
56 size_t i;
57 int8_t *_in = (int8_t *)in;
58 uint16_t *_out = (uint16_t *)out;
59
60 for (i = 0; i < in_samples; i++, _in += 3, _out++)
61 memcpy(_out, _in + 1, 2);
62 }
63
convert_s24le_to_s16le(const uint8_t * in,size_t in_samples,uint8_t * out)64 void convert_s24le_to_s16le(const uint8_t *in, size_t in_samples, uint8_t *out)
65 {
66 size_t i;
67 int32_t *_in = (int32_t *)in;
68 uint16_t *_out = (uint16_t *)out;
69
70 for (i = 0; i < in_samples; i++, _in++, _out++)
71 *_out = (int16_t)((*_in & 0x00ffffff) >> 8);
72 }
73
convert_s32le_to_s16le(const uint8_t * in,size_t in_samples,uint8_t * out)74 void convert_s32le_to_s16le(const uint8_t *in, size_t in_samples, uint8_t *out)
75 {
76 size_t i;
77 int32_t *_in = (int32_t *)in;
78 uint16_t *_out = (uint16_t *)out;
79
80 for (i = 0; i < in_samples; i++, _in++, _out++)
81 *_out = (int16_t)(*_in >> 16);
82 }
83
convert_s16le_to_u8(const uint8_t * in,size_t in_samples,uint8_t * out)84 void convert_s16le_to_u8(const uint8_t *in, size_t in_samples, uint8_t *out)
85 {
86 size_t i;
87 int16_t *_in = (int16_t *)in;
88
89 for (i = 0; i < in_samples; i++, _in++, out++)
90 *out = (uint8_t)(*_in >> 8) + 128;
91 }
92
convert_s16le_to_s243le(const uint8_t * in,size_t in_samples,uint8_t * out)93 void convert_s16le_to_s243le(const uint8_t *in, size_t in_samples, uint8_t *out)
94 {
95 size_t i;
96 int16_t *_in = (int16_t *)in;
97 uint8_t *_out = (uint8_t *)out;
98
99 for (i = 0; i < in_samples; i++, _in++, _out += 3) {
100 *_out = 0;
101 memcpy(_out + 1, _in, 2);
102 }
103 }
104
convert_s16le_to_s24le(const uint8_t * in,size_t in_samples,uint8_t * out)105 void convert_s16le_to_s24le(const uint8_t *in, size_t in_samples, uint8_t *out)
106 {
107 size_t i;
108 int16_t *_in = (int16_t *)in;
109 uint32_t *_out = (uint32_t *)out;
110
111 for (i = 0; i < in_samples; i++, _in++, _out++)
112 *_out = ((uint32_t)(int32_t)*_in << 8);
113 }
114
convert_s16le_to_s32le(const uint8_t * in,size_t in_samples,uint8_t * out)115 void convert_s16le_to_s32le(const uint8_t *in, size_t in_samples, uint8_t *out)
116 {
117 size_t i;
118 int16_t *_in = (int16_t *)in;
119 uint32_t *_out = (uint32_t *)out;
120
121 for (i = 0; i < in_samples; i++, _in++, _out++)
122 *_out = ((uint32_t)(int32_t)*_in << 16);
123 }
124
125 /*
126 * Channel converter: mono to stereo.
127 */
s16_mono_to_stereo(const uint8_t * _in,size_t in_frames,uint8_t * _out)128 size_t s16_mono_to_stereo(const uint8_t *_in, size_t in_frames, uint8_t *_out)
129 {
130 size_t i;
131 const int16_t *in = (const int16_t *)_in;
132 int16_t *out = (int16_t *)_out;
133
134 for (i = 0; i < in_frames; i++) {
135 out[2 * i] = in[i];
136 out[2 * i + 1] = in[i];
137 }
138 return in_frames;
139 }
140
141 /*
142 * Channel converter: stereo to mono.
143 */
s16_stereo_to_mono(const uint8_t * _in,size_t in_frames,uint8_t * _out)144 size_t s16_stereo_to_mono(const uint8_t *_in, size_t in_frames, uint8_t *_out)
145 {
146 size_t i;
147 const int16_t *in = (const int16_t *)_in;
148 int16_t *out = (int16_t *)_out;
149
150 for (i = 0; i < in_frames; i++)
151 out[i] = s16_add_and_clip(in[2 * i], in[2 * i + 1]);
152 return in_frames;
153 }
154
155 /*
156 * Channel converter: mono to 5.1 surround.
157 *
158 * Fit mono to front center of the output, or split to front left/right
159 * if front center is missing from the output channel layout.
160 */
s16_mono_to_51(size_t left,size_t right,size_t center,const uint8_t * _in,size_t in_frames,uint8_t * _out)161 size_t s16_mono_to_51(size_t left, size_t right, size_t center,
162 const uint8_t *_in, size_t in_frames, uint8_t *_out)
163 {
164 size_t i;
165 const int16_t *in = (const int16_t *)_in;
166 int16_t *out = (int16_t *)_out;
167
168 memset(out, 0, sizeof(*out) * 6 * in_frames);
169
170 if (center != -1)
171 for (i = 0; i < in_frames; i++)
172 out[6 * i + center] = in[i];
173 else if (left != -1 && right != -1)
174 for (i = 0; i < in_frames; i++) {
175 out[6 * i + right] = in[i] / 2;
176 out[6 * i + left] = in[i] / 2;
177 }
178 else
179 /* Select the first channel to convert to as the
180 * default behavior.
181 */
182 for (i = 0; i < in_frames; i++)
183 out[6 * i] = in[i];
184
185 return in_frames;
186 }
187
188 /*
189 * Channel converter: stereo to 5.1 surround.
190 *
191 * Fit the left/right of input to the front left/right of output respectively
192 * and fill others with zero. If any of the front left/right is missed from
193 * the output channel layout, mix to front center.
194 */
s16_stereo_to_51(size_t left,size_t right,size_t center,const uint8_t * _in,size_t in_frames,uint8_t * _out)195 size_t s16_stereo_to_51(size_t left, size_t right, size_t center,
196 const uint8_t *_in, size_t in_frames, uint8_t *_out)
197 {
198 size_t i;
199 const int16_t *in = (const int16_t *)_in;
200 int16_t *out = (int16_t *)_out;
201
202 memset(out, 0, sizeof(*out) * 6 * in_frames);
203
204 if (left != -1 && right != -1)
205 for (i = 0; i < in_frames; i++) {
206 out[6 * i + left] = in[2 * i];
207 out[6 * i + right] = in[2 * i + 1];
208 }
209 else if (center != -1)
210 for (i = 0; i < in_frames; i++)
211 out[6 * i + center] =
212 s16_add_and_clip(in[2 * i], in[2 * i + 1]);
213 else
214 /* Select the first two channels to convert to as the
215 * default behavior.
216 */
217 for (i = 0; i < in_frames; i++) {
218 out[6 * i] = in[2 * i];
219 out[6 * i + 1] = in[2 * i + 1];
220 }
221
222 return in_frames;
223 }
224
225 /*
226 * Channel converter: quad to 5.1 surround.
227 *
228 * Fit the front left/right of input to the front left/right of output
229 * and rear left/right of input to the rear left/right of output
230 * respectively and fill others with zero.
231 */
s16_quad_to_51(size_t font_left,size_t front_right,size_t rear_left,size_t rear_right,const uint8_t * _in,size_t in_frames,uint8_t * _out)232 size_t s16_quad_to_51(size_t font_left, size_t front_right, size_t rear_left,
233 size_t rear_right, const uint8_t *_in, size_t in_frames,
234 uint8_t *_out)
235 {
236 size_t i;
237 const int16_t *in = (const int16_t *)_in;
238 int16_t *out = (int16_t *)_out;
239
240 memset(out, 0, sizeof(*out) * 6 * in_frames);
241
242 if (font_left != -1 && front_right != -1 && rear_left != -1 &&
243 rear_right != -1)
244 for (i = 0; i < in_frames; i++) {
245 out[6 * i + font_left] = in[4 * i];
246 out[6 * i + front_right] = in[4 * i + 1];
247 out[6 * i + rear_left] = in[4 * i + 2];
248 out[6 * i + rear_right] = in[4 * i + 3];
249 }
250 else
251 /* Use default 5.1 channel mapping for the conversion.
252 */
253 for (i = 0; i < in_frames; i++) {
254 out[6 * i] = in[4 * i];
255 out[6 * i + 1] = in[4 * i + 1];
256 out[6 * i + 4] = in[4 * i + 2];
257 out[6 * i + 5] = in[4 * i + 3];
258 }
259
260 return in_frames;
261 }
262
263 /*
264 * Channel converter: 5.1 surround to stereo.
265 *
266 * The out buffer can have room for just stereo samples. This convert function
267 * is used as the default behavior when channel layout is not set from the
268 * client side.
269 */
s16_51_to_stereo(const uint8_t * _in,size_t in_frames,uint8_t * _out)270 size_t s16_51_to_stereo(const uint8_t *_in, size_t in_frames, uint8_t *_out)
271 {
272 const int16_t *in = (const int16_t *)_in;
273 int16_t *out = (int16_t *)_out;
274 static const unsigned int left_idx = 0;
275 static const unsigned int right_idx = 1;
276 static const unsigned int center_idx = 2;
277 /* static const unsigned int lfe_idx = 3; */
278 /* static const unsigned int left_surround_idx = 4; */
279 /* static const unsigned int right_surround_idx = 5; */
280
281 size_t i;
282 int16_t half_center;
283 /* Use the normalized_factor from the left channel = 1 / (|1| + |0.707|)
284 * to prevent mixing overflow.
285 */
286 const float normalized_factor = 0.585;
287 for (i = 0; i < in_frames; i++) {
288 half_center =
289 in[6 * i + center_idx] * 0.707 * normalized_factor;
290 out[2 * i + left_idx] =
291 in[6 * i + left_idx] * normalized_factor + half_center;
292 out[2 * i + right_idx] =
293 in[6 * i + right_idx] * normalized_factor + half_center;
294 }
295 return in_frames;
296 }
297
298 /*
299 * Channel converter: 5.1 surround to quad (front L/R, rear L/R).
300 *
301 * The out buffer can have room for just quad samples. This convert function
302 * is used as the default behavior when channel layout is not set from the
303 * client side.
304 */
s16_51_to_quad(const uint8_t * _in,size_t in_frames,uint8_t * _out)305 size_t s16_51_to_quad(const uint8_t *_in, size_t in_frames, uint8_t *_out)
306 {
307 const int16_t *in = (const int16_t *)_in;
308 int16_t *out = (int16_t *)_out;
309 static const unsigned int l_quad = 0;
310 static const unsigned int r_quad = 1;
311 static const unsigned int rl_quad = 2;
312 static const unsigned int rr_quad = 3;
313
314 static const unsigned int l_51 = 0;
315 static const unsigned int r_51 = 1;
316 static const unsigned int center_51 = 2;
317 static const unsigned int lfe_51 = 3;
318 static const unsigned int rl_51 = 4;
319 static const unsigned int rr_51 = 5;
320
321 /* Use normalized_factor from the left channel = 1 / (|1| + |0.707| + |0.5|)
322 * to prevent overflow. */
323 const float normalized_factor = 0.453;
324 size_t i;
325 for (i = 0; i < in_frames; i++) {
326 int16_t half_center;
327 int16_t lfe;
328
329 half_center = in[6 * i + center_51] * 0.707 * normalized_factor;
330 lfe = in[6 * i + lfe_51] * 0.5 * normalized_factor;
331 out[4 * i + l_quad] = normalized_factor * in[6 * i + l_51] +
332 half_center + lfe;
333 out[4 * i + r_quad] = normalized_factor * in[6 * i + r_51] +
334 half_center + lfe;
335 out[4 * i + rl_quad] =
336 normalized_factor * in[6 * i + rl_51] + lfe;
337 out[4 * i + rr_quad] =
338 normalized_factor * in[6 * i + rr_51] + lfe;
339 }
340 return in_frames;
341 }
342
343 /*
344 * Channel converter: stereo to quad (front L/R, rear L/R).
345 *
346 * Fit left/right of input to the front left/right of output respectively
347 * and fill others with zero.
348 */
s16_stereo_to_quad(size_t front_left,size_t front_right,size_t rear_left,size_t rear_right,const uint8_t * _in,size_t in_frames,uint8_t * _out)349 size_t s16_stereo_to_quad(size_t front_left, size_t front_right,
350 size_t rear_left, size_t rear_right,
351 const uint8_t *_in, size_t in_frames, uint8_t *_out)
352 {
353 size_t i;
354 const int16_t *in = (const int16_t *)_in;
355 int16_t *out = (int16_t *)_out;
356
357 if (front_left != -1 && front_right != -1 && rear_left != -1 &&
358 rear_right != -1)
359 for (i = 0; i < in_frames; i++) {
360 out[4 * i + front_left] = in[2 * i];
361 out[4 * i + front_right] = in[2 * i + 1];
362 out[4 * i + rear_left] = in[2 * i];
363 out[4 * i + rear_right] = in[2 * i + 1];
364 }
365 else
366 /* Select the first four channels to convert to as the
367 * default behavior.
368 */
369 for (i = 0; i < in_frames; i++) {
370 out[4 * i] = in[2 * i];
371 out[4 * i + 1] = in[2 * i + 1];
372 out[4 * i + 2] = in[2 * i];
373 out[4 * i + 3] = in[2 * i + 1];
374 }
375
376 return in_frames;
377 }
378
379 /*
380 * Channel converter: quad (front L/R, rear L/R) to stereo.
381 */
s16_quad_to_stereo(size_t front_left,size_t front_right,size_t rear_left,size_t rear_right,const uint8_t * _in,size_t in_frames,uint8_t * _out)382 size_t s16_quad_to_stereo(size_t front_left, size_t front_right,
383 size_t rear_left, size_t rear_right,
384 const uint8_t *_in, size_t in_frames, uint8_t *_out)
385 {
386 size_t i;
387 const int16_t *in = (const int16_t *)_in;
388 int16_t *out = (int16_t *)_out;
389
390 if (front_left == -1 || front_right == -1 || rear_left == -1 ||
391 rear_right == -1) {
392 front_left = 0;
393 front_right = 1;
394 rear_left = 2;
395 rear_right = 3;
396 }
397
398 for (i = 0; i < in_frames; i++) {
399 out[2 * i] = s16_add_and_clip(in[4 * i + front_left],
400 in[4 * i + rear_left] / 4);
401 out[2 * i + 1] = s16_add_and_clip(in[4 * i + front_right],
402 in[4 * i + rear_right] / 4);
403 }
404 return in_frames;
405 }
406
407 /*
408 * Channel converter: N channels to M channels.
409 *
410 * The out buffer must have room for M channel. This convert function is used
411 * as the default behavior when channel layout is not set from the client side.
412 */
s16_default_all_to_all(struct cras_audio_format * out_fmt,size_t num_in_ch,size_t num_out_ch,const uint8_t * _in,size_t in_frames,uint8_t * _out)413 size_t s16_default_all_to_all(struct cras_audio_format *out_fmt,
414 size_t num_in_ch, size_t num_out_ch,
415 const uint8_t *_in, size_t in_frames,
416 uint8_t *_out)
417 {
418 unsigned int in_ch, out_ch, i;
419 const int16_t *in = (const int16_t *)_in;
420 int16_t *out = (int16_t *)_out;
421 int32_t sum;
422
423 for (i = 0; i < in_frames; i++) {
424 sum = 0;
425 for (in_ch = 0; in_ch < num_in_ch; in_ch++) {
426 sum += (int32_t)in[in_ch + i * num_in_ch];
427 }
428 /*
429 * 1. Divide `int32_t` by `size_t` without an explicit
430 * conversion will generate corrupted results.
431 * 2. After the division, `sum` should be in the range of
432 * int16_t. No clipping is needed.
433 */
434 sum /= (int32_t)num_in_ch;
435 for (out_ch = 0; out_ch < num_out_ch; out_ch++) {
436 out[out_ch + i * num_out_ch] = (int16_t)sum;
437 }
438 }
439 return in_frames;
440 }
441
442 /*
443 * Copies the input channels across output channels. Drops input channels that
444 * don't fit. Ignores output channels greater than the number of input channels.
445 */
s16_some_to_some(const struct cras_audio_format * out_fmt,const size_t num_in_ch,const size_t num_out_ch,const uint8_t * _in,const size_t frame_count,uint8_t * _out)446 size_t s16_some_to_some(const struct cras_audio_format *out_fmt,
447 const size_t num_in_ch, const size_t num_out_ch,
448 const uint8_t *_in, const size_t frame_count,
449 uint8_t *_out)
450 {
451 unsigned int i;
452 const int16_t *in = (const int16_t *)_in;
453 int16_t *out = (int16_t *)_out;
454 const size_t num_copy_ch = MIN(num_in_ch, num_out_ch);
455
456 memset(out, 0, frame_count * cras_get_format_bytes(out_fmt));
457 for (i = 0; i < frame_count; i++, out += num_out_ch, in += num_in_ch) {
458 memcpy(out, in, num_copy_ch * sizeof(int16_t));
459 }
460
461 return frame_count;
462 }
463
464 /*
465 * Multiplies buffer vector with coefficient vector.
466 */
s16_multiply_buf_with_coef(float * coef,const int16_t * buf,size_t size)467 int16_t s16_multiply_buf_with_coef(float *coef, const int16_t *buf, size_t size)
468 {
469 int32_t sum = 0;
470 int i;
471
472 for (i = 0; i < size; i++)
473 sum += coef[i] * buf[i];
474 sum = MAX(sum, -0x8000);
475 sum = MIN(sum, 0x7fff);
476 return (int16_t)sum;
477 }
478
479 /*
480 * Channel layout converter.
481 *
482 * Converts channels based on the channel conversion coefficient matrix.
483 */
s16_convert_channels(float ** ch_conv_mtx,size_t num_in_ch,size_t num_out_ch,const uint8_t * _in,size_t in_frames,uint8_t * _out)484 size_t s16_convert_channels(float **ch_conv_mtx, size_t num_in_ch,
485 size_t num_out_ch, const uint8_t *_in,
486 size_t in_frames, uint8_t *_out)
487 {
488 unsigned i, fr;
489 unsigned in_idx = 0;
490 unsigned out_idx = 0;
491 const int16_t *in = (const int16_t *)_in;
492 int16_t *out = (int16_t *)_out;
493
494 for (fr = 0; fr < in_frames; fr++) {
495 for (i = 0; i < num_out_ch; i++)
496 out[out_idx + i] = s16_multiply_buf_with_coef(
497 ch_conv_mtx[i], &in[in_idx], num_in_ch);
498 in_idx += num_in_ch;
499 out_idx += num_out_ch;
500 }
501
502 return in_frames;
503 }
504