diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2011-06-29 06:37:04 +0000 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2011-06-29 06:37:04 +0000 |
commit | a2b6703a369f6cdbfec1f150c408dadc877631fb (patch) | |
tree | 3145a8c1372c44711d38feefeba39c7d4098f139 /firmware/target/arm/pcm-mixer-armv4.c | |
parent | 8411614b8a068a4f274c3841aa55aab1df1bc246 (diff) | |
download | rockbox-a2b6703a369f6cdbfec1f150c408dadc877631fb.tar.gz rockbox-a2b6703a369f6cdbfec1f150c408dadc877631fb.zip |
Commit FS#12150 - Fully-functional audio mixer - and finally whip old limitations about playback of voice and other sounds when paused. Channels are independent in state and amplitude. Fade on stop/pause is handled by the channel's volume control rather than global volume which means it now works from anywhere. Opens up the possibility of plugin sounds during music playback by merely adding an additional channel enum. If any PCM drivers were not properly modified, see one of the last comments in the task for a description of the simple change that is expected. Some params are tunable in firmware/export/pcm-mixer.h as well.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30097 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target/arm/pcm-mixer-armv4.c')
-rw-r--r-- | firmware/target/arm/pcm-mixer-armv4.c | 182 |
1 files changed, 182 insertions, 0 deletions
diff --git a/firmware/target/arm/pcm-mixer-armv4.c b/firmware/target/arm/pcm-mixer-armv4.c new file mode 100644 index 0000000000..4818544d7b --- /dev/null +++ b/firmware/target/arm/pcm-mixer-armv4.c | |||
@@ -0,0 +1,182 @@ | |||
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 | #define MIXER_OPTIMIZED_WRITE_SAMPLES | ||
23 | #define MIXER_OPTIMIZED_MIX_SAMPLES | ||
24 | |||
25 | /* Mix channels' samples and apply gain factors */ | ||
26 | static FORCE_INLINE void mix_samples(void *out, | ||
27 | void *src0, | ||
28 | int32_t src0_amp, | ||
29 | void *src1, | ||
30 | int32_t src1_amp, | ||
31 | size_t size) | ||
32 | { | ||
33 | if (src0_amp == MIX_AMP_UNITY && src1_amp == MIX_AMP_UNITY) | ||
34 | { | ||
35 | /* Both are unity amplitude */ | ||
36 | int32_t l0, l1, h0, h1; | ||
37 | asm volatile ( | ||
38 | "1: \n" | ||
39 | "ldrsh %4, [%1], #2 \n" | ||
40 | "ldrsh %5, [%2], #2 \n" | ||
41 | "ldrsh %6, [%1], #2 \n" | ||
42 | "ldrsh %7, [%2], #2 \n" | ||
43 | "add %4, %4, %5 \n" | ||
44 | "add %6, %6, %7 \n" | ||
45 | "mov %5, %4, asr #15 \n" | ||
46 | "teq %5, %5, asr #31 \n" | ||
47 | "eorne %4, %8, %4, asr #31 \n" | ||
48 | "mov %7, %6, asr #15 \n" | ||
49 | "teq %7, %7, asr #31 \n" | ||
50 | "eorne %6, %8, %6, asr #31 \n" | ||
51 | "subs %3, %3, #4 \n" | ||
52 | "and %4, %4, %8, lsr #16 \n" | ||
53 | "orr %6, %4, %6, lsl #16 \n" | ||
54 | "str %6, [%0], #4 \n" | ||
55 | "bhi 1b \n" | ||
56 | : "+r"(out), "+r"(src0), "+r"(src1), "+r"(size), | ||
57 | "=&r"(l0), "=&r"(l1), "=&r"(h0), "=&r"(h1) | ||
58 | : "r"(0xffff7fff)); | ||
59 | } | ||
60 | else if (src0_amp != MIX_AMP_UNITY && src1_amp != MIX_AMP_UNITY) | ||
61 | { | ||
62 | /* Neither are unity amplitude */ | ||
63 | int32_t l0, l1, h0, h1; | ||
64 | asm volatile ( | ||
65 | "1: \n" | ||
66 | "ldrsh %4, [%1], #2 \n" | ||
67 | "ldrsh %5, [%2], #2 \n" | ||
68 | "ldrsh %6, [%1], #2 \n" | ||
69 | "ldrsh %7, [%2], #2 \n" | ||
70 | "mul %4, %8, %4 \n" | ||
71 | "mul %5, %9, %5 \n" | ||
72 | "mul %6, %8, %6 \n" | ||
73 | "mul %7, %9, %7 \n" | ||
74 | "mov %4, %4, asr #16 \n" | ||
75 | "add %4, %4, %5, asr #16 \n" | ||
76 | "mov %6, %6, asr #16 \n" | ||
77 | "add %6, %6, %7, asr #16 \n" | ||
78 | "mov %5, %4, asr #15 \n" | ||
79 | "teq %5, %5, asr #31 \n" | ||
80 | "eorne %4, %10, %4, asr #31 \n" | ||
81 | "mov %7, %6, asr #15 \n" | ||
82 | "teq %7, %7, asr #31 \n" | ||
83 | "eorne %6, %10, %6, asr #31 \n" | ||
84 | "subs %3, %3, #4 \n" | ||
85 | "and %4, %4, %10, lsr #16 \n" | ||
86 | "orr %6, %4, %6, lsl #16 \n" | ||
87 | "str %6, [%0], #4 \n" | ||
88 | "bhi 1b \n" | ||
89 | : "+r"(out), "+r"(src0), "+r"(src1), "+r"(size), | ||
90 | "=&r"(l0), "=&r"(l1), "=&r"(h0), "=&r"(h1) | ||
91 | : "r"(src0_amp), "r"(src1_amp), "r"(0xffff7fff)); | ||
92 | } | ||
93 | else | ||
94 | { | ||
95 | /* One is unity amplitude */ | ||
96 | if (src0_amp != MIX_AMP_UNITY) | ||
97 | { | ||
98 | /* Keep unity in src0, amp0 */ | ||
99 | int16_t *src_tmp = src0; | ||
100 | src0 = src1; | ||
101 | src1 = src_tmp; | ||
102 | src1_amp = src0_amp; | ||
103 | src0_amp = MIX_AMP_UNITY; | ||
104 | } | ||
105 | |||
106 | int32_t l0, l1, h0, h1; | ||
107 | asm volatile ( | ||
108 | "1: \n" | ||
109 | "ldrsh %4, [%1], #2 \n" | ||
110 | "ldrsh %5, [%2], #2 \n" | ||
111 | "ldrsh %6, [%1], #2 \n" | ||
112 | "ldrsh %7, [%2], #2 \n" | ||
113 | "mul %5, %8, %5 \n" | ||
114 | "mul %7, %8, %7 \n" | ||
115 | "add %4, %4, %5, asr #16 \n" | ||
116 | "add %6, %6, %7, asr #16 \n" | ||
117 | "mov %5, %4, asr #15 \n" | ||
118 | "teq %5, %5, asr #31 \n" | ||
119 | "eorne %4, %9, %4, asr #31 \n" | ||
120 | "mov %7, %6, asr #15 \n" | ||
121 | "teq %7, %7, asr #31 \n" | ||
122 | "eorne %6, %9, %6, asr #31 \n" | ||
123 | "subs %3, %3, #4 \n" | ||
124 | "and %4, %4, %9, lsr #16 \n" | ||
125 | "orr %6, %4, %6, lsl #16 \n" | ||
126 | "str %6, [%0], #4 \n" | ||
127 | "bhi 1b \n" | ||
128 | : "+r"(out), "+r"(src0), "+r"(src1), "+r"(size), | ||
129 | "=&r"(l0), "=&r"(l1), "=&r"(h0), "=&r"(h1) | ||
130 | : "r"(src1_amp), "r"(0xffff7fff)); | ||
131 | } | ||
132 | } | ||
133 | |||
134 | /* Write channel's samples and apply gain factor */ | ||
135 | static FORCE_INLINE void write_samples(void *out, | ||
136 | void *src, | ||
137 | int32_t amp, | ||
138 | size_t size) | ||
139 | { | ||
140 | if (LIKELY(amp == MIX_AMP_UNITY)) | ||
141 | { | ||
142 | /* Channel is unity amplitude */ | ||
143 | asm volatile ( | ||
144 | "ands r1, %2, #0x1f \n" | ||
145 | "beq 2f \n" | ||
146 | "1: \n" | ||
147 | "ldr r0, [%1], #4 \n" | ||
148 | "subs r1, r1, #4 \n" | ||
149 | "str r0, [%0], #4 \n" | ||
150 | "bne 1b \n" | ||
151 | "bics %2, %2, #0x1f \n" | ||
152 | "beq 3f \n" | ||
153 | "2: \n" | ||
154 | "ldmia %1!, { r0-r7 } \n" | ||
155 | "subs %2, %2, #32 \n" | ||
156 | "stmia %0!, { r0-r7 } \n" | ||
157 | "bhi 2b \n" | ||
158 | "3: \n" | ||
159 | : "+r"(out), "+r"(src), "+r"(size) | ||
160 | : | ||
161 | : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7"); | ||
162 | } | ||
163 | else | ||
164 | { | ||
165 | /* Channel needs amplitude cut */ | ||
166 | uint32_t l, h; | ||
167 | asm volatile ( | ||
168 | "1: \n" | ||
169 | "ldrsh %3, [%1], #2 \n" | ||
170 | "ldrsh %4, [%1], #2 \n" | ||
171 | "subs %2, %2, #4 \n" | ||
172 | "mul %3, %5, %3 \n" | ||
173 | "mul %4, %5, %4 \n" | ||
174 | "and %4, %4, %6, lsl #16 \n" | ||
175 | "orr %4, %4, %3, lsr #16 \n" | ||
176 | "str %4, [%0], #4 \n" | ||
177 | "bhi 1b \n" | ||
178 | : "+r"(out), "+r"(src), "+r"(size), | ||
179 | "=&r"(l), "=&r"(h) | ||
180 | : "r"(amp), "r"(0xffffffffu)); | ||
181 | } | ||
182 | } | ||