summaryrefslogtreecommitdiff
path: root/firmware/asm/generic/pcm-mixer.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/asm/generic/pcm-mixer.c')
-rw-r--r--firmware/asm/generic/pcm-mixer.c100
1 files changed, 100 insertions, 0 deletions
diff --git a/firmware/asm/generic/pcm-mixer.c b/firmware/asm/generic/pcm-mixer.c
new file mode 100644
index 0000000000..93841be70d
--- /dev/null
+++ b/firmware/asm/generic/pcm-mixer.c
@@ -0,0 +1,100 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2011 by Michael Sevakis
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "dsp-util.h" /* for clip_sample_16 */
23/* Mix channels' samples and apply gain factors */
24static FORCE_INLINE void mix_samples(uint32_t *out,
25 int16_t *src0,
26 int32_t src0_amp,
27 int16_t *src1,
28 int32_t src1_amp,
29 size_t size)
30{
31 if (src0_amp == MIX_AMP_UNITY && src1_amp == MIX_AMP_UNITY)
32 {
33 /* Both are unity amplitude */
34 do
35 {
36 int32_t l = *src0++ + *src1++;
37 int32_t h = *src0++ + *src1++;
38 *out++ = (uint16_t)clip_sample_16(l) | (clip_sample_16(h) << 16);
39 }
40 while ((size -= 4) > 0);
41 }
42 else if (src0_amp != MIX_AMP_UNITY && src1_amp != MIX_AMP_UNITY)
43 {
44 /* Neither are unity amplitude */
45 do
46 {
47 int32_t l = (*src0++ * src0_amp >> 16) + (*src1++ * src1_amp >> 16);
48 int32_t h = (*src0++ * src0_amp >> 16) + (*src1++ * src1_amp >> 16);
49 *out++ = (uint16_t)clip_sample_16(l) | (clip_sample_16(h) << 16);
50 }
51 while ((size -= 4) > 0);
52 }
53 else
54 {
55 /* One is unity amplitude */
56 if (src0_amp != MIX_AMP_UNITY)
57 {
58 /* Keep unity in src0, amp0 */
59 int16_t *src_tmp = src0;
60 src0 = src1;
61 src1 = src_tmp;
62 src1_amp = src0_amp;
63 src0_amp = MIX_AMP_UNITY;
64 }
65
66 do
67 {
68 int32_t l = *src0++ + (*src1++ * src1_amp >> 16);
69 int32_t h = *src0++ + (*src1++ * src1_amp >> 16);
70 *out++ = (uint16_t)clip_sample_16(l) | (clip_sample_16(h) << 16);
71 }
72 while ((size -= 4) > 0);
73 }
74}
75
76/* Write channel's samples and apply gain factor */
77static FORCE_INLINE void write_samples(uint32_t *out,
78 int16_t *src,
79 int32_t amp,
80 size_t size)
81{
82 if (LIKELY(amp == MIX_AMP_UNITY))
83 {
84 /* Channel is unity amplitude */
85 memcpy(out, src, size);
86 }
87 else
88 {
89 /* Channel needs amplitude cut */
90 do
91 {
92 int32_t l = *src++ * amp >> 16;
93 int32_t h = *src++ * amp & 0xffff0000;
94 *out++ = (uint16_t)l | h;
95 }
96 while ((size -= 4) > 0);
97 }
98}
99
100#endif