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