summaryrefslogtreecommitdiff
path: root/apps/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins')
-rw-r--r--apps/plugins/sdl/progs/quake/snd_mix_arm.S109
1 files changed, 46 insertions, 63 deletions
diff --git a/apps/plugins/sdl/progs/quake/snd_mix_arm.S b/apps/plugins/sdl/progs/quake/snd_mix_arm.S
index 15733d8912..0573e85923 100644
--- a/apps/plugins/sdl/progs/quake/snd_mix_arm.S
+++ b/apps/plugins/sdl/progs/quake/snd_mix_arm.S
@@ -19,12 +19,14 @@
19 * 19 *
20 ***************************************************************************/ 20 ***************************************************************************/
21 21
22 /** Sound mixing code for ARM. **/ 22 /*
23 /* Takes 8-bit mono audio and outputs stereo 16-bit samples. 23 * Sound mixing code for ARM.
24 * stereo volumes are passed as arguments. 24 *
25 * 25 * Takes an array of 8-bit mono audio and outputs stereo 16-bit
26 * Bear with me. This is my first ARM assembly, ever. 26 * samples. Stereo volumes are passed as arguments r0 and r1.
27 */ 27 *
28 * Bear with me. This is my first ARM assembly, ever.
29 */
28 30
29 .text 31 .text
30 .align 2 32 .align 2
@@ -33,93 +35,74 @@
33 35
34#if defined(__ARM_ARCH_5TEJ__) 36#if defined(__ARM_ARCH_5TEJ__)
35SND_PaintChannelFrom8: 37SND_PaintChannelFrom8:
36 // r0: int true_lvol 38 ;; r0: int true_lvol
37 // r1: int true_rvol 39 ;; r1: int true_rvol
38 // r2: char *sfx 40 ;; r2: char *sfx
39 // r3: int count 41 ;; r3: int count
40 42
41 stmfd sp!, {r4, r5, r6, r7, r8, sl} 43 stmfd sp!, {r4, r5, r6, r7, r8, sl}
42 44
43 ldr ip, =paintbuffer 45 ldr ip, =paintbuffer
44 ldr ip, [ip] 46 ldr ip, [ip]
45 47
46 mov r0, r0, asl #16 // pre-scale both volumes by 2^16 48 mov r0, r0, asl #16 ; prescale by 2^16
47 mov r1, r1, asl #16 49 mov r1, r1, asl #16
48 50
49 sub r3, r3, #1 // we'll count backwards 51 sub r3, r3, #1 ; count backwards
50 // sl = 0xffff0000
51 ldrh sl, =0xffff
52 52
53.loop: 53 ldrh sl, =0xffff ; halfword mask
54 ldrsb r4, [r2, r3] // load *sfx[i] -> r4
55 54
56 // keep endianness in mind here 551:
57 // buffer looks like [left_0, left_1, right_0, right_1] in memory 56 ldrsb r4, [r2, r3] ; load input sample
58 // but it is loaded as [right1, right0, left1, left0] to registers 57 ldr r8, [ip, r3, lsl #2] ; load output sample pair from paintbuffer
59 ldr r8, [ip, r3, lsl #2] // load paintbuffer[0:1] = RIGHTCHANNEL:LEFTCHANNEL 58 ; (left:right in memory -> right:left in register)
59 ;; right channel (high half)
60 mul r5, r4, r1 ; scaledright = sfx[i] * (true_rvol << 16) -- bottom half is zero
61 qadd r7, r5, r8 ; right = scaledright + right (in high half of word)
62 bic r7, r7, sl ; zero bottom half of r7
60 63
61 // handle high half (right channel) first 64 ;; left channel (low half)
62 mul r5, r4, r1 // SCALEDRIGHT = SFXI * (true_rvol << 16) -- bottom half is zero 65 mul r5, r4, r0 ; scaledleft = sfx[i] * (true_rvol << 16)
66 mov r8, r8, lsl #16 ; extract original left channel from paintbuffer
67 qadd r8, r5, r8 ; left = scaledleft + left
63 68
64 // r7 holds right channel in high half (dirty bottom half) 69 orr r7, r7, r8, lsr #16 ; combine right:left in r7
65 qadd r7, r5, r8 // RIGHTCHANORIG = SCALEDRIGHT + RIGHTCHANORIG (high half) 70 str r7, [ip, r3, lsl #2] ; write right:left to output buffer
66
67 bic r7, r7, sl // zero bottom bits of r7
68
69 // trash r5, r6 and handle left channel
70 mul r5, r4, r0 // SCALEDLEFT = SFXI * (true_rvol << 16)
71
72 mov r8, r8, lsl #16 // extract original left channel from paintbuffer
73
74 // r8 holds left channel in high half with zero bottom half
75 qadd r8, r5, r8
76
77 // combine the two 16-bit samples in r7 as 32-bit [left:right]
78 // (use lsr to not sign-extend the lower half)
79 orr r7, r7, r8, lsr #16
80
81 str r7, [ip, r3, lsl #2] // write 32-bit to paintbuffer
82 subs r3, r3, #1 71 subs r3, r3, #1
83 bgt .loop // must use instead of bne because of the corner case count=1
84
85 72
73 bgt 1b ; must use bgt instead of bne in case count=1
86 74
87 ldmfd sp!, {r4, r5, r6, r7, r8, sl} 75 ldmfd sp!, {r4, r5, r6, r7, r8, sl}
88 76
89 bx lr 77 bx lr
90 78
91#elif defined(__ARM_ARCH_6__) // ARMv6 with QADD16 (disabled) 79#elif defined(__ARM_ARCH_6__) ; ARMv6 with QADD16 (disabled)
92SND_PaintChannelFrom8: 80SND_PaintChannelFrom8:
93 // r0: int true_lvol 81 ;; r0: int true_lvol
94 // r1: int true_rvol 82 ;; r1: int true_rvol
95 // r2: char *sfx 83 ;; r2: char *sfx
96 // r3: int count 84 ;; r3: int count
97 85
98 stmfd sp!, {r4, r5, r6, r7} 86 stmfd sp!, {r4, r5, r6, r7}
99 87
100 ldr ip, =paintbuffer 88 ldr ip, =paintbuffer
101 ldr ip, [ip] 89 ldr ip, [ip] ; load paintbuffer address
102 sub r3, r3, #1 // we'll count backwards 90 sub r3, r3, #1 ; we'll count backwards
103.loop: 911:
104 ldrsb r4, [r2, r3] // load *sfx[i] -> r4 92 ldrsb r4, [r2, r3] ; load sfx[i] -> r4
105 93 ldr r7, [ip, r3, lsl #2] ; load old sample pair
106 // keep endianness in mind here
107 // buffer looks like [left_0, left_1, right_0, right_1] in memory
108 // but it is loaded as [right1, right0, left1, left0] to registers
109 ldr r7, [ip, r3, lsl #2] // load paintbuffer[0:1] = RIGHTCHANNEL:LEFTCHANNEL
110 94
111 // handle high half (right channel) first 95 mul r5, r4, r1 ; SCALEDRIGHT = SFXI * true_rvol
112 mul r5, r4, r1 // SCALEDRIGHT = SFXI * true_rvol 96 mul r6, r4, r0 ; SCALEDLEFT = SFXI * true_rvol
113 mul r6, r4, r0 // SCALEDLEFT = SFXI * true_rvol
114 97
115 orr r6, r6, r5, lsl #16 98 orr r6, r6, r5, lsl #16 ; combine samples as 32-bit
116 99
117 qadd16 r6, r6, r7 100 qadd16 r6, r6, r7 ; parallel 16-bit add
118 101
119 str r6, [ip, r3, lsl #2] // write 32-bit to paintbuffer 102 str r6, [ip, r3, lsl #2] ; write 32-bit to paintbuffer
120 103
121 subs r3, r3, #1 104 subs r3, r3, #1
122 bne .loop 105 bgt 1b
123 106
124 ldmfd sp!, {r4, r5, r6, r7} 107 ldmfd sp!, {r4, r5, r6, r7}
125 108