Home | History | Annotate | Download | only in server
      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. */
     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 
     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. */
     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. */
     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 
     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 
    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 
    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 
    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 
    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. */
    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. */
    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 
    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 
    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 
    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 
    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 
    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. */
    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. */
    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 
    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 
    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 
    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 
    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. */
    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 
    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 
    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. */
    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. */
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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