From 491bf88adedd563d19ac8bc2bfefdd08dcb2efc0 Mon Sep 17 00:00:00 2001 From: Dennis Ranke Date: Sun, 24 Apr 2022 00:01:54 +0200 Subject: [PATCH] add first version of sound doku --- platform/bin/platform.uw8 | Bin 3758 -> 3757 bytes platform/src/ges.cwa | 2 +- site/content/docs.md | 135 +++++++++++++++++++++++++++++++------- src/run-web.html | 2 +- 4 files changed, 113 insertions(+), 26 deletions(-) diff --git a/platform/bin/platform.uw8 b/platform/bin/platform.uw8 index 24341b3723d70f68413da73b414e8eae140306c6..e0f701c877d0d016c09cb5258e6f03f07b7788df 100644 GIT binary patch delta 3338 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 U9jG^}YJ)2VqKK}BL6ytaMo;#M+5i9m delta 3338 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 U9jG^}YJ)2VqKK}BL6ytaM!o`r=>Px# diff --git a/platform/src/ges.cwa b/platform/src/ges.cwa index dc97114..f52aaef 100644 --- a/platform/src/ges.cwa +++ b/platform/src/ges.cwa @@ -16,7 +16,7 @@ export fn gesSnd(t: i32) -> f32 { let i: i32; loop clearLoop { (baseAddr + i)!GesBufferOffset = 0; - branch_if (i := i + 4) < 128*8: clearLoop; + branch_if (i := i + 4) < 128*4: clearLoop; } let ch: i32; diff --git a/site/content/docs.md b/site/content/docs.md index f2cbec0..c6489b4 100644 --- a/site/content/docs.md +++ b/site/content/docs.md @@ -234,7 +234,8 @@ Avoid the reserved control chars, they are currently NOPs but their behavior can | 2-3 | - | Reserved | | 4 | - | Switch to normal mode | | 5 | - | Switch to graphics mode | -| 6-7 | - | Reserved | +| 6 | - | Reserved | +| 7 | - | Bell / trigger sound channel 0 | | 8 | - | Move cursor left | | 9 | - | Move cursor right | | 10 | - | Move cursor down | @@ -276,34 +277,120 @@ Sets the cursor position. In normal mode `x` and `y` are multiplied by 8 to get ## Sound +### Low level operation + +MicroW8 actually runs two instances of your module. On the first instance, it calls `upd` and displays the framebuffer found in its memory. On the +second instance, it calls `snd` instead with an incrementing sample index and expects that function to return sound samples for the left and right +channel at 44100 Hz. If your module does not export a `snd` function, it calls the api function `sndGes` instead. + +As the only means of communication, 32 bytes starting at address 0x00050 are copied from main to sound memory after `upd` returns. At the same time, +32 bytes starting at 0x12c80 are copied from sound to main memory. + +By default, the `sndGes` function generates sound based on the 32 bytes at 0x00050. This means that in the default configuration those 32 bytes act +as sound registers. See the `sndGes` function for the meaning of those registers. + +### fn playNote(channel: i32, note: i32) + +Triggers a note (1-127) on the given channel (0-3). Notes are semitones with 69 being A4 (same as MIDI). A note value of 0 stops the +sound playing on that channel. A note value 128-255 will trigger note-128 and immediately stop it (playing attack+release parts of envelope). + +This function assumes the default setup, with the `sndGes` registers located at 0x00050. + +### fn sndGes(sampleIndex: i32) -> f32 + +This implements a sound chip, generating sound based on 32 bytes of sound registers. + +The spec of this sound chip are: + +- 4 channels +- rect, saw, tri, noise wave forms selectable per channel +- each wave form supports some kind of pulse width modulation +- each channel has an optional automatic low pass filter, or can be sent to one of two manually controllable filters +- each channel can select between a narrow and a wide stereo positioning. The two stereo positions of each channel are fixed. + +This function requires 1024 bytes of working memory, the first 32 bytes of which are interpreted as the sound registers. +The base address of its working memory can be configured by writing the address to 0x12c78. It defaults to 0x00050. + +Here is a short description of the 32 sound registers. + ``` -Per channel: +00 - CTRL0 +06 - CTRL1 +0c - CTRL2 +12 - CTRL3 + | 7 6 | 5 | 4 | 3 2 | 1 | 0 | + | wave | ring | wide | filter | trigger | note on | -00 : CTRL - wave form, ring, sync, filter send, trigger - bit 0: note on flag - bit 1: note trigger - bit 2,3: filter 0,1 send - bit 6,7: wave form (rect, saw, tri, noise) -01 : PULS - pulse width -02 : FINE - fine tuning -03 : NOTE - note -04 : ENVA - attack, decay -05 : ENVR - sustain, release + note on: stay in decay/sustain part of envelope + trigger: the attack part of the envlope is triggered when either this changes + or note on is changed from 0 to 1. + filter : 0 - no filter + 1 - fixed 6db 1-pole filter with cutoff two octaves above note + 2 - programmable filter 0 + 3 - programmable filter 1 + wide : use wide stereo panning + ring : ring modulate with triangle wave at frequency of previous channel + wave : 0 - rectangle + 1 - saw + 2 - triangle + 3 - noise -50-56: channel 0 -56-5b: channel 1 -5c-61: channel 2 -62-67: channel 3 +01 - PULS0 +07 - PULS1 +0d - PULS2 +13 - PULS3 + Pulse width 0-255, with 0 being the plain version of each wave form. + rectangle - 50%-100% pulse width + saw - inverts 0%-100% of the saw wave form around the center + triangle - morphs into an octave up triangle wave + noise - blends into a decimated saw wave (just try it out) -68: VO01 - volumes channel 0&1 -69: VO23 - volumes channel 2&3 +02 - FINE0 +08 - FINE1 +0e - FINE2 +14 - FINE3 + Fractional note -6a : FCTR 0 - type, resonance -6b : FCTR 1 - type, resonance -6c : FFIN 0 - cutoff fine tuning -6d : FNOT 0 - cutoff note -6e : FFIN 1 - cutoff fine tuning -6f : FNOT 1 - cutoff note +03 - NOTE0 +09 - NOTE1 +0f - NOTE2 +15 - NOTE3 + Note, 69 = A4 + +04 - ENVA0 +0a - ENVA1 +10 - ENVA2 +16 - ENVA3 + | 7 6 5 4 | 3 2 1 0 | + | decay | attack | + +05 - ENVB0 +0b - ENVB1 +11 - ENVB2 +17 - ENVB3 + | 7 6 5 4 | 3 2 1 0 | + | release | sustain | + +18 - VO01 + | 7 6 5 4 | 3 2 1 0 | + | volume 1 | volume 0 | + +19 - VO23 + | 7 6 5 4 | 3 2 1 0 | + | volume 3 | volume 2 | + +1a - FCTR0 +1b - FCTR1 + | 7 6 5 4 | 3 | 2 | 1 | 0 | + | resonance | 0 | band | high | low | + +1c - FFIN0 +1e - FFIN1 + cutoff frequency - fractional note + +1d - FNOT0 +1f - FNOT1 + cutoff frequency - note ``` # The `uw8` tool diff --git a/src/run-web.html b/src/run-web.html index 088401f..54df7a2 100644 --- a/src/run-web.html +++ b/src/run-web.html @@ -1 +1 @@ -uw8-run

\ No newline at end of file +uw8-run
\ No newline at end of file