diff --git a/Programs/CosmOS/Apps/Lander.asm b/Programs/CosmOS/Apps/Lander.asm index c3c8938..aba3f79 100644 --- a/Programs/CosmOS/Apps/Lander.asm +++ b/Programs/CosmOS/Apps/Lander.asm @@ -2661,10 +2661,18 @@ hideSprite: ; ---- The bang, set up once and played in two writes ---- ; -; A patch is twenty odd writes and a note is two, which is the whole point of the selector and +; A patch is forty odd writes and a note is two, which is the whole point of the selector and ; value registers - so the instrument is built at startup like the tiles are, and a crash only ; has to say "this channel, this note". ; +; ---- And the numbers came out of soundThing ---- +; +; The first version of this was guessed at in bytes, and a byte is not seconds or hertz: a +; cutoff of 40 looked small and is 57 Hz, which made the bang a low gurgle. Voyager's sound +; device is soundThing's voice engine with the editor taken off, so a patch designed there - +; where it can be HEARD - means the same thing here. SoundPatch converts one into the table +; below. Change the sound in soundThing and convert it again; do not edit the numbers. +; ; ---- Channel three, counting down ---- ; ; Effects take the top channel and work downwards, so music, if it ever arrives, can take @@ -2673,87 +2681,31 @@ hideSprite: putBoom: INIA 0x03 OUTA 0x41 ; Channel three. Every parameter write below lands on it. + SETD.0 BoomPatch + CALL playPatch + RET - ; ---- Noise, which is what an explosion is ---- - ; - ; Every other waveform here has a pitch, and a pitched bang is a note. Writing a port leaves - ; A alone, so the three that selected the channel would select parameter three; the wave is - ; parameter nought and has to be said. - RSTA +; ---- A whole patch, out of a table ---- +; +; DP0 names a count and then that many parameter and value pairs. Every sound after this one +; costs a table and a call rather than forty lines of its own. +playPatch: + LDA.0 + SETD.1 PatchLeft + STA.1 + INCD.0 +playPatchOne: + LDA.0 OUTA 0x42 - INIA 0d5 ; Noise. - OUTA 0x43 - INIA 0x01 ; Oscillator nought, gain. - OUTA 0x42 - INIA 0xFF - OUTA 0x43 - - ; ---- Instant, then a long way down ---- - ; - ; No attack at all, because a bang that fades in is not a bang. A sustain of nothing does NOT - ; end the note - a voice holding at nothing is what a held key is - so the gate still has to - ; be dropped afterwards, which the explosion does once its pieces have gone. - INIA 0x20 ; Amplitude envelope, attack. - OUTA 0x42 - RSTA - OUTA 0x43 - INIA 0x21 ; ---- Decay: about half a second ---- - OUTA 0x42 ; - ; A byte is not seconds. It is squared and scaled to four of them, - ; so 200 is two and a half - which over the eight tenths of a - ; second the pieces are in the air is not a bang fading, it is the - ; first third of one, and it read as a flat wash of noise. - INIA 0d90 - OUTA 0x43 - INIA 0x22 ; Sustain: nothing. - OUTA 0x42 - RSTA - OUTA 0x43 - INIA 0x23 ; Release. - OUTA 0x42 - INIA 0d40 - OUTA 0x43 - - ; ---- And a filter closing, which is what makes it a boom and not a hiss ---- - ; - ; Noise on its own is a cymbal. The modulation envelope shuts the low pass over the same - ; moment the level falls, so the bright part is only at the front of it. - INIA 0x40 ; Filter, on. - OUTA 0x42 - INIA 0x01 - OUTA 0x43 - INIA 0x41 ; Type: low pass. - OUTA 0x42 - RSTA - OUTA 0x43 - INIA 0x42 ; Cutoff, low, which is where it ends up. - OUTA 0x42 - INIA 0d40 - OUTA 0x43 - INIA 0x43 ; A little resonance, so the sweep can be heard. - OUTA 0x42 - INIA 0d120 - OUTA 0x43 - INIA 0x44 ; What opens it: the modulation envelope. - OUTA 0x42 - INIA 0d2 - OUTA 0x43 - INIA 0x45 ; And how far above where it sits. - OUTA 0x42 - INIA 0d200 - OUTA 0x43 - INIA 0x30 ; That envelope: open at once, - OUTA 0x42 - RSTA - OUTA 0x43 - INIA 0x31 ; shut over about a third of a second, - OUTA 0x42 - INIA 0d90 - OUTA 0x43 - INIA 0x32 ; and stay shut. - OUTA 0x42 - RSTA + INCD.0 + LDA.0 OUTA 0x43 + INCD.0 + SETD.1 PatchLeft + LDA.1 + DECA + STA.1 + BNA playPatchOne RET ; Two writes, which is what a note is meant to cost. @@ -3948,6 +3900,8 @@ CopyLeft: 0x00 HideSlot: 0x00 +PatchLeft: + 0x00 ; What a flame is being asked to be, before it is written out. FlameSlot: @@ -4132,3 +4086,5 @@ LanderArtAt: #Reserve 0d2 #Include math.asm + +#Include boom.asm diff --git a/Programs/Sounds/boom.asm b/Programs/Sounds/boom.asm new file mode 100644 index 0000000..c6bd568 --- /dev/null +++ b/Programs/Sounds/boom.asm @@ -0,0 +1,55 @@ +; BoomPatch, converted from External/soundThing/patches/Drums/Kick808.json by SoundPatch. +; Designed in soundThing, where it can be heard. Do not edit the numbers +; here: change the patch and convert it again. + +#Data + +BoomPatch: + 0d47 ; how many pairs follow + 0x50 0x01 ; the level is the amplitude envelope + 0x00 0d0 ; oscillator 0, waveform + 0x01 0d255 ; gain + 0x02 0d128 ; duty + 0x03 0d128 ; detune, in cents + 0x04 0d127 ; octave + 0x05 0d1 ; on + 0x06 0d0 ; what moves its width + 0x07 0d128 ; and how far + 0x08 0d2 ; what moves its pitch + 0x09 0d197 ; and how far + 0x0A 0d0 ; what moves its gain + 0x0B 0d128 ; and how far + 0x10 0d5 ; oscillator 1, waveform + 0x11 0d146 ; gain + 0x12 0d128 ; duty + 0x13 0d128 ; detune, in cents + 0x14 0d128 ; octave + 0x15 0d1 ; on + 0x16 0d0 ; what moves its width + 0x17 0d128 ; and how far + 0x18 0d0 ; what moves its pitch + 0x19 0d128 ; and how far + 0x1A 0d0 ; what moves its gain + 0x1B 0d128 ; and how far + 0x20 0d4 ; amplitude envelope, attack + 0x21 0d79 ; decay + 0x22 0d0 ; sustain + 0x23 0d31 ; release + 0x30 0d4 ; modulation envelope, attack + 0x31 0d35 ; decay + 0x32 0d0 ; sustain + 0x33 0d13 ; release + 0x40 0d1 ; filter, on + 0x41 0d0 ; type: 0 low, 1 high, 2 band + 0x42 0d92 ; cutoff, in hertz + 0x43 0d10 ; resonance + 0x44 0d0 ; what moves the cutoff + 0x45 0d128 ; and how far, in hertz + 0x46 0d0 ; what moves the resonance + 0x47 0d128 ; and how far + 0x60 0d0 ; LFO 0, on + 0x61 0d0 ; waveform + 0x62 0d127 ; rate, in hertz + 0x70 0d0 ; LFO 1, on + 0x71 0d0 ; waveform + 0x72 0d127 ; rate, in hertz diff --git a/README.md b/README.md index 9d3a2a6..20b2630 100644 --- a/README.md +++ b/README.md @@ -24,8 +24,10 @@ wrote Asm.sbx: program 7533, data 4099, labels 555 | [`Source/Assembler`](Source/Assembler) | The assembler that runs on a host | | [`Source/DiskTool`](Source/DiskTool) | SplitDisk, which reads and writes SplitBit's filesystem | | [`Source/Linter`](Source/Linter) | SplitLint, which points out needlessly long assembly forms | +| [`Source/Patch`](Source/Patch) | SoundPatch, which turns a soundThing patch into a table the sound device takes | | [`Programs/Examples`](Programs/Examples) | Programs to read: hello, a calculator, Fibonacci, a prime sieve, Life, the colours | | [`Programs/Libraries`](Programs/Libraries) | Code included by name rather than linked, since there is no linker | +| [`Programs/Sounds`](Programs/Sounds) | Patch tables, converted from soundThing and checked in so the build never needs it | | [`Programs/Loader`](Programs/Loader) | The standalone loader CosmOS grew out of | | [`Programs/CosmOS`](Programs/CosmOS) | The operating system, its applications, and the native assembler | | [`Programs/testPrograms`](Programs/testPrograms) | What the test suite drives | @@ -114,7 +116,7 @@ Manual. ## Getting Started: -Clone it and build the four tools. You need gcc and make, or similar: +Clone it and build the five tools. You need gcc and make, or similar: ``` git clone https://github.com/RealBusinessAccount/SplitBit-Emulator.git @@ -304,6 +306,32 @@ this is what turns such a count into a list of routine names. Without `-o` the output takes the source file's name, in the directory you called the assembler from, with the extension the format asks for: `.bin` for a boot image and `.sbx` for a loadable program. Included files are looked for beside the file that includes them, and then along the directories given with `-I`. +## Making A Patch: SoundPatch + +``` +./SoundPatch