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