From f8658f6afa6b2f3c2612d9b0cdd7a88f75b3457a Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sat, 2 Jul 2022 19:28:24 +0200 Subject: [PATCH] precalc vera freq to not use floating point math anymore --- compiler/res/prog8lib/cx16/psg.p8 | 66 +++++++++++++++-------------- docs/source/todo.rst | 4 +- examples/cx16/bdmusic.p8 | 69 +++++-------------------------- 3 files changed, 48 insertions(+), 91 deletions(-) diff --git a/compiler/res/prog8lib/cx16/psg.p8 b/compiler/res/prog8lib/cx16/psg.p8 index 99d6890b2..c376ae7cd 100644 --- a/compiler/res/prog8lib/cx16/psg.p8 +++ b/compiler/res/prog8lib/cx16/psg.p8 @@ -23,10 +23,10 @@ psg { ; ; this would rely on floating point math to convert hertz to vera frequency ; ; TODO should be replaced by integer math maybe with a lookup table? ; uword vera_freq = (hertz / 0.3725290298461914) as uword -; freq_vera(voice_num, vera_freq) +; freq(voice_num, vera_freq) ; } - sub freq_vera(ubyte voice_num, uword vera_freq) { + sub freq(ubyte voice_num, uword vera_freq) { cx16.vpoke(1, $f9c1 + voice_num*4, msb(vera_freq)) cx16.vpoke(1, $f9c0 + voice_num*4, lsb(vera_freq)) } @@ -53,47 +53,49 @@ psg { } sub silent() { - ubyte voice - for voice in 0 to 15 { - volume(voice, 0) - envelope_volumes[voice] = 0 - envelope_states[voice] = 1 + for cx16.r9L in 0 to 15 { + volume(cx16.r9L, 0) + envelope_volumes[cx16.r9L] = 0 + envelope_states[cx16.r9L] = 1 } } sub envelopes_irq() { - ubyte vera_ctrl = cx16.VERA_CTRL - ubyte vera_addr_h = cx16.VERA_ADDR_H - ubyte vera_addr_m = cx16.VERA_ADDR_M - ubyte vera_addr_l = cx16.VERA_ADDR_L - uword vol_word - ubyte voice - for voice in 0 to 15 { - if envelope_states[voice] { + ; cx16.r0 = the volume word (volume scaled by 256) + ; cx16.r15L = the voice number + ; the other virtual registers are used to backup vera registers. + + cx16.r13L = cx16.VERA_CTRL + cx16.r13H = cx16.VERA_ADDR_L + cx16.r14L = cx16.VERA_ADDR_M + cx16.r14H = cx16.VERA_ADDR_H + + for cx16.r15L in 0 to 15 { + if envelope_states[cx16.r15L] { ; release - vol_word = envelope_volumes[voice] - envelope_releases[voice] - if msb(vol_word) & %11000000 { - vol_word = 0 - envelope_releases[voice] = 0 + cx16.r0 = envelope_volumes[cx16.r15L] - envelope_releases[cx16.r15L] + if msb(cx16.r0) & %11000000 { + cx16.r0 = 0 + envelope_releases[cx16.r15L] = 0 } - envelope_volumes[voice] = vol_word - volume(voice, msb(vol_word)) + envelope_volumes[cx16.r15L] = cx16.r0 + volume(cx16.r15L, msb(cx16.r0)) } else { ; attack - vol_word = envelope_volumes[voice] + envelope_attacks[voice] - if msb(vol_word) & %11000000 or envelope_attacks[voice]==0 { - vol_word = mkword(63, 0) - envelope_attacks[voice] = 0 - envelope_states[voice] = 1 ; start release + cx16.r0 = envelope_volumes[cx16.r15L] + envelope_attacks[cx16.r15L] + if msb(cx16.r0) & %11000000 or envelope_attacks[cx16.r15L]==0 { + cx16.r0 = mkword(63, 0) + envelope_attacks[cx16.r15L] = 0 + envelope_states[cx16.r15L] = 1 ; start release } - envelope_volumes[voice] = vol_word - volume(voice, msb(vol_word)) + envelope_volumes[cx16.r15L] = cx16.r0 + volume(cx16.r15L, msb(cx16.r0)) } } - cx16.VERA_CTRL = vera_ctrl - cx16.VERA_ADDR_L = vera_addr_l - cx16.VERA_ADDR_M = vera_addr_m - cx16.VERA_ADDR_H = vera_addr_h + cx16.VERA_CTRL = cx16.r13L + cx16.VERA_ADDR_L = cx16.r13H + cx16.VERA_ADDR_M = cx16.r14L + cx16.VERA_ADDR_H = cx16.r14H } ubyte[16] envelope_states diff --git a/docs/source/todo.rst b/docs/source/todo.rst index e174b356a..461d67e42 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -3,7 +3,9 @@ TODO For next release ^^^^^^^^^^^^^^^^ -... +- optimize msb(cx16.r0) -> cx16.r0H, lsb(cx16.r0) -> cx16.r0L +- convert the sounds in cx16 tehtriz to use the psg module instead +- notify petaxian that it could use the psg module too? Need help with ^^^^^^^^^^^^^^ diff --git a/examples/cx16/bdmusic.p8 b/examples/cx16/bdmusic.p8 index 6d0731df8..3be13b74b 100644 --- a/examples/cx16/bdmusic.p8 +++ b/examples/cx16/bdmusic.p8 @@ -1,6 +1,5 @@ %import textio %import syslib -%import floats %import psg main { @@ -20,18 +19,16 @@ main { for note in notes { ubyte note0 = lsb(note) ubyte note1 = msb(note) - psg.freq_vera(0, vera_freq(note0)) - psg.freq_vera(1, vera_freq(note1)) + psg.freq(0, vera_freqs[note0]) + psg.freq(1, vera_freqs[note1]) psg.envelope(0, 255, 6) psg.envelope(1, 255, 6) print_notes(note0, note1) sys.wait(10) } } - } - sub vera_freq(ubyte note) -> uword { - return (freqs_hz[note-10] / 0.3725290298461914) as uword + psg.silent() } sub print_notes(ubyte n1, ubyte n2) { @@ -67,56 +64,12 @@ main { $3532, $322e, $2e29, $2926, $2730, $242c, $2027, $1420 ] - float[] freqs_hz = [ - ; first 10 are unused so should index by i-10 - 44.6, - 47.4, - 50.4, - 53.4, - 56.6, - 59.6, - 63.5, - 67.1, - 71.3, - 75.5, - 80.0, - 84.7, - 89.3, - 94.9, - 100.7, - 106.8, - 113.2, - 119.3, - 127.1, - 134.1, - 142.7, - 151.0, - 160.0, - 169.5, - 178.5, - 189.7, - 201.4, - 213.6, - 226.3, - 238.5, - 254.1, - 268.3, - 285.3, - 301.9, - 320.0, - 339.0, - 357.0, - 379.5, - 402.9, - 427.3, - 452.6, - 477.0, - 508.2, - 536.5, - 570.7, - 603.8, - 639.9, - 678.0, - 714.1 - ] + uword[] vera_freqs = [ + 0,0,0,0,0,0,0,0,0,0, ; first 10 notes are not used + 120, 127, 135, 143, 152, 160, 170, 180, 191, 203, + 215, 227, 240, 255, 270, 287, 304, 320, 341, 360, + 383, 405, 429, 455, 479, 509, 541, 573, 607, 640, + 682, 720, 766, 810, 859, 910, 958, 1019, 1082, 1147, + 1215, 1280, 1364, 1440, 1532, 1621, 1718, 1820, 1917] + }