mirror of
https://github.com/irmen/prog8.git
synced 2024-12-24 16:29:21 +00:00
add max volume to psg envelope
This commit is contained in:
parent
3ec05709d5
commit
ea2812f50f
@ -19,6 +19,7 @@ psg {
|
|||||||
cx16.vpoke(1, $f9c2 + voice_num * 4, channel | volume)
|
cx16.vpoke(1, $f9c2 + voice_num * 4, channel | volume)
|
||||||
cx16.vpoke(1, $f9c3 + voice_num * 4, waveform | pulsewidth)
|
cx16.vpoke(1, $f9c3 + voice_num * 4, waveform | pulsewidth)
|
||||||
envelope_volumes[voice_num] = mkword(volume, 0)
|
envelope_volumes[voice_num] = mkword(volume, 0)
|
||||||
|
envelope_maxvolumes[voice_num] = volume
|
||||||
}
|
}
|
||||||
|
|
||||||
; sub freq_hz(ubyte voice_num, float hertz) {
|
; sub freq_hz(ubyte voice_num, float hertz) {
|
||||||
@ -37,6 +38,7 @@ psg {
|
|||||||
uword reg = $f9c2 + voice_num * 4
|
uword reg = $f9c2 + voice_num * 4
|
||||||
cx16.vpoke(1, reg, cx16.vpeek(1, reg) & %11000000 | vol)
|
cx16.vpoke(1, reg, cx16.vpeek(1, reg) & %11000000 | vol)
|
||||||
envelope_volumes[voice_num] = mkword(vol, 0)
|
envelope_volumes[voice_num] = mkword(vol, 0)
|
||||||
|
envelope_maxvolumes[voice_num] = vol
|
||||||
}
|
}
|
||||||
|
|
||||||
sub pulse_width(ubyte voice_num, ubyte pw) {
|
sub pulse_width(ubyte voice_num, ubyte pw) {
|
||||||
@ -44,61 +46,68 @@ psg {
|
|||||||
cx16.vpoke(1, reg, cx16.vpeek(1, reg) & %11000000 | pw)
|
cx16.vpoke(1, reg, cx16.vpeek(1, reg) & %11000000 | pw)
|
||||||
}
|
}
|
||||||
|
|
||||||
sub envelope(ubyte voice_num, ubyte attack, ubyte sustain, ubyte release) {
|
sub envelope(ubyte voice_num, ubyte maxvolume, ubyte attack, ubyte sustain, ubyte release) {
|
||||||
envelope_states[voice_num] = 255
|
envelope_states[voice_num] = 255
|
||||||
envelope_attacks[voice_num] = attack * $0040
|
envelope_attacks[voice_num] = attack
|
||||||
envelope_sustains[voice_num] = sustain
|
envelope_sustains[voice_num] = sustain
|
||||||
envelope_releases[voice_num] = release * $0040
|
envelope_releases[voice_num] = release
|
||||||
if attack
|
if attack
|
||||||
attack = 0
|
attack = 0
|
||||||
else
|
else
|
||||||
attack = 63 ; max volume when no attack is set
|
attack = maxvolume ; max volume when no attack is set
|
||||||
envelope_volumes[voice_num] = mkword(attack, 0)
|
envelope_volumes[voice_num] = mkword(attack, 0)
|
||||||
|
envelope_maxvolumes[voice_num] = maxvolume
|
||||||
envelope_states[voice_num] = 0
|
envelope_states[voice_num] = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
sub silent() {
|
sub silent() {
|
||||||
for cx16.r15L in 0 to 15 {
|
for cx16.r1L in 0 to 15 {
|
||||||
envelope_states[cx16.r15L] = 255
|
envelope_states[cx16.r1L] = 255
|
||||||
envelope_volumes[cx16.r15L] = 0
|
envelope_volumes[cx16.r1L] = 0
|
||||||
volume(cx16.r15L, 0)
|
volume(cx16.r1L, 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sub envelopes_irq() {
|
sub envelopes_irq() {
|
||||||
|
; If you want to use real-time volume envelopes (Attack-Sustain-Release),
|
||||||
|
; you have to call this routine every 1/60th second, for example from your vsync irq handler,
|
||||||
|
; or just install this routine as the only irq handler if you don't have to do other things there.
|
||||||
|
; Example: cx16.set_irq(&psg.envelopes_irq, true)
|
||||||
|
|
||||||
; cx16.r0 = the volume word (volume scaled by 256)
|
; cx16.r0 = the volume word (volume scaled by 256)
|
||||||
; cx16.r15L = the voice number
|
; cx16.r1L = the voice number
|
||||||
; the other virtual registers are used to backup vera registers.
|
; cx16.r2L = attack value
|
||||||
|
|
||||||
; calculate new volumes
|
; calculate new volumes
|
||||||
for cx16.r15L in 0 to 15 {
|
for cx16.r1L in 0 to 15 {
|
||||||
when envelope_states[cx16.r15L] {
|
when envelope_states[cx16.r1L] {
|
||||||
0 -> {
|
0 -> {
|
||||||
; attack
|
; attack
|
||||||
cx16.r0 = envelope_volumes[cx16.r15L] + envelope_attacks[cx16.r15L]
|
cx16.r2L = envelope_maxvolumes[cx16.r1L]
|
||||||
if msb(cx16.r0) & %11000000 or envelope_attacks[cx16.r15L]==0 {
|
cx16.r0 = envelope_volumes[cx16.r1L] + envelope_attacks[cx16.r1L] * $0040
|
||||||
cx16.r0 = mkword(63, 0)
|
if msb(cx16.r0) > cx16.r2L or envelope_attacks[cx16.r1L]==0 {
|
||||||
envelope_attacks[cx16.r15L] = 0
|
cx16.r0 = mkword(cx16.r2L, 0)
|
||||||
envelope_states[cx16.r15L] = 1 ; start sustain
|
envelope_attacks[cx16.r1L] = 0
|
||||||
|
envelope_states[cx16.r1L] = 1 ; start sustain
|
||||||
}
|
}
|
||||||
envelope_volumes[cx16.r15L] = cx16.r0
|
envelope_volumes[cx16.r1L] = cx16.r0
|
||||||
}
|
}
|
||||||
1 -> {
|
1 -> {
|
||||||
; sustain
|
; sustain
|
||||||
if envelope_sustains[cx16.r15L] {
|
if envelope_sustains[cx16.r1L] {
|
||||||
envelope_sustains[cx16.r15L]--
|
envelope_sustains[cx16.r1L]--
|
||||||
} else {
|
} else {
|
||||||
envelope_states[cx16.r15L] = 2 ; start release
|
envelope_states[cx16.r1L] = 2 ; start release
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
2 -> {
|
2 -> {
|
||||||
; release
|
; release
|
||||||
cx16.r0 = envelope_volumes[cx16.r15L] - envelope_releases[cx16.r15L]
|
cx16.r0 = envelope_volumes[cx16.r1L] - envelope_releases[cx16.r1L] * $0040
|
||||||
if msb(cx16.r0) & %11000000 {
|
if msb(cx16.r0) & %11000000 {
|
||||||
cx16.r0 = 0
|
cx16.r0 = 0
|
||||||
envelope_releases[cx16.r15L] = 0
|
envelope_releases[cx16.r1L] = 0
|
||||||
}
|
}
|
||||||
envelope_volumes[cx16.r15L] = cx16.r0
|
envelope_volumes[cx16.r1L] = cx16.r0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -113,15 +122,16 @@ psg {
|
|||||||
cx16.VERA_ADDR_L = $c2
|
cx16.VERA_ADDR_L = $c2
|
||||||
cx16.VERA_ADDR_M = $f9
|
cx16.VERA_ADDR_M = $f9
|
||||||
cx16.VERA_ADDR_H = 1 | %00110000
|
cx16.VERA_ADDR_H = 1 | %00110000
|
||||||
for cx16.r15L in 0 to 15 {
|
for cx16.r1L in 0 to 15 {
|
||||||
cx16.VERA_DATA0 = cx16.VERA_DATA1 & %11000000 | msb(envelope_volumes[cx16.r15L])
|
cx16.VERA_DATA0 = cx16.VERA_DATA1 & %11000000 | msb(envelope_volumes[cx16.r1L])
|
||||||
}
|
}
|
||||||
cx16.pop_vera_context()
|
cx16.pop_vera_context()
|
||||||
}
|
}
|
||||||
|
|
||||||
ubyte[16] envelope_states
|
ubyte[16] envelope_states
|
||||||
uword[16] envelope_volumes
|
uword[16] envelope_volumes ; scaled by 256
|
||||||
uword[16] envelope_attacks
|
ubyte[16] envelope_attacks
|
||||||
ubyte[16] envelope_sustains
|
ubyte[16] envelope_sustains
|
||||||
uword[16] envelope_releases
|
ubyte[16] envelope_releases
|
||||||
|
ubyte[16] envelope_maxvolumes
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ For next release
|
|||||||
^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^
|
||||||
...
|
...
|
||||||
|
|
||||||
|
|
||||||
Need help with
|
Need help with
|
||||||
^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^
|
||||||
- c128 target: various machine specific things (free zp locations, how banking works, getting the floating point routines working, ...)
|
- c128 target: various machine specific things (free zp locations, how banking works, getting the floating point routines working, ...)
|
||||||
|
@ -12,8 +12,8 @@ main {
|
|||||||
psg.voice(1, psg.RIGHT, 0, psg.NOISE, 0)
|
psg.voice(1, psg.RIGHT, 0, psg.NOISE, 0)
|
||||||
psg.freq(0, 1000)
|
psg.freq(0, 1000)
|
||||||
psg.freq(1, 2000)
|
psg.freq(1, 2000)
|
||||||
psg.envelope(0, 50, 0, 5)
|
psg.envelope(0, 63, 50, 0, 5)
|
||||||
psg.envelope(1, 80, 0, 6)
|
psg.envelope(1, 63, 80, 0, 6)
|
||||||
sys.wait(100)
|
sys.wait(100)
|
||||||
psg.silent()
|
psg.silent()
|
||||||
cx16.restore_irq()
|
cx16.restore_irq()
|
||||||
@ -68,8 +68,8 @@ main {
|
|||||||
ubyte note1 = msb(note)
|
ubyte note1 = msb(note)
|
||||||
psg.freq(0, vera_freqs[note0])
|
psg.freq(0, vera_freqs[note0])
|
||||||
psg.freq(1, vera_freqs[note1])
|
psg.freq(1, vera_freqs[note1])
|
||||||
psg.envelope(0, 255, 0, 6)
|
psg.envelope(0, 63, 255, 0, 6)
|
||||||
psg.envelope(1, 255, 0, 6)
|
psg.envelope(1, 63, 255, 0, 6)
|
||||||
print_notes(note0, note1)
|
print_notes(note0, note1)
|
||||||
sys.wait(10)
|
sys.wait(10)
|
||||||
}
|
}
|
||||||
|
@ -602,35 +602,35 @@ sound {
|
|||||||
; soft click/"tschk" sound
|
; soft click/"tschk" sound
|
||||||
psg.freq(0, 15600)
|
psg.freq(0, 15600)
|
||||||
psg.voice(0, psg.LEFT | psg.RIGHT, 32, psg.NOISE, 0)
|
psg.voice(0, psg.LEFT | psg.RIGHT, 32, psg.NOISE, 0)
|
||||||
psg.envelope(0, 200, 1, 100)
|
psg.envelope(0, 32, 200, 1, 100)
|
||||||
}
|
}
|
||||||
|
|
||||||
sub blockdrop() {
|
sub blockdrop() {
|
||||||
; swish
|
; swish
|
||||||
psg.freq(1, 4600)
|
psg.freq(1, 4600)
|
||||||
psg.voice(1, psg.LEFT | psg.RIGHT, 32, psg.NOISE, 0)
|
psg.voice(1, psg.LEFT | psg.RIGHT, 32, psg.NOISE, 0)
|
||||||
psg.envelope(1, 200, 5, 20)
|
psg.envelope(1, 32, 200, 5, 20)
|
||||||
}
|
}
|
||||||
|
|
||||||
sub swapping() {
|
sub swapping() {
|
||||||
; beep
|
; beep
|
||||||
psg.freq(2, 1500)
|
psg.freq(2, 1500)
|
||||||
psg.voice(2, psg.LEFT | psg.RIGHT, 32, psg.TRIANGLE, 0)
|
psg.voice(2, psg.LEFT | psg.RIGHT, 32, psg.TRIANGLE, 0)
|
||||||
psg.envelope(2, 100, 6, 10)
|
psg.envelope(2, 40, 100, 6, 10)
|
||||||
}
|
}
|
||||||
|
|
||||||
sub lineclear() {
|
sub lineclear() {
|
||||||
; explosion
|
; explosion
|
||||||
psg.freq(3, 1400)
|
psg.freq(3, 1400)
|
||||||
psg.voice(3, psg.LEFT | psg.RIGHT, 63, psg.NOISE, 0)
|
psg.voice(3, psg.LEFT | psg.RIGHT, 63, psg.NOISE, 0)
|
||||||
psg.envelope(3, 100, 8, 10)
|
psg.envelope(3, 63, 100, 8, 10)
|
||||||
}
|
}
|
||||||
|
|
||||||
sub lineclear_big() {
|
sub lineclear_big() {
|
||||||
; big explosion
|
; big explosion
|
||||||
psg.freq(4, 2500)
|
psg.freq(4, 2500)
|
||||||
psg.voice(4, psg.LEFT | psg.RIGHT, 63, psg.NOISE, 0)
|
psg.voice(4, psg.LEFT | psg.RIGHT, 63, psg.NOISE, 0)
|
||||||
psg.envelope(4, 100, 20, 10)
|
psg.envelope(4, 63, 100, 20, 10)
|
||||||
}
|
}
|
||||||
|
|
||||||
sub gameover() {
|
sub gameover() {
|
||||||
@ -639,7 +639,7 @@ sound {
|
|||||||
psg.freq(6, 600)
|
psg.freq(6, 600)
|
||||||
psg.voice(5, psg.LEFT | psg.RIGHT, 0, psg.SAWTOOTH, 0)
|
psg.voice(5, psg.LEFT | psg.RIGHT, 0, psg.SAWTOOTH, 0)
|
||||||
psg.voice(6, psg.LEFT | psg.RIGHT, 0, psg.TRIANGLE, 0)
|
psg.voice(6, psg.LEFT | psg.RIGHT, 0, psg.TRIANGLE, 0)
|
||||||
psg.envelope(5, 100, 30, 10)
|
psg.envelope(5, 50, 100, 30, 10)
|
||||||
psg.envelope(6, 100, 30, 10)
|
psg.envelope(6, 50, 100, 30, 10)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user