2 * Generic routines for mixing audio samples
4 * (C) irixxxx, 2019,2020 added filtering
6 * This work is licensed under the terms of MAME license.
7 * See COPYING file in the top-level directory.
13 @ this assumes src is word aligned
14 .global mix_16h_to_32 @ int *dest, short *src, int count
24 add r3, r3, r4, asr #1
35 add r4, r4, r12,asr #17 @ we use 5/8 volume
36 add r4, r4, r12,asr #19
38 add r3, r3, r12,asr #17
39 add r3, r3, r12,asr #19
40 add r6, r6, lr, asr #17
41 add r6, r6, lr, asr #19
43 add r5, r5, lr, asr #17
44 add r5, r5, lr, asr #19
54 add r3, r3, r12,asr #17
55 add r3, r3, r12,asr #19
56 add r4, r4, r5, asr #17
57 add r4, r4, r5, asr #19
62 ldmeqfd sp!, {r4-r6,pc}
65 add r3, r3, r4, asr #1
66 add r3, r3, r4, asr #3
74 .global mix_16h_to_32_s1 @ int *dest, short *src, int count
87 add r4, r4, r12,asr #17 @ we use 5/8 volume
88 add r4, r4, r12,asr #19
90 add r3, r3, r12,asr #17
91 add r3, r3, r12,asr #19
92 add r6, r6, lr, asr #17
93 add r6, r6, lr, asr #19
95 add r5, r5, lr, asr #17
96 add r5, r5, lr, asr #19
102 beq m16_32_s1_no_unal2
106 add r3, r3, r12,asr #17
107 add r3, r3, r12,asr #19
108 add r4, r4, r5, asr #17
109 add r4, r4, r5, asr #19
114 ldmeqfd sp!, {r4-r6,pc}
117 add r3, r3, r4, asr #1
118 add r3, r3, r4, asr #3
121 ldmfd sp!, {r4-r6,lr}
126 .global mix_16h_to_32_s2 @ int *dest, short *src, int count
129 stmfd sp!, {r4-r6,lr}
139 add r4, r4, r12,asr #17 @ we use 5/8 volume
140 add r4, r4, r12,asr #19
142 add r3, r3, r12,asr #17
143 add r3, r3, r12,asr #19
144 add r6, r6, lr, asr #17
145 add r6, r6, lr, asr #19
147 add r5, r5, lr, asr #17
148 add r5, r5, lr, asr #19
154 beq m16_32_s2_no_unal2
158 add r3, r3, r12,asr #17
159 add r3, r3, r12,asr #19
160 add r4, r4, r5, asr #17
161 add r4, r4, r5, asr #19
166 ldmeqfd sp!, {r4-r6,pc}
169 add r3, r3, r4, asr #1
170 add r3, r3, r4, asr #3
173 ldmfd sp!, {r4-r6,lr}
178 .global mix_16h_to_32_resample_stereo @ int *dest, short *src, int count, int fac16
180 mix_16h_to_32_resample_stereo:
181 stmfd sp!, {r4-r9,lr}
190 ldr r12,[r1, r9, lsl #2]
193 ldr lr ,[r1, r9, lsl #2]
196 add r6, r6, r12,asr #17 @ we use 5/8 volume
197 add r6, r6, r12,asr #19
199 add r5, r5, r12,asr #17
200 add r5, r5, r12,asr #19
201 add r8, r8, lr, asr #17
202 add r8, r8, lr, asr #19
204 add r7, r7, lr, asr #17
205 add r7, r7, lr, asr #19
211 ldmeqfd sp!, {r4-r9,pc}
213 ldr lr ,[r1, r9, lsl #2]
216 add r5, r5, r12,asr #17
217 add r5, r5, r12,asr #19
218 add r6, r6, lr, asr #17
219 add r6, r6, lr, asr #19
222 ldmfd sp!, {r4-r9,lr}
227 .global mix_16h_to_32_resample_mono @ int *dest, short *src, int count, int fac16
229 mix_16h_to_32_resample_mono:
230 stmfd sp!, {r4-r6,r9,lr}
239 ldr r12,[r1, r9, lsl #2]
242 ldr lr ,[r1, r9, lsl #2]
245 add r5, r5, r12,asr #18 @ we use 5/8 volume (= 5/16 vol per channel)
246 add r5, r5, r12,asr #20
248 add r5, r5, r12,asr #18
249 add r5, r5, r12,asr #20
250 add r6, r6, lr, asr #18
251 add r6, r6, lr, asr #20
253 add r6, r6, lr, asr #18
254 add r6, r6, lr, asr #20
260 ldmeqfd sp!, {r4-r6,r9,pc}
262 ldr lr ,[r1, r9, lsl #2]
265 add r5, r5, r12,asr #18
266 add r5, r5, r12,asr #20
267 add r5, r5, lr, asr #18
268 add r5, r5, lr, asr #20
271 ldmfd sp!, {r4-r6,r9,lr}
277 @ reg=int_sample, r12=1, r8=tmp, kills flags
279 sub \reg, \reg, \reg, asr #3 @ reduce audio lvl some to avoid clipping
280 add r8, r12, \reg, asr #15
281 bics r8, r8, #1 @ in non-overflow conditions r8 is 0 or 1
286 @ limit and shift up by 16
287 @ reg=int_sample, r12=1, r8=tmp, kills flags
289 sub \reg, \reg, \reg, asr #3 @ reduce audio lvl some to avoid clipping
290 add r8, r12,\reg, asr #15
291 bics r8, r8, #1 @ in non-overflow conditions r8 is 0 or 1
292 moveq \reg, \reg, lsl #16
293 movne \reg, #0x80000000
294 subpl \reg, \reg, #0x00010000
298 @ filter out DC offset
299 @ in=int_sample (max 20 bit), y=filter memory, r8=tmp
301 rsb r8, \y, \in, lsl #12 @ fixpoint 20.12
302 add \y, \y, r8, asr #12 @ alpha = 1-1/4094
303 sub \in, \in, \y, asr #12
307 @ in=int_sample (max 20 bit), y=filter memory, r12=alpha(Q8), r8=tmp
310 @ rsb r8, r8, \in, lsl #4 @ fixpoint 20.12
311 sub r8, \in, \y, asr #12 @ fixpoint 20.12
317 @ mix 32bit audio (with 16bits really used, upper bits indicate overflow) with normal 16 bit audio with left channel only
318 @ warning: this function assumes dest is word aligned
319 .global mix_32_to_16_stereo @ short *dest, int *src, int count
322 stmfd sp!, {r4-r8,r10-r11,lr}
330 ldmia r12, {r3,r10-r11,lr}
336 add r5, r5, r8, asr #16
337 add r7, r7, r12,asr #16
340 add r4, r4, r8, asr #16
341 add r6, r6, r12,asr #16
357 orr r4, r5, r4, lsr #16
358 orr r5, r7, r6, lsr #16
363 @ check for remaining bytes to convert
365 beq m32_16_st_no_unal2
368 add r5, r5, r6, asr #16
370 add r4, r4, r6, asr #16
379 orr r4, r5, r4, lsr #16
385 stmia r12, {r3,r10-r11,lr}
387 ldmfd sp!, {r4-r8,r10-r11,lr}
391 @ mix 32bit audio (with 16bits really used, upper bits indicate overflow) with normal 16 bit audio (for mono sound)
392 .global mix_32_to_16_mono @ short *dest, int *src, int count
395 stmfd sp!, {r4-r8,r10-r11,lr}
402 @ check if dest is word aligned
404 beq m32_16_mo_no_unalw
423 add r5, r5, r8, asr #16
424 add r7, r7, r12,asr #16
427 add r4, r4, r8, asr #16
428 add r6, r6, r12,asr #16
444 orr r4, r5, r4, lsr #16
445 orr r5, r7, r6, lsr #16
450 @ check for remaining bytes to convert
452 beq m32_16_mo_no_unal2
455 add r5, r5, r6, asr #16
457 add r4, r4, r6, asr #16
466 orr r4, r5, r4, lsr #16
471 beq m32_16_mo_no_unal
487 ldmfd sp!, {r4-r8,r10-r11,lr}
496 .global mix_32_to_16_level
503 @ same as mix_32_to_16_stereo, but with additional shift
504 .global mix_32_to_16_stereo_lvl @ short *dest, int *src, int count
506 mix_32_to_16_stereo_lvl:
507 stmfd sp!, {r4-r11,lr}
509 ldr r9, =mix_32_to_16_level
514 ldmia r12, {r3,r10-r11,lr}
524 add r5, r5, r8, asr #16
525 add r7, r7, r12,asr #16
528 add r4, r4, r8, asr #16
529 add r6, r6, r12,asr #16
549 orr r4, r5, r4, lsr #16
550 orr r5, r7, r6, lsr #16
555 @ check for remaining bytes to convert
557 beq m32_16_st_l_no_unal2
560 add r5, r5, r6, asr #16
562 add r4, r4, r6, asr #16
573 orr r4, r5, r4, lsr #16
576 m32_16_st_l_no_unal2:
579 stmia r12, {r3,r10-r11,lr}
581 ldmfd sp!, {r4-r11,lr}
584 #endif /* __GP2X__ */
586 .global mix_reset @ int alpha_q16
603 .ds 8 @ filter history for left channel
604 .ds 8 @ filter history for right channel
606 @ vim:filetype=armasm