gigatron/rom/Contrib/at67/gbas/audio/SoundFx.gbas
2025-01-28 19:17:01 +03:00

479 lines
9.7 KiB
Plaintext

_runtimePath_ "../runtime"
_runtimeStart_ &h7FFF
_arraysStart_ &h7FFF
const X_POS = 34
const Y_POS = 46
const VU_LEVELS = 64
'frequency sweep
const F_LUT=&h0500
def word(F_LUT, y, 0.0, 360.0, 256) = sin(y)*2000.0 + 5000.0
'volume sweep
const V_LUT=&h08A0
const V_SIZ=64
def byte(V_LUT, y, 0.0, 360.0, V_SIZ) = 63.0 - (cos(y)*0.5 + 0.5)*55.0
'extinction function, (modelled in Desmos), used to control attack and decay for crash sound
'don't use variable names that clash with functions, i.e. 'x' and 'exp'
const D_LUT=&h09A0
const D_SIZ=64
def byte(D_LUT, y, 0.0, 0.5, D_SIZ) = 63.0 - exp(-y)*(1.0-exp(-2.0*y))*2.5*58.0
const T_LUT=&h09E0
const T_SIZ=8
def byte(T_LUT, y, 0.0, 3.0, T_SIZ) = 63.0 - 1.398*exp(-y)*(1.0-exp(-10.0*y))*63.0
_spriteStripeChunks_ 32, &h0400, ascending
load sprite, ../../res/image/VUerase.tga, 0
load sprite, ../../res/image/VUdraw.tga, 1, FlipY
t = 0 : f = t : v = 0
'audio fix for ROMv5a
poke &h21, peek(&h21) OR 3
sound off
set FGBG_COLOUR, &h3C00
cls
mode 2
at 33,2 : print "Keys: <1> to <0>"
at 33 : print " <q> to <r>"
dim volume%(4) = 127
dim ypos%(4) = 1
kk = 255
state = 0
init midiv
loop:
'wait
set SOUND_TIMER, 2
gosub vuMeter
k = get("SERIAL_RAW")
if kk &&= 255 then gosub k
gosub state
kk = k
goto &loop
midiOff:
set MIDI_STREAM, &h0000
sound off
return
1: gosub siren
return
2: gosub crash
return
3: gosub beep
return
4: gosub tictoc
return
5: gosub pucDeath
return
6: gosub ghostMove
return
7: gosub invaderMove
return
8: gosub invaderShoot
return
9: gosub saucerMove
return
10: gosub invaderExplode
return
11: gosub testSfx
return
12: gosub saucerExplode
return
13: gosub playerExplode
return
14: if get("MIDI_STREAM") &= &h0000
play midiv, &h0AA0, 2
else
tick midiv
endif
return
48: state = 14
return
49: t = 0
state = 1
gosub midiOff
return
50: t = 0
state = 2
gosub midiOff
return
51: t = 0
state = 3
gosub midiOff
return
52: t = 0
state = 4
gosub midiOff
return
53: t = 0
state = 5
gosub midiOff
return
54: t = 0
state = 6
gosub midiOff
return
55: t = 0
f = 0
vv = 63
state = 7
gosub midiOff
return
56: t = 0
state = 8
gosub midiOff
return
57: t = 0
f = 0
vv = 63
state = 9
gosub midiOff
return
113:t = 0
f = 0
vv = 63
state = 10
gosub midiOff
return
119:t = 0
f = 0
vv = 63
state = 11
gosub midiOff
return
101:t = 0
f = 0
vv = 60
state = 12
gosub midiOff
return
114:t = 0
f = 0
vv = 63
state = 13
gosub midiOff
return
vuMeter:
for i=1 to 4
i8 = i LSL 8
v = peek(i8 + &h00FA)
vol = volume(i)
y = ypos(i)
if v &>= VU_LEVELS
i4 = (i LSL 4) + X_POS
if deek(i8 + &h00FC) &= 0 then goto decay 'if frequency is 0, (i.e. note off), then decay
if v &< vol
y = ((VU_LEVELS-1) - (v - VU_LEVELS)) LSR 1 'transform 127->64 to 0->63
vol = v
else
decay:
dec y
inc vol
if y &< 1
inc y
dec vol
endif
endif
'erase led
sprite noFlip, 0, i4, (Y_POS + 32) - (y + 1)
'adjust height of led bar
lut = (y LSL 2) + y + y + get("SPRITE_LUT", 1)
save = peek(lut)
poke lut, -1
sprite flipY, 1, i4, Y_POS
sprite flipY, 1, i4 + 6, Y_POS
poke lut, save
endif
volume(i) = vol
ypos(i) = y
next i
return
siren:
v_lut = peek(V_LUT + (t AND (V_SIZ - 1)))
f_lut = deek(F_LUT + (t LSL 1))
sound on, 1, f_lut , v_lut, 2
sound on, 2, f_lut+100, v_lut, 2
sound on, 3, f_lut+200, v_lut, 2
sound on, 4, f_lut+300, v_lut, 2
inc t
if t &= 64
t = 0
state = 0
sound off
endif
return
crash:
d_lut = peek(D_LUT + (t AND (D_SIZ - 1)))
f_lut = deek(F_LUT + ((t AND 1) LSL 1))
sound on, 1, f_lut , d_lut, 0
sound on, 2, f_lut+100, d_lut, 0
sound on, 3, f_lut+200, d_lut, 0
sound on, 4, f_lut+300, d_lut, 0
inc t
if t &= 64
t = 0
state = 0
sound off
endif
return
beep:
sound on, 1, 8000, 63, 1
inc t
if t &= 3
t = 0
state = 0
sound off
endif
return
tictoc:
t_lut = peek(T_LUT + (t AND (T_SIZ - 1)))
sound on, 1, t_lut LSL 4, t_lut, 0
inc t
if t &= T_SIZ-2
t = 0
state = 0
sound off
endif
return
dim pnotes%(15) = 74, 72, 71, 69, 67, 65, 64, 62, 60, 62, 64, 65, 67, 69, 71, 72
def byte(&h0701, x, 0.0, 1.0, 64, 4) = sin(pow(x + 1.8, 3.13)*57.2957795)*31.0 + 32.0
'def byte(&h0701, y, 0.0, 1.0, 64, 4) = (sin(pow(y + 1.8, 3.13)*57.2957795)*exp(-1.5*y)*1.2)*31.0 + 32.0
'def byte(&h0701, y, 0.0, 1.0, 64, 4) = sin(pow(y + 1.8, 3.13)*57.2957795)*(1-y)*31.0 + 32.0
pucDeath:
n = get("MIDI_NOTE", peek(@pnotes + (t AND 15)))
sound on, 1, n - f, 63 - (t LSR 2), 1
inc t
if (t AND 7) &= 0
f = f + 200
endif
if t &= 128
t = 0
f = 0
state = 0
sound off
endif
return
dim gnotes%(15) = 60, 62, 64, 65, 67, 69, 71, 72, 74, 72, 71, 69, 67, 65, 64, 62
ghostMove:
n = get("MIDI_NOTE", peek(@gnotes + (t AND 15)) + 10)
sound on, 1, n, 63, 2
inc t
if t &= 128
t = 0
state = 0
sound off
endif
return
'overwrite waveform 0 in audio memory, (invader move)
'load wave, ../../res/audio/Invader/IMove.gtwav, &h0702, 4
dim inotes%(3) = 40, 38, 36, 34
vv = 0
invaderMove:
n = get("MIDI_NOTE", peek(@inotes + (f AND 3)))
sound on, 1, n, vv, 3
inc t
if t &= 25
t = 0
vv = 63
inc f
if f &= 4
f = 0
state = 0
sound off
endif
elseif t &= 4
vv = 0
endif
return
const I_LUT=&h6EA0
const IF_LUT=&h6DA0
const I_SIZ=32
'def word(I_LUT, y, 0.0, 1.0, I_SIZ) = (10.0*exp(-15.0*y)*(1.0-exp(-9.75*(y-0.015)))*0.343 + 0.25)*25000.0
def byte(I_LUT, y, 0.0, 1.0, I_SIZ) = exp(-5.0*pow(y, 3.0))*32.0
'def byte(I_LUT, y, 0.0, 10.0, I_SIZ) = exp(-0.2*y)*(sin(15.0*y/6.28*360.0)*0.25 + 0.75)*32.0
def word(IF_LUT, y, 0.0, 1.0, I_SIZ) = exp(-3.0*y)*6000.0 + 14000.0
invaderShootOld:
ff = max(25000 - f, 13000)
sound on, 1, ff, vv, 2
'sound on, 1, deek(I_LUT + (t AND 31)), vv, 2
inc t
vv = vv - 2
if vv &<= 0
t = 0
vv = 63
state = 0
sound off
endif
return
invaderShoot:
ff = deek(IF_LUT + ((t AND 31) LSL 1))
vvv = peek(I_LUT + (t AND 31))
sound on, 1, ff, vvv, 3
sound on, 2, ff, vvv, 0
inc t
if t &= 32
t = 0
state = 0
sound off
endif
return
const SF_LUT=&h6CA0
const SF_SIZ=12
'def word(SF_LUT, y, 0.0, 360.0, SF_SIZ) = (sin(y)*0.5 + 0.5) * 5000.0
'def word(SF_LUT, y, 0.5, 1.5, SF_SIZ) = sin(exp(-pow(4.0*y - 4.0, 2.0))/6.28*360) * 5000.0
'def word(SF_LUT, y, 0.0, 180.0, SF_SIZ) = sin(y) * sin(y) * 2121.0 + 2121.0
def word(SF_LUT, y, 0.0, SF_SIZ, SF_SIZ) = (y % (SF_SIZ/2)) * 300.0 + 3000.0
'def word(SF_LUT, y, 0.0, 360, SF_SIZ) = (asin(cos(y))/90.0*0.5 + 0.5) * 300.0 + 3000.0
'def byte(&h0702, x, 0.0, 360.0, 64, 4) = sin(x)*31.0 + 32.0
saucerMove:
ff = deek(SF_LUT + (t LSL 1))
sound on, 1, ff, 32, 2
inc t
if t &= SF_SIZ
t = 0
endif
return
const IE_LUT=&h6BA0
const IE_SIZ=3
'def word(IE_LUT, y, 0.0, 1.0, IE_SIZ) = exp(-3.0*y)*5000.0
'def word(IE_LUT, y, 0.0, 720.0, IE_SIZ) = sin(y) * sin(y) * 1000.0 + 500
'def word(IE_LUT, y, 0.0, 360, IE_SIZ) = (asin(cos(y))/90.0*0.5 + 0.5) * 3000.0 + 3000.0
def word(IE_LUT, y, 0.0, IE_SIZ, IE_SIZ) = 6000.0*(1 - exp(-0.5*y))
'def byte(&h0702, x, 0.0, 720.0, 64, 4) = sin(x)*31.0 + 32.0
invaderExplode:
sound on, 1, deek(IE_LUT + (t LSL 1)), vv, 2
inc t
if t &= IE_SIZ then t = 0
vv = vv - 2
if vv &<= 0
t = 0
vv = 60
state = 0
sound off
endif
return
testSfx:
ff = 16384 - (vv LSL 8) + f
sound on, 1, ff, vv, 2
inc t
vv = vv - 8
if vv &<= 0
t = 0
vv = 63
f = f + 1000
if f &= 4000
f = 0
state = 0
sound off
endif
endif
return
const SEF_LUT=&h69A0
const SEF_SIZ=12
'def word(SEF_LUT, y, 0.0, 180.0, SEF_SIZ) = sin(y) * sin(y) * 2121.0 + 2121.0
def word(SEF_LUT, y, 0.0, SEF_SIZ, SEF_SIZ) = (y % (SEF_SIZ/2)) * 300.0 + 3000.0
saucerExplode:
m = min(vv + 10, 63)
ff = deek(SEF_LUT + (t LSL 1)) - f
sound on, 1, ff, vv, 2
sound on, 2, ff LSR 4, vv, 0
inc t
if t &= SEF_SIZ
t = 0
f = f + 600
vv = vv - 15
if vv &<= 0
f = 0
vv = 60
state = 0
sound off
endif
endif
return
const PEF_LUT=&h6AA0
const PEF_SIZ=32
'def word(PEF_LUT, y, 0.0, 180.0, PEF_SIZ) = sin(y) * sin(y) * 2121.0 + 2121.0
'def word(PEF_LUT, y, 0.0, PEF_SIZ, PEF_SIZ) = (y % (PEF_SIZ/2)) * 300.0 + 3000.0
'def word(PEF_LUT, y, 0.0, 360, PEF_SIZ) = (asin(cos(y))/90.0*0.5 + 0.5) * 300.0 + 300.0
'def word(PEF_LUT, y, 0.0, PEF_SIZ, PEF_SIZ) = 900.0*(exp(-1.125*y)) + 300.0
def word(PEF_LUT, 0.0, PEF_SIZ, PEF_SIZ) = rand(PEF_SIZ) / PEF_SIZ * 300.0
playerExplode:
f = deek(PEF_LUT + (t LSL 1))
sound on, 1, f, vv, 0
sound on, 2, f, vv, 0
sound on, 3, f, vv, 0
sound on, 4, f, vv, 0
inc t
if t &= PEF_SIZ then t = 0
vv = vv - 1
if vv &<= 0
t = 0
vv = 60
state = 0
sound off
endif
return
module "MidiFx.i"