Commit 9a2d1b3e authored by Jeffrey Lee's avatar Jeffrey Lee
Browse files

Make the voice generator correctly adjust itself for the current sound system configuration

Detail:
  s/Percussion - Similar to StringLib, Percussion uses various accumulator values that were tuned for a 48us sample period an 100Hz buffer fill rate. These values will now be calculated dynamically based around the current sound system configuration, ensuring the correct output is produced across all sensible configurations. Also swapped single-reg LDM/STM for Pull/Push to fix performance warnings from the assembler.
Admin:
  Tested on BB-xM
  Voices now sound correct at high and low sample rates, small and large buffer sizes
  Part of the fix for ticket #347:
  https://www.riscosopen.org/tracker/tickets/347


Version 1.16. Tagged as 'Percussion-1_16'
parent 667077b5
;
; This file is automatically maintained by srccommit, do not edit manually.
; Last processed by srccommit version: 1.68.
; Last processed by srccommit version: 1.1.
;
GBLS Module_MajorVersion
GBLA Module_Version
......@@ -11,13 +11,13 @@
GBLS Module_HelpVersion
GBLS Module_ComponentName
GBLS Module_ComponentPath
Module_MajorVersion SETS "1.15"
Module_Version SETA 115
Module_MajorVersion SETS "1.16"
Module_Version SETA 116
Module_MinorVersion SETS ""
Module_Date SETS "21 Jun 2004"
Module_ApplicationDate SETS "21-Jun-04"
Module_Date SETS "28 Jun 2014"
Module_ApplicationDate SETS "28-Jun-14"
Module_ComponentName SETS "Percussion"
Module_ComponentPath SETS "RiscOS/Sources/HWSupport/Sound/Voices/Percussion"
Module_FullVersion SETS "1.15"
Module_HelpVersion SETS "1.15 (21 Jun 2004)"
Module_ComponentPath SETS "castle/RiscOS/Sources/HWSupport/Sound/Voices/Percussion"
Module_FullVersion SETS "1.16"
Module_HelpVersion SETS "1.16 (28 Jun 2014)"
END
/* (1.15)
/* (1.16)
*
* This file is automatically maintained by srccommit, do not edit manually.
* Last processed by srccommit version: 1.68.
* Last processed by srccommit version: 1.1.
*
*/
#define Module_MajorVersion_CMHG 1.15
#define Module_MajorVersion_CMHG 1.16
#define Module_MinorVersion_CMHG
#define Module_Date_CMHG 21 Jun 2004
#define Module_Date_CMHG 28 Jun 2014
#define Module_MajorVersion "1.15"
#define Module_Version 115
#define Module_MajorVersion "1.16"
#define Module_Version 116
#define Module_MinorVersion ""
#define Module_Date "21 Jun 2004"
#define Module_Date "28 Jun 2014"
#define Module_ApplicationDate "21-Jun-04"
#define Module_ApplicationDate "28-Jun-14"
#define Module_ComponentName "Percussion"
#define Module_ComponentPath "RiscOS/Sources/HWSupport/Sound/Voices/Percussion"
#define Module_ComponentPath "castle/RiscOS/Sources/HWSupport/Sound/Voices/Percussion"
#define Module_FullVersion "1.15"
#define Module_HelpVersion "1.15 (21 Jun 2004)"
#define Module_LibraryVersionInfo "1:15"
#define Module_FullVersion "1.16"
#define Module_HelpVersion "1.16 (28 Jun 2014)"
#define Module_LibraryVersionInfo "1:16"
......@@ -190,7 +190,7 @@ Token_Noise DCB "Noise", 0
ALIGN
Finalise_Module ROUT
STMFD R13!,{R14}
Entry
LDR R2,[R12] ; workspace
ADD R0,R2,#Voice1 ; WS IS LINK
LDR R1,[R0,#SoundVoiceIndex]
......@@ -204,8 +204,8 @@ Finalise_Module ROUT
ADD R0,R2,#Voice4 ; WS IS LINK
LDR R1,[R0,#SoundVoiceIndex]
SWI XSound_RemoveVoice
LDMFD R13!,{R14} ; return - the release is assumed to work correctly!
RETURNVC
CLRV
EXIT ; return - the release is assumed to work correctly!
; Note that we can leave the workspace as it is : if this is a fatal entry,
; the workspace will be deleted, while for a non-fatal entry, the workspace
......@@ -358,7 +358,7 @@ Voice1Base
B GateOff1
B Instantiate
B Free
LDMFD R13!,{PC}
Pull "PC"
& Voice1TitleString - Voice1Base
& DSegSize
& 0 ; data segmentSSCB index at load time..
......@@ -367,19 +367,19 @@ Voice1TitleString = "Percussion-Soft",0
ALIGN
Fill1
ADRL R0,Filt1
STMFD R13!,{R0} ; filter code pointer
Push "R0" ; filter code pointer
B Fill
UpdateFill1
ADRL R0,Filt1
STMFD R13!,{R0} ; filter code pointer
Push "R0" ; filter code pointer
B UpdateFill
GateOn1
ADRL R0,Filt1
STMFD R13!,{R0} ; filter code pointer
Push "R0" ; filter code pointer
B GateOn
GateOff1
ADRL R0,Filt1
STMFD R13!,{R0} ; filter code pointer
Push "R0" ; filter code pointer
B GateOff
Voice2 * .-WorkSpaceImage
......@@ -390,7 +390,7 @@ Voice2Base
B GateOff2
B Instantiate
B Free
LDMFD R13!,{PC}
Pull "PC"
& Voice2TitleString - Voice2Base
& DSegSize
& 0 ; data segmentSSCB index at load time..
......@@ -399,19 +399,19 @@ Voice2TitleString = "Percussion-Medium",0
ALIGN
Fill2
ADRL R0,Filt2
STMFD R13!,{R0} ; filter code pointer
Push "R0" ; filter code pointer
B Fill
UpdateFill2
ADRL R0,Filt2
STMFD R13!,{R0} ; filter code pointer
Push "R0" ; filter code pointer
B UpdateFill
GateOn2
ADRL R0,Filt2
STMFD R13!,{R0} ; filter code pointer
Push "R0" ; filter code pointer
B GateOn
GateOff2
ADRL R0,Filt2
STMFD R13!,{R0} ; filter code pointer
Push "R0" ; filter code pointer
B GateOff
Voice3 * .-WorkSpaceImage
......@@ -422,7 +422,7 @@ Voice3Base
B GateOff3
B Instantiate
B Free
LDMFD R13!,{PC}
Pull "PC"
& Voice3TitleString - Voice3Base
& DSegSize
& 0 ; data segmentSSCB index at load time..
......@@ -431,19 +431,19 @@ Voice3TitleString = "Percussion-Snare",0
ALIGN
Fill3
ADRL R0,Filt3
STMFD R13!,{R0} ; filter code pointer
Push "R0" ; filter code pointer
B Fill
UpdateFill3
ADRL R0,Filt3
STMFD R13!,{R0} ; filter code pointer
Push "R0" ; filter code pointer
B UpdateFill
GateOn3
ADRL R0,Filt3
STMFD R13!,{R0} ; filter code pointer
Push "R0" ; filter code pointer
B GateOn
GateOff3
ADRL R0,Filt3
STMFD R13!,{R0} ; filter code pointer
Push "R0" ; filter code pointer
B GateOff
Voice4 * .-WorkSpaceImage
......@@ -454,7 +454,7 @@ Voice4Base
B GateOff4
B Instantiate
B Free
LDMFD R13!,{PC}
Pull "PC"
& Voice3TitleString - Voice3Base
& DSegSize
& 0 ; data segmentSSCB index at load time..
......@@ -463,19 +463,19 @@ Voice4TitleString = "Percussion-Noise",0
ALIGN
Fill4
ADRL R0,Filt4
STMFD R13!,{R0} ; filter code pointer
Push "R0" ; filter code pointer
B Fill
UpdateFill4
ADRL R0,Filt4
STMFD R13!,{R0} ; filter code pointer
Push "R0" ; filter code pointer
B UpdateFill
GateOn4
ADRL R0,Filt4
STMFD R13!,{R0} ; filter code pointer
Push "R0" ; filter code pointer
B GateOn
GateOff4
ADRL R0,Filt4
STMFD R13!,{R0} ; filter code pointer
Push "R0" ; filter code pointer
B GateOff
DSize & DSegSize
......@@ -491,7 +491,7 @@ LintoLog & SoundLevel1Base + SoundLevel1LogTable
; R0 preserved if success, R0 changed if fail
Instantiate
[ {TRUE}
STMFD r13!, {r0-r3,lr}
Push "r0-r3,lr"
MOV r1, r0 ; preserve channel in r1
MOV r0, #ModHandReason_Claim
LDR r3, DSize
......@@ -501,9 +501,10 @@ Instantiate
STR r2, [lr, r1, ASL #2]
MOVVS r0, #-1 ; a different r0 on exit to indicate failure
STRVS r0, [sp]
LDMFD r13!,{r0-r3,lr,pc}
Pull "r0-r3,lr"
Pull "pc"
|
LDMFD R13!,{PC}
Pull "PC"
]
;**************************************
......@@ -515,21 +516,28 @@ Instantiate
; R0 preserved ; always works!
Free ROUT
[ {TRUE}
STMFD r13!, {r0-r3,lr}
Push "r0-r3,lr"
ADRL r3, Instance0
LDR r2, [r3, r0, ASL #2]
MOV lr, #0
STR lr, [r3, r0, ASL #2]
MOV r0, #ModHandReason_Free
SWI XOS_Module
LDMFD r13!, {r0-r3,lr,pc}
Pull "r0-r3,lr"
Pull "pc"
|
LDMFD R13!,{PC}
Pull "PC"
]
; Constants
CentiSec & 65536*4/208 ; truncated divide
CentiSecScale & &68DB8 ; (2^32)/10000
RandSeed & &AAAAAAAA
DrumPitch & &D055 ; Drum pitch scale factor:
; * Original CentiSec value was 65536*4/208
; * Which was really an approximation of 65536*48*4/10000,
; for a 48s sample period
; * Original DrumPitch was &400
; * 65536*OriginalDrumPitch/OriginalCentiSec = &D055
;**************************************
;* VOICE INITIALISE/GATE ON *
......@@ -537,6 +545,7 @@ RandSeed & &AAAAAAAA
; Init Entry -
; Initialise WaveTable for this instance
; R7 is channel number
; R8 is sample period in s
; R9 is SoundChannelB base:
; r10 DMA buffer limit (+1)
; r11 DMA buffer interleave increment
......@@ -546,7 +555,44 @@ RandSeed & &AAAAAAAA
; on RETURN mext down (must LDMFD R13!,{junk,pc})
; NO r14 - IRQs are enabled and r14 cannot be trusted
GateOn ROUT
; Calculate increment such that a 16 bit accumulator will overflow every
; centisecond, when incremented after every 4th sample
; i.e. 65536*period*4/10000
; or 65536*102400*4/ratein1024hz
MSR CPSR_c,#SVC32_mode
Push "R14"
MOV R0,#0
SWI XSound_Mode ; Check Sound_SampleRate supported
TEQ R0,#1
BEQ %FT01
LDR R0,CentiSecScale
MUL R4,R0,R8
MOV R4,R4,LSR #14
B %FT02
01
SWI XSound_SampleRate ; Get current rate (r0=1)
; 65536*102400*4 is too large for a 32 bit int, divide everything by 8
MOV R2,R2,LSR #3 ; /8
MOV R0,#&C8000000 ; 65536*102400*4/8
DivRem R4,R0,R2,R1
02
Pull "R14"
MSR CPSR_c,#IRQ32_mode
LDMIA R9,{R0,R1,R2,R3} ; get instance params
; R3 is our duration in buffer fills
; Recalculate it to be the duration in centiseconds
; i.e. R3*cs_per_buffer = R3*(R8/10000)*(R10-R12)/R11
; -> R3*R4*(R10-R12)/(R11*65536*4)
MUL R3,R4,R3
SUB R8,R10,R12
MUL R3,R8,R3
; Noddy division by R11, assuming 1/2/4/8 byte channel interleave
TEQ R11,#2
MOVEQ R3,R3,LSR #1
CMP R11,#4
MOVEQ R3,R3,LSR #2
MOVGT R3,R3,LSR #3
MOV R3,R3,LSR #16+2
; compute instance data segment pointer
[ {TRUE}
GetChannelDataSeg R8, R7, R6
......@@ -582,14 +628,15 @@ GateOn ROUT
; t in centi-seconds
MOV R3,R3,LSL #20 ; mask to 12-bit
MOV R3,R3,LSR #20
LDR R4,CentiSec ; centi-second count
; Duration update
; set default to every n centi-seconds
; LDR R5,DrumPitch DWFDWF
; MOV R5,R5,LSL #1 ; *4 for 4 samples/check
MOV R5,#&400
LDR R5,DrumPitch
MUL R5,R4,R5
MOVS R5,R5,LSR #16
ORR R5,R5,#&FF000000 ; force acc overflow!
ADC R5,R5,#&FF000000 ; force acc overflow! (+ round up division)
ORR R5,R5,#&00FF0000 ; immediately
; must convert amp to linear...
; algorithm:
......@@ -609,7 +656,9 @@ GateOn ROUT
LDR R0,[R8,#RegSav1] ; smooth update of
BIC R0,R0,#&00FF ; preserve 16-bit acc
BIC R0,R0,#&FF00
ORR R1,R0,#&100
MOV R1,R5,LSL #16
ORRS R1,R0,R1,LSR #16+2 ; original pitch was &100, i.e. DrumPitch/4
ADDCS R1,R1,#1
; ORR R1,R1,R0 ; new inc
; swap R9 to local instance...
......@@ -688,7 +737,7 @@ Fill_RND2
STR R1,[R9,#SeedH]
ADD R6,R9,#DLine ; restore r6
ADR R1,Fill_RND3
STMFD R13!,{R1}
Push "r1"
LDR PC,[R13,#4]
; B Fill_Filt
Fill_RND3 ; mute first buffer
......@@ -793,7 +842,7 @@ Fill_Wave ROUT
40
STMIB R9,{R1,R2,R3,R4,R5} ; preserve world
ADR R1,%45
STMFD R13!,{R1}
Push "r1"
LDR PC,[R13,#4]
; B Fill_Filt
45 B %20 ; return
......@@ -1082,6 +1131,7 @@ Filt1 ROUT
; Fill Update Entry -
; Smooth control change params
; R7 is channel number
; R8 is sample period in s
; R9 is SoundChannelB base:
; r10 DMA buffer limit (+1)
; r11 DMA buffer interleave increment
......@@ -1091,7 +1141,44 @@ Filt1 ROUT
; on RETURN mext down (must LDMFD R13!,{junk,pc})
; NO r14 - IRQs are enabled and r14 cannot be trusted
UpdateFill ROUT
; Calculate increment such that a 16 bit accumulator will overflow every
; centisecond, when incremented after every 4th sample
; i.e. 65536*period*4/10000
; or 65536*102400*4/ratein1024hz
MSR CPSR_c,#SVC32_mode
Push "R14"
MOV R0,#0
SWI XSound_Mode ; Check Sound_SampleRate supported
TEQ R0,#1
BEQ %FT01
LDR R0,CentiSecScale
MUL R4,R0,R8
MOV R4,R4,LSR #14
B %FT02
01
SWI XSound_SampleRate ; Get current rate (r0=1)
; 65536*102400*4 is too large for a 32 bit int, divide everything by 8
MOV R2,R2,LSR #3 ; /8
MOV R0,#&C8000000 ; 65536*102400*4/8
DivRem R4,R0,R2,R1
02
Pull "R14"
MSR CPSR_c,#IRQ32_mode
LDMIA R9,{R0,R1,R2,R3} ; get instance params
; R3 is our duration in buffer fills
; Recalculate it to be the duration in centiseconds
; i.e. R3*cs_per_buffer = R3*(R8/10000)*(R10-R12)/R11
; -> R3*R4*(R10-R12)/(R11*65536*4)
MUL R3,R4,R3
SUB R8,R10,R12
MUL R3,R8,R3
; Noddy division by R11, assuming 1/2/4/8 byte channel interleave
TEQ R11,#2
MOVEQ R3,R3,LSR #1
CMP R11,#4
MOVEQ R3,R3,LSR #2
MOVGT R3,R3,LSR #3
MOV R3,R3,LSR #16+2
; compute instance data segment pointer
[ {TRUE}
GetChannelDataSeg R8, R7, R6
......@@ -1132,12 +1219,13 @@ UpdateFill ROUT
BEQ %10
MOV R3,R3,LSL #20 ; mask to 12-bit
MOV R3,R3,LSR #20
LDR R4,CentiSec ; centi-second count
; Duration update
; set default to every n centi-seconds
; MOV R5,R4,LSR #1 ; div by 4
MOV R5,#&400
ORR R5,R5,#&FF000000 ; force acc overflow!
LDR R5,DrumPitch
MUL R5,R4,R5
MOVS R5,R5,LSR #16
ADC R5,R5,#&FF000000 ; force acc overflow! (+ round up division)
ORR R5,R5,#&00FF0000 ; immediately
; must convert amp to linear...
; algorithm:
......@@ -1163,7 +1251,9 @@ UpdateFill ROUT
LDR R0,[R8,#RegSav1] ; smooth update of
BIC R0,R0,#&00FF ; preserve 16-bit acc
BIC R0,R0,#&FF00
ORR R1,R0,#&100
MOV R1,R5,LSL #16
ORRS R1,R0,R1,LSR #16+2 ; original pitch was &100, i.e. DrumPitch/4
ADDCS R1,R1,#1
; ORR R1,R1,R0 ; new inc
; swap R9 to local instance...
; R8 is data segment pointer
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment