4f265db7 |
1 | @ vim:filetype=armasm |
2 | |
6cadc2da |
3 | @ Generic routines for mixing audio samples |
4 | @ (c) Copyright 2007, Grazvydas "notaz" Ignotas |
5 | |
4f265db7 |
6 | |
4a32f01f |
7 | .text |
8 | .align 4 |
9 | |
4f265db7 |
10 | @ this assumes src is word aligned |
11 | .global mix_16h_to_32 @ int *dest, short *src, int count |
12 | |
13 | mix_16h_to_32: |
14 | stmfd sp!, {r4-r6,lr} |
15 | /* |
16 | tst r1, #2 |
17 | beq m16_32_mo_unalw |
18 | ldrsh r4, [r1], #2 |
19 | ldr r3, [r0] |
20 | sub r2, r2, #1 |
21 | add r3, r3, r4, asr #1 |
22 | str r3, [r0], #4 |
23 | */ |
24 | m16_32_mo_unalw: |
25 | subs r2, r2, #4 |
26 | bmi m16_32_end |
27 | |
28 | m16_32_loop: |
29 | ldmia r0, {r3-r6} |
30 | ldmia r1!,{r12,lr} |
31 | subs r2, r2, #4 |
32 | add r4, r4, r12,asr #17 @ we use half volume |
33 | mov r12,r12,lsl #16 |
34 | add r3, r3, r12,asr #17 |
35 | add r6, r6, lr, asr #17 |
36 | mov lr, lr, lsl #16 |
37 | add r5, r5, lr, asr #17 |
38 | stmia r0!,{r3-r6} |
39 | bpl m16_32_loop |
40 | |
41 | m16_32_end: |
42 | tst r2, #2 |
43 | beq m16_32_no_unal2 |
44 | ldr r5, [r1], #4 |
45 | ldmia r0, {r3,r4} |
46 | mov r12,r5, lsl #16 |
47 | add r3, r3, r12,asr #17 |
48 | add r4, r4, r5, asr #17 |
49 | stmia r0!,{r3,r4} |
50 | |
51 | m16_32_no_unal2: |
52 | tst r2, #1 |
53 | ldmeqfd sp!, {r4-r6,pc} |
54 | ldrsh r4, [r1], #2 |
55 | ldr r3, [r0] |
56 | add r3, r3, r4, asr #1 |
57 | str r3, [r0], #4 |
58 | |
59 | ldmfd sp!, {r4-r6,lr} |
60 | bx lr |
61 | |
62 | |
63 | |
64 | .global mix_16h_to_32_s1 @ int *dest, short *src, int count |
65 | |
66 | mix_16h_to_32_s1: |
67 | stmfd sp!, {r4-r6,lr} |
68 | |
69 | subs r2, r2, #4 |
70 | bmi m16_32_s1_end |
71 | |
72 | m16_32_s1_loop: |
73 | ldmia r0, {r3-r6} |
74 | ldr r12,[r1], #8 |
75 | ldr lr, [r1], #8 |
76 | subs r2, r2, #4 |
77 | add r4, r4, r12,asr #17 |
78 | mov r12,r12,lsl #16 |
79 | add r3, r3, r12,asr #17 @ we use half volume |
80 | add r6, r6, lr, asr #17 |
81 | mov lr, lr, lsl #16 |
82 | add r5, r5, lr, asr #17 |
83 | stmia r0!,{r3-r6} |
84 | bpl m16_32_s1_loop |
85 | |
86 | m16_32_s1_end: |
87 | tst r2, #2 |
88 | beq m16_32_s1_no_unal2 |
89 | ldr r5, [r1], #8 |
90 | ldmia r0, {r3,r4} |
91 | mov r12,r5, lsl #16 |
92 | add r3, r3, r12,asr #17 |
93 | add r4, r4, r5, asr #17 |
94 | stmia r0!,{r3,r4} |
95 | |
96 | m16_32_s1_no_unal2: |
97 | tst r2, #1 |
98 | ldmeqfd sp!, {r4-r6,pc} |
99 | ldrsh r4, [r1], #2 |
100 | ldr r3, [r0] |
101 | add r3, r3, r4, asr #1 |
102 | str r3, [r0], #4 |
103 | |
104 | ldmfd sp!, {r4-r6,lr} |
105 | bx lr |
106 | |
107 | |
108 | |
109 | .global mix_16h_to_32_s2 @ int *dest, short *src, int count |
110 | |
111 | mix_16h_to_32_s2: |
112 | stmfd sp!, {r4-r6,lr} |
113 | |
114 | subs r2, r2, #4 |
115 | bmi m16_32_s2_end |
116 | |
117 | m16_32_s2_loop: |
118 | ldmia r0, {r3-r6} |
119 | ldr r12,[r1], #16 |
120 | ldr lr, [r1], #16 |
121 | subs r2, r2, #4 |
122 | add r4, r4, r12,asr #17 |
123 | mov r12,r12,lsl #16 |
124 | add r3, r3, r12,asr #17 @ we use half volume |
125 | add r6, r6, lr, asr #17 |
126 | mov lr, lr, lsl #16 |
127 | add r5, r5, lr, asr #17 |
128 | stmia r0!,{r3-r6} |
129 | bpl m16_32_s2_loop |
130 | |
131 | m16_32_s2_end: |
132 | tst r2, #2 |
133 | beq m16_32_s2_no_unal2 |
134 | ldr r5, [r1], #16 |
135 | ldmia r0, {r3,r4} |
136 | mov r12,r5, lsl #16 |
137 | add r3, r3, r12,asr #17 |
138 | add r4, r4, r5, asr #17 |
139 | stmia r0!,{r3,r4} |
140 | |
141 | m16_32_s2_no_unal2: |
142 | tst r2, #1 |
143 | ldmeqfd sp!, {r4-r6,pc} |
144 | ldrsh r4, [r1], #2 |
145 | ldr r3, [r0] |
146 | add r3, r3, r4, asr #1 |
147 | str r3, [r0], #4 |
148 | |
149 | ldmfd sp!, {r4-r6,lr} |
150 | bx lr |
151 | |
152 | |
153 | |
154 | @ limit |
155 | @ reg=int_sample, lr=1, r3=tmp, kills flags |
156 | .macro Limit reg |
7a93adeb |
157 | add r3, lr, \reg, asr #15 |
4f265db7 |
158 | bics r3, r3, #1 @ in non-overflow conditions r3 is 0 or 1 |
159 | movne \reg, #0x8000 |
7a93adeb |
160 | subpl \reg, \reg, #1 |
4f265db7 |
161 | .endm |
162 | |
163 | |
164 | @ limit and shift up by 16 |
165 | @ reg=int_sample, lr=1, r3=tmp, kills flags |
166 | .macro Limitsh reg |
167 | @ movs r4, r3, asr #16 |
168 | @ cmnne r4, #1 |
169 | @ beq c32_16_no_overflow |
170 | @ tst r4, r4 |
171 | @ mov r3, #0x8000 |
172 | @ subpl r3, r3, #1 |
173 | |
7a93adeb |
174 | add r3, lr, \reg, asr #15 |
4f265db7 |
175 | bics r3, r3, #1 @ in non-overflow conditions r3 is 0 or 1 |
176 | moveq \reg, \reg, lsl #16 |
177 | movne \reg, #0x80000000 |
7a93adeb |
178 | subpl \reg, \reg, #0x00010000 |
4f265db7 |
179 | .endm |
180 | |
181 | |
182 | @ mix 32bit audio (with 16bits really used, upper bits indicate overflow) with normal 16 bit audio with left channel only |
183 | @ warning: this function assumes dest is word aligned |
184 | .global mix_32_to_16l_stereo @ short *dest, int *src, int count |
185 | |
186 | mix_32_to_16l_stereo: |
187 | stmfd sp!, {r4-r8,lr} |
188 | |
189 | mov lr, #1 |
190 | |
191 | mov r2, r2, lsl #1 |
192 | subs r2, r2, #4 |
193 | bmi m32_16l_st_end |
194 | |
195 | m32_16l_st_loop: |
196 | ldmia r0, {r8,r12} |
197 | ldmia r1!, {r4-r7} |
198 | mov r8, r8, lsl #16 |
199 | mov r12,r12,lsl #16 |
200 | add r4, r4, r8, asr #16 |
201 | add r5, r5, r8, asr #16 |
202 | add r6, r6, r12,asr #16 |
203 | add r7, r7, r12,asr #16 |
204 | Limitsh r4 |
205 | Limitsh r5 |
206 | Limitsh r6 |
207 | Limitsh r7 |
208 | subs r2, r2, #4 |
209 | orr r4, r5, r4, lsr #16 |
210 | orr r5, r7, r6, lsr #16 |
211 | stmia r0!, {r4,r5} |
212 | bpl m32_16l_st_loop |
213 | |
214 | m32_16l_st_end: |
215 | @ check for remaining bytes to convert |
216 | tst r2, #2 |
217 | beq m32_16l_st_no_unal2 |
218 | ldrsh r6, [r0] |
219 | ldmia r1!,{r4,r5} |
220 | add r4, r4, r6 |
221 | add r5, r5, r6 |
222 | Limitsh r4 |
223 | Limitsh r5 |
224 | orr r4, r5, r4, lsr #16 |
225 | str r4, [r0], #4 |
226 | |
227 | m32_16l_st_no_unal2: |
228 | ldmfd sp!, {r4-r8,lr} |
229 | bx lr |
230 | |
231 | |
232 | @ mix 32bit audio (with 16bits really used, upper bits indicate overflow) with normal 16 bit audio (for mono sound) |
233 | .global mix_32_to_16_mono @ short *dest, int *src, int count |
234 | |
235 | mix_32_to_16_mono: |
236 | stmfd sp!, {r4-r8,lr} |
237 | |
238 | mov lr, #1 |
239 | |
240 | @ check if dest is word aligned |
241 | tst r0, #2 |
242 | beq m32_16_mo_no_unalw |
7a93adeb |
243 | ldrsh r5, [r0] |
4f265db7 |
244 | ldr r4, [r1], #4 |
245 | sub r2, r2, #1 |
246 | add r4, r4, r5 |
247 | Limit r4 |
248 | strh r4, [r0], #2 |
249 | |
250 | m32_16_mo_no_unalw: |
251 | subs r2, r2, #4 |
252 | bmi m32_16_mo_end |
253 | |
254 | m32_16_mo_loop: |
255 | ldmia r0, {r8,r12} |
256 | ldmia r1!, {r4-r7} |
257 | add r5, r5, r8, asr #16 |
258 | mov r8, r8, lsl #16 |
259 | add r4, r4, r8, asr #16 |
260 | add r7, r7, r12,asr #16 |
261 | mov r12,r12,lsl #16 |
262 | add r6, r6, r12,asr #16 |
263 | Limitsh r4 |
264 | Limitsh r5 |
265 | Limitsh r6 |
266 | Limitsh r7 |
267 | subs r2, r2, #4 |
268 | orr r4, r5, r4, lsr #16 |
269 | orr r5, r7, r6, lsr #16 |
270 | stmia r0!, {r4,r5} |
271 | bpl m32_16_mo_loop |
272 | |
273 | m32_16_mo_end: |
274 | @ check for remaining bytes to convert |
275 | tst r2, #2 |
276 | beq m32_16_mo_no_unal2 |
277 | ldr r6, [r0] |
278 | ldmia r1!,{r4,r5} |
279 | add r5, r5, r6, asr #16 |
280 | mov r6, r6, lsl #16 |
281 | add r4, r4, r6, asr #16 |
282 | Limitsh r4 |
283 | Limitsh r5 |
284 | orr r4, r5, r4, lsr #16 |
285 | str r4, [r0], #4 |
286 | |
287 | m32_16_mo_no_unal2: |
288 | tst r2, #1 |
289 | ldmeqfd sp!, {r4-r8,pc} |
7a93adeb |
290 | ldrsh r5, [r0] |
4f265db7 |
291 | ldr r4, [r1], #4 |
292 | add r4, r4, r5 |
293 | Limit r4 |
294 | strh r4, [r0], #2 |
295 | |
296 | ldmfd sp!, {r4-r8,lr} |
297 | bx lr |
298 | |
4a32f01f |
299 | |
300 | |
301 | .data |
302 | .align 4 |
303 | |
304 | .global mix_32_to_16l_level |
305 | mix_32_to_16l_level: |
306 | .word 0 |
307 | |
308 | .text |
309 | .align 4 |
310 | |
311 | @ same as mix_32_to_16l_stereo, but with additional shift |
312 | .global mix_32_to_16l_stereo_lvl @ short *dest, int *src, int count |
313 | |
314 | mix_32_to_16l_stereo_lvl: |
315 | stmfd sp!, {r4-r9,lr} |
316 | |
317 | ldr r9, =mix_32_to_16l_level |
318 | mov lr, #1 |
319 | ldr r9, [r9] |
320 | |
321 | mov r2, r2, lsl #1 |
322 | subs r2, r2, #4 |
323 | bmi m32_16l_st_l_end |
324 | |
325 | m32_16l_st_l_loop: |
326 | ldmia r0, {r8,r12} |
327 | ldmia r1!, {r4-r7} |
328 | mov r8, r8, lsl #16 |
329 | mov r12,r12,lsl #16 |
330 | add r4, r4, r8, asr #16 |
331 | add r5, r5, r8, asr #16 |
332 | add r6, r6, r12,asr #16 |
333 | add r7, r7, r12,asr #16 |
334 | mov r4, r4, asr r9 |
335 | mov r5, r5, asr r9 |
336 | mov r6, r6, asr r9 |
337 | mov r7, r7, asr r9 |
338 | Limitsh r4 |
339 | Limitsh r5 |
340 | Limitsh r6 |
341 | Limitsh r7 |
342 | subs r2, r2, #4 |
343 | orr r4, r5, r4, lsr #16 |
344 | orr r5, r7, r6, lsr #16 |
345 | stmia r0!, {r4,r5} |
346 | bpl m32_16l_st_l_loop |
347 | |
348 | m32_16l_st_l_end: |
349 | @ check for remaining bytes to convert |
350 | tst r2, #2 |
351 | beq m32_16l_st_l_no_unal2 |
352 | ldrsh r6, [r0] |
353 | ldmia r1!,{r4,r5} |
354 | add r4, r4, r6 |
355 | add r5, r5, r6 |
356 | mov r4, r4, asr r9 |
357 | mov r5, r5, asr r9 |
358 | Limitsh r4 |
359 | Limitsh r5 |
360 | orr r4, r5, r4, lsr #16 |
361 | str r4, [r0], #4 |
362 | |
363 | m32_16l_st_l_no_unal2: |
364 | ldmfd sp!, {r4-r9,lr} |
365 | bx lr |
366 | |
367 | |