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