738 lines
24 KiB
Plaintext
738 lines
24 KiB
Plaintext
''*****************************
|
|
''* Hydra Sound System v1.2 *
|
|
''* (C)2007 Andrew Arsenault *
|
|
''*****************************
|
|
''http://www.andrewarsenault.com/hss/
|
|
''e-mail: ym2413a@yahoo.com
|
|
''
|
|
'' Cogs used: 2
|
|
'' HUB-RAM: ~2.7k
|
|
|
|
'' Please visit the website for the latest version, documentation, examples and media files.
|
|
'' Thank you! --Ym2413a
|
|
|
|
'' 25.01.2009 Anpassungen für ein komfortableres Interface zur Visualisierung und Steuerung
|
|
|
|
CON
|
|
#0, iEndFlag 'Repeat oder Ende wurde erreicht
|
|
iRowFlag 'Flag das Songzeile fertig ist
|
|
iEngineC 'Patternzähler
|
|
iBeatC 'Beatzähler
|
|
iRepeat 'zähler für loops
|
|
#5, iChannel
|
|
#5, iChannel1
|
|
#10, iChannel2
|
|
#15, iChannel3
|
|
#16, iChannel4
|
|
#0, iNote
|
|
iOktave
|
|
iVolume
|
|
iEffekt
|
|
iInstrument
|
|
|
|
VAR
|
|
|
|
'Interface
|
|
word intreg[5 * 5]
|
|
|
|
'Sound Engine Stack
|
|
long hsnd_stack[18]
|
|
long cog1, cog2
|
|
|
|
'WavSynth Parameters
|
|
long snd_regs[48] 'Regs for Sound Hardware (8x6)+5dpcm
|
|
long dpcm_regs[5]
|
|
|
|
'DPCM Command Variables
|
|
word dpcmreg_ptr
|
|
|
|
'Global Hmus Player Vars
|
|
word tempo
|
|
word song_pc
|
|
word song_div
|
|
word song_ptr
|
|
word chfre[4]
|
|
byte chfx[4]
|
|
byte chvol[4]
|
|
byte hmus_state
|
|
byte hmvol
|
|
byte fxphs
|
|
|
|
'Sound FX Variables
|
|
word runlen[2]
|
|
word envamp[2]
|
|
word sfx_ptr[2]
|
|
byte envphs[2]
|
|
byte fmcnt[2], fmfreq[2]
|
|
byte loadsfx[2]
|
|
|
|
CON
|
|
|
|
'' Hss Master Control
|
|
|
|
PUB start: okay
|
|
|
|
okay := cog1 := cognew(@entry, @snd_regs)
|
|
okay := cog2 := cognew(hsound, @hsnd_stack)
|
|
|
|
PUB stop
|
|
|
|
cogstop(cog2)
|
|
cogstop(cog1)
|
|
|
|
PUB peek(addrptr) : var1
|
|
|
|
var1 := LONG[@snd_regs][addrptr]
|
|
|
|
PUB intread(index): wert 'interface: auslesen eines interfaceregisters
|
|
|
|
wert := intreg[index]
|
|
|
|
|
|
CON
|
|
|
|
'' Hydra Music Commands
|
|
|
|
PUB hmus_load(songptr) | z
|
|
|
|
hmvol := 15
|
|
song_div := 0
|
|
song_ptr := songptr
|
|
song_pc := WORD[songptr][8]
|
|
tempo := WORD[songptr][12]
|
|
repeat z from 0 to 3
|
|
chfx[z] := 0
|
|
|
|
repeat z from 0 to 5*5 'interface: playerinterface alle werte löschen
|
|
intreg[z] := 0
|
|
|
|
|
|
PUB hmus_play
|
|
|
|
hmus_state := 1
|
|
|
|
PUB hmus_stop | z
|
|
|
|
hmus_state := 0
|
|
repeat z from 0 to 3
|
|
chvol[z] := 0
|
|
|
|
PUB hmus_pause
|
|
|
|
hmus_state := 0
|
|
|
|
PUB hmus_tempo(var1)
|
|
|
|
tempo := var1
|
|
|
|
PUB get_hmus_tempo : var1
|
|
|
|
var1 := tempo
|
|
|
|
PUB hmus_vol(var1)
|
|
|
|
hmvol := var1 <# 15 #> 0
|
|
|
|
PUB get_hmus_vol : var1
|
|
|
|
var1 := hmvol
|
|
|
|
CON
|
|
|
|
'' FXsynth Commands
|
|
|
|
PUB sfx_play(chan, soundptr)
|
|
|
|
if(chan == 1)
|
|
sfx_ptr[0] := soundptr
|
|
loadsfx[0] := 0
|
|
if(chan == 2)
|
|
sfx_ptr[1] := soundptr
|
|
loadsfx[1] := 0
|
|
|
|
PUB sfx_stop(chan)
|
|
|
|
if(chan == 1)
|
|
sfx_ptr[0] := 0
|
|
if(chan == 2)
|
|
sfx_ptr[1] := 0
|
|
|
|
PUB sfx_keyoff(chan)
|
|
|
|
if(chan == 1)
|
|
envphs[0] := 3
|
|
if(chan == 2)
|
|
envphs[1] := 3
|
|
|
|
CON
|
|
|
|
'' Hydra DPCM Commands
|
|
|
|
PUB dpcm_play(soundptr)
|
|
|
|
dpcmreg_ptr := soundptr
|
|
|
|
PUB dpcm_stop
|
|
|
|
dpcmreg_ptr := 1
|
|
|
|
CON
|
|
''*****************************
|
|
''* Hss Sound Engine *
|
|
''*****************************
|
|
PRI Hsound
|
|
repeat
|
|
'Update Music Engine
|
|
UpdateMus(song_ptr, Hmus_state) 'Update Music Player
|
|
'volume/frequenzwerte werden in die soundregister geschrieben
|
|
VolumeInterpol 'Delay and Interpolate Volume to Remove Pops and Clicks.
|
|
|
|
'Update DPCM Engine
|
|
if(dpcmreg_ptr)
|
|
DpcmUpdate 'Update the DPCM registers
|
|
|
|
'Update SoundFX Engine
|
|
|
|
'FX channel A
|
|
FXSynth(0,32)
|
|
'FX channel B
|
|
FXSynth(1, 40)
|
|
|
|
PRI VolumeInterpol | z, channelmul, musvar, freqval
|
|
|
|
fxphs += 5
|
|
|
|
'Volume Interpolation
|
|
repeat z from 0 to 3 step 1
|
|
channelmul := 4+(8*z)
|
|
musvar := (chvol[z]*(hmvol+1))&$F0
|
|
snd_regs[channelmul] := (snd_regs[channelmul] & 15)+musvar
|
|
|
|
'Freq Interpolation
|
|
channelmul -= 1 'Jump down a REG to Freq
|
|
musvar := chfre[z]<<16
|
|
|
|
if(chfx[z] == 0) 'None
|
|
snd_regs[channelmul] := musvar
|
|
|
|
elseif(chfx[z] < 3) 'Vibrato (light/hard)
|
|
if(fxphs < 128)
|
|
snd_regs[channelmul] := musvar+(chfre[z]<<(7+chfx[z]))
|
|
else
|
|
snd_regs[channelmul] := musvar-(chfre[z]<<(7+chfx[z]))
|
|
|
|
elseif(chfx[z] == 3) 'Tremolo
|
|
if(fxphs < 128)
|
|
snd_regs[channelmul] := musvar
|
|
else
|
|
snd_regs[channelmul] := musvar<<1
|
|
|
|
else 'Portamento
|
|
freqval := snd_regs[channelmul]>>16
|
|
if(freqval & $F000 == chfre[z] & $F000)
|
|
snd_regs[channelmul] := musvar
|
|
elseif(freqval < chfre[z])
|
|
snd_regs[channelmul] := snd_regs[channelmul]+(chfx[z]<<22)
|
|
else
|
|
snd_regs[channelmul] := snd_regs[channelmul]-(chfx[z]<<22)
|
|
|
|
PRI UpdateMus(songptr, state) | i, channel, channelmul, scrdat, freq, freqoct, flag
|
|
|
|
if(state == 0)
|
|
return ''Song is not playing.
|
|
|
|
song_div++ 'zeitfaktor; wird erhöht bis...
|
|
|
|
if(song_div => tempo) 'Tempo Divider 'schwellwert erreicht, dann nächster beat
|
|
song_div := 0
|
|
flag := 0
|
|
intreg[iBeatC] := intreg[iBeatC] + 1 'interface: beatconter erhöhen
|
|
intreg[iRowFlag] := 0 'interface: Kennung das Zeile bearbeitet wird
|
|
repeat i from 5 to 5*5 'interface: channelwerte löschen
|
|
intreg[i] := 0
|
|
|
|
repeat 'Score Decoder and Processor
|
|
scrdat := BYTE[song_ptr][song_pc] 'song_pc ist zeiger auf wert in MusicDat
|
|
channel := scrdat & 3 'untere zwei bit enthalten die kanalnummer
|
|
channelmul := channel<<3 'jedem channel sind 8 registerwerte zugeordent
|
|
intreg[iEngineC] := song_pc 'interface: enginecounter setzen
|
|
song_pc++ 'zeiger auf nächsten wert setzen
|
|
|
|
''Base Commands
|
|
if(scrdat == 0) 'End Row 'nächste trackerzeile
|
|
intreg[iRowFlag] := 1 'interface: Zeile fertig bearbeitet
|
|
quit
|
|
|
|
if(scrdat == 1) 'Repeat Song 'wiederholt ab MusicLoop (MusicDat ist also die einleitung)
|
|
song_pc := WORD[songptr][9]
|
|
intreg[iRepeat] := intreg[iRepeat] + 1 'interface: flag das songende erreicht wurde
|
|
quit
|
|
|
|
if(scrdat == 2) 'End Song 'status wird auf 0 gesetzt
|
|
intreg[iEndFlag] := 1 'interface: flag das songende erreicht wurde
|
|
hmus_stop
|
|
quit
|
|
|
|
if(scrdat == 3) 'Set Flag
|
|
flag := 1
|
|
next
|
|
|
|
if((scrdat & $3C) == $20) 'Patch HI Note 'oktave erhöhen und veränderung zu "Change Note"
|
|
flag := 2
|
|
scrdat := scrdat>>3
|
|
scrdat += 64+channel
|
|
|
|
if(scrdat & 4) 'Change Note
|
|
freq := scrdat>>3 'note Bit3 bis Bit7 (32 Noten)
|
|
freqoct := freq/12
|
|
freq -= freqoct*12
|
|
case flag
|
|
1 : freqoct += 2
|
|
2 : freqoct += 6
|
|
other : freqoct += 4
|
|
flag := 0
|
|
snd_regs[4+channelmul] := snd_regs[4+channelmul] & $FE
|
|
intreg[(channel*iChannel)+iChannel+iNote] := freq + 1 'interface: note setzen (0 ist erste note!)
|
|
intreg[(channel*iChannel)+iChannel+iOktave] := freqoct 'interface: oktave setzen
|
|
'frequenz aus tabelle holen
|
|
'je nach oktave wird nach rechts verschoben (/2)
|
|
chfre[channel] := NoteFreqs[freq]>>(6-freqoct)
|
|
snd_regs[4+channelmul] := (snd_regs[4+channelmul] & $FE)+1
|
|
next 'Repeat To Next Datum
|
|
|
|
if(scrdat & 8) 'Change Evelope / Channel Effect
|
|
if(flag)
|
|
intreg[(channel*iChannel)+iChannel+iEffekt] := scrdat>>4 + 1 'interface: effektwert setzen
|
|
chfx[channel] := scrdat>>4
|
|
flag := 0
|
|
else
|
|
intreg[(channel*iChannel)+iChannel+iVolume] := scrdat>>4 'interface: volume setzen
|
|
chvol[channel] := scrdat>>4
|
|
next 'Repeat To Next Datum
|
|
|
|
if(scrdat & 16) 'Change Instrument
|
|
freq := (scrdat & $E0)>>3
|
|
freq += flag<<5
|
|
flag := 0
|
|
intreg[(channel*iChannel)+iChannel+iInstrument] := freq>>2 + 1 'interface: instrument setzen
|
|
snd_regs[0+channelmul] := songptr+WORD[songptr+32][freq] 'zeiger auf neues instrumentensample
|
|
snd_regs[1+channelmul] := WORD[songptr+32][freq+1] 'ende des samples
|
|
snd_regs[2+channelmul] := WORD[songptr+32][freq+2] 'loop
|
|
snd_regs[4+channelmul] := WORD[songptr+32][freq+3] & $0F 'flags?
|
|
next 'Repeat To Next Datum
|
|
|
|
if(scrdat & 64) 'Detune
|
|
chfre[channel] := chfre[channel]+(chfre[channel]>>8)
|
|
|
|
|
|
|
|
PRI DpcmUpdate
|
|
|
|
if(dpcmreg_ptr > 15) 'Play Sample.
|
|
dpcm_regs[2] := 65535 'End sample if one was playing
|
|
dpcm_regs[0] := dpcmreg_ptr+8
|
|
dpcm_regs[4] := 128
|
|
dpcm_regs[3] := LONG[dpcmreg_ptr][1] 'Get sampling rate
|
|
dpcm_regs[1] := WORD[dpcmreg_ptr][1] 'Get length
|
|
dpcm_regs[2] := 0 'Reset play counter
|
|
elseif(dpcmreg_ptr == 1) 'Stop Sample
|
|
dpcm_regs[2] := 65535 'End sample
|
|
dpcm_regs[4] := 128
|
|
|
|
dpcmreg_ptr := 0
|
|
|
|
PRI FXSynth(SoundVars, ChannelFX) | TimeCnt, SoundFX, Modwav, FMwav, AMwav
|
|
TimeCnt := Cnt
|
|
SoundFX := sfx_ptr[SoundVars]
|
|
|
|
if(loadsfx[SoundVars] == 0)
|
|
'Setup OSC WaveForm
|
|
case BYTE[SoundFX][0]
|
|
$00: 'Sine
|
|
snd_regs[ChannelFX] := @SineTable
|
|
snd_regs[1+ChannelFX] := 64
|
|
$01: 'Fast Sine
|
|
snd_regs[ChannelFX] := @FastSine
|
|
snd_regs[1+ChannelFX] := 32
|
|
$02: 'Sawtooth
|
|
snd_regs[ChannelFX] := @Sawtooth
|
|
snd_regs[1+ChannelFX] := 64
|
|
$03: 'Square
|
|
snd_regs[ChannelFX] := @SqrTable
|
|
snd_regs[1+ChannelFX] := 32
|
|
$04: 'Fast Square
|
|
snd_regs[ChannelFX] := @FastSqr
|
|
snd_regs[1+ChannelFX] := 8
|
|
$05: 'Buzz
|
|
snd_regs[ChannelFX] := @NoteFreqs
|
|
snd_regs[1+ChannelFX] := 24
|
|
$06: 'Noise
|
|
snd_regs[ChannelFX] := $F002
|
|
snd_regs[1+ChannelFX] := 3000
|
|
|
|
snd_regs[2+ChannelFX] := 0
|
|
snd_regs[4+ChannelFX] := $01
|
|
|
|
loadsfx[SoundVars] := 1
|
|
runlen[SoundVars] := 0
|
|
fmcnt[SoundVars] := 0
|
|
fmfreq[SoundVars] := 0
|
|
envamp[SoundVars] := 0
|
|
envphs[SoundVars] := 0
|
|
|
|
''Modulation Code
|
|
fmfreq[SoundVars]++
|
|
if(fmfreq[SoundVars] => BYTE[SoundFX][4])
|
|
fmfreq[SoundVars] := 0
|
|
fmcnt[SoundVars]++
|
|
fmcnt[SoundVars] := fmcnt[SoundVars] & $3F
|
|
|
|
case BYTE[SoundFX][5]
|
|
$00:
|
|
Modwav := BYTE[@SineTable][fmcnt[SoundVars]]
|
|
$01:
|
|
Modwav := BYTE[@FastSine][fmcnt[SoundVars] & 31]
|
|
$02:
|
|
Modwav := fmcnt[SoundVars]<<2
|
|
$03:
|
|
Modwav := !fmcnt[SoundVars]<<2
|
|
$04:
|
|
if(fmcnt[SoundVars] & 8)
|
|
Modwav := $ff
|
|
else
|
|
Modwav := $00
|
|
$05:
|
|
Modwav := BYTE[$F002][fmcnt[SoundVars]]
|
|
$FF:
|
|
Modwav := BYTE[SoundFX+12][fmcnt[SoundVars] & 15]
|
|
|
|
fmwav := Modwav/(BYTE[SoundFX][6]) 'FM amount
|
|
amwav := 256-(Modwav/(BYTE[SoundFX][7])) 'AM amount
|
|
amwav := (BYTE[SoundFX][3]*amwav)>>8
|
|
|
|
''Envelope Generator
|
|
if(envphs[SoundVars] == 0) 'Attack
|
|
envamp[SoundVars] += BYTE[SoundFX][8]
|
|
if(envamp[SoundVars] > 8191)
|
|
envamp[SoundVars] := 8191
|
|
envphs[SoundVars] := 1
|
|
if(BYTE[SoundFX][8] == $ff)
|
|
envamp[SoundVars] := 8191
|
|
if(envphs[SoundVars] == 1) 'Decay
|
|
envamp[SoundVars] -= BYTE[SoundFX][9]
|
|
if(envamp[SoundVars] & $8000)
|
|
envphs[SoundVars] := 2
|
|
if(envamp[SoundVars] =< (BYTE[SoundFX][10]<<5))
|
|
envphs[SoundVars] := 2
|
|
if(envphs[SoundVars] == 2) 'Sustain
|
|
envamp[SoundVars] := (BYTE[SoundFX][10]<<5)
|
|
if(envphs[SoundVars] == 3) 'Release
|
|
envamp[SoundVars] -= BYTE[SoundFX][11]
|
|
if(envamp[SoundVars] & $8000)
|
|
envamp[SoundVars] := 4
|
|
|
|
amwav := ((envamp[SoundVars]>>9)*(amwav+1))>>4
|
|
|
|
''Run Length and Outputing
|
|
if(SoundFX > 15)
|
|
runlen[SoundVars]++
|
|
snd_regs[3+ChannelFX] := (BYTE[SoundFX][2]+fmwav)<<24 'Update Frequency
|
|
snd_regs[4+ChannelFX] := (amwav<<4)+(snd_regs[4+ChannelFX] & $0F) 'Update Amplitude
|
|
else
|
|
snd_regs[4+ChannelFX] := $00 'Mute
|
|
|
|
if(BYTE[SoundFX][1] == $ff) '$ff = never stop
|
|
runlen[SoundVars] := 0
|
|
|
|
if(runlen[SoundVars] > (BYTE[SoundFX][1]<<5)) 'Duration KeyOff
|
|
envphs[SoundVars] := 3
|
|
|
|
WaitCnt(TimeCnt + 52_000) ''Delay for Synth Engine Update.
|
|
|
|
DAT
|
|
|
|
SineTable byte $80, $8c, $98, $a5, $b0, $bc, $c6, $d0
|
|
byte $da, $e2, $ea, $f0, $f5, $fa, $fd, $fe
|
|
byte $ff, $fe, $fd, $fa, $f5, $f0, $ea, $e2
|
|
byte $da, $d0, $c6, $bc, $b0, $a5, $98, $8c
|
|
byte $80, $73, $67, $5a, $4f, $43, $39, $2f
|
|
byte $25, $1d, $15, $0f, $0a, $05, $02, $01
|
|
byte $00, $01, $02, $05, $0a, $0f, $15, $1d
|
|
byte $25, $2f, $39, $43, $4f, $5a, $67, $73
|
|
|
|
Sawtooth byte $ff, $fb, $f7, $f3, $ef, $eb, $e7, $e3
|
|
byte $df, $db, $d7, $d3, $cf, $cb, $c7, $c3
|
|
byte $bf, $bb, $b7, $b3, $af, $ab, $a7, $a3
|
|
byte $9f, $9b, $97, $93, $8f, $8b, $87, $83
|
|
byte $80, $7c, $78, $74, $70, $6c, $68, $64
|
|
byte $60, $5c, $58, $54, $50, $4c, $48, $44
|
|
byte $40, $3c, $38, $34, $30, $2c, $28, $24
|
|
byte $20, $1c, $18, $14, $10, $0c, $08, $04
|
|
|
|
FastSine byte $80, $98, $b0, $c6, $da, $ea, $f5, $fd
|
|
byte $ff, $fd, $f5, $ea, $da, $c6, $b0, $98
|
|
byte $80, $67, $4f, $39, $25, $15, $0a, $02
|
|
byte $00, $02, $0a, $15, $25, $39, $4f, $67
|
|
|
|
SqrTable byte $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff
|
|
byte $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff
|
|
byte $00, $00, $00, $00, $00, $00, $00, $00
|
|
byte $00, $00, $00, $00, $00, $00, $00, $00
|
|
|
|
FastSqr byte $ff, $ff, $ff, $ff, $00, $00, $00, $00
|
|
|
|
'Note LookupTable.
|
|
NoteFreqs word $85F3, $8DEA, $965B, $9F4B, $A8C4, $B2CD, $BD6F, $C8B3, $D4A2, $E147, $EEAC, $FCDE 'Top Octave Lookup
|
|
|
|
CON
|
|
''*****************************
|
|
''* WaveTable Synth v1.2 *
|
|
''* DPCM Synth v1.1 *
|
|
''* (C)2006 Andrew Arsenault *
|
|
''*****************************
|
|
DAT
|
|
org
|
|
entry mov dira,Port_Pins 'Setup output pins
|
|
|
|
mov ctra,Right_ctra 'Setup Right Audio Channel
|
|
mov ctrb,Left_ctra 'Setup Left Audio Channel
|
|
|
|
mov ChlA_wave,#256 'Set channel signals.
|
|
mov ChlA_offset,#0 'Set channel's offset.
|
|
mov ChlA_counter,#0
|
|
|
|
mov Time,#10
|
|
add Time,cnt 'Prepare for asm type WAITCNT loop.
|
|
|
|
'MAIN LOOP
|
|
update waitcnt Time,Timing_delay 'Wait for CNT = D, then add S into D
|
|
|
|
'Transfer Sound Registers
|
|
mov addrregs,par
|
|
mov y,NumberOfChannels
|
|
|
|
'Fetch Channel's Registers
|
|
transferchl rdlong ChlAp_sampptr,addrregs
|
|
add addrregs,#4
|
|
rdlong ChlAp_sampend,addrregs
|
|
add addrregs,#4
|
|
rdlong Ch1Ap_samplpp,addrregs
|
|
add addrregs,#4
|
|
rdlong Ch1Ap_freq,addrregs
|
|
add addrregs,#4
|
|
rdlong ChlAp_keyon,addrregs
|
|
|
|
'Fetch Channel's Static Variables
|
|
add addrregs,#8
|
|
rdlong ChlA_offset,addrregs
|
|
add addrregs,#4
|
|
rdlong ChlA_counter,addrregs
|
|
|
|
'Run Synth Engine on Channel
|
|
call #wvsynth
|
|
|
|
'Store Channel's Static Variables (Tucked Center X move to Wave)
|
|
wrlong ChlA_counter,addrregs
|
|
sub addrregs,#4
|
|
sub x,#256
|
|
wrlong ChlA_offset,addrregs
|
|
sub addrregs,#4
|
|
mov ChlA_wave,x 'Doesn't Waste anything doing this.
|
|
wrlong ChlA_wave,addrregs
|
|
add addrregs,#12
|
|
|
|
'Loop Until All Channel's Are Done.
|
|
djnz y,#transferchl
|
|
|
|
'Run DPCM Engine
|
|
call #dpcm
|
|
|
|
'Mix Channels Together
|
|
mov addrregs,par
|
|
mov ChlA_wave,#0
|
|
add addrregs,#5*4
|
|
mov y,NumberOfChannels
|
|
|
|
mixchls rdlong x,addrregs
|
|
add ChlA_wave,x
|
|
add addrregs,#8*4
|
|
djnz y,#mixchls
|
|
|
|
mov x,DPCM_wave 'Add DPCM
|
|
shl x,#2
|
|
add ChlA_wave,x
|
|
|
|
shl ChlA_wave,#20 'Convert 12bit singal into a 32bit one.
|
|
|
|
'Update output Channels then repeat again.
|
|
mov frqa,ChlA_wave
|
|
mov frqb,ChlA_wave
|
|
|
|
jmp #update
|
|
|
|
|
|
|
|
|
|
'-------------------------Dpcm Engine-------------------------'
|
|
|
|
dpcm mov addrregs,par
|
|
add addrregs,#192
|
|
|
|
rdlong DPCM_address,addrregs 'Start Address
|
|
add addrregs,#4
|
|
rdlong DPCM_runlen,addrregs 'File Lenght
|
|
add addrregs,#4
|
|
rdlong DPCM_offset,addrregs 'File Offset
|
|
add addrregs,#4
|
|
rdlong DPCM_freq,addrregs 'Playback Speed
|
|
add addrregs,#4
|
|
rdlong DPCM_wave,addrregs 'Waveform Amp
|
|
|
|
'Check for if keyon/length is set.
|
|
cmp DPCM_offset,DPCM_runlen wc
|
|
if_ae jmp #mute_dpcm 'End of file
|
|
|
|
'Freq Timer/Divider and Increase sampling offset
|
|
add DPCM_counter,DPCM_freq wc
|
|
if_nc jmp #done_dpcm
|
|
|
|
'Decode DPCM
|
|
add DPCM_address,DPCM_offset
|
|
rdbyte x,DPCM_address 'Fetch Datum
|
|
|
|
mov DPCM_delta,x
|
|
shr DPCM_delta,#6
|
|
mov y,#1
|
|
shl y,DPCM_delta
|
|
mov DPCM_delta,y
|
|
|
|
mov y,#1
|
|
shl y,DPCM_phs
|
|
test x,y wc
|
|
if_c add DPCM_wave,DPCM_delta
|
|
if_nc sub DPCM_wave,DPCM_delta
|
|
|
|
add DPCM_phs,#1
|
|
cmp DPCM_phs,#6 wc
|
|
if_b jmp #done_dpcm
|
|
|
|
mov DPCM_phs,#0
|
|
add DPCM_offset,#1
|
|
jmp #done_dpcm
|
|
|
|
mute_dpcm mov DPCM_wave, #128
|
|
|
|
done_dpcm mov addrregs,par
|
|
add addrregs,#200
|
|
wrlong DPCM_offset,addrregs 'File Offset
|
|
add addrregs,#8
|
|
wrlong DPCM_wave,addrregs 'Wave
|
|
dpcm_ret ret
|
|
|
|
'-----------------------Dpcm Engine End-----------------------'
|
|
|
|
|
|
|
|
'-------------------------Sound Engine-------------------------'
|
|
|
|
'Freq Timer/Divider and Increase sampling offset
|
|
wvsynth add ChlA_counter,Ch1Ap_freq wc
|
|
if_c add ChlA_offset,#1
|
|
|
|
'Reset sample position and lock at zero if Keyoff.
|
|
test ChlAp_keyon,#%0001 wc
|
|
if_nc mov ChlA_offset,#0
|
|
|
|
'Reset(loop) if needed
|
|
cmp ChlA_offset,ChlAp_sampend wc
|
|
if_ae mov ChlA_offset,Ch1Ap_samplpp
|
|
|
|
'Check BitRate and Set Offset
|
|
mov x,ChlA_offset
|
|
test ChlAp_keyon,#%0010 wc
|
|
if_c shr x,#1
|
|
|
|
'Fetch WaveTable
|
|
mov ChlA_wave,ChlAp_sampptr
|
|
add ChlA_wave,x
|
|
rdbyte ChlA_wave,ChlA_wave
|
|
|
|
'Check BitRate and Skip if 8bit
|
|
test ChlAp_keyon,#%0010 wc
|
|
if_nc jmp #skip_4bitsam
|
|
|
|
'Convert 4bit to 8bit
|
|
test ChlA_offset,#%0001 wc
|
|
if_c shr ChlA_wave,#4
|
|
if_nc and ChlA_wave,#%00001111
|
|
|
|
mov x,ChlA_wave
|
|
shl ChlA_wave,#4
|
|
add ChlA_wave,x
|
|
|
|
'Center Amplitude and mute if Keyoff.
|
|
skip_4bitsam test ChlAp_keyon,#%0001 wc
|
|
if_nc mov ChlA_wave,#128
|
|
|
|
'Volume Multiply
|
|
mov x,#0
|
|
test ChlAp_keyon,#%10000000 wc
|
|
if_c add x,ChlA_wave
|
|
if_nc add x,#128
|
|
|
|
shr ChlA_wave,#1
|
|
test ChlAp_keyon,#%01000000 wc
|
|
if_c add x,ChlA_wave
|
|
if_nc add x,#64
|
|
add x,#64
|
|
|
|
shr ChlA_wave,#1
|
|
test ChlAp_keyon,#%00100000 wc
|
|
if_c add x,ChlA_wave
|
|
if_nc add x,#32
|
|
add x,#96
|
|
|
|
shr ChlA_wave,#1
|
|
test ChlAp_keyon,#%00010000 wc
|
|
if_c add x,ChlA_wave
|
|
if_nc add x,#16
|
|
add x,#112
|
|
|
|
'Return Audio as X.
|
|
wvsynth_ret ret
|
|
|
|
'-----------------------Sound Engine End-----------------------'
|
|
|
|
Port_Pins long %00000000_00000000_00000011_00000000
|
|
|
|
'- CTR PLL -------- BPIN --- APIN
|
|
Right_ctra long %0_00110_000_00000000_000000_000_001000
|
|
Left_ctra long %0_00110_000_00000000_000000_000_001001
|
|
|
|
Timing_delay long 2500 'Sampling Rate = 32,000.00hz
|
|
NumberOfChannels long 6
|
|
|
|
Time res 1
|
|
addrregs res 1
|
|
x res 1
|
|
y res 1
|
|
|
|
'WaveTable Synth Accumulators
|
|
ChlA_wave res 1
|
|
ChlA_offset res 1
|
|
ChlA_counter res 1
|
|
ChlAp_sampptr res 1
|
|
ChlAp_sampend res 1
|
|
Ch1Ap_samplpp res 1
|
|
Ch1Ap_freq res 1
|
|
ChlAp_keyon res 1
|
|
|
|
'DPCM Accumulators
|
|
DPCM_wave res 1
|
|
DPCM_address res 1
|
|
DPCM_offset res 1
|
|
DPCM_counter res 1
|
|
DPCM_freq res 1
|
|
DPCM_runlen res 1
|
|
DPCM_phs res 1
|
|
DPCM_delta res 1 |