Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /**************************************/
- /* Project: NitroLib */
- /* File: snd_MixProc.s */
- /* Copyright (c) 2011, Aikku */
- /**************************************/
- /* HISTORY */
- /**************************************/
- /* 10-07-04 */
- /* Added 8-bit DPCM support (x^2) */
- /* 10-06-29 */
- /* Removed 11-bit mode */
- /* Removed timing */
- /* Added emulator #define */
- /* Optimized reverb */
- /* 10-06-18 */
- /* Added reverb \o/ */
- /* 10-05-22 */
- /* Added sound buffer flushing */
- /* 10-05-20 */
- /* Added 11-bit mixing (faster) */
- /* 10-05-08 */
- /* Fixed bugs */
- /* 10-05-03 */
- /* Added LERP all #define */
- /* Added proper delta rounding */
- /* 10-05-01 */
- /* Changed envelopes to 8.8 */
- /* Doubled update speed (~120Hz) */
- /* Added linear envelope #define */
- /* 10-04-30 */
- /* Fixed command queue bug */
- /* 10-04-25 */
- /* Fixed usage timing */
- /* 10-04-20 */
- /* Added cycle usage #define */
- /* 10-04-19 */
- /* Added queue system */
- /* 10-04-18 */
- /* Complete rewrote looping scheme */
- /* Fixed sample count calculator */
- /* Fixed LERP shift bug */
- /* 10-04-16 */
- /* Switched back to 32728Hz */
- /* Switched to 24 channels */
- /* Added linear interpolation def */
- /* Changed delta table (x^2 -> x^3) */
- /* 10-04-11 */
- /* Improved mixing loop (remove end */
- /* of sample check from every skip) */
- /* chan.end -> chan.sampRem */
- /* samp.loopLen -> samp.loopStart */
- /* 10-04-09 */
- /* Fixed sample skipping loop */
- /* Optimized mixdown pre-loop */
- /* Switched to 22050Hz */
- /* 10-04-07 */
- /* Switched to oct-buffer */
- /* Added end-of-sample code */
- /* 10-04-05 */
- /* Removed sound multiplier from */
- /* mixdown. */
- /* Fixed mixdown code. */
- /* Added IRQ off #define. */
- /* 10-03-30 */
- /* Fixed buffer clear */
- /* Fixed samp end pointer */
- /* Optimized samp storeback */
- /* 10-03-27 */
- /* Change cpsr at once - not modify */
- /* 10-03-26 */
- /* Added mADPCM code v0.1 */
- /* smp += tab[(signed)nib]! */
- /* 10-03-25 */
- /* Initial release. */
- /**************************************/
- #define EMU 1
- #define LERP 1
- #define LERP_ALL 1
- #define IRQ_ON 1
- #define LINEAR 0
- #define REVERB 1
- #define UNROLL_COMBS 1
- /**************************************/
- .section .itcm, "ax", %progbits
- .align
- .arm
- /**************************************/
- snd_MixProc:
- #if IRQ_ON
- mov r0, #0x04000000
- ldr r1, [r0, #0x210]
- bic r1, r1, #0x08
- str r1, [r0, #0x210]
- stmfd sp!, {lr}
- mrs r0, cpsr
- mrs r1, spsr
- msr cpsr, #0x1F
- stmfd sp!, {r0-r1,r4-r12,lr}
- #else
- stmfd sp!, {r4-r11,lr}
- #endif
- ldr r0, =snd_MixBuf
- ldr r1, =0
- ldr r2, =0
- ldr r3, =0
- ldr r4, =0
- ldr r5, =0
- ldr r6, =0
- ldr r7, =0
- ldr r8, =0
- ldr r9, =272
- 1: stmia r0!, {r1-r8}
- stmia r0!, {r1-r8}
- stmia r0!, {r1-r8}
- stmia r0!, {r1-r8}
- subs r9, r9, #0x10
- bne 1b
- ldr r4, =snd_QueueDat
- ldrh r5, [r4], #0x04
- mov r6, r5, lsr #0x08
- bic r5, r5, r6, lsl #0x08
- and r6, r6, #0x3F
- 1: cmp r5, r6
- beq 2f
- ldr r1, [r4, r5]
- add r5, r5, #0x04
- and r5, r5, #0x3F
- mov r0, r1, lsr #0x1C
- mov r2, r0, lsr #0x02
- bic r1, r1, r0, lsl #0x1C
- bic r0, r0, r2, lsl #0x02
- adr lr, 1b
- ldr pc, [pc, r2, lsl #0x02]
- nop
- .word snd_iSeqPlay
- .word snd_iSeqStop
- .word snd_iSeqKill
- 2: strb r5, [r4, #-0x04]
- blx snd_SeqProc
- ldr r0, =snd_ChnDat - 0x38
- ldr r1, =24
- .Lchan_read_loop:
- ldr r2, [r0, #0x38]!
- tst r2, #0x80
- beq .Lchan_read_ok
- tst r2, #0x40
- beq .Lchan_skip_noteon
- bic r2, r2, #0x00000043
- bic r2, r2, #0x00FF0000
- bic r2, r2, #0xFF000000
- @ r3 = subPos
- @ r4 = smp
- @ r5 = smpRem
- @ r6 = smpDat
- @ r7 = smpNow
- add r8, r0, #0x24
- ldr r7, [r0, #0x18] @ r7 = wave
- ldr r6, [r7, #0x10]! @ r6 = smpPack, r7 = smp.data
- ldr r5, [r7, #0x04-0x10] @ r5 = loopLen
- ldr r4, [r7, #0x00-0x10]
- add r5, r5, r4 @ r5 = smpLen
- mov r5, r5, lsl #0x0A
- mov r4, #0x00 @ r4 = smp = 0
- mov r3, #0x00 @ r3 = subPos = 0
- stmia r8, {r3-r7}
- .Lchan_skip_noteon:
- tst r2, #0x08
- bne 1f
- tst r2, #0x20
- @bicne r2, r2, #0x20 @ pointless, only ever changed here
- orrne r2, r2, #0x03
- and lr, r2, #0xFF00
- 1: bic r3, r2, #0xFF
- bic r3, r3, #0xFF00
- and r4, r2, #0x03
- ldr pc, [pc, r4, lsl #0x02]
- nop
- .word .Lchan_attack
- .word .Lchan_decay
- .word .Lchan_sustain
- .word .Lchan_release
- .Lchan_attack:
- ldrh r4, [r0, #0x04]
- adds r3, r3, r4, lsl #0x10
- bcs 1f
- bne .Lchan_env_ok @ env <= FFFF, env != 0
- 1: mvn r3, #0x00
- mov r3, r3, lsl #0x10
- add r2, r2, #0x01
- b .Lchan_env_ok
- .Lchan_decay:
- ldrh r4, [r0, #0x06]
- subs r3, r3, r4, lsl #0x10
- movcc r3, #0x00
- ldrh r4, [r0, #0x08]
- cmp r4, r3, lsr #0x10
- movhi r3, r4, lsl #0x10
- addhi r2, r2, #0x01
- b .Lchan_env_ok
- .Lchan_sustain:
- ldrh r3, [r0, #0x08]
- mov r3, r3, lsl #0x10
- b .Lchan_env_ok
- .Lchan_release:
- ldrh r4, [r0, #0x0A]
- cmp r4, #0x00
- subnes r3, r3, r4, lsl #0x10
- movls r3, #0x00
- .Lchan_env_ok:
- movs r6, r3, lsr #0x01
- mov r2, r2, lsl #0x10
- orrne r2, r3, r2, lsr #0x10
- str r2, [r0]
- beq .Lchan_read_ok
- #if LINEAR
- ldr r5, [r0, #0x10]
- mov r4, r5, lsr #0x08
- and r4, r4, #0xFF
- smulbb r4, r4, r4 @ 7F*7F = 3F01
- smulwb r3, r6, r4 @ 7FFF0000*3F01>>16 = 1F8040FF
- ldrh r4, [r0, #0x14]
- and r6, r4, #0xFF
- smulwb r3, r3, r6 @ 1F8040FF*7F>>16 = 000FA0A0
- and r4, r4, #0xFF00
- rsb r6, r4, #0x7F00
- smulwb r4, r3, r4 @ 000FA0A0*7F00>>16 = 0007C0AF
- smulwb r3, r3, r6
- mov r3, r3, lsr #0x08
- mov r4, r4, lsr #0x08
- orr r3, r3, r4, lsl #0x10
- #else
- ldr r5, [r0, #0x10]
- mov r4, r5, lsr #0x08
- and r4, r4, #0xFF
- smulbb r4, r4, r4 @ 7F*7F = 3F01
- smulwt r6, r6, r6 @ 7FFF8000*7FFF>>16 = 3FFF4000
- smulwb r3, r6, r4 @ 3FFF4000*3F01>>16 = 0FC010BF
- ldrh r4, [r0, #0x14]
- and r6, r4, #0xFF
- smulwb r3, r3, r6 @ 0FC010BF*7F>>16 = 0007D048
- and r4, r4, #0xFF00
- rsb r6, r4, #0x7F00
- smulwb r4, r3, r4 @ 0007D048*7F00>>16 = 0003E053
- smulwb r3, r3, r6
- mov r3, r3, lsr #0x07
- mov r4, r4, lsr #0x07
- orr r3, r3, r4, lsl #0x10
- #endif
- ldr ip, [r0, #0x18]
- and r7, r5, #0xFF
- cmp r7, #0xFF
- ldreqh r4, [r0, #0x16]
- moveq r4, r4, lsl #0x02
- beq .Lchan_freq_ok
- .Lchan_calc_freq:
- cmp lr, #0x00
- movne r7, lr, lsr #0x08
- and r6, r5, #0xFF0000 @ bndMul
- mov r8, r5, asr #0x08 @ bnd
- smultt r6, r6, r8
- add r4, r6, r7, lsl #0x06 @ bnd + key<<6
- ldr r5, [r0, #0x0C]
- and r6, r5, #0xFF
- subs r6, r6, #0x01
- strneb r6, [r0, #0x0C]
- bne .Lchan_lfo_ok
- ands r6, r5, #0xFF0000
- andnes r7, r5, #0xFF00
- beq .Lchan_lfo_ok
- add r7, r5, r7, lsl #0x10
- str r7, [r0, #0x0C]
- mov r5, r5, lsr #0x18
- and r7, r5, #0x3F
- tst r5, #0x40
- rsbne r7, r7, #0x80
- tst r5, #0x80
- rsbne r7, r7, #0x00
- smultb r5, r6, r7
- add r4, r4, r5, asr #0x06
- .Lchan_lfo_ok:
- ands r5, r4, #0x3F
- and r4, r4, #0x7F << 6
- ldr r6, =snd_FrqTab
- ldr r4, [r6, r4, lsr #0x04]!
- ldrne r6, [r6, #0x04] @ only needed if tune != 0 [else mul by 0]
- sub r6, r6, r4
- mov r6, r6, lsl #0x05
- smulwb r5, r6, r5
- add r4, r4, r5, lsl #0x05 @ lower 8-32 bits are precision, anyway
- ldr r8, [ip, #0x08]
- umull r8, r4, r4, r8
- .Lchan_freq_ok:
- ldr r5, =0x080280C8
- umulls r5, r4, r4, r5
- addcs r4, r4, #0x01
- ldmia ip, {r5-r6}
- cmp r5, #0x00 @ looped?
- addne r5, ip, r5 @ yes - set start pos
- addne r5, r5, #0x10 @ skip header
- str r5, .Lloop_start @ <- loop start
- strne r6, .Lloop_len @ <- loop len
- ldrne r7, [ip, #0x0C]
- strne r7, .Lloop_smp @ <- loop smp
- ldrh r5, [r0, #0x24]
- orr r4, r4, r5, lsl #0x10
- add r5, r0, #0x24
- ldmib r5, {r5-r8}
- ldr r9, =snd_DelTab
- ldr sl, =snd_MixBuf
- ldr fp, =272
- stmfd sp!, {r0,r1,r6,fp}
- .Lchan_mix_prep:
- ldr r6, [sp, #0x08]
- smulbb r1, r4, fp @ assume delta < 0x8000U (32.0)
- rsbs r1, r1, r6
- movcc r1, #0x00
- str r1, [sp, #0x08]
- bge .Lchan_calcmix
- mov r1, #0x04000000
- str r6, [r1, #0x290]
- mov r2, r4, lsl #0x10
- mov r2, r2, lsr #0x10
- str r2, [r1, #0x298]
- str r1, [r1, #0x280]
- 1: ldr r0, [r1, #0x280]
- tst r0, #0x8000
- bne 1b
- ldr fp, [r1, #0x2A0]
- ldr r0, [r1, #0x2A8]
- cmp r0, #0x00
- addne fp, fp, #0x01
- .Lchan_calcmix:
- ldr r0, [sp, #0x0C]
- sub r0, r0, fp
- str r0, [sp, #0x0C]
- #if LERP
- mov r0, r4, lsl #0x10
- cmp r0, #0x04000000
- bhi .Lmix_no_lerp
- mov r0, r4, lsr #0x10
- bic r4, r4, r0, lsl #0x10
- orr r4, r4, r0, lsl #0x15
- .Lmix_lerp:
- mov ip, r7, lsr #0x18
- ldr ip, [r9, ip, lsl #0x02]
- tst fp, #0x01
- beq .Lchan_mix_lerp
- @ r0: [smp temp]
- @ r1: [smp temp]
- @ r2: [smp temp]
- @ r3: volL | volR<<16
- @ r4: delta | subPos<<16
- @ r5: smpLast<<16
- @ r6: [smp temp] [smpRem]
- @ r7: smpPack
- @ r8: smpNow
- @ r9: tabPos
- @ sl: dstBuffer
- @ fp: mixCount
- @ ip: smpDel
- @ sp: ---
- @ lr: [mix temp]
- .macro mixl d0, d1
- smulwt lr, ip, r4
- qdadd lr, r5, lr
- smlawb \d0, lr, r3, \d0
- smlawt \d1, lr, r3, \d1
- adds r4, r4, r4, lsl #0x15
- bpl 1f
- bic r4, r4, #0x80000000
- qadd r5, r5, ip
- movs r7, r7, lsl #0x08
- ldreq r7, [r8, #0x04]!
- mov ip, r7, lsr #0x18
- ldr ip, [r9, ip, lsl #0x02]
- 1:
- .endm
- .Lchan_mixrem_lerp:
- ldmia sl, {r0,r1}
- mixl r0, r1
- stmia sl!, {r0,r1}
- subs fp, fp, #0x01
- beq .Lchan_mix_lerp_ok
- .Lchan_mix_lerp:
- ldmia sl, {r0,r1,r2,r6}
- mixl r0, r1
- mixl r2, r6
- stmia sl!, {r0,r1,r2,r6}
- subs fp, fp, #0x02
- bne .Lchan_mix_lerp
- .Lchan_mix_lerp_ok:
- mov r0, r4, lsr #0x15
- bic r4, r4, r0, lsl #0x15
- orr r4, r4, r0, lsl #0x10
- b .Lchan_mix_ok
- #endif
- .Lmix_no_lerp:
- #if LERP_ALL
- mov lr, r7, lsr #0x18
- ldr lr, [r9, lr, lsl #0x02]
- #endif
- tst fp, #0x01
- beq .Lchan_mix
- @ r0: [smp temp]
- @ r1: [smp temp]
- @ r2: [smp temp]
- @ r3: volL | volR<<16
- @ r4: delta | subPos<<16
- @ r5: smpLast<<16
- @ r6: [smp temp] [smpRem]
- @ r7: smpPack
- @ r8: smpNow
- @ r9: tabPos
- @ sl: dstBuffer
- @ fp: mixCount
- @ ip: [mix temp]
- @ sp: ---
- @ lr: [delta] (only when LERP_ALL is enabled)
- .macro mix d0, d1
- #if LERP_ALL
- smulwt ip, lr, r4
- mov ip, ip, lsl #0x10-10
- qadd ip, ip, r5
- smlawb \d0, ip, r3, \d0
- smlawt \d1, ip, r3, \d1
- #else
- smlawb \d0, r5, r3, \d0
- smlawt \d1, r5, r3, \d1
- #endif
- add r4, r4, r4, lsl #0x10
- #if LERP
- sub r4, r4, #0x04000000
- #else
- subs ip, r4, #0x04000000
- bmi 2f
- #endif
- #if LERP_ALL
- 1: qadd r5, r5, lr
- movs r7, r7, lsl #0x08
- ldreq r7, [r8, #0x04]!
- mov lr, r7, lsr #0x18
- ldr lr, [r9, lr, lsl #0x02]
- #else
- 1: mov lr, r7, lsr #0x18
- ldr lr, [r9, lr, lsl #0x02]
- movs r7, r7, lsl #0x08
- ldreq r7, [r8, #0x04]!
- qadd r5, r5, lr
- #endif
- #if LERP
- subs r4, r4, #0x04000000
- bpl 1b
- add r4, r4, #0x04000000
- #else
- subs ip, ip, #0x04000000
- bpl 1b
- add r4, ip, #0x04000000
- #endif
- 2:
- .endm
- .Lchan_mixrem:
- ldmia sl, {r0,r1}
- mix r0, r1
- stmia sl!, {r0,r1}
- subs fp, fp, #0x01
- beq .Lchan_mix_nolerp_ok
- .Lchan_mix:
- ldmia sl, {r0,r1,r2,r6}
- mix r0, r1
- mix r2, r6
- stmia sl!, {r0,r1,r2,r6}
- subs fp, fp, #0x02
- bne .Lchan_mix
- .Lchan_mix_nolerp_ok:
- .Lchan_mix_ok:
- ldr r6, [sp, #0x08]
- ldr fp, [sp, #0x0C]
- cmp r6, #0x00
- blle .Lsmp_end
- cmp fp, #0x00
- bne .Lchan_mix_prep
- ldmfd sp!, {r0,r1}
- add sp, sp, #0x08
- mov r4, r4, lsr #0x10
- add r2, r0, #0x24
- stmia r2, {r4-r8}
- .Lchan_read_ok:
- subs r1, r1, #0x01
- bne .Lchan_read_loop
- .Lstart_mixdown:
- mvn r5, #0x00
- mov r4, r5, lsr #0x11
- mov r3, #0x02 * 272
- ldr r2, =snd_MixInf
- ldrb r1, [r2]
- add r0, r1, #0x01
- and r0, r0, #0x3F
- strb r0, [r2]
- ldr r0, =snd_OutBuf
- smlabb r0, r1, r3, r0
- add r1, r0, r3, lsl #0x06
- ldr r2, =snd_MixBuf
- #if REVERB
- stmfd sp!, {r0-r1,r3}
- #endif
- #if !EMU
- .Lflush_lines:
- bic r7, r0, #0x1F
- bic r8, r1, #0x1F
- and r9, r0, #0x1F
- add r9, r9, r3
- .Lflush_go:
- mcr p15, 0, r7, c7, c14, 1
- mcr p15, 0, r8, c7, c14, 1
- add r7, r7, #0x20
- add r8, r8, #0x20
- subs r9, r9, #0x20
- bhi .Lflush_go
- #endif
- @ r0: dstL
- @ r1: dstR
- @ r2: src
- @ r3: cnt*2
- @ r4: 7FFFh
- @ r5: 0xFFFFFFFF
- @ r9: [smp]
- @ sl: [smp]
- @ fp: [smp]
- @ ip: [smp]
- .macro mux src, sid
- mov \src, \src, asr #0x0B
- teq \src, \src, lsl #0x10
- submi \src, r4, \src, asr #0x1F
- .if \sid == 0
- and \src, \src, r5, lsr #0x10
- .endif
- .endm
- 1: ldmia r2!, {r9-ip}
- mux r9, 0
- mux fp, 1
- orr r9, r9, fp, lsl #0x10
- str r9, [r0], #0x04
- mux sl, 0
- mux ip, 1
- orr sl, sl, ip, lsl #0x10
- str sl, [r1], #0x04
- subs r3, r3, #0x02*2
- bne 1b
- /**************************************/
- /* REVERB PROCESSING */
- /**************************************/
- #if REVERB
- /**************************************/
- .Lrev_go:
- ldmfd sp!, {r0-r2}
- ldr r3, =snd_OutBuf + 272*64*2
- ldr r4, =snd_CmbDat-4
- @ r0: dstL
- @ r1: dstR
- @ r2: cnt*2
- @ r3: bufEndL
- @ r4: combData
- @ r5: combSrcL
- @ r6: combSrcR
- @ r7: combOld
- @ r8: combScale
- @ r9: comAdr
- @ sl: smpL
- @ fp: smpR
- .macro comb
- ldmib r4!, {r5-r8}
- mov ip, r7, lsl #0x10
- bic r7, r7, ip, lsr #0x10
- ldrsh lr, [r6], #0x02
- mov lr, lr, lsl #0x10
- qadd r7, r7, lr
- movs r7, r7, asr #0x11
- adcmi r7, r7, #0x00
- ldrsh lr, [r5], #0x02
- mov lr, lr, lsl #0x10
- qadd ip, ip, lr
- movs ip, ip, asr #0x11
- adcmi ip, ip, #0x010000 @ to compensate for sign [upper = -1+1 = 0]
- orr r7, ip, r7, lsl #0x10
- smulbb ip, r7, r8
- smultb lr, r7, r8
- qadd sl, sl, ip
- qadd fp, fp, lr
- cmp r5, r3
- ldreq r5, =snd_OutBuf
- moveq r6, r3
- stmdb r4, {r5-r7}
- .endm
- .Lrev_do:
- ldrsh sl, [r0]
- ldrsh fp, [r1]
- mov sl, sl, lsl #0x10
- mov fp, fp, lsl #0x10
- #if UNROLL_COMBS
- comb
- comb
- comb
- comb
- #else
- 1: comb
- adds r0, r0, #0x40000000
- bcc 1b
- #endif
- mov sl, sl, asr #0x10
- mov fp, fp, asr #0x10
- strh sl, [r0], #0x02
- strh fp, [r1], #0x02
- subs r2, r2, #0x02*1
- subne r4, r4, #0x10*4
- bne .Lrev_do
- /**************************************/
- #endif
- /**************************************/
- #if IRQ_ON
- ldmfd sp!, {r0-r1,r4-r12,lr}
- msr cpsr, r0
- msr spsr, r1
- mov r0, #0x04000000
- ldr r1, [r0, #0x210]
- orr r1, r1, #0x08
- str r1, [r0, #0x210]
- ldmfd sp!, {pc}
- #else
- ldmfd sp!, {r4-r11,pc}
- #endif
- .Lloop_start:
- .word 0
- .Lloop_len:
- .word 0
- .Lloop_smp:
- .word 0
- .Lsmp_end:
- ldr r8, .Lloop_start
- cmp r8, #0x00
- beq .Lsmp_no_loop
- mov r1, r6
- ldr r7, .Lloop_len
- add r6, r6, r7, lsl #0x0A
- str r6, [sp, #0x08]
- ldr r5, .Lloop_smp
- ldr r7, [r8]
- mov r7, r7, lsl #0x08
- cmp r1, #0x00
- moveq pc, lr
- 1: mov r0, r7, lsr #0x18
- ldr r0, [r9, r0, lsl #0x02]
- qadd r5, r5, r0
- movs r7, r7, lsl #0x08
- ldreq r7, [r8, #0x04]!
- adds r1, r1, #0x400
- bmi 1b
- mov pc, lr
- .Lsmp_no_loop:
- ldmfd sp!, {r0-r1}
- add sp, sp, #0x08
- strb r8, [r0]
- b .Lchan_read_ok
- /**************************************/
- .align
- .pool
- /**************************************/
- .size snd_MixProc, .-snd_MixProc
- .global snd_MixProc
- /**************************************/
- /* EOF */
- /**************************************/
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement