quake: clean up asm mixer
Fixes my ugly formatting.
This commit is contained in:
parent
01cccaf2d2
commit
c0cc9aa9e8
1 changed files with 46 additions and 63 deletions
|
@ -19,12 +19,14 @@
|
|||
*
|
||||
***************************************************************************/
|
||||
|
||||
/** Sound mixing code for ARM. **/
|
||||
/* Takes 8-bit mono audio and outputs stereo 16-bit samples.
|
||||
* stereo volumes are passed as arguments.
|
||||
*
|
||||
* Bear with me. This is my first ARM assembly, ever.
|
||||
*/
|
||||
/*
|
||||
* Sound mixing code for ARM.
|
||||
*
|
||||
* Takes an array of 8-bit mono audio and outputs stereo 16-bit
|
||||
* samples. Stereo volumes are passed as arguments r0 and r1.
|
||||
*
|
||||
* Bear with me. This is my first ARM assembly, ever.
|
||||
*/
|
||||
|
||||
.text
|
||||
.align 2
|
||||
|
@ -33,93 +35,74 @@
|
|||
|
||||
#if defined(__ARM_ARCH_5TEJ__)
|
||||
SND_PaintChannelFrom8:
|
||||
// r0: int true_lvol
|
||||
// r1: int true_rvol
|
||||
// r2: char *sfx
|
||||
// r3: int count
|
||||
;; r0: int true_lvol
|
||||
;; r1: int true_rvol
|
||||
;; r2: char *sfx
|
||||
;; r3: int count
|
||||
|
||||
stmfd sp!, {r4, r5, r6, r7, r8, sl}
|
||||
|
||||
ldr ip, =paintbuffer
|
||||
ldr ip, [ip]
|
||||
|
||||
mov r0, r0, asl #16 // pre-scale both volumes by 2^16
|
||||
mov r0, r0, asl #16 ; prescale by 2^16
|
||||
mov r1, r1, asl #16
|
||||
|
||||
sub r3, r3, #1 // we'll count backwards
|
||||
// sl = 0xffff0000
|
||||
ldrh sl, =0xffff
|
||||
sub r3, r3, #1 ; count backwards
|
||||
|
||||
.loop:
|
||||
ldrsb r4, [r2, r3] // load *sfx[i] -> r4
|
||||
ldrh sl, =0xffff ; halfword mask
|
||||
|
||||
// keep endianness in mind here
|
||||
// buffer looks like [left_0, left_1, right_0, right_1] in memory
|
||||
// but it is loaded as [right1, right0, left1, left0] to registers
|
||||
ldr r8, [ip, r3, lsl #2] // load paintbuffer[0:1] = RIGHTCHANNEL:LEFTCHANNEL
|
||||
1:
|
||||
ldrsb r4, [r2, r3] ; load input sample
|
||||
ldr r8, [ip, r3, lsl #2] ; load output sample pair from paintbuffer
|
||||
; (left:right in memory -> right:left in register)
|
||||
;; right channel (high half)
|
||||
mul r5, r4, r1 ; scaledright = sfx[i] * (true_rvol << 16) -- bottom half is zero
|
||||
qadd r7, r5, r8 ; right = scaledright + right (in high half of word)
|
||||
bic r7, r7, sl ; zero bottom half of r7
|
||||
|
||||
// handle high half (right channel) first
|
||||
mul r5, r4, r1 // SCALEDRIGHT = SFXI * (true_rvol << 16) -- bottom half is zero
|
||||
;; left channel (low half)
|
||||
mul r5, r4, r0 ; scaledleft = sfx[i] * (true_rvol << 16)
|
||||
mov r8, r8, lsl #16 ; extract original left channel from paintbuffer
|
||||
qadd r8, r5, r8 ; left = scaledleft + left
|
||||
|
||||
// r7 holds right channel in high half (dirty bottom half)
|
||||
qadd r7, r5, r8 // RIGHTCHANORIG = SCALEDRIGHT + RIGHTCHANORIG (high half)
|
||||
|
||||
bic r7, r7, sl // zero bottom bits of r7
|
||||
|
||||
// trash r5, r6 and handle left channel
|
||||
mul r5, r4, r0 // SCALEDLEFT = SFXI * (true_rvol << 16)
|
||||
|
||||
mov r8, r8, lsl #16 // extract original left channel from paintbuffer
|
||||
|
||||
// r8 holds left channel in high half with zero bottom half
|
||||
qadd r8, r5, r8
|
||||
|
||||
// combine the two 16-bit samples in r7 as 32-bit [left:right]
|
||||
// (use lsr to not sign-extend the lower half)
|
||||
orr r7, r7, r8, lsr #16
|
||||
|
||||
str r7, [ip, r3, lsl #2] // write 32-bit to paintbuffer
|
||||
orr r7, r7, r8, lsr #16 ; combine right:left in r7
|
||||
str r7, [ip, r3, lsl #2] ; write right:left to output buffer
|
||||
subs r3, r3, #1
|
||||
bgt .loop // must use instead of bne because of the corner case count=1
|
||||
|
||||
|
||||
bgt 1b ; must use bgt instead of bne in case count=1
|
||||
|
||||
ldmfd sp!, {r4, r5, r6, r7, r8, sl}
|
||||
|
||||
bx lr
|
||||
|
||||
#elif defined(__ARM_ARCH_6__) // ARMv6 with QADD16 (disabled)
|
||||
#elif defined(__ARM_ARCH_6__) ; ARMv6 with QADD16 (disabled)
|
||||
SND_PaintChannelFrom8:
|
||||
// r0: int true_lvol
|
||||
// r1: int true_rvol
|
||||
// r2: char *sfx
|
||||
// r3: int count
|
||||
;; r0: int true_lvol
|
||||
;; r1: int true_rvol
|
||||
;; r2: char *sfx
|
||||
;; r3: int count
|
||||
|
||||
stmfd sp!, {r4, r5, r6, r7}
|
||||
|
||||
ldr ip, =paintbuffer
|
||||
ldr ip, [ip]
|
||||
sub r3, r3, #1 // we'll count backwards
|
||||
.loop:
|
||||
ldrsb r4, [r2, r3] // load *sfx[i] -> r4
|
||||
ldr ip, [ip] ; load paintbuffer address
|
||||
sub r3, r3, #1 ; we'll count backwards
|
||||
1:
|
||||
ldrsb r4, [r2, r3] ; load sfx[i] -> r4
|
||||
ldr r7, [ip, r3, lsl #2] ; load old sample pair
|
||||
|
||||
// keep endianness in mind here
|
||||
// buffer looks like [left_0, left_1, right_0, right_1] in memory
|
||||
// but it is loaded as [right1, right0, left1, left0] to registers
|
||||
ldr r7, [ip, r3, lsl #2] // load paintbuffer[0:1] = RIGHTCHANNEL:LEFTCHANNEL
|
||||
mul r5, r4, r1 ; SCALEDRIGHT = SFXI * true_rvol
|
||||
mul r6, r4, r0 ; SCALEDLEFT = SFXI * true_rvol
|
||||
|
||||
// handle high half (right channel) first
|
||||
mul r5, r4, r1 // SCALEDRIGHT = SFXI * true_rvol
|
||||
mul r6, r4, r0 // SCALEDLEFT = SFXI * true_rvol
|
||||
orr r6, r6, r5, lsl #16 ; combine samples as 32-bit
|
||||
|
||||
orr r6, r6, r5, lsl #16
|
||||
qadd16 r6, r6, r7 ; parallel 16-bit add
|
||||
|
||||
qadd16 r6, r6, r7
|
||||
|
||||
str r6, [ip, r3, lsl #2] // write 32-bit to paintbuffer
|
||||
str r6, [ip, r3, lsl #2] ; write 32-bit to paintbuffer
|
||||
|
||||
subs r3, r3, #1
|
||||
bne .loop
|
||||
bgt 1b
|
||||
|
||||
ldmfd sp!, {r4, r5, r6, r7}
|
||||
|
||||
|
|
Loading…
Reference in a new issue