• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (c) 2012 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 
6 #include <stdint.h>
7 
8 #include "cras_system_state.h"
9 #include "cras_mix_ops.h"
10 
11 #define MAX_VOLUME_TO_SCALE 0.9999999
12 #define MIN_VOLUME_TO_SCALE 0.0000001
13 
14 /* function suffixes for SIMD ops */
15 #ifdef OPS_SSE42
16 #define OPS(a) a##_sse42
17 #elif OPS_AVX
18 #define OPS(a) a##_avx
19 #elif OPS_AVX2
20 #define OPS(a) a##_avx2
21 #elif OPS_FMA
22 #define OPS(a) a##_fma
23 #else
24 #define OPS(a) a
25 #endif
26 
27 /* Checks if the scaler needs a scaling operation.
28  * We skip scaling for scaler too close to 1.0.
29  * Note that this is not subjected to MAX_VOLUME_TO_SCALE
30  * and MIN_VOLUME_TO_SCALE. */
need_to_scale(float scaler)31 static inline int need_to_scale(float scaler)
32 {
33 	return (scaler < 0.99 || scaler > 1.01);
34 }
35 
36 /*
37  * Signed 16 bit little endian functions.
38  */
39 
cras_mix_add_clip_s16_le(int16_t * dst,const int16_t * src,size_t count)40 static void cras_mix_add_clip_s16_le(int16_t *dst, const int16_t *src,
41 				     size_t count)
42 {
43 	int32_t sum;
44 	size_t i;
45 
46 	for (i = 0; i < count; i++) {
47 		sum = dst[i] + src[i];
48 		if (sum > INT16_MAX)
49 			sum = INT16_MAX;
50 		else if (sum < INT16_MIN)
51 			sum = INT16_MIN;
52 		dst[i] = sum;
53 	}
54 }
55 
56 /* Adds src into dst, after scaling by vol.
57  * Just hard limits to the min and max S16 value, can be improved later. */
scale_add_clip_s16_le(int16_t * dst,const int16_t * src,size_t count,float vol)58 static void scale_add_clip_s16_le(int16_t *dst, const int16_t *src,
59 				  size_t count, float vol)
60 {
61 	int32_t sum;
62 	size_t i;
63 
64 	if (vol > MAX_VOLUME_TO_SCALE)
65 		return cras_mix_add_clip_s16_le(dst, src, count);
66 
67 	for (i = 0; i < count; i++) {
68 		sum = dst[i] + (int16_t)(src[i] * vol);
69 		if (sum > INT16_MAX)
70 			sum = INT16_MAX;
71 		else if (sum < INT16_MIN)
72 			sum = INT16_MIN;
73 		dst[i] = sum;
74 	}
75 }
76 
77 /* Adds the first stream to the mix.  Don't need to mix, just setup to the new
78  * values. If volume is 1.0, just memcpy. */
copy_scaled_s16_le(int16_t * dst,const int16_t * src,size_t count,float volume_scaler)79 static void copy_scaled_s16_le(int16_t *dst, const int16_t *src, size_t count,
80 			       float volume_scaler)
81 {
82 	int i;
83 
84 	if (volume_scaler > MAX_VOLUME_TO_SCALE) {
85 		memcpy(dst, src, count * sizeof(*src));
86 		return;
87 	}
88 
89 	for (i = 0; i < count; i++)
90 		dst[i] = src[i] * volume_scaler;
91 }
92 
cras_scale_buffer_inc_s16_le(uint8_t * buffer,unsigned int count,float scaler,float increment,float target,int step)93 static void cras_scale_buffer_inc_s16_le(uint8_t *buffer, unsigned int count,
94 					 float scaler, float increment,
95 					 float target, int step)
96 {
97 	int i = 0, j;
98 	int16_t *out = (int16_t *)buffer;
99 
100 	if (scaler < MIN_VOLUME_TO_SCALE && increment < 0) {
101 		memset(out, 0, count * sizeof(*out));
102 		return;
103 	}
104 
105 	while (i + step <= count) {
106 		for (j = 0; j < step; j++) {
107 			float applied_scaler = scaler;
108 
109 			if ((applied_scaler > target && increment > 0) ||
110 			    (applied_scaler < target && increment < 0))
111 				applied_scaler = target;
112 
113 			if (applied_scaler > MAX_VOLUME_TO_SCALE) {
114 			} else if (applied_scaler < MIN_VOLUME_TO_SCALE) {
115 				out[i] = 0;
116 			} else {
117 				out[i] *= applied_scaler;
118 			}
119 			i++;
120 		}
121 		scaler += increment;
122 	}
123 }
124 
cras_scale_buffer_s16_le(uint8_t * buffer,unsigned int count,float scaler)125 static void cras_scale_buffer_s16_le(uint8_t *buffer, unsigned int count,
126 				     float scaler)
127 {
128 	int i;
129 	int16_t *out = (int16_t *)buffer;
130 
131 	if (scaler > MAX_VOLUME_TO_SCALE)
132 		return;
133 
134 	if (scaler < MIN_VOLUME_TO_SCALE) {
135 		memset(out, 0, count * sizeof(*out));
136 		return;
137 	}
138 
139 	for (i = 0; i < count; i++)
140 		out[i] *= scaler;
141 }
142 
cras_mix_add_s16_le(uint8_t * dst,uint8_t * src,unsigned int count,unsigned int index,int mute,float mix_vol)143 static void cras_mix_add_s16_le(uint8_t *dst, uint8_t *src, unsigned int count,
144 				unsigned int index, int mute, float mix_vol)
145 {
146 	int16_t *out = (int16_t *)dst;
147 	int16_t *in = (int16_t *)src;
148 
149 	if (mute || (mix_vol < MIN_VOLUME_TO_SCALE)) {
150 		if (index == 0)
151 			memset(out, 0, count * sizeof(*out));
152 		return;
153 	}
154 
155 	if (index == 0)
156 		return copy_scaled_s16_le(out, in, count, mix_vol);
157 
158 	scale_add_clip_s16_le(out, in, count, mix_vol);
159 }
160 
cras_mix_add_scale_stride_s16_le(uint8_t * dst,uint8_t * src,unsigned int dst_stride,unsigned int src_stride,unsigned int count,float scaler)161 static void cras_mix_add_scale_stride_s16_le(uint8_t *dst, uint8_t *src,
162 					     unsigned int dst_stride,
163 					     unsigned int src_stride,
164 					     unsigned int count, float scaler)
165 {
166 	unsigned int i;
167 
168 	/* optimise the loops for vectorization */
169 	if (dst_stride == src_stride && dst_stride == 2) {
170 		for (i = 0; i < count; i++) {
171 			int32_t sum;
172 			if (need_to_scale(scaler))
173 				sum = *(int16_t *)dst +
174 				      *(int16_t *)src * scaler;
175 			else
176 				sum = *(int16_t *)dst + *(int16_t *)src;
177 			if (sum > INT16_MAX)
178 				sum = INT16_MAX;
179 			else if (sum < INT16_MIN)
180 				sum = INT16_MIN;
181 			*(int16_t *)dst = sum;
182 			dst += 2;
183 			src += 2;
184 		}
185 	} else if (dst_stride == src_stride && dst_stride == 4) {
186 		for (i = 0; i < count; i++) {
187 			int32_t sum;
188 			if (need_to_scale(scaler))
189 				sum = *(int16_t *)dst +
190 				      *(int16_t *)src * scaler;
191 			else
192 				sum = *(int16_t *)dst + *(int16_t *)src;
193 			if (sum > INT16_MAX)
194 				sum = INT16_MAX;
195 			else if (sum < INT16_MIN)
196 				sum = INT16_MIN;
197 			*(int16_t *)dst = sum;
198 			dst += 4;
199 			src += 4;
200 		}
201 	} else {
202 		for (i = 0; i < count; i++) {
203 			int32_t sum;
204 			if (need_to_scale(scaler))
205 				sum = *(int16_t *)dst +
206 				      *(int16_t *)src * scaler;
207 			else
208 				sum = *(int16_t *)dst + *(int16_t *)src;
209 			if (sum > INT16_MAX)
210 				sum = INT16_MAX;
211 			else if (sum < INT16_MIN)
212 				sum = INT16_MIN;
213 			*(int16_t *)dst = sum;
214 			dst += dst_stride;
215 			src += src_stride;
216 		}
217 	}
218 }
219 
220 /*
221  * Signed 24 bit little endian functions.
222  */
223 
scale_s24_le(int32_t value,float scaler)224 static int32_t scale_s24_le(int32_t value, float scaler)
225 {
226 	value = ((uint32_t)(value & 0x00ffffff)) << 8;
227 	value *= scaler;
228 	return (value >> 8) & 0x00ffffff;
229 }
230 
cras_mix_add_clip_s24_le(int32_t * dst,const int32_t * src,size_t count)231 static void cras_mix_add_clip_s24_le(int32_t *dst, const int32_t *src,
232 				     size_t count)
233 {
234 	int32_t sum;
235 	size_t i;
236 
237 	for (i = 0; i < count; i++) {
238 		sum = dst[i] + src[i];
239 		if (sum > 0x007fffff)
240 			sum = 0x007fffff;
241 		else if (sum < (int32_t)0xff800000)
242 			sum = (int32_t)0xff800000;
243 		dst[i] = sum;
244 	}
245 }
246 
247 /* Adds src into dst, after scaling by vol.
248  * Just hard limits to the min and max S24 value, can be improved later. */
scale_add_clip_s24_le(int32_t * dst,const int32_t * src,size_t count,float vol)249 static void scale_add_clip_s24_le(int32_t *dst, const int32_t *src,
250 				  size_t count, float vol)
251 {
252 	int32_t sum;
253 	size_t i;
254 
255 	if (vol > MAX_VOLUME_TO_SCALE)
256 		return cras_mix_add_clip_s24_le(dst, src, count);
257 
258 	for (i = 0; i < count; i++) {
259 		sum = dst[i] + (int32_t)(src[i] * vol);
260 		if (sum > 0x007fffff)
261 			sum = 0x007fffff;
262 		else if (sum < (int32_t)0xff800000)
263 			sum = (int32_t)0xff800000;
264 		dst[i] = sum;
265 	}
266 }
267 
268 /* Adds the first stream to the mix.  Don't need to mix, just setup to the new
269  * values. If volume is 1.0, just memcpy. */
copy_scaled_s24_le(int32_t * dst,const int32_t * src,size_t count,float volume_scaler)270 static void copy_scaled_s24_le(int32_t *dst, const int32_t *src, size_t count,
271 			       float volume_scaler)
272 {
273 	int i;
274 
275 	if (volume_scaler > MAX_VOLUME_TO_SCALE) {
276 		memcpy(dst, src, count * sizeof(*src));
277 		return;
278 	}
279 
280 	for (i = 0; i < count; i++)
281 		dst[i] = scale_s24_le(src[i], volume_scaler);
282 }
283 
cras_scale_buffer_inc_s24_le(uint8_t * buffer,unsigned int count,float scaler,float increment,float target,int step)284 static void cras_scale_buffer_inc_s24_le(uint8_t *buffer, unsigned int count,
285 					 float scaler, float increment,
286 					 float target, int step)
287 {
288 	int i = 0, j;
289 	int32_t *out = (int32_t *)buffer;
290 
291 	if (scaler < MIN_VOLUME_TO_SCALE && increment < 0) {
292 		memset(out, 0, count * sizeof(*out));
293 		return;
294 	}
295 
296 	while (i + step <= count) {
297 		for (j = 0; j < step; j++) {
298 			float applied_scaler = scaler;
299 
300 			if ((applied_scaler > target && increment > 0) ||
301 			    (applied_scaler < target && increment < 0))
302 				applied_scaler = target;
303 
304 			if (applied_scaler > MAX_VOLUME_TO_SCALE) {
305 			} else if (applied_scaler < MIN_VOLUME_TO_SCALE) {
306 				out[i] = 0;
307 			} else {
308 				out[i] = scale_s24_le(out[i], applied_scaler);
309 			}
310 			i++;
311 		}
312 		scaler += increment;
313 	}
314 }
315 
cras_scale_buffer_s24_le(uint8_t * buffer,unsigned int count,float scaler)316 static void cras_scale_buffer_s24_le(uint8_t *buffer, unsigned int count,
317 				     float scaler)
318 {
319 	int i;
320 	int32_t *out = (int32_t *)buffer;
321 
322 	if (scaler > MAX_VOLUME_TO_SCALE)
323 		return;
324 
325 	if (scaler < MIN_VOLUME_TO_SCALE) {
326 		memset(out, 0, count * sizeof(*out));
327 		return;
328 	}
329 
330 	for (i = 0; i < count; i++)
331 		out[i] = scale_s24_le(out[i], scaler);
332 }
333 
cras_mix_add_s24_le(uint8_t * dst,uint8_t * src,unsigned int count,unsigned int index,int mute,float mix_vol)334 static void cras_mix_add_s24_le(uint8_t *dst, uint8_t *src, unsigned int count,
335 				unsigned int index, int mute, float mix_vol)
336 {
337 	int32_t *out = (int32_t *)dst;
338 	int32_t *in = (int32_t *)src;
339 
340 	if (mute || (mix_vol < MIN_VOLUME_TO_SCALE)) {
341 		if (index == 0)
342 			memset(out, 0, count * sizeof(*out));
343 		return;
344 	}
345 
346 	if (index == 0)
347 		return copy_scaled_s24_le(out, in, count, mix_vol);
348 
349 	scale_add_clip_s24_le(out, in, count, mix_vol);
350 }
351 
cras_mix_add_scale_stride_s24_le(uint8_t * dst,uint8_t * src,unsigned int dst_stride,unsigned int src_stride,unsigned int count,float scaler)352 static void cras_mix_add_scale_stride_s24_le(uint8_t *dst, uint8_t *src,
353 					     unsigned int dst_stride,
354 					     unsigned int src_stride,
355 					     unsigned int count, float scaler)
356 {
357 	unsigned int i;
358 
359 	/* optimise the loops for vectorization */
360 	if (dst_stride == src_stride && dst_stride == 4) {
361 		for (i = 0; i < count; i++) {
362 			int32_t sum;
363 			if (need_to_scale(scaler))
364 				sum = *(int32_t *)dst +
365 				      scale_s24_le(*(int32_t *)src, scaler);
366 			else
367 				sum = *(int32_t *)dst + *(int32_t *)src;
368 			if (sum > 0x007fffff)
369 				sum = 0x007fffff;
370 			else if (sum < (int32_t)0xff800000)
371 				sum = (int32_t)0xff800000;
372 			*(int32_t *)dst = sum;
373 			dst += 4;
374 			src += 4;
375 		}
376 	} else {
377 		for (i = 0; i < count; i++) {
378 			int32_t sum;
379 			if (need_to_scale(scaler))
380 				sum = *(int32_t *)dst +
381 				      scale_s24_le(*(int32_t *)src, scaler);
382 			else
383 				sum = *(int32_t *)dst + *(int32_t *)src;
384 			if (sum > 0x007fffff)
385 				sum = 0x007fffff;
386 			else if (sum < (int32_t)0xff800000)
387 				sum = (int32_t)0xff800000;
388 			*(int32_t *)dst = sum;
389 			dst += dst_stride;
390 			src += src_stride;
391 		}
392 	}
393 }
394 
395 /*
396  * Signed 32 bit little endian functions.
397  */
398 
cras_mix_add_clip_s32_le(int32_t * dst,const int32_t * src,size_t count)399 static void cras_mix_add_clip_s32_le(int32_t *dst, const int32_t *src,
400 				     size_t count)
401 {
402 	int64_t sum;
403 	size_t i;
404 
405 	for (i = 0; i < count; i++) {
406 		sum = (int64_t)dst[i] + (int64_t)src[i];
407 		if (sum > INT32_MAX)
408 			sum = INT32_MAX;
409 		else if (sum < INT32_MIN)
410 			sum = INT32_MIN;
411 		dst[i] = sum;
412 	}
413 }
414 
415 /* Adds src into dst, after scaling by vol.
416  * Just hard limits to the min and max S32 value, can be improved later. */
scale_add_clip_s32_le(int32_t * dst,const int32_t * src,size_t count,float vol)417 static void scale_add_clip_s32_le(int32_t *dst, const int32_t *src,
418 				  size_t count, float vol)
419 {
420 	int64_t sum;
421 	size_t i;
422 
423 	if (vol > MAX_VOLUME_TO_SCALE)
424 		return cras_mix_add_clip_s32_le(dst, src, count);
425 
426 	for (i = 0; i < count; i++) {
427 		sum = (int64_t)dst[i] + (int64_t)(src[i] * vol);
428 		if (sum > INT32_MAX)
429 			sum = INT32_MAX;
430 		else if (sum < INT32_MIN)
431 			sum = INT32_MIN;
432 		dst[i] = sum;
433 	}
434 }
435 
436 /* Adds the first stream to the mix.  Don't need to mix, just setup to the new
437  * values. If volume is 1.0, just memcpy. */
copy_scaled_s32_le(int32_t * dst,const int32_t * src,size_t count,float volume_scaler)438 static void copy_scaled_s32_le(int32_t *dst, const int32_t *src, size_t count,
439 			       float volume_scaler)
440 {
441 	int i;
442 
443 	if (volume_scaler > MAX_VOLUME_TO_SCALE) {
444 		memcpy(dst, src, count * sizeof(*src));
445 		return;
446 	}
447 
448 	for (i = 0; i < count; i++)
449 		dst[i] = src[i] * volume_scaler;
450 }
451 
cras_scale_buffer_inc_s32_le(uint8_t * buffer,unsigned int count,float scaler,float increment,float target,int step)452 static void cras_scale_buffer_inc_s32_le(uint8_t *buffer, unsigned int count,
453 					 float scaler, float increment,
454 					 float target, int step)
455 {
456 	int i = 0, j;
457 	int32_t *out = (int32_t *)buffer;
458 
459 	if (scaler < MIN_VOLUME_TO_SCALE && increment < 0) {
460 		memset(out, 0, count * sizeof(*out));
461 		return;
462 	}
463 
464 	while (i + step <= count) {
465 		for (j = 0; j < step; j++) {
466 			float applied_scaler = scaler;
467 
468 			if ((applied_scaler > target && increment > 0) ||
469 			    (applied_scaler < target && increment < 0))
470 				applied_scaler = target;
471 
472 			if (applied_scaler > MAX_VOLUME_TO_SCALE) {
473 			} else if (applied_scaler < MIN_VOLUME_TO_SCALE) {
474 				out[i] = 0;
475 			} else {
476 				out[i] *= applied_scaler;
477 			}
478 			i++;
479 		}
480 		scaler += increment;
481 	}
482 }
483 
cras_scale_buffer_s32_le(uint8_t * buffer,unsigned int count,float scaler)484 static void cras_scale_buffer_s32_le(uint8_t *buffer, unsigned int count,
485 				     float scaler)
486 {
487 	int i;
488 	int32_t *out = (int32_t *)buffer;
489 
490 	if (scaler > MAX_VOLUME_TO_SCALE)
491 		return;
492 
493 	if (scaler < MIN_VOLUME_TO_SCALE) {
494 		memset(out, 0, count * sizeof(*out));
495 		return;
496 	}
497 
498 	for (i = 0; i < count; i++)
499 		out[i] *= scaler;
500 }
501 
cras_mix_add_s32_le(uint8_t * dst,uint8_t * src,unsigned int count,unsigned int index,int mute,float mix_vol)502 static void cras_mix_add_s32_le(uint8_t *dst, uint8_t *src, unsigned int count,
503 				unsigned int index, int mute, float mix_vol)
504 {
505 	int32_t *out = (int32_t *)dst;
506 	int32_t *in = (int32_t *)src;
507 
508 	if (mute || (mix_vol < MIN_VOLUME_TO_SCALE)) {
509 		if (index == 0)
510 			memset(out, 0, count * sizeof(*out));
511 		return;
512 	}
513 
514 	if (index == 0)
515 		return copy_scaled_s32_le(out, in, count, mix_vol);
516 
517 	scale_add_clip_s32_le(out, in, count, mix_vol);
518 }
519 
cras_mix_add_scale_stride_s32_le(uint8_t * dst,uint8_t * src,unsigned int dst_stride,unsigned int src_stride,unsigned int count,float scaler)520 static void cras_mix_add_scale_stride_s32_le(uint8_t *dst, uint8_t *src,
521 					     unsigned int dst_stride,
522 					     unsigned int src_stride,
523 					     unsigned int count, float scaler)
524 {
525 	unsigned int i;
526 
527 	/* optimise the loops for vectorization */
528 	if (dst_stride == src_stride && dst_stride == 4) {
529 		for (i = 0; i < count; i++) {
530 			int64_t sum;
531 			if (need_to_scale(scaler))
532 				sum = *(int32_t *)dst +
533 				      *(int32_t *)src * scaler;
534 			else
535 				sum = *(int32_t *)dst + *(int32_t *)src;
536 			if (sum > INT32_MAX)
537 				sum = INT32_MAX;
538 			else if (sum < INT32_MIN)
539 				sum = INT32_MIN;
540 			*(int32_t *)dst = sum;
541 			dst += 4;
542 			src += 4;
543 		}
544 	} else {
545 		for (i = 0; i < count; i++) {
546 			int64_t sum;
547 			if (need_to_scale(scaler))
548 				sum = *(int32_t *)dst +
549 				      *(int32_t *)src * scaler;
550 			else
551 				sum = *(int32_t *)dst + *(int32_t *)src;
552 			if (sum > INT32_MAX)
553 				sum = INT32_MAX;
554 			else if (sum < INT32_MIN)
555 				sum = INT32_MIN;
556 			*(int32_t *)dst = sum;
557 			dst += dst_stride;
558 			src += src_stride;
559 		}
560 	}
561 }
562 
563 /*
564  * Signed 24 bit little endian in three bytes functions.
565  */
566 
567 /* Convert 3bytes Signed 24bit integer to a Signed 32bit integer.
568  * Just a helper function. */
convert_single_s243le_to_s32le(int32_t * dst,const uint8_t * src)569 static inline void convert_single_s243le_to_s32le(int32_t *dst,
570 						  const uint8_t *src)
571 {
572 	*dst = 0;
573 	memcpy((uint8_t *)dst + 1, src, 3);
574 }
575 
convert_single_s32le_to_s243le(uint8_t * dst,const int32_t * src)576 static inline void convert_single_s32le_to_s243le(uint8_t *dst,
577 						  const int32_t *src)
578 {
579 	memcpy(dst, (uint8_t *)src + 1, 3);
580 }
581 
cras_mix_add_clip_s24_3le(uint8_t * dst,const uint8_t * src,size_t count)582 static void cras_mix_add_clip_s24_3le(uint8_t *dst, const uint8_t *src,
583 				      size_t count)
584 {
585 	int64_t sum;
586 	int32_t dst_frame;
587 	int32_t src_frame;
588 	size_t i;
589 
590 	for (i = 0; i < count; i++, dst += 3, src += 3) {
591 		convert_single_s243le_to_s32le(&dst_frame, dst);
592 		convert_single_s243le_to_s32le(&src_frame, src);
593 		sum = (int64_t)dst_frame + (int64_t)src_frame;
594 		if (sum > INT32_MAX)
595 			sum = INT32_MAX;
596 		else if (sum < INT32_MIN)
597 			sum = INT32_MIN;
598 		dst_frame = (int32_t)sum;
599 		convert_single_s32le_to_s243le(dst, &dst_frame);
600 	}
601 }
602 
603 /* Adds src into dst, after scaling by vol.
604  * Just hard limits to the min and max S24 value, can be improved later. */
scale_add_clip_s24_3le(uint8_t * dst,const uint8_t * src,size_t count,float vol)605 static void scale_add_clip_s24_3le(uint8_t *dst, const uint8_t *src,
606 				   size_t count, float vol)
607 {
608 	int64_t sum;
609 	int32_t dst_frame;
610 	int32_t src_frame;
611 	size_t i;
612 
613 	if (vol > MAX_VOLUME_TO_SCALE)
614 		return cras_mix_add_clip_s24_3le(dst, src, count);
615 
616 	for (i = 0; i < count; i++, dst += 3, src += 3) {
617 		convert_single_s243le_to_s32le(&dst_frame, dst);
618 		convert_single_s243le_to_s32le(&src_frame, src);
619 		sum = (int64_t)dst_frame + (int64_t)(src_frame * vol);
620 		if (sum > INT32_MAX)
621 			sum = INT32_MAX;
622 		else if (sum < INT32_MIN)
623 			sum = INT32_MIN;
624 		dst_frame = (int32_t)sum;
625 		convert_single_s32le_to_s243le(dst, &dst_frame);
626 	}
627 }
628 
629 /* Adds the first stream to the mix.  Don't need to mix, just setup to the new
630  * values. If volume is 1.0, just memcpy. */
copy_scaled_s24_3le(uint8_t * dst,const uint8_t * src,size_t count,float volume_scaler)631 static void copy_scaled_s24_3le(uint8_t *dst, const uint8_t *src, size_t count,
632 				float volume_scaler)
633 {
634 	int32_t frame;
635 	size_t i;
636 
637 	if (volume_scaler > MAX_VOLUME_TO_SCALE) {
638 		memcpy(dst, src, 3 * count * sizeof(*src));
639 		return;
640 	}
641 
642 	for (i = 0; i < count; i++, dst += 3, src += 3) {
643 		convert_single_s243le_to_s32le(&frame, src);
644 		frame *= volume_scaler;
645 		convert_single_s32le_to_s243le(dst, &frame);
646 	}
647 }
648 
cras_scale_buffer_inc_s24_3le(uint8_t * buffer,unsigned int count,float scaler,float increment,float target,int step)649 static void cras_scale_buffer_inc_s24_3le(uint8_t *buffer, unsigned int count,
650 					  float scaler, float increment,
651 					  float target, int step)
652 {
653 	int32_t frame;
654 	int i = 0, j;
655 
656 	if (scaler < MIN_VOLUME_TO_SCALE && increment < 0) {
657 		memset(buffer, 0, 3 * count * sizeof(*buffer));
658 		return;
659 	}
660 
661 	while (i + step <= count) {
662 		for (j = 0; j < step; j++) {
663 			float applied_scaler = scaler;
664 
665 			if ((applied_scaler > target && increment > 0) ||
666 			    (applied_scaler < target && increment < 0))
667 				applied_scaler = target;
668 
669 			convert_single_s243le_to_s32le(&frame, buffer);
670 
671 			if (applied_scaler > MAX_VOLUME_TO_SCALE) {
672 			} else if (applied_scaler < MIN_VOLUME_TO_SCALE) {
673 				frame = 0;
674 			} else {
675 				frame *= applied_scaler;
676 			}
677 
678 			convert_single_s32le_to_s243le(buffer, &frame);
679 
680 			i++;
681 			buffer += 3;
682 		}
683 		scaler += increment;
684 	}
685 }
686 
cras_scale_buffer_s24_3le(uint8_t * buffer,unsigned int count,float scaler)687 static void cras_scale_buffer_s24_3le(uint8_t *buffer, unsigned int count,
688 				      float scaler)
689 {
690 	int32_t frame;
691 	int i;
692 
693 	if (scaler > MAX_VOLUME_TO_SCALE)
694 		return;
695 
696 	if (scaler < MIN_VOLUME_TO_SCALE) {
697 		memset(buffer, 0, 3 * count * sizeof(*buffer));
698 		return;
699 	}
700 
701 	for (i = 0; i < count; i++, buffer += 3) {
702 		convert_single_s243le_to_s32le(&frame, buffer);
703 		frame *= scaler;
704 		convert_single_s32le_to_s243le(buffer, &frame);
705 	}
706 }
707 
cras_mix_add_s24_3le(uint8_t * dst,uint8_t * src,unsigned int count,unsigned int index,int mute,float mix_vol)708 static void cras_mix_add_s24_3le(uint8_t *dst, uint8_t *src, unsigned int count,
709 				 unsigned int index, int mute, float mix_vol)
710 {
711 	uint8_t *out = dst;
712 	uint8_t *in = src;
713 
714 	if (mute || (mix_vol < MIN_VOLUME_TO_SCALE)) {
715 		if (index == 0)
716 			memset(out, 0, 3 * count * sizeof(*out));
717 		return;
718 	}
719 
720 	if (index == 0)
721 		return copy_scaled_s24_3le(out, in, count, mix_vol);
722 
723 	scale_add_clip_s24_3le(out, in, count, mix_vol);
724 }
725 
cras_mix_add_scale_stride_s24_3le(uint8_t * dst,uint8_t * src,unsigned int dst_stride,unsigned int src_stride,unsigned int count,float scaler)726 static void cras_mix_add_scale_stride_s24_3le(uint8_t *dst, uint8_t *src,
727 					      unsigned int dst_stride,
728 					      unsigned int src_stride,
729 					      unsigned int count, float scaler)
730 {
731 	unsigned int i;
732 	int64_t sum;
733 	int32_t dst_frame;
734 	int32_t src_frame;
735 
736 	for (i = 0; i < count; i++) {
737 		convert_single_s243le_to_s32le(&dst_frame, dst);
738 		convert_single_s243le_to_s32le(&src_frame, src);
739 		if (need_to_scale(scaler))
740 			sum = (int64_t)dst_frame + (int64_t)src_frame * scaler;
741 		else
742 			sum = (int64_t)dst_frame + (int64_t)src_frame;
743 		if (sum > INT32_MAX)
744 			sum = INT32_MAX;
745 		else if (sum < INT32_MIN)
746 			sum = INT32_MIN;
747 		dst_frame = (int32_t)sum;
748 		convert_single_s32le_to_s243le(dst, &dst_frame);
749 		dst += dst_stride;
750 		src += src_stride;
751 	}
752 }
753 
scale_buffer_increment(snd_pcm_format_t fmt,uint8_t * buff,unsigned int count,float scaler,float increment,float target,int step)754 static void scale_buffer_increment(snd_pcm_format_t fmt, uint8_t *buff,
755 				   unsigned int count, float scaler,
756 				   float increment, float target, int step)
757 {
758 	switch (fmt) {
759 	case SND_PCM_FORMAT_S16_LE:
760 		return cras_scale_buffer_inc_s16_le(buff, count, scaler,
761 						    increment, target, step);
762 	case SND_PCM_FORMAT_S24_LE:
763 		return cras_scale_buffer_inc_s24_le(buff, count, scaler,
764 						    increment, target, step);
765 	case SND_PCM_FORMAT_S32_LE:
766 		return cras_scale_buffer_inc_s32_le(buff, count, scaler,
767 						    increment, target, step);
768 	case SND_PCM_FORMAT_S24_3LE:
769 		return cras_scale_buffer_inc_s24_3le(buff, count, scaler,
770 						     increment, target, step);
771 	default:
772 		break;
773 	}
774 }
775 
scale_buffer(snd_pcm_format_t fmt,uint8_t * buff,unsigned int count,float scaler)776 static void scale_buffer(snd_pcm_format_t fmt, uint8_t *buff,
777 			 unsigned int count, float scaler)
778 {
779 	switch (fmt) {
780 	case SND_PCM_FORMAT_S16_LE:
781 		return cras_scale_buffer_s16_le(buff, count, scaler);
782 	case SND_PCM_FORMAT_S24_LE:
783 		return cras_scale_buffer_s24_le(buff, count, scaler);
784 	case SND_PCM_FORMAT_S32_LE:
785 		return cras_scale_buffer_s32_le(buff, count, scaler);
786 	case SND_PCM_FORMAT_S24_3LE:
787 		return cras_scale_buffer_s24_3le(buff, count, scaler);
788 	default:
789 		break;
790 	}
791 }
792 
mix_add(snd_pcm_format_t fmt,uint8_t * dst,uint8_t * src,unsigned int count,unsigned int index,int mute,float mix_vol)793 static void mix_add(snd_pcm_format_t fmt, uint8_t *dst, uint8_t *src,
794 		    unsigned int count, unsigned int index, int mute,
795 		    float mix_vol)
796 {
797 	switch (fmt) {
798 	case SND_PCM_FORMAT_S16_LE:
799 		return cras_mix_add_s16_le(dst, src, count, index, mute,
800 					   mix_vol);
801 	case SND_PCM_FORMAT_S24_LE:
802 		return cras_mix_add_s24_le(dst, src, count, index, mute,
803 					   mix_vol);
804 	case SND_PCM_FORMAT_S32_LE:
805 		return cras_mix_add_s32_le(dst, src, count, index, mute,
806 					   mix_vol);
807 	case SND_PCM_FORMAT_S24_3LE:
808 		return cras_mix_add_s24_3le(dst, src, count, index, mute,
809 					    mix_vol);
810 	default:
811 		break;
812 	}
813 }
814 
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)815 static void mix_add_scale_stride(snd_pcm_format_t fmt, uint8_t *dst,
816 				 uint8_t *src, unsigned int count,
817 				 unsigned int dst_stride,
818 				 unsigned int src_stride, float scaler)
819 {
820 	switch (fmt) {
821 	case SND_PCM_FORMAT_S16_LE:
822 		return cras_mix_add_scale_stride_s16_le(
823 			dst, src, dst_stride, src_stride, count, scaler);
824 	case SND_PCM_FORMAT_S24_LE:
825 		return cras_mix_add_scale_stride_s24_le(
826 			dst, src, dst_stride, src_stride, count, scaler);
827 	case SND_PCM_FORMAT_S32_LE:
828 		return cras_mix_add_scale_stride_s32_le(
829 			dst, src, dst_stride, src_stride, count, scaler);
830 	case SND_PCM_FORMAT_S24_3LE:
831 		return cras_mix_add_scale_stride_s24_3le(
832 			dst, src, dst_stride, src_stride, count, scaler);
833 	default:
834 		break;
835 	}
836 }
837 
mix_mute_buffer(uint8_t * dst,size_t frame_bytes,size_t count)838 static size_t mix_mute_buffer(uint8_t *dst, size_t frame_bytes, size_t count)
839 {
840 	memset(dst, 0, count * frame_bytes);
841 	return count;
842 }
843 
844 const struct cras_mix_ops OPS(mixer_ops) = {
845 	.scale_buffer = scale_buffer,
846 	.scale_buffer_increment = scale_buffer_increment,
847 	.add = mix_add,
848 	.add_scale_stride = mix_add_scale_stride,
849 	.mute_buffer = mix_mute_buffer,
850 };
851