diff --git a/.gitignore b/.gitignore index d261e99..4eb45e6 100644 --- a/.gitignore +++ b/.gitignore @@ -31,6 +31,6 @@ actual_output/ **/__debug_bin node_modules -*.raw + sointu-server temp_song_file.* \ No newline at end of file diff --git a/.gitpod.yml b/.gitpod.yml new file mode 100644 index 0000000..00753b9 --- /dev/null +++ b/.gitpod.yml @@ -0,0 +1,14 @@ +# This configuration file was automatically generated by Gitpod. +# Please adjust to your needs (see https://www.gitpod.io/docs/introduction/learn-gitpod/gitpod-yaml) +# and commit this file to your remote git repository to share the goodness with others. + +# Learn more from ready-to-use templates: https://www.gitpod.io/docs/introduction/getting-started/quickstart + +tasks: + - init: | + wget https://github.com/WebAssembly/wabt/releases/download/1.0.32/wabt-1.0.32-ubuntu.tar.gz + tar -xvzf wabt-1.0.32-ubuntu.tar.gz + sudo apt install nasm + + + diff --git a/chords.wasm b/chords.wasm deleted file mode 100644 index e4a6b7a..0000000 Binary files a/chords.wasm and /dev/null differ diff --git a/convert.js b/convert.js deleted file mode 100644 index b52f9ac..0000000 --- a/convert.js +++ /dev/null @@ -1,1084 +0,0 @@ -import yaml from 'json-to-pretty-yaml'; -import groove from './tests/grooveisinthecode.js'; -import { writeFile } from 'fs/promises'; - -const doc = { - bpm: groove.BPM, - rowsperbeat: 4, - score: { - length: groove.instrumentPatternLists[0].length, - rowsperpattern: groove.patternsize, - tracks: groove.instrumentPatternLists.slice(0, 7).map(track => { - const patternMap = {}; - track.forEach(patternIndex => { - patternMap[`${patternIndex}`] = groove.patterns[patternIndex-1]; - }); - const patternIndices = Object.keys(patternMap); - const patterns = patternIndices.map(patternIndex => patternMap[`${patternIndex}`]); - const order = track.map((patternIndex) => { - return patternIndices.indexOf(`${patternIndex}`); - }); - return { - numvoices: 1, - order, - patterns - } - }) - }, - patch: [ - { - "numvoices": 1, - "units": [ - { - "type": "oscillator", - "parameters": { - "color": 2, - "detune": 48, - "gain": 16, - "lfo": 0, - "phase": 0, - "shape": 63, - "stereo": 1, - "transpose": 64, - "type": 1, - "unison": 3 - } - }, - { - "type": "oscillator", - "parameters": { - "color": 126, - "detune": 78, - "gain": 16, - "phase": 0, - "shape": 64, - "stereo": 1, - "transpose": 64, - "type": 1, - "unison": 3 - } - }, - { - "type": "addp", - "parameters": { - "stereo": 1 - } - }, - { - "type": "oscillator", - "parameters": { - "color": 2, - "detune": 59, - "gain": 16, - "phase": 0, - "shape": 64, - "stereo": 1, - "transpose": 64, - "type": 1, - "unison": 3 - } - }, - { - "type": "addp", - "parameters": { - "stereo": 1 - } - }, - { - "type": "noise", - "parameters": { - "gain": 6, - "shape": 64, - "stereo": 1 - } - }, - { - "type": "filter", - "parameters": { - "bandpass": 0, - "frequency": 128, - "highpass": 1, - "lowpass": 0, - "negbandpass": 0, - "neghighpass": 0, - "resonance": 128, - "stereo": 1 - } - }, - { - "type": "addp", - "parameters": { - "stereo": 1 - } - }, - { - "type": "envelope", - "parameters": { - "attack": 50, - "decay": 64, - "gain": 96, - "release": 64, - "stereo": 1, - "sustain": 64 - } - }, - { - "type": "mulp", - "parameters": { - "stereo": 1 - } - }, - { - "type": "filter", - "parameters": { - "bandpass": 0, - "frequency": 32, - "highpass": 1, - "lowpass": 0, - "negbandpass": 0, - "neghighpass": 0, - "resonance": 128, - "stereo": 1 - } - }, - { - "type": "delay", - "parameters": { - "damp": 64, - "dry": 64, - "feedback": 64, - "notetracking": 0, - "pregain": 64, - "stereo": 1 - }, - "varargs": [ - 9187, - 9187 - ] - }, - { - "type": "outaux", - "parameters": { - "auxgain": 128, - "outgain": 0, - "stereo": 1 - } - } - ] - }, - { - "numvoices": 1, - "units": [ - { - "type": "envelope", - "parameters": { - "attack": 48, - "decay": 63, - "gain": 128, - "release": 64, - "stereo": 0, - "sustain": 0 - } - }, - { - "type": "distort", - "parameters": { - "drive": 112, - "stereo": 0 - } - }, - { - "type": "oscillator", - "parameters": { - "color": 0, - "detune": 64, - "gain": 128, - "looplength": 1486, - "loopstart": 2536, - "phase": 64, - "samplestart": 250849, - "shape": 64, - "stereo": 0, - "transpose": 64, - "type": 1, - "unison": 0 - } - }, - { - "type": "mulp", - "parameters": { - "stereo": 0 - } - }, - { - "type": "filter", - "parameters": { - "bandpass": 0, - "frequency": 16, - "highpass": 1, - "lowpass": 0, - "negbandpass": 0, - "neghighpass": 0, - "resonance": 128, - "stereo": 0 - } - }, - { - "type": "filter", - "id": 1, - "parameters": { - "bandpass": 0, - "frequency": 22, - "highpass": 0, - "lowpass": 1, - "negbandpass": 0, - "neghighpass": 0, - "resonance": 128, - "stereo": 0 - } - }, - { - "type": "pan", - "parameters": { - "panning": 64, - "stereo": 0 - } - }, - { - "type": "out", - "parameters": { - "gain": 128, - "stereo": 1 - } - }, - { - "parameters": {} - }, - { - "type": "envelope", - "parameters": { - "attack": 0, - "decay": 64, - "gain": 128, - "release": 0, - "stereo": 0, - "sustain": 0 - } - }, - { - "type": "distort", - "parameters": { - "drive": 32, - "stereo": 0 - } - }, - { - "type": "send", - "parameters": { - "amount": 79, - "port": 0, - "sendpop": 1, - "stereo": 0, - "target": 1 - } - } - ] - }, - { - "numvoices": 1, - "units": [ - { - "type": "oscillator", - "parameters": { - "color": 2, - "detune": 48, - "gain": 16, - "lfo": 0, - "phase": 0, - "shape": 63, - "stereo": 1, - "transpose": 64, - "type": 1, - "unison": 3 - } - }, - { - "type": "oscillator", - "parameters": { - "color": 126, - "detune": 78, - "gain": 16, - "phase": 0, - "shape": 64, - "stereo": 1, - "transpose": 64, - "type": 1, - "unison": 3 - } - }, - { - "type": "addp", - "parameters": { - "stereo": 1 - } - }, - { - "type": "oscillator", - "parameters": { - "color": 2, - "detune": 59, - "gain": 16, - "phase": 0, - "shape": 64, - "stereo": 1, - "transpose": 64, - "type": 1, - "unison": 3 - } - }, - { - "type": "addp", - "parameters": { - "stereo": 1 - } - }, - { - "type": "noise", - "parameters": { - "gain": 6, - "shape": 64, - "stereo": 1 - } - }, - { - "type": "filter", - "parameters": { - "bandpass": 0, - "frequency": 128, - "highpass": 1, - "lowpass": 0, - "negbandpass": 0, - "neghighpass": 0, - "resonance": 128, - "stereo": 1 - } - }, - { - "type": "addp", - "parameters": { - "stereo": 1 - } - }, - { - "type": "envelope", - "parameters": { - "attack": 50, - "decay": 64, - "gain": 96, - "release": 64, - "stereo": 1, - "sustain": 64 - } - }, - { - "type": "mulp", - "parameters": { - "stereo": 1 - } - }, - { - "type": "filter", - "parameters": { - "bandpass": 0, - "frequency": 32, - "highpass": 1, - "lowpass": 0, - "negbandpass": 0, - "neghighpass": 0, - "resonance": 128, - "stereo": 1 - } - }, - { - "type": "delay", - "parameters": { - "damp": 64, - "dry": 64, - "feedback": 64, - "notetracking": 0, - "pregain": 64, - "stereo": 1 - }, - "varargs": [ - 9187, - 9187 - ] - }, - { - "type": "outaux", - "parameters": { - "auxgain": 128, - "outgain": 0, - "stereo": 1 - } - } - ] - }, - { - "numvoices": 1, - "units": [ - { - "type": "oscillator", - "parameters": { - "color": 2, - "detune": 48, - "gain": 16, - "lfo": 0, - "phase": 0, - "shape": 63, - "stereo": 1, - "transpose": 64, - "type": 1, - "unison": 3 - } - }, - { - "type": "oscillator", - "parameters": { - "color": 126, - "detune": 78, - "gain": 16, - "phase": 0, - "shape": 64, - "stereo": 1, - "transpose": 64, - "type": 1, - "unison": 3 - } - }, - { - "type": "addp", - "parameters": { - "stereo": 1 - } - }, - { - "type": "oscillator", - "parameters": { - "color": 2, - "detune": 59, - "gain": 16, - "phase": 0, - "shape": 64, - "stereo": 1, - "transpose": 64, - "type": 1, - "unison": 3 - } - }, - { - "type": "addp", - "parameters": { - "stereo": 1 - } - }, - { - "type": "noise", - "parameters": { - "gain": 6, - "shape": 64, - "stereo": 1 - } - }, - { - "type": "filter", - "parameters": { - "bandpass": 0, - "frequency": 128, - "highpass": 1, - "lowpass": 0, - "negbandpass": 0, - "neghighpass": 0, - "resonance": 128, - "stereo": 1 - } - }, - { - "type": "addp", - "parameters": { - "stereo": 1 - } - }, - { - "type": "envelope", - "parameters": { - "attack": 50, - "decay": 64, - "gain": 96, - "release": 64, - "stereo": 1, - "sustain": 64 - } - }, - { - "type": "mulp", - "parameters": { - "stereo": 1 - } - }, - { - "type": "filter", - "parameters": { - "bandpass": 0, - "frequency": 32, - "highpass": 1, - "lowpass": 0, - "negbandpass": 0, - "neghighpass": 0, - "resonance": 128, - "stereo": 1 - } - }, - { - "type": "delay", - "parameters": { - "damp": 64, - "dry": 64, - "feedback": 64, - "notetracking": 0, - "pregain": 64, - "stereo": 1 - }, - "varargs": [ - 9187, - 9187 - ] - }, - { - "type": "outaux", - "parameters": { - "auxgain": 128, - "outgain": 0, - "stereo": 1 - } - } - ] - }, - { - "numvoices": 1, - "units": [ - { - "type": "oscillator", - "parameters": { - "color": 2, - "detune": 48, - "gain": 16, - "lfo": 0, - "phase": 0, - "shape": 63, - "stereo": 1, - "transpose": 64, - "type": 1, - "unison": 3 - } - }, - { - "type": "oscillator", - "parameters": { - "color": 126, - "detune": 78, - "gain": 16, - "phase": 0, - "shape": 64, - "stereo": 1, - "transpose": 64, - "type": 1, - "unison": 3 - } - }, - { - "type": "addp", - "parameters": { - "stereo": 1 - } - }, - { - "type": "oscillator", - "parameters": { - "color": 2, - "detune": 59, - "gain": 16, - "phase": 0, - "shape": 64, - "stereo": 1, - "transpose": 64, - "type": 1, - "unison": 3 - } - }, - { - "type": "addp", - "parameters": { - "stereo": 1 - } - }, - { - "type": "noise", - "parameters": { - "gain": 6, - "shape": 64, - "stereo": 1 - } - }, - { - "type": "filter", - "parameters": { - "bandpass": 0, - "frequency": 128, - "highpass": 1, - "lowpass": 0, - "negbandpass": 0, - "neghighpass": 0, - "resonance": 128, - "stereo": 1 - } - }, - { - "type": "addp", - "parameters": { - "stereo": 1 - } - }, - { - "type": "envelope", - "parameters": { - "attack": 50, - "decay": 64, - "gain": 96, - "release": 64, - "stereo": 1, - "sustain": 64 - } - }, - { - "type": "mulp", - "parameters": { - "stereo": 1 - } - }, - { - "type": "filter", - "parameters": { - "bandpass": 0, - "frequency": 32, - "highpass": 1, - "lowpass": 0, - "negbandpass": 0, - "neghighpass": 0, - "resonance": 128, - "stereo": 1 - } - }, - { - "type": "delay", - "parameters": { - "damp": 64, - "dry": 64, - "feedback": 64, - "notetracking": 0, - "pregain": 64, - "stereo": 1 - }, - "varargs": [ - 9187, - 9187 - ] - }, - { - "type": "outaux", - "parameters": { - "auxgain": 128, - "outgain": 0, - "stereo": 1 - } - } - ] - }, - { - "numvoices": 1, - "units": [ - { - "type": "envelope", - "parameters": { - "attack": 36, - "decay": 69, - "gain": 128, - "release": 32, - "stereo": 0, - "sustain": 0 - } - }, - { - "type": "distort", - "parameters": { - "drive": 112, - "stereo": 0 - } - }, - { - "type": "oscillator", - "id": 1, - "parameters": { - "color": 128, - "detune": 64, - "gain": 128, - "looplength": 1, - "phase": 0, - "shape": 64, - "stereo": 0, - "transpose": 64, - "type": 0 - } - }, - { - "type": "mulp", - "parameters": { - "stereo": 0 - } - }, - { - "type": "filter", - "parameters": { - "bandpass": 0, - "frequency": 14, - "highpass": 1, - "lowpass": 0, - "negbandpass": 0, - "neghighpass": 0, - "resonance": 128, - "stereo": 0 - } - }, - { - "type": "push", - "parameters": { - "stereo": 0 - } - }, - { - "type": "filter", - "parameters": { - "bandpass": 0, - "frequency": 16, - "highpass": 0, - "lowpass": 1, - "negbandpass": 0, - "neghighpass": 0, - "resonance": 128, - "stereo": 0 - } - }, - { - "type": "delay", - "parameters": { - "count": 8, - "damp": 64, - "delay": 1, - "dry": 0, - "feedback": 96, - "notetracking": 0, - "pregain": 32, - "stereo": 0 - }, - "varargs": [ - 1116, - 1188, - 1276, - 1356, - 1422, - 1492, - 1556, - 1618 - ] - }, - { - "type": "addp", - "parameters": { - "stereo": 0 - } - }, - { - "type": "pan", - "parameters": { - "panning": 64, - "stereo": 0 - } - }, - { - "type": "out", - "parameters": { - "gain": 64, - "stereo": 1 - } - }, - { - "parameters": {} - }, - { - "type": "envelope", - "parameters": { - "attack": 0, - "decay": 70, - "gain": 128, - "release": 70, - "stereo": 0, - "sustain": 0 - } - }, - { - "type": "distort", - "parameters": { - "drive": 5, - "stereo": 0 - } - }, - { - "type": "send", - "parameters": { - "amount": 101, - "port": 0, - "sendpop": 1, - "stereo": 0, - "target": 1 - } - }, - { - "parameters": {} - }, - { - "type": "envelope", - "parameters": { - "attack": 48, - "decay": 58, - "gain": 128, - "release": 0, - "stereo": 0, - "sustain": 0 - } - }, - { - "type": "distort", - "parameters": { - "drive": 64, - "stereo": 0 - } - }, - { - "type": "send", - "parameters": { - "amount": 32, - "port": 5, - "sendpop": 1, - "stereo": 0, - "target": 1, - "unit": 0, - "voice": 0 - } - } - ] - }, - { - "numvoices": 1, - "units": [ - { - "type": "envelope", - "parameters": { - "attack": 32, - "decay": 60, - "gain": 128, - "release": 0, - "stereo": 0, - "sustain": 0 - } - }, - { - "type": "oscillator", - "id": 1, - "parameters": { - "color": 64, - "detune": 64, - "gain": 128, - "phase": 0, - "shape": 64, - "stereo": 0, - "transpose": 64, - "type": 1 - } - }, - { - "type": "mulp", - "parameters": { - "stereo": 0 - } - }, - { - "parameters": {} - }, - { - "type": "envelope", - "parameters": { - "attack": 32, - "decay": 64, - "gain": 64, - "release": 66, - "stereo": 0, - "sustain": 0 - } - }, - { - "type": "distort", - "parameters": { - "drive": 32, - "stereo": 0 - } - }, - { - "type": "noise", - "parameters": { - "gain": 64, - "shape": 64, - "stereo": 0 - } - }, - { - "type": "mulp", - "parameters": { - "stereo": 0 - } - }, - { - "type": "filter", - "parameters": { - "bandpass": 0, - "frequency": 106, - "highpass": 1, - "lowpass": 0, - "negbandpass": 0, - "neghighpass": 0, - "resonance": 128, - "stereo": 0 - } - }, - { - "type": "addp", - "parameters": { - "stereo": 0 - } - }, - { - "parameters": {} - }, - { - "type": "distort", - "parameters": { - "drive": 112, - "stereo": 0 - } - }, - { - "type": "delay", - "parameters": { - "count": 8, - "damp": 0, - "delay": 1, - "dry": 128, - "feedback": 40, - "notetracking": 0, - "pregain": 24, - "stereo": 0 - }, - "varargs": [ - 1116, - 1188, - 1276, - 1356, - 1422, - 1492, - 1556, - 1618 - ] - }, - { - "type": "compressor", - "parameters": { - "attack": 51, - "invgain": 64, - "ratio": 112, - "release": 49, - "stereo": 0, - "threshold": 64 - } - }, - { - "type": "mulp", - "parameters": { - "stereo": 0 - } - }, - { - "parameters": {} - }, - { - "type": "pan", - "parameters": { - "panning": 68, - "stereo": 0 - } - }, - { - "type": "outaux", - "parameters": { - "auxgain": 0, - "outgain": 64, - "stereo": 1 - } - }, - { - "parameters": {} - }, - { - "type": "envelope", - "parameters": { - "attack": 0, - "decay": 60, - "gain": 128, - "release": 0, - "stereo": 0, - "sustain": 0 - } - }, - { - "type": "distort", - "parameters": { - "drive": 5, - "stereo": 0 - } - }, - { - "type": "send", - "parameters": { - "amount": 90, - "port": 0, - "sendpop": 1, - "stereo": 0, - "target": 1, - "unit": 0, - "voice": 0 - } - } - ] - } - ] -} - -await writeFile('tests/groove.yaml', yaml.stringify(doc)); \ No newline at end of file diff --git a/groove.wasm b/groove.wasm deleted file mode 100644 index 41f95de..0000000 Binary files a/groove.wasm and /dev/null differ diff --git a/groove.wat b/groove.wat deleted file mode 100644 index d63e01d..0000000 --- a/groove.wat +++ /dev/null @@ -1,879 +0,0 @@ -(module - - -;;------------------------------------------------------------------------------ -;; Import the difficult math functions from javascript -;; (seriously now, it's 2020) -;;------------------------------------------------------------------------------ -(func $pow (import "m" "pow") (param f32) (param f32) (result f32)) -(func $log2 (import "m" "log2") (param f32) (result f32)) -(func $sin (import "m" "sin") (param f32) (result f32)) - -;;------------------------------------------------------------------------------ -;; Types. Only useful to define the jump table type, which is -;; (int stereo) void -;;------------------------------------------------------------------------------ -(type $opcode_func_signature (func (param i32))) - -;;------------------------------------------------------------------------------ -;; The one and only memory -;;------------------------------------------------------------------------------ -(memory (export "m") 357) - -;;------------------------------------------------------------------------------ -;; Globals. Putting all with same initialization value should compress most -;;------------------------------------------------------------------------------ -(global $WRK (mut i32) (i32.const 0)) -(global $COM (mut i32) (i32.const 0)) -(global $VAL (mut i32) (i32.const 0)) -(global $delayWRK (mut i32) (i32.const 0)) -(global $globaltick (mut i32) (i32.const 0)) -(global $row (mut i32) (i32.const 0)) -(global $pattern (mut i32) (i32.const 0)) -(global $sample (mut i32) (i32.const 0)) -(global $voice (mut i32) (i32.const 0)) -(global $voicesRemain (mut i32) (i32.const 0)) -(global $randseed (mut i32) (i32.const 1)) -(global $sp (mut i32) (i32.const 1280)) -(global $outputBufPtr (mut i32) (i32.const 6424448)) -;; TODO: only export start and length with certain compiler options; in demo use, they can be hard coded -;; in the intro -(global $outputStart (export "s") i32 (i32.const 6424448)) -(global $outputLength (export "l") i32 (i32.const 16932864)) -(global $output16bit (export "t") i32 (i32.const 0)) - - -;;------------------------------------------------------------------------------ -;; Functions to emulate FPU stack in software -;;------------------------------------------------------------------------------ -(func $peek (result f32) - (f32.load (global.get $sp)) -) - -(func $peek2 (result f32) - (f32.load offset=4 (global.get $sp)) -) - -(func $pop (result f32) - (call $peek) - (global.set $sp (i32.add (global.get $sp) (i32.const 4))) -) - -(func $push (param $value f32) - (global.set $sp (i32.sub (global.get $sp) (i32.const 4))) - (f32.store (global.get $sp) (local.get $value)) -) - -;;------------------------------------------------------------------------------ -;; Helper functions -;;------------------------------------------------------------------------------ -(func $swap (param f32 f32) (result f32 f32) ;; x,y -> y,x - local.get 1 - local.get 0 -) - -(func $scanValueByte (result i32) ;; scans positions $VAL for a byte, incrementing $VAL afterwards - (i32.load8_u (global.get $VAL)) ;; in other words: returns byte [$VAL++] - (global.set $VAL (i32.add (global.get $VAL) (i32.const 1))) ;; $VAL++ -) - -;;------------------------------------------------------------------------------ -;; "Entry point" for the player -;;------------------------------------------------------------------------------ -(start $render) ;; we run render automagically when the module is instantiated - -(func $render (param) - loop $pattern_loop - (global.set $row (i32.const 0)) - loop $row_loop - (call $su_update_voices) - (global.set $sample (i32.const 0)) - loop $sample_loop - (global.set $COM (i32.const 504)) - (global.set $VAL (i32.const 609)) - (global.set $WRK (i32.const 1472)) - (global.set $voice (i32.const 1472)) - (global.set $voicesRemain (i32.const 7)) - (global.set $delayWRK (i32.const 132608)) - (call $su_run_vm) - (i64.store (global.get $outputBufPtr) (i64.load (i32.const 1440))) ;; load the sample from left & right channels as one 64bit int and store it in the address pointed by outputBufPtr - (global.set $outputBufPtr (i32.add (global.get $outputBufPtr) (i32.const 8))) ;; advance outputbufptr - (i64.store (i32.const 1440) (i64.const 0)) ;; clear the left and right ports - (global.set $sample (i32.add (global.get $sample) (i32.const 1))) - (global.set $globaltick (i32.add (global.get $globaltick) (i32.const 1))) - (br_if $sample_loop (i32.lt_s (global.get $sample) (i32.const 5512))) - end - (global.set $row (i32.add (global.get $row) (i32.const 1))) - (br_if $row_loop (i32.lt_s (global.get $row) (i32.const 16))) - end - (global.set $pattern (i32.add (global.get $pattern) (i32.const 1))) - (br_if $pattern_loop (i32.lt_s (global.get $pattern) (i32.const 24))) - end -) -;; the simple implementation of update_voices: each track has exactly one voice -(func $su_update_voices (local $si i32) (local $di i32) (local $tracksRemaining i32) (local $note i32) - (local.set $tracksRemaining (i32.const 7)) - (local.set $si (global.get $pattern)) - (local.set $di (i32.const 1472)) - loop $track_loop - (i32.load8_u offset=336 (local.get $si)) - (i32.mul (i32.const 16)) - (i32.add (global.get $row)) - (i32.load8_u offset=0) - (local.tee $note) - (if (i32.ne (i32.const 1))(then - (i32.store offset=4 (local.get $di) (i32.const 1)) ;; release the note - (if (i32.gt_u (local.get $note) (i32.const 1))(then - (memory.fill (local.get $di) (i32.const 0) (i32.const 4096)) - (i32.store (local.get $di) (local.get $note)) - )) - )) - (local.set $di (i32.add (local.get $di) (i32.const 4096))) - (local.set $si (i32.add (local.get $si) (i32.const 24))) - (br_if $track_loop (local.tee $tracksRemaining (i32.sub (local.get $tracksRemaining) (i32.const 1)))) - end -) - -;;------------------------------------------------------------------------------- -;; su_run_vm function: runs the entire virtual machine once, creating 1 sample -;;------------------------------------------------------------------------------- -(func $su_run_vm (local $opcodeWithStereo i32) (local $opcode i32) (local $paramNum i32) (local $paramX4 i32) (local $WRKplusparam i32) - loop $vm_loop - (local.set $opcodeWithStereo (i32.load8_u (global.get $COM))) - (global.set $COM (i32.add (global.get $COM) (i32.const 1))) ;; move to next instruction - (global.set $WRK (i32.add (global.get $WRK) (i32.const 64))) ;; move WRK to next unit - (if (local.tee $opcode (i32.shr_u (local.get $opcodeWithStereo) (i32.const 1)))(then ;; if $opcode = $opcodeStereo >> 1; $opcode != 0 { - (local.set $paramNum (i32.const 0)) - (local.set $paramX4 (i32.const 0)) - loop $transform_values_loop - (if (i32.lt_u (local.get $paramNum) (i32.load8_u offset=918 (local.get $opcode)))(then ;;(i32.ge (local.get $paramNum) (i32.load8_u (local.get $opcode))) /*TODO: offset to transformvalues - (local.set $WRKplusparam (i32.add (global.get $WRK) (local.get $paramX4))) - (f32.store offset=1280 - (local.get $paramX4) - (f32.add - (f32.mul - (f32.convert_i32_u (call $scanValueByte)) - (f32.const 0.0078125) ;; scale from 0-128 to 0.0 - 1.0 - ) - (f32.load offset=32 (local.get $WRKplusparam)) ;; add modulation - ) - ) - (f32.store offset=32 (local.get $WRKplusparam) (f32.const 0.0)) ;; clear modulations - (local.set $paramNum (i32.add (local.get $paramNum) (i32.const 1))) ;; $paramNum++ - (local.set $paramX4 (i32.add (local.get $paramX4) (i32.const 4))) - br $transform_values_loop ;; continue looping - )) - ;; paramNum was >= the number of parameters to transform, exiting loop - end - (call_indirect (type $opcode_func_signature) (i32.and (local.get $opcodeWithStereo) (i32.const 1)) (local.get $opcode)) - )(else ;; advance to next voice - (global.set $voice (i32.add (global.get $voice) (i32.const 4096))) ;; advance to next voice - (global.set $WRK (global.get $voice)) ;; set WRK point to beginning of voice - (global.set $voicesRemain (i32.sub (global.get $voicesRemain) (i32.const 1))) - (br_if 2 (i32.eqz (global.get $voicesRemain))) ;; if no more voices remain, return from function - )) - br $vm_loop - end -) -;;------------------------------------------------------------------------------- -;; ADDP opcode: add the two top most signals on the stack and pop -;;------------------------------------------------------------------------------- -;; Mono: a b -> a+b -;; Stereo: a b c d -> a+c b+d -;;------------------------------------------------------------------------------- -(func $su_op_addp (param $stereo i32) - (if (local.get $stereo) (then - call $pop ;; a - call $pop ;; b a - call $swap ;; a b - call $pop ;; c a b - f32.add ;; c+a b - call $swap ;; b c+a - call $pop ;; d b c+a - f32.add ;; d+b c+a - call $push ;; c+a - call $push - )(else - (call $push (f32.add (call $pop) (call $pop))) - )) -) - -;;------------------------------------------------------------------------------- -;; MULP opcode: multiply the two top most signals on the stack and pop -;;------------------------------------------------------------------------------- -;; Mono: a b -> a*b -;; Stereo: a b c d -> a*c b*d -;;------------------------------------------------------------------------------- -(func $su_op_mulp (param $stereo i32) - (if (local.get $stereo) (then - call $pop ;; a - call $pop ;; b a - call $swap ;; a b - call $pop ;; c a b - f32.mul ;; c*a b - call $swap ;; b c*a - call $pop ;; d b c*a - f32.mul ;; d*b c*a - call $push ;; c*a - call $push - )(else - (call $push (f32.mul (call $pop) (call $pop))) - )) -) - -;;------------------------------------------------------------------------------- -;; PUSH opcode: push the topmost signal on the stack -;;------------------------------------------------------------------------------- -;; Mono: a -> a a -;; Stereo: a b -> a b a b -;;------------------------------------------------------------------------------- -(func $su_op_push (param $stereo i32) - (call $push (call $peek)) -) - -;;------------------------------------------------------------------------------- -;; XCH opcode: exchange the signals on the stack -;;------------------------------------------------------------------------------- -;; Mono: a b -> b a -;; stereo: a b c d -> c d a b -;;------------------------------------------------------------------------------- -(func $su_op_xch (param $stereo i32) - call $pop - call $pop - call $swap - call $push - call $push -) - - -;;------------------------------------------------------------------------------- -;; DISTORT opcode: apply distortion on the signal -;;------------------------------------------------------------------------------- -;; Mono: x -> x*a/(1-a+(2*a-1)*abs(x)) where x is clamped first -;; Stereo: l r -> l*a/(1-a+(2*a-1)*abs(l)) r*a/(1-a+(2*a-1)*abs(r)) -;;------------------------------------------------------------------------------- -(func $su_op_distort (param $stereo i32) - (call $pop) - (call $waveshaper (call $input (i32.const 0))) - (call $push) -) - -;;------------------------------------------------------------------------------- -;; FILTER opcode: perform low/high/band-pass/notch etc. filtering on the signal -;;------------------------------------------------------------------------------- -;; Mono: x -> filtered(x) -;; Stereo: l r -> filtered(l) filtered(r) -;;------------------------------------------------------------------------------- -(func $su_op_filter (param $stereo i32) (local $flags i32) (local $freq f32) (local $high f32) (local $low f32) (local $band f32) (local $retval f32) - (call $stereoHelper (local.get $stereo) (i32.const 4)) - (if (local.get $stereo)(then - ;; This is hacky: rewind the $VAL one byte backwards as the right channel already - ;; scanned it once. Find a way to avoid rewind - (global.set $VAL (i32.sub (global.get $VAL) (i32.const 1))) - )) - (local.set $flags (call $scanValueByte)) - (local.set $freq (f32.mul - (call $input (i32.const 0)) - (call $input (i32.const 0)) - )) - (local.set $low ;; l' = f2*b + l - (f32.add ;; f2*b+l - (f32.mul ;; f2*b - (local.tee $band (f32.load offset=4 (global.get $WRK))) ;; b - (local.get $freq) ;; f2 - ) - (f32.load (global.get $WRK)) ;; l - ) - ) - (local.set $high ;; h' = x - l' - r*b - (f32.sub ;; x - l' - r*b - (f32.sub ;; x - l' - (call $pop) ;; x (signal) - (local.get $low) ;; l' - ) - (f32.mul ;; r*b - (call $input (i32.const 1)) ;; r - (local.get $band) ;; b - ) - ) - ) - (local.set $band ;; b' = f2 * h' + b - (f32.add ;; f2 * h' + b - (f32.mul ;; f2 * h' - (local.get $freq) ;; f2 - (local.get $high) ;; h' - ) - (local.get $band) ;; b - ) - ) - (local.set $retval (f32.const 0)) - (if (i32.and (local.get $flags) (i32.const 0x40)) (then - (local.set $retval (f32.add (local.get $retval) (local.get $low))) - )) - (if (i32.and (local.get $flags) (i32.const 0x10)) (then - (local.set $retval (f32.add (local.get $retval) (local.get $high))) - )) - (f32.store (global.get $WRK) (local.get $low)) - (f32.store offset=4 (global.get $WRK) (local.get $band)) - (call $push (local.get $retval)) -) -;;------------------------------------------------------------------------------- -;; PAN opcode: pan the signal -;;------------------------------------------------------------------------------- -;; Mono: s -> s*(1-p) s*p -;; Stereo: l r -> l*(1-p) r*p -;; -;; where p is the panning in [0,1] range -;;------------------------------------------------------------------------------- -(func $su_op_pan (param $stereo i32) - (call $peek) ;; F: s P: s - (f32.mul - (call $input (i32.const 0)) - (call $pop) - ) ;; F: P: p*s s - (call $push) ;; F: p*s P: s - (call $peek) ;; F: p*s P: p*s s - f32.sub ;; F: p*s P: s-p*s - (call $push) ;; F: (1-p)*s p*s -) - -;;------------------------------------------------------------------------------- -;; DELAY opcode: adds delay effect to the signal -;;------------------------------------------------------------------------------- -;; Mono: perform delay on ST0, using delaycount delaylines starting -;; at delayindex from the delaytable -;; Stereo: perform delay on ST1, using delaycount delaylines starting -;; at delayindex + delaycount from the delaytable (so the right delays -;; can be different) -;;------------------------------------------------------------------------------- -(func $su_op_delay (param $stereo i32) (local $delayIndex i32) (local $delayCount i32) (local $output f32) (local $s f32) (local $filtstate f32) (local $delayCountStash i32) - (local.set $delayIndex (i32.mul (call $scanValueByte) (i32.const 2))) - (local.set $delayCountStash (call $scanValueByte)) - (if (local.get $stereo)(then - (call $su_op_xch (i32.const 0)) - )) - loop $stereoLoop - (local.set $delayCount (local.get $delayCountStash)) - (local.set $output (f32.mul - (call $input (i32.const 1)) - (call $peek) - )) - loop $delayLoop - (local.tee $s (f32.load offset=12 - (i32.add ;; delayWRK + ((globalTick-delaytimes[delayIndex])&65535)*4 - (i32.mul ;; ((globalTick-delaytimes[delayIndex])&65535)*4 - (i32.and ;; (globalTick-delaytimes[delayIndex])&65535 - (i32.sub ;; globalTick-delaytimes[delayIndex] - (global.get $globaltick) - (i32.load16_u - offset=899 - (local.get $delayIndex) - ) - ) - (i32.const 65535) - ) - (i32.const 4) - ) - (global.get $delayWRK) - ) - )) - (local.set $output (f32.add (local.get $output))) - (f32.store - (global.get $delayWRK) - (local.tee $filtstate - (f32.add - (f32.mul - (f32.sub - (f32.load (global.get $delayWRK)) - (local.get $s) - ) - (call $input (i32.const 3)) - ) - (local.get $s) - ) - ) - ) - (f32.store offset=12 - (i32.add ;; delayWRK + globalTick*4 - (i32.mul ;; globalTick)&65535)*4 - (i32.and ;; globalTick&65535 - (global.get $globaltick) - (i32.const 65535) - ) - (i32.const 4) - ) - (global.get $delayWRK) - ) - (f32.add - (f32.mul - (call $input (i32.const 2)) - (local.get $filtstate) - ) - (f32.mul - (f32.mul - (call $input (i32.const 0)) - (call $input (i32.const 0)) - ) - (call $peek) - ) - ) - ) - (global.set $delayWRK (i32.add (global.get $delayWRK) (i32.const 262156))) - (local.set $delayIndex (i32.add (local.get $delayIndex) (i32.const 2))) - (br_if $delayLoop (i32.gt_s (local.tee $delayCount (i32.sub (local.get $delayCount) (i32.const 2))) (i32.const 0))) - end - (f32.store offset=4 - (global.get $delayWRK) - (local.tee $filtstate - (f32.add - (local.get $output) - (f32.sub - (f32.mul - (f32.const 0.99609375) - (f32.load offset=4 (global.get $delayWRK)) - ) - (f32.load offset=8 (global.get $delayWRK)) - ) - ) - ) - ) - (f32.store offset=8 - (global.get $delayWRK) - (local.get $output) - ) - (drop (call $pop)) - (call $push (local.get $filtstate)) - (call $su_op_xch (i32.const 0)) - (br_if $stereoLoop (i32.eqz (local.tee $stereo (i32.eqz (local.get $stereo))))) - end - (call $su_op_xch (i32.const 0)) -) - -;;------------------------------------------------------------------------------- -;; COMPRES opcode: push compressor gain to stack -;;------------------------------------------------------------------------------- -;; Mono: push g on stack, where g is a suitable gain for the signal -;; you can either MULP to compress the signal or SEND it to a GAIN -;; somewhere else for compressor side-chaining. -;; Stereo: push g g on stack, where g is calculated using l^2 + r^2 -;;------------------------------------------------------------------------------- -(func $su_op_compressor (param $stereo i32) (local $x2 f32) (local $level f32) (local $t2 f32) - (local.tee $x2 (f32.mul - (call $peek) - (call $peek) - )) - (local.tee $level (f32.load (global.get $WRK))) - f32.lt - call $nonLinearMap ;; $nonlinearMap(x^2 $threshold, note the local.tees - (call $push - (call $pow ;; (t^2/l)^(r/2) - (f32.div ;; t^2/l - (local.get $t2) - (local.get $level) - ) - (f32.mul ;; r/2 - (call $input (i32.const 4)) ;; r - (f32.const 0.5) ;; 0.5 - ) - ) - ) - )(else - (call $push (f32.const 1)) ;; unity gain if we are below threshold - )) - (call $push (f32.div ;; apply post-gain ("make up gain") - (call $pop) - (call $input (i32.const 2)) - )) - (f32.store (global.get $WRK) (local.get $level)) ;; save the updated levels -) - - - -;;------------------------------------------------------------------------------- -;; ENVELOPE opcode: pushes an ADSR envelope value on stack [0,1] -;;------------------------------------------------------------------------------- -;; Mono: push the envelope value on stack -;; Stereo: push the envelope valeu on stack twice -;;------------------------------------------------------------------------------- -(func $su_op_envelope (param $stereo i32) (local $state i32) (local $level f32) (local $delta f32) - (if (i32.load offset=4 (global.get $voice)) (then ;; if voice.release > 0 - (i32.store (global.get $WRK) (i32.const 3)) ;; set envelope state to release - )) - (local.set $state (i32.load (global.get $WRK))) - (local.set $level (f32.load offset=4 (global.get $WRK))) - (local.set $delta (call $nonLinearMap (local.get $state))) - (if (local.get $state) (then - (if (i32.eq (local.get $state) (i32.const 1))(then ;; state is 1 aka decay - (local.set $level (f32.sub (local.get $level) (local.get $delta))) - (if (f32.le (local.get $level) (call $input (i32.const 2)))(then - (local.set $level (call $input (i32.const 2))) - (local.set $state (i32.const 2)) - )) - )) - (if (i32.eq (local.get $state) (i32.const 3))(then ;; state is 3 aka release - (local.set $level (f32.sub (local.get $level) (local.get $delta))) - (if (f32.le (local.get $level) (f32.const 0)) (then - (local.set $level (f32.const 0)) - )) - )) - )(else ;; the state is 0 aka attack - (local.set $level (f32.add (local.get $level) (local.get $delta))) - (if (f32.ge (local.get $level) (f32.const 1))(then - (local.set $level (f32.const 1)) - (local.set $state (i32.const 1)) - )) - )) - (i32.store (global.get $WRK) (local.get $state)) - (f32.store offset=4 (global.get $WRK) (local.get $level)) - (call $push (f32.mul (local.get $level) (call $input (i32.const 4)))) - (if (local.get $stereo)(then - (call $push (call $peek)) - )) -) - -;;------------------------------------------------------------------------------- -;; NOISE opcode: creates noise -;;------------------------------------------------------------------------------- -;; Mono: push a random value [-1,1] value on stack -;; Stereo: push two (different) random values on stack -;;------------------------------------------------------------------------------- -(func $su_op_noise (param $stereo i32) - (if (local.get $stereo) (then - (call $su_op_noise (i32.const 0)) - )) - (global.set $randseed (i32.mul (global.get $randseed) (i32.const 16007))) - (f32.mul - (call $waveshaper - ;; Note: in x86 code, the constant looks like a positive integer, but has actually the MSB set i.e. is considered negative by the FPU. This tripped me big time. - (f32.div (f32.convert_i32_s (global.get $randseed)) (f32.const -2147483648)) - (call $input (i32.const 0)) - ) - (call $input (i32.const 1)) - ) - (call $push) -) - -;;------------------------------------------------------------------------------- -;; OSCILLAT opcode: oscillator, the heart of the synth -;;------------------------------------------------------------------------------- -;; Mono: push oscillator value on stack -;; Stereo: push l r on stack, where l has opposite detune compared to r -;;------------------------------------------------------------------------------- -(func $su_op_oscillator (param $stereo i32) (local $flags i32) (local $detune f32) (local $phase f32) (local $color f32) (local $amplitude f32) - (local $unison i32) (local $WRK_stash i32) (local $detune_stash f32) - (local.set $flags (call $scanValueByte)) - (local.set $detune (call $inputSigned (i32.const 1))) - loop $stereoLoop - (local.set $unison (i32.add (i32.and (local.get $flags) (i32.const 3)) (i32.const 1))) - (local.set $WRK_stash (global.get $WRK)) - (local.set $detune_stash (local.get $detune)) - (call $push (f32.const 0)) - loop $unisonLoop - (f32.store ;; update phase - (global.get $WRK) - (local.tee $phase - (f32.sub - (local.tee $phase - ;; Transpose calculation starts - (f32.div - (call $inputSigned (i32.const 0)) - (f32.const 0.015625) - ) ;; scale back to 0 - 128 - (f32.add (local.get $detune)) ;; add detune. detune is -1 to 1 so can detune a full note up or down at max - (f32.add (select - (f32.const 0) - (f32.convert_i32_u (i32.load (global.get $voice))) - (i32.and (local.get $flags) (i32.const 0x8)) - )) ;; if lfo is not enabled, add the note number to it - (f32.mul (f32.const 0.0833333)) ;; /12, in full octaves - (call $pow2) - (f32.mul (select - (f32.const 0.000038) ;; pretty random scaling constant to get LFOs into reasonable range. Historical reasons, goes all the way back to 4klang - (f32.const 0.000092696138) ;; scaling constant to get middle-C to where it should be - (i32.and (local.get $flags) (i32.const 0x8)) - )) - (f32.add (f32.load (global.get $WRK))) ;; add the current phase of the oscillator - ) - (f32.floor (local.get $phase)) - ) - ) - ) - (f32.add (local.get $phase) (call $input (i32.const 2))) - (local.set $phase (f32.sub (local.tee $phase) (f32.floor (local.get $phase)))) ;; phase = phase mod 1.0 - (local.set $color (call $input (i32.const 3))) - (if (i32.and (local.get $flags) (i32.const 0x40)) (then - (local.set $amplitude (call $oscillator_sine (local.get $phase) (local.get $color))) - )) - (if (i32.and (local.get $flags) (i32.const 0x20)) (then - (local.set $amplitude (call $oscillator_trisaw (local.get $phase) (local.get $color))) - )) - (call $waveshaper (local.get $amplitude) (call $input (i32.const 4))) - (call $push (f32.mul - (call $input (i32.const 5)) - )) - (call $push (f32.add (call $pop) (call $pop))) - (if (local.tee $unison (i32.sub (local.get $unison) (i32.const 1)))(then - (f32.store offset=1288 (i32.const 0) - (f32.add - (call $input (i32.const 2)) - (f32.const 0.08333333) ;; 1/12, add small phase shift so all oscillators don't start in phase - ) - ) - (global.set $WRK (i32.add (global.get $WRK) (i32.const 8))) ;; WARNING: this is a bug. WRK should be nonvolatile, but we are changing it. It does not cause immediate problems but modulations will be off. - (local.set $detune (f32.neg (f32.mul - (local.get $detune) ;; each unison oscillator has a detune with flipped sign and halved amount... this creates detunes that concentrate around the fundamental - (f32.const 0.5) - ))) - br $unisonLoop - )) - end - (global.set $WRK (local.get $WRK_stash)) - (local.set $detune (local.get $detune_stash)) - (local.set $detune (f32.neg (local.get $detune))) ;; flip the detune for secon round - (global.set $WRK (i32.add (global.get $WRK) (i32.const 4))) ;; WARNING: this is a bug. WRK should be nonvolatile, but we are changing it. It does not cause immediate problems but modulations will be off. - (br_if $stereoLoop (i32.eqz (local.tee $stereo (i32.eqz (local.get $stereo))))) - end -) -(func $oscillator_sine (param $phase f32) (param $color f32) (result f32) - (select - (f32.const 0) - (call $sin (f32.mul - (f32.div - (local.get $phase) - (local.get $color) - ) - (f32.const 6.28318530718) - )) - (f32.ge (local.get $phase) (local.get $color)) - ) -) - -(func $oscillator_trisaw (param $phase f32) (param $color f32) (result f32) - (if (f32.ge (local.get $phase) (local.get $color)) (then - (local.set $phase (f32.sub (f32.const 1) (local.get $phase))) - (local.set $color (f32.sub (f32.const 1) (local.get $color))) - )) - (f32.div (local.get $phase) (local.get $color)) - (f32.mul (f32.const 2)) - (f32.sub (f32.const 1)) -) - - - - -;;------------------------------------------------------------------------------- -;; OUTAUX opcode: outputs to main and aux1 outputs and pops the signal -;;------------------------------------------------------------------------------- -;; Mono: add outgain*ST0 to main left port and auxgain*ST0 to aux1 left -;; Stereo: also add outgain*ST1 to main right port and auxgain*ST1 to aux1 right -;;------------------------------------------------------------------------------- -(func $su_op_outaux (param $stereo i32) (local $addr i32) - (local.set $addr (i32.const 1440)) - loop $stereoLoop - (f32.store ;; send - (local.get $addr) - (f32.add - (f32.mul - (call $peek) - (call $input (i32.const 0)) - ) - (f32.load (local.get $addr)) - ) - ) - (f32.store offset=8 - (local.get $addr) - (f32.add - (f32.mul - (call $pop) - (call $input (i32.const 1)) - ) - (f32.load offset=8 (local.get $addr)) - ) - ) - (local.set $addr (i32.add (local.get $addr) (i32.const 4))) - (br_if $stereoLoop (i32.eqz (local.tee $stereo (i32.eqz (local.get $stereo))))) - end -) - -;;------------------------------------------------------------------------------- -;; SEND opcode: adds the signal to a port -;;------------------------------------------------------------------------------- -;; Mono: adds signal to a memory address, defined by a word in VAL stream -;; Stereo: also add right signal to the following address -;;------------------------------------------------------------------------------- -(func $su_op_send (param $stereo i32) (local $address i32) (local $scaledAddress i32) - (local.set $address (i32.add (call $scanValueByte) (i32.shl (call $scanValueByte) (i32.const 8)))) - (if (i32.eqz (i32.and (local.get $address) (i32.const 8)))(then - (call $push (call $peek)) - )) - (local.set $scaledAddress (i32.add (i32.mul (i32.and (local.get $address) (i32.const 0x7FF7)) (i32.const 4)) - (select - (i32.const 1408) - (global.get $voice) - (i32.and (local.get $address)(i32.const 0x8000)) - ) - )) - (f32.store offset=32 - (local.get $scaledAddress) - (f32.add - (f32.load offset=32 (local.get $scaledAddress)) - (f32.mul - (call $inputSigned (i32.const 0)) - (call $pop) - ) - ) - ) -) - -;;------------------------------------------------------------------------------- -;; OUT opcode: outputs and pops the signal -;;------------------------------------------------------------------------------- -;; Stereo: add ST0 to left out and ST1 to right out, then pop -;;------------------------------------------------------------------------------- -(func $su_op_out (param $stereo i32) (local $ptr i32) - (local.set $ptr (i32.const 1440)) ;; synth.left - (f32.store (local.get $ptr) - (f32.add - (f32.mul - (call $pop) - (call $input (i32.const 0)) - ) - (f32.load (local.get $ptr)) - ) - ) - (local.set $ptr (i32.const 1444)) ;; synth.right, note that ATM does not seem to support mono ocpode at all - (f32.store (local.get $ptr) - (f32.add - (f32.mul - (call $pop) - (call $input (i32.const 0)) - ) - (f32.load (local.get $ptr)) - ) - ) -) - - - -;;------------------------------------------------------------------------------- -;; $input returns the float value of a transformed to 0.0 - 1.0f range. -;; The transformed values start at 512 (TODO: change magic constants somehow) -;;------------------------------------------------------------------------------- -(func $input (param $inputNumber i32) (result f32) - (f32.load offset=1280 (i32.mul (local.get $inputNumber) (i32.const 4))) -) - -;;------------------------------------------------------------------------------- -;; $inputSigned returns the float value of a transformed to -1.0 - 1.0f range. -;;------------------------------------------------------------------------------- -(func $inputSigned (param $inputNumber i32) (result f32) - (f32.sub (f32.mul (call $input (local.get $inputNumber)) (f32.const 2)) (f32.const 1)) -) - -;;------------------------------------------------------------------------------- -;; $nonLinearMap: x -> 2^(-24*input[x]) -;;------------------------------------------------------------------------------- -(func $nonLinearMap (param $value i32) (result f32) - (call $pow2 - (f32.mul - (f32.const -24) - (call $input (local.get $value)) - ) - ) -) - -;;------------------------------------------------------------------------------- -;; $pow2: x -> 2^x -;;------------------------------------------------------------------------------- -(func $pow2 (param $value f32) (result f32) - (call $pow (f32.const 2) (local.get $value)) -) - -;;------------------------------------------------------------------------------- -;; Waveshaper(x,a): "distorts" signal x by amount a -;; Returns x*a/(1-a+(2*a-1)*abs(x)) -;;------------------------------------------------------------------------------- -(func $waveshaper (param $signal f32) (param $amount f32) (result f32) - (local.set $signal (call $clip (local.get $signal))) - (f32.mul - (local.get $signal) - (f32.div - (local.get $amount) - (f32.add - (f32.const 1) - (f32.sub - (f32.mul - (f32.sub - (f32.add (local.get $amount) (local.get $amount)) - (f32.const 1) - ) - (f32.abs (local.get $signal)) - ) - (local.get $amount) - ) - ) - ) - ) -) - -;;------------------------------------------------------------------------------- -;; Clip(a : f32) returns min(max(a,-1),1) -;;------------------------------------------------------------------------------- -(func $clip (param $value f32) (result f32) - (f32.min (f32.max (local.get $value) (f32.const -1.0)) (f32.const 1.0)) -) - -(func $stereoHelper (param $stereo i32) (param $tableIndex i32) - (if (local.get $stereo)(then - (call $pop) - (global.set $WRK (i32.add (global.get $WRK) (i32.const 16))) - (call_indirect (type $opcode_func_signature) (i32.const 0) (local.get $tableIndex)) - (global.set $WRK (i32.sub (global.get $WRK) (i32.const 16))) - (call $push) - )) -) - -;;------------------------------------------------------------------------------- -;; The opcode table jump table. This is constructed to only include the opcodes -;; that are used so that the jump table is as small as possible. -;;------------------------------------------------------------------------------- -(table 15 funcref) -(elem (i32.const 1) ;; start the indices at 1, as 0 is reserved for advance - $su_op_oscillator - $su_op_addp - $su_op_noise - $su_op_filter - $su_op_envelope - $su_op_mulp - $su_op_delay - $su_op_outaux - $su_op_distort - $su_op_pan - $su_op_out - $su_op_send - $su_op_push - $su_op_compressor -) - - - -;; All data is collected into a byte buffer and emitted at once -(data (i32.const 0) "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\4a\01\48\01\00\00\43\01\01\00\45\01\01\01\3e\01\1a\01\00\26\01\00\26\01\1a\01\00\00\00\00\00\00\18\01\00\24\01\00\24\01\18\01\00\00\00\00\00\00\1f\01\00\2b\01\00\2b\01\1f\01\00\00\00\00\00\00\1d\01\00\29\01\00\29\01\1d\01\00\00\00\00\00\00\1a\01\00\26\01\00\26\01\1a\01\01\01\01\01\01\00\18\01\00\24\01\00\24\01\18\01\01\01\01\01\01\00\1f\01\00\2b\01\00\2b\01\1f\01\01\01\01\01\01\00\1d\01\00\29\01\00\29\01\1d\01\01\01\01\01\01\00\4a\01\48\01\00\00\43\01\01\00\45\01\01\00\3e\01\41\01\00\45\01\00\46\01\01\01\01\01\01\01\01\00\41\01\00\41\01\01\3c\01\01\01\01\01\01\01\01\00\3e\01\00\41\01\00\41\01\01\01\01\01\01\01\01\00\45\01\00\3c\01\01\40\01\01\01\01\01\01\01\01\00\45\01\00\3e\01\00\3e\01\01\01\01\01\01\01\01\00\3c\01\00\45\01\01\43\01\01\01\01\01\01\01\01\00\40\00\00\00\40\00\00\00\40\00\00\00\40\00\00\00\00\00\00\00\4f\01\00\00\00\00\00\00\4f\00\00\00\00\00\00\00\4f\01\00\00\00\00\00\32\4f\00\00\1e\00\00\00\00\42\01\00\00\00\00\00\00\4f\00\00\00\0a\0a\0a\0a\0a\0a\0a\0a\01\0a\0a\0a\01\0a\0a\0a\0a\0a\0a\0a\0a\0a\0a\0a\02\03\04\05\02\03\04\05\06\07\08\09\06\07\08\09\02\03\04\05\02\03\04\05\00\00\00\00\00\00\00\00\0b\0c\0b\0c\0b\0c\0b\0c\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\0d\0e\0d\0e\0d\0e\0d\0e\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\0f\10\0f\10\0f\10\0f\10\00\00\00\00\00\00\00\00\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\00\00\00\00\12\12\12\13\12\12\12\14\12\12\12\14\12\12\12\12\12\12\12\12\03\03\05\03\05\07\09\05\0b\0d\09\0f\11\00\0a\12\02\0c\08\08\14\17\0a\12\18\00\03\03\05\03\05\07\09\05\0b\0d\09\0f\11\00\03\03\05\03\05\07\09\05\0b\0d\09\0f\11\00\03\03\05\03\05\07\09\05\0b\0d\09\0f\11\00\0a\12\02\0c\08\1a\08\0e\04\14\17\0a\12\18\0a\12\18\00\0a\02\0c\0a\12\06\0c\08\04\12\0e\1c\0c\14\11\0a\12\18\00\40\30\00\02\3f\10\23\40\4e\00\7e\40\10\23\40\3b\00\02\40\10\23\40\06\80\80\10\32\40\40\40\60\20\80\10\40\40\40\40\00\01\00\80\30\3f\00\40\80\70\40\40\40\00\40\80\20\10\80\10\16\80\40\40\80\00\40\00\00\80\20\4f\68\00\40\30\00\02\3f\10\23\40\4e\00\7e\40\10\23\40\3b\00\02\40\10\23\40\06\80\80\10\32\40\40\40\60\20\80\10\40\40\40\40\00\01\00\80\40\30\00\02\3f\10\23\40\4e\00\7e\40\10\23\40\3b\00\02\40\10\23\40\06\80\80\10\32\40\40\40\60\20\80\10\40\40\40\40\00\01\00\80\40\30\00\02\3f\10\23\40\4e\00\7e\40\10\23\40\3b\00\02\40\10\23\40\06\80\80\10\32\40\40\40\60\20\80\10\40\40\40\40\00\01\00\80\24\45\00\20\80\70\40\40\00\80\40\80\40\0e\80\10\10\80\40\20\00\60\40\02\0f\40\40\00\46\00\46\80\05\65\48\94\30\3a\00\00\80\40\20\4d\94\20\3c\00\00\80\40\40\00\40\40\80\20\20\40\00\42\40\20\40\40\6a\80\10\70\18\80\28\00\02\0f\33\31\40\40\70\44\40\00\00\3c\00\00\80\05\5a\38\98\e3\23\e3\23\5c\04\a4\04\fc\04\4c\05\8e\05\d4\05\14\06\52\06\06\00\02\02\05\00\04\02\01\01\01\01\00\05") - -;;(data (i32.const 8388610) "\52\49\46\46\b2\eb\0c\20\57\41\56\45\66\6d\74\20\12\20\20\20\03\20\02\20\44\ac\20\20\20\62\05\20\08\20\20\20\20\20\66\61\63\74\04\20\20\20\e0\3a\03\20\64\61\74\61\80\eb\0c\20") - -) ;; END MODULE diff --git a/package.json b/package.json deleted file mode 100644 index c4975c8..0000000 --- a/package.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "type": "module", - "scripts": { - "test": "node convert.js && ./sointu-compile -o . -arch=wasm tests/groove.yaml && wat2wasm groove.wat && node testwasm.mjs" - }, - "dependencies": { - "json-to-pretty-yaml": "^1.2.2" - } -} diff --git a/templates/wasm/player.wat b/templates/wasm/player.wat index 7042921..b1614fa 100644 --- a/templates/wasm/player.wat +++ b/templates/wasm/player.wat @@ -822,11 +822,11 @@ (func $render_128_samples (param) (result i32) (local $rendersamplecount i32) (local $should_update_voices i32) +{{- if .Output16Bit }} (local $channel i32) {{- end }} (i32.const 0) (local.set $rendersamplecount) (i32.const 0) - (local.set $should_update_voices) - {{- if .Output16Bit }} (local $channel i32) {{- end }} + (local.set $should_update_voices) (loop $sample_loop (if (i32.eq (global.get $sample) (i32.const 0)) (then diff --git a/test_chords.wat b/test_chords.wat deleted file mode 100644 index bc111e8..0000000 --- a/test_chords.wat +++ /dev/null @@ -1,441 +0,0 @@ -(module - - -;;------------------------------------------------------------------------------ -;; Import the difficult math functions from javascript -;; (seriously now, it's 2020) -;;------------------------------------------------------------------------------ -(func $pow (import "m" "pow") (param f32) (param f32) (result f32)) -(func $log2 (import "m" "log2") (param f32) (result f32)) -(func $sin (import "m" "sin") (param f32) (result f32)) - -;;------------------------------------------------------------------------------ -;; Types. Only useful to define the jump table type, which is -;; (int stereo) void -;;------------------------------------------------------------------------------ -(type $opcode_func_signature (func (param i32))) - -;;------------------------------------------------------------------------------ -;; The one and only memory -;;------------------------------------------------------------------------------ -(memory (export "m") 15) - -;;------------------------------------------------------------------------------ -;; Globals. Putting all with same initialization value should compress most -;;------------------------------------------------------------------------------ -(global $WRK (mut i32) (i32.const 0)) -(global $COM (mut i32) (i32.const 0)) -(global $VAL (mut i32) (i32.const 0)) -(global $COM_instr_start (mut i32) (i32.const 0)) -(global $VAL_instr_start (mut i32) (i32.const 0)) -(global $globaltick (mut i32) (i32.const 0)) -(global $row (mut i32) (i32.const 0)) -(global $pattern (mut i32) (i32.const 0)) -(global $sample (mut i32) (i32.const 0)) -(global $voice (mut i32) (i32.const 0)) -(global $voicesRemain (mut i32) (i32.const 0)) -(global $randseed (mut i32) (i32.const 1)) -(global $sp (mut i32) (i32.const 384)) -(global $outputBufPtr (mut i32) (i32.const 131712)) -;; TODO: only export start and length with certain compiler options; in demo use, they can be hard coded -;; in the intro -(global $outputStart (export "s") i32 (i32.const 131712)) -(global $outputLength (export "l") i32 (i32.const 846720)) -(global $output16bit (export "t") i32 (i32.const 0)) - - -;;------------------------------------------------------------------------------ -;; Functions to emulate FPU stack in software -;;------------------------------------------------------------------------------ -(func $peek (result f32) - (f32.load (global.get $sp)) -) - -(func $peek2 (result f32) - (f32.load offset=4 (global.get $sp)) -) - -(func $pop (result f32) - (call $peek) - (global.set $sp (i32.add (global.get $sp) (i32.const 4))) -) - -(func $push (param $value f32) - (global.set $sp (i32.sub (global.get $sp) (i32.const 4))) - (f32.store (global.get $sp) (local.get $value)) -) - -;;------------------------------------------------------------------------------ -;; Helper functions -;;------------------------------------------------------------------------------ -(func $swap (param f32 f32) (result f32 f32) ;; x,y -> y,x - local.get 1 - local.get 0 -) - -(func $scanValueByte (result i32) ;; scans positions $VAL for a byte, incrementing $VAL afterwards - (i32.load8_u (global.get $VAL)) ;; in other words: returns byte [$VAL++] - (global.set $VAL (i32.add (global.get $VAL) (i32.const 1))) ;; $VAL++ -) - -;;------------------------------------------------------------------------------ -;; "Entry point" for the player -;;------------------------------------------------------------------------------ -(start $render) ;; we run render automagically when the module is instantiated - -(func $render (param) - loop $pattern_loop - (global.set $row (i32.const 0)) - loop $row_loop - (call $su_update_voices) - (global.set $sample (i32.const 0)) - loop $sample_loop - (global.set $COM (i32.const 51)) - (global.set $VAL (i32.const 58)) - (global.set $COM_instr_start (global.get $COM)) - (global.set $VAL_instr_start (global.get $VAL)) - (global.set $WRK (i32.const 576)) - (global.set $voice (i32.const 576)) - (global.set $voicesRemain (i32.const 3)) - (call $su_run_vm) - (i64.store (global.get $outputBufPtr) (i64.load (i32.const 544))) ;; load the sample from left & right channels as one 64bit int and store it in the address pointed by outputBufPtr - (global.set $outputBufPtr (i32.add (global.get $outputBufPtr) (i32.const 8))) ;; advance outputbufptr - (i64.store (i32.const 544) (i64.const 0)) ;; clear the left and right ports - (global.set $sample (i32.add (global.get $sample) (i32.const 1))) - (global.set $globaltick (i32.add (global.get $globaltick) (i32.const 1))) - (br_if $sample_loop (i32.lt_s (global.get $sample) (i32.const 6615))) - end - (global.set $row (i32.add (global.get $row) (i32.const 1))) - (br_if $row_loop (i32.lt_s (global.get $row) (i32.const 16))) - end - (global.set $pattern (i32.add (global.get $pattern) (i32.const 1))) - (br_if $pattern_loop (i32.lt_s (global.get $pattern) (i32.const 1))) - end -) -;; the simple implementation of update_voices: each track has exactly one voice -(func $su_update_voices (local $si i32) (local $di i32) (local $tracksRemaining i32) (local $note i32) - (local.set $tracksRemaining (i32.const 3)) - (local.set $si (global.get $pattern)) - (local.set $di (i32.const 576)) - loop $track_loop - (i32.load8_u offset=48 (local.get $si)) - (i32.mul (i32.const 16)) - (i32.add (global.get $row)) - (i32.load8_u offset=0) - (local.tee $note) - (if (i32.ne (i32.const 1))(then - (i32.store offset=4 (local.get $di) (i32.const 1)) ;; release the note - (if (i32.gt_u (local.get $note) (i32.const 1))(then - (memory.fill (local.get $di) (i32.const 0) (i32.const 4096)) - (i32.store (local.get $di) (local.get $note)) - )) - )) - (local.set $di (i32.add (local.get $di) (i32.const 4096))) - (local.set $si (i32.add (local.get $si) (i32.const 1))) - (br_if $track_loop (local.tee $tracksRemaining (i32.sub (local.get $tracksRemaining) (i32.const 1)))) - end -) - -;;------------------------------------------------------------------------------- -;; su_run_vm function: runs the entire virtual machine once, creating 1 sample -;;------------------------------------------------------------------------------- -(func $su_run_vm (local $opcodeWithStereo i32) (local $opcode i32) (local $paramNum i32) (local $paramX4 i32) (local $WRKplusparam i32) - loop $vm_loop - (local.set $opcodeWithStereo (i32.load8_u (global.get $COM))) - (global.set $COM (i32.add (global.get $COM) (i32.const 1))) ;; move to next instruction - (global.set $WRK (i32.add (global.get $WRK) (i32.const 64))) ;; move WRK to next unit - (if (local.tee $opcode (i32.shr_u (local.get $opcodeWithStereo) (i32.const 1)))(then ;; if $opcode = $opcodeStereo >> 1; $opcode != 0 { - (local.set $paramNum (i32.const 0)) - (local.set $paramX4 (i32.const 0)) - loop $transform_values_loop - (if (i32.lt_u (local.get $paramNum) (i32.load8_u offset=82 (local.get $opcode)))(then ;;(i32.ge (local.get $paramNum) (i32.load8_u (local.get $opcode))) /*TODO: offset to transformvalues - (local.set $WRKplusparam (i32.add (global.get $WRK) (local.get $paramX4))) - (f32.store offset=384 - (local.get $paramX4) - (f32.add - (f32.mul - (f32.convert_i32_u (call $scanValueByte)) - (f32.const 0.0078125) ;; scale from 0-128 to 0.0 - 1.0 - ) - (f32.load offset=32 (local.get $WRKplusparam)) ;; add modulation - ) - ) - (f32.store offset=32 (local.get $WRKplusparam) (f32.const 0.0)) ;; clear modulations - (local.set $paramNum (i32.add (local.get $paramNum) (i32.const 1))) ;; $paramNum++ - (local.set $paramX4 (i32.add (local.get $paramX4) (i32.const 4))) - br $transform_values_loop ;; continue looping - )) - ;; paramNum was >= the number of parameters to transform, exiting loop - end - (call_indirect (type $opcode_func_signature) (i32.and (local.get $opcodeWithStereo) (i32.const 1)) (local.get $opcode)) - )(else ;; advance to next voice - (global.set $voice (i32.add (global.get $voice) (i32.const 4096))) ;; advance to next voice - (global.set $WRK (global.get $voice)) ;; set WRK point to beginning of voice - (global.set $voicesRemain (i32.sub (global.get $voicesRemain) (i32.const 1))) - (if (i32.and (i32.shr_u (i32.const 6) (global.get $voicesRemain)) (i32.const 1))(then - (global.set $VAL (global.get $VAL_instr_start)) - (global.set $COM (global.get $COM_instr_start)) - )) - (global.set $VAL_instr_start (global.get $VAL)) - (global.set $COM_instr_start (global.get $COM)) - (br_if 2 (i32.eqz (global.get $voicesRemain))) ;; if no more voices remain, return from function - )) - br $vm_loop - end -) -;;------------------------------------------------------------------------------- -;; MULP opcode: multiply the two top most signals on the stack and pop -;;------------------------------------------------------------------------------- -;; Mono: a b -> a*b -;; Stereo: a b c d -> a*c b*d -;;------------------------------------------------------------------------------- -(func $su_op_mulp (param $stereo i32) - call $pop ;; a - call $pop ;; b a - call $swap ;; a b - call $pop ;; c a b - f32.mul ;; c*a b - call $swap ;; b c*a - call $pop ;; d b c*a - f32.mul ;; d*b c*a - call $push ;; c*a - call $push -) - - - - - -;;------------------------------------------------------------------------------- -;; ENVELOPE opcode: pushes an ADSR envelope value on stack [0,1] -;;------------------------------------------------------------------------------- -;; Mono: push the envelope value on stack -;; Stereo: push the envelope valeu on stack twice -;;------------------------------------------------------------------------------- -(func $su_op_envelope (param $stereo i32) (local $state i32) (local $level f32) (local $delta f32) - (if (i32.load offset=4 (global.get $voice)) (then ;; if voice.release > 0 - (i32.store (global.get $WRK) (i32.const 3)) ;; set envelope state to release - )) - (local.set $state (i32.load (global.get $WRK))) - (local.set $level (f32.load offset=4 (global.get $WRK))) - (local.set $delta (call $nonLinearMap (local.get $state))) - (if (local.get $state) (then - (if (i32.eq (local.get $state) (i32.const 1))(then ;; state is 1 aka decay - (local.set $level (f32.sub (local.get $level) (local.get $delta))) - (if (f32.le (local.get $level) (call $input (i32.const 2)))(then - (local.set $level (call $input (i32.const 2))) - (local.set $state (i32.const 2)) - )) - )) - (if (i32.eq (local.get $state) (i32.const 3))(then ;; state is 3 aka release - (local.set $level (f32.sub (local.get $level) (local.get $delta))) - (if (f32.le (local.get $level) (f32.const 0)) (then - (local.set $level (f32.const 0)) - )) - )) - )(else ;; the state is 0 aka attack - (local.set $level (f32.add (local.get $level) (local.get $delta))) - (if (f32.ge (local.get $level) (f32.const 1))(then - (local.set $level (f32.const 1)) - (local.set $state (i32.const 1)) - )) - )) - (i32.store (global.get $WRK) (local.get $state)) - (f32.store offset=4 (global.get $WRK) (local.get $level)) - (call $push (f32.mul (local.get $level) (call $input (i32.const 4)))) -) - -;;------------------------------------------------------------------------------- -;; OSCILLAT opcode: oscillator, the heart of the synth -;;------------------------------------------------------------------------------- -;; Mono: push oscillator value on stack -;; Stereo: push l r on stack, where l has opposite detune compared to r -;;------------------------------------------------------------------------------- -(func $su_op_oscillator (param $stereo i32) (local $flags i32) (local $detune f32) (local $phase f32) (local $color f32) (local $amplitude f32) - (local.set $flags (call $scanValueByte)) - (local.set $detune (call $inputSigned (i32.const 1))) - (f32.store ;; update phase - (global.get $WRK) - (local.tee $phase - (f32.sub - (local.tee $phase - ;; Transpose calculation starts - (f32.div - (call $inputSigned (i32.const 0)) - (f32.const 0.015625) - ) ;; scale back to 0 - 128 - (f32.add (local.get $detune)) ;; add detune. detune is -1 to 1 so can detune a full note up or down at max - (f32.add (select - (f32.const 0) - (f32.convert_i32_u (i32.load (global.get $voice))) - (i32.and (local.get $flags) (i32.const 0x8)) - )) ;; if lfo is not enabled, add the note number to it - (f32.mul (f32.const 0.0833333)) ;; /12, in full octaves - (call $pow2) - (f32.mul (select - (f32.const 0.000038) ;; pretty random scaling constant to get LFOs into reasonable range. Historical reasons, goes all the way back to 4klang - (f32.const 0.000092696138) ;; scaling constant to get middle-C to where it should be - (i32.and (local.get $flags) (i32.const 0x8)) - )) - (f32.add (f32.load (global.get $WRK))) ;; add the current phase of the oscillator - ) - (f32.floor (local.get $phase)) - ) - ) - ) - (f32.add (local.get $phase) (call $input (i32.const 2))) - (local.set $phase (f32.sub (local.tee $phase) (f32.floor (local.get $phase)))) ;; phase = phase mod 1.0 - (local.set $color (call $input (i32.const 3))) - (if (i32.and (local.get $flags) (i32.const 0x40)) (then - (local.set $amplitude (call $oscillator_sine (local.get $phase) (local.get $color))) - )) - (call $waveshaper (local.get $amplitude) (call $input (i32.const 4))) - (call $push (f32.mul - (call $input (i32.const 5)) - )) -) -(func $oscillator_sine (param $phase f32) (param $color f32) (result f32) - (select - (f32.const 0) - (call $sin (f32.mul - (f32.div - (local.get $phase) - (local.get $color) - ) - (f32.const 6.28318530718) - )) - (f32.ge (local.get $phase) (local.get $color)) - ) -) - - - - -;;------------------------------------------------------------------------------- -;; OUT opcode: outputs and pops the signal -;;------------------------------------------------------------------------------- -;; Stereo: add ST0 to left out and ST1 to right out, then pop -;;------------------------------------------------------------------------------- -(func $su_op_out (param $stereo i32) (local $ptr i32) - (local.set $ptr (i32.const 544)) ;; synth.left - (f32.store (local.get $ptr) - (f32.add - (f32.mul - (call $pop) - (call $input (i32.const 0)) - ) - (f32.load (local.get $ptr)) - ) - ) - (local.set $ptr (i32.const 548)) ;; synth.right, note that ATM does not seem to support mono ocpode at all - (f32.store (local.get $ptr) - (f32.add - (f32.mul - (call $pop) - (call $input (i32.const 0)) - ) - (f32.load (local.get $ptr)) - ) - ) -) - - - -;;------------------------------------------------------------------------------- -;; $input returns the float value of a transformed to 0.0 - 1.0f range. -;; The transformed values start at 512 (TODO: change magic constants somehow) -;;------------------------------------------------------------------------------- -(func $input (param $inputNumber i32) (result f32) - (f32.load offset=384 (i32.mul (local.get $inputNumber) (i32.const 4))) -) - -;;------------------------------------------------------------------------------- -;; $inputSigned returns the float value of a transformed to -1.0 - 1.0f range. -;;------------------------------------------------------------------------------- -(func $inputSigned (param $inputNumber i32) (result f32) - (f32.sub (f32.mul (call $input (local.get $inputNumber)) (f32.const 2)) (f32.const 1)) -) - -;;------------------------------------------------------------------------------- -;; $nonLinearMap: x -> 2^(-24*input[x]) -;;------------------------------------------------------------------------------- -(func $nonLinearMap (param $value i32) (result f32) - (call $pow2 - (f32.mul - (f32.const -24) - (call $input (local.get $value)) - ) - ) -) - -;;------------------------------------------------------------------------------- -;; $pow2: x -> 2^x -;;------------------------------------------------------------------------------- -(func $pow2 (param $value f32) (result f32) - (call $pow (f32.const 2) (local.get $value)) -) - -;;------------------------------------------------------------------------------- -;; Waveshaper(x,a): "distorts" signal x by amount a -;; Returns x*a/(1-a+(2*a-1)*abs(x)) -;;------------------------------------------------------------------------------- -(func $waveshaper (param $signal f32) (param $amount f32) (result f32) - (local.set $signal (call $clip (local.get $signal))) - (f32.mul - (local.get $signal) - (f32.div - (local.get $amount) - (f32.add - (f32.const 1) - (f32.sub - (f32.mul - (f32.sub - (f32.add (local.get $amount) (local.get $amount)) - (f32.const 1) - ) - (f32.abs (local.get $signal)) - ) - (local.get $amount) - ) - ) - ) - ) -) - -;;------------------------------------------------------------------------------- -;; Clip(a : f32) returns min(max(a,-1),1) -;;------------------------------------------------------------------------------- -(func $clip (param $value f32) (result f32) - (f32.min (f32.max (local.get $value) (f32.const -1.0)) (f32.const 1.0)) -) - -(func $stereoHelper (param $stereo i32) (param $tableIndex i32) - (if (local.get $stereo)(then - (call $pop) - (global.set $WRK (i32.add (global.get $WRK) (i32.const 16))) - (call_indirect (type $opcode_func_signature) (i32.const 0) (local.get $tableIndex)) - (global.set $WRK (i32.sub (global.get $WRK) (i32.const 16))) - (call $push) - )) -) - -;;------------------------------------------------------------------------------- -;; The opcode table jump table. This is constructed to only include the opcodes -;; that are used so that the jump table is as small as possible. -;;------------------------------------------------------------------------------- -(table 5 funcref) -(elem (i32.const 1) ;; start the indices at 1, as 0 is reserved for advance - $su_op_envelope - $su_op_oscillator - $su_op_mulp - $su_op_out -) - - - -;; All data is collected into a byte buffer and emitted at once -(data (i32.const 0) "\40\00\00\00\44\00\00\00\42\00\00\00\45\00\00\00\00\44\00\00\47\00\00\00\45\00\00\00\49\00\00\00\00\00\47\00\4b\00\00\00\49\00\00\00\4c\00\00\00\00\01\02\02\02\04\04\07\09\00\40\40\40\40\20\40\40\40\40\20\58\40\00\80\40\80\40\58\40\00\80\40\80\40\80\05\06\00\01") - -;;(data (i32.const 8388610) "\52\49\46\46\b2\eb\0c\20\57\41\56\45\66\6d\74\20\12\20\20\20\03\20\02\20\44\ac\20\20\20\62\05\20\08\20\20\20\20\20\66\61\63\74\04\20\20\20\e0\3a\03\20\64\61\74\61\80\eb\0c\20") - -) ;; END MODULE diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 2b33299..26fad3e 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -31,7 +31,7 @@ function(regression_test testname) SOURCES "${source}" "${wasmtemplates}" DEPENDS sointu-compiler ) - add_test(${wasmtarget} ${NODE} ${CMAKE_CURRENT_SOURCE_DIR}/wasm_test_renderer.es6 ${wasmfile} ${CMAKE_CURRENT_SOURCE_DIR}/expected_output/${testname}.raw) + add_test(${wasmtarget} ${NODE} ${CMAKE_CURRENT_SOURCE_DIR}/wasm_test_renderer.js ${wasmfile} ${CMAKE_CURRENT_SOURCE_DIR}/expected_output/${testname}.raw) endif() endif() @@ -57,6 +57,7 @@ function(regression_test testname) endfunction(regression_test) +regression_test(test_diff_wasm_x86 "" WASMX86DIFF) regression_test(test_envelope "" ENVELOPE) regression_test(test_envelope_stereo ENVELOPE) regression_test(test_loadval "" LOADVAL) diff --git a/tests/expected_output/test_diff_wasm_x86.raw b/tests/expected_output/test_diff_wasm_x86.raw new file mode 100644 index 0000000..0d7cf2c Binary files /dev/null and b/tests/expected_output/test_diff_wasm_x86.raw differ diff --git a/tests/test_diff_wasm_x86.yml b/tests/test_diff_wasm_x86.yml index efe6002..14d0fe5 100644 --- a/tests/test_diff_wasm_x86.yml +++ b/tests/test_diff_wasm_x86.yml @@ -427,25 +427,6 @@ patch: auxgain: 2 stereo: 1 id: 12 - - type: loadnote - id: 13 - - type: envelope - parameters: - attack: 0 - gain: 128 - stereo: 0 - decay: 80 - sustain: 0 - release: 80 - id: 14 - - type: mulp - id: 15 - - type: sync - parameters: {} - id: 16 - - type: pop - parameters: {} - id: 17 - numvoices: 1 units: - type: envelope @@ -456,17 +437,17 @@ patch: release: 32 stereo: 0 sustain: 15 - id: 18 + id: 13 - type: noise parameters: gain: 128 shape: 64 stereo: 0 - id: 19 + id: 14 - type: mulp parameters: stereo: 0 - id: 20 + id: 15 - type: filter parameters: bandpass: 1 @@ -477,49 +458,30 @@ patch: neghighpass: 0 resonance: 128 stereo: 0 - id: 21 + id: 16 - type: loadnote parameters: stereo: 0 - id: 22 + id: 17 - type: mulp parameters: stereo: 0 - id: 23 + id: 18 - type: pan parameters: panning: 64 stereo: 0 - id: 24 + id: 19 - type: outaux parameters: outgain: 100 auxgain: 100 stereo: 1 - id: 25 - - type: loadnote - id: 26 - - type: envelope - parameters: - attack: 0 - gain: 128 - stereo: 0 - decay: 80 - sustain: 0 - release: 80 - id: 27 - - type: mulp - id: 28 - - type: sync - parameters: {} - id: 29 - - type: pop - parameters: {} - id: 30 + id: 20 - numvoices: 1 units: - type: envelope - id: 31 + id: 21 parameters: attack: 32 decay: 70 @@ -539,47 +501,28 @@ patch: transpose: 76 type: 2 unison: 0 - id: 32 + id: 22 - type: mulp parameters: stereo: 0 - id: 33 + id: 23 - type: filter parameters: lowpass: 1 frequency: 27 resonance: 128 - id: 34 + id: 24 - type: pan parameters: panning: 64 stereo: 0 - id: 35 + id: 25 - type: outaux parameters: outgain: 90 auxgain: 15 stereo: 1 - id: 36 - - type: loadnote - id: 37 - - type: envelope - parameters: - attack: 0 - gain: 128 - stereo: 0 - decay: 80 - sustain: 0 - release: 80 - id: 38 - - type: mulp - id: 39 - - type: sync - parameters: {} - id: 40 - - type: pop - parameters: {} - id: 41 + id: 26 - numvoices: 1 units: - type: oscillator @@ -594,7 +537,7 @@ patch: transpose: 76 type: 1 unison: 1 - id: 42 + id: 27 - type: oscillator parameters: color: 80 @@ -607,13 +550,13 @@ patch: transpose: 76 type: 1 unison: 1 - id: 43 + id: 28 - type: addp parameters: stereo: 0 - id: 44 + id: 29 - type: envelope - id: 45 + id: 30 parameters: attack: 32 decay: 80 @@ -627,14 +570,14 @@ patch: port: 4 sendpop: 0 stereo: 0 - target: 45 - id: 46 + target: 30 + id: 31 - type: mulp parameters: stereo: 0 - id: 47 + id: 32 - type: filter - id: 48 + id: 33 parameters: lowpass: 1 frequency: 30 @@ -651,41 +594,22 @@ patch: varargs: - 16537 - 16537 - id: 49 + id: 34 - type: pan parameters: panning: 64 stereo: 0 - id: 50 + id: 35 - type: outaux parameters: outgain: 20 auxgain: 10 stereo: 1 - id: 51 - - type: loadnote - id: 52 - - type: envelope - parameters: - attack: 0 - gain: 128 - stereo: 0 - decay: 80 - sustain: 0 - release: 80 - id: 53 - - type: mulp - id: 54 - - type: sync - parameters: {} - id: 55 - - type: pop - parameters: {} - id: 56 + id: 36 - numvoices: 1 units: - type: envelope - id: 57 + id: 37 parameters: attack: 16 decay: 98 @@ -699,10 +623,10 @@ patch: port: 4 sendpop: 0 stereo: 0 - target: 57 - id: 58 + target: 37 + id: 38 - type: push - id: 59 + id: 39 - type: oscillator parameters: color: 110 @@ -715,387 +639,292 @@ patch: transpose: 64 type: 1 unison: 3 - id: 60 + id: 40 - type: mulp parameters: stereo: 1 - id: 61 + id: 41 - type: filter parameters: stereo: 1 lowpass: 1 frequency: 110 resonance: 10 - id: 62 + id: 42 - type: filter parameters: stereo: 1 lowpass: 1 frequency: 85 resonance: 64 - id: 63 + id: 43 - type: pan parameters: panning: 64 stereo: 1 - id: 64 + id: 44 - type: outaux parameters: outgain: 30 auxgain: 100 stereo: 1 - id: 65 - - type: loadnote - id: 66 + id: 45 + - numvoices: 1 + units: - type: envelope + id: 46 parameters: - attack: 0 - gain: 128 + attack: 16 + decay: 98 + gain: 7 + release: 98 stereo: 0 - decay: 80 sustain: 0 - release: 80 + - type: send + parameters: + amount: 127 + port: 4 + sendpop: 0 + stereo: 0 + target: 46 + id: 47 + - type: push + id: 48 + - type: oscillator + parameters: + color: 110 + detune: 58 + gain: 2 + lfo: 0 + phase: 58 + shape: 110 + stereo: 1 + transpose: 64 + type: 1 + unison: 3 + id: 49 + - type: mulp + parameters: + stereo: 1 + id: 50 + - type: filter + parameters: + stereo: 1 + lowpass: 1 + frequency: 110 + resonance: 10 + id: 51 + - type: filter + parameters: + stereo: 1 + lowpass: 1 + frequency: 85 + resonance: 64 + id: 52 + - type: pan + parameters: + panning: 64 + stereo: 1 + id: 53 + - type: outaux + parameters: + outgain: 30 + auxgain: 100 + stereo: 1 + id: 54 + - numvoices: 1 + units: + - type: envelope + id: 55 + parameters: + attack: 16 + decay: 98 + gain: 7 + release: 98 + stereo: 0 + sustain: 0 + - type: send + parameters: + amount: 127 + port: 4 + sendpop: 0 + stereo: 0 + target: 55 + id: 56 + - type: push + id: 57 + - type: oscillator + parameters: + color: 110 + detune: 58 + gain: 2 + lfo: 0 + phase: 58 + shape: 110 + stereo: 1 + transpose: 64 + type: 1 + unison: 3 + id: 58 + - type: mulp + parameters: + stereo: 1 + id: 59 + - type: filter + parameters: + stereo: 1 + lowpass: 1 + frequency: 110 + resonance: 10 + id: 60 + - type: filter + parameters: + stereo: 1 + lowpass: 1 + frequency: 85 + resonance: 64 + id: 61 + - type: pan + parameters: + panning: 64 + stereo: 1 + id: 62 + - type: outaux + parameters: + outgain: 30 + auxgain: 100 + stereo: 1 + id: 63 + - numvoices: 1 + units: + - type: envelope + id: 64 + parameters: + attack: 16 + decay: 98 + gain: 7 + release: 98 + stereo: 0 + sustain: 0 + - type: send + parameters: + amount: 127 + port: 4 + sendpop: 0 + stereo: 0 + target: 64 + id: 65 + - type: push + id: 66 + - type: oscillator + parameters: + color: 110 + detune: 58 + gain: 2 + lfo: 0 + phase: 58 + shape: 110 + stereo: 1 + transpose: 64 + type: 1 + unison: 3 id: 67 - type: mulp + parameters: + stereo: 1 id: 68 - - type: sync - parameters: {} + - type: filter + parameters: + stereo: 1 + lowpass: 1 + frequency: 110 + resonance: 10 id: 69 - - type: pop - parameters: {} + - type: filter + parameters: + stereo: 1 + lowpass: 1 + frequency: 85 + resonance: 64 id: 70 - - numvoices: 1 - units: - - type: envelope + - type: pan + parameters: + panning: 64 + stereo: 1 id: 71 + - type: outaux parameters: - attack: 16 - decay: 98 - gain: 7 - release: 98 - stereo: 0 - sustain: 0 - - type: send - parameters: - amount: 127 - port: 4 - sendpop: 0 - stereo: 0 - target: 71 + outgain: 30 + auxgain: 100 + stereo: 1 id: 72 - - type: push + - numvoices: 1 + units: + - type: envelope id: 73 - - type: oscillator parameters: - color: 110 - detune: 58 - gain: 2 - lfo: 0 - phase: 58 - shape: 110 - stereo: 1 - transpose: 64 - type: 1 - unison: 3 + attack: 16 + decay: 98 + gain: 7 + release: 98 + stereo: 0 + sustain: 0 + - type: send + parameters: + amount: 127 + port: 4 + sendpop: 0 + stereo: 0 + target: 73 id: 74 - - type: mulp - parameters: - stereo: 1 + - type: push id: 75 - - type: filter + - type: oscillator parameters: + color: 110 + detune: 58 + gain: 2 + lfo: 0 + phase: 58 + shape: 110 stereo: 1 - lowpass: 1 - frequency: 110 - resonance: 10 + transpose: 64 + type: 1 + unison: 3 id: 76 - - type: filter + - type: mulp parameters: stereo: 1 - lowpass: 1 - frequency: 85 - resonance: 64 id: 77 - - type: pan + - type: filter parameters: - panning: 64 stereo: 1 + lowpass: 1 + frequency: 110 + resonance: 10 id: 78 - - type: outaux + - type: filter parameters: - outgain: 30 - auxgain: 100 stereo: 1 + lowpass: 1 + frequency: 85 + resonance: 64 id: 79 - - type: loadnote + - type: pan + parameters: + panning: 64 + stereo: 1 id: 80 - - type: envelope + - type: outaux parameters: - attack: 0 - gain: 128 - stereo: 0 - decay: 80 - sustain: 0 - release: 80 + outgain: 30 + auxgain: 100 + stereo: 1 id: 81 - - type: mulp + - numvoices: 1 + units: + - type: envelope id: 82 - - type: sync - parameters: {} - id: 83 - - type: pop - parameters: {} - id: 84 - - numvoices: 1 - units: - - type: envelope - id: 85 - parameters: - attack: 16 - decay: 98 - gain: 7 - release: 98 - stereo: 0 - sustain: 0 - - type: send - parameters: - amount: 127 - port: 4 - sendpop: 0 - stereo: 0 - target: 85 - id: 86 - - type: push - id: 87 - - type: oscillator - parameters: - color: 110 - detune: 58 - gain: 2 - lfo: 0 - phase: 58 - shape: 110 - stereo: 1 - transpose: 64 - type: 1 - unison: 3 - id: 88 - - type: mulp - parameters: - stereo: 1 - id: 89 - - type: filter - parameters: - stereo: 1 - lowpass: 1 - frequency: 110 - resonance: 10 - id: 90 - - type: filter - parameters: - stereo: 1 - lowpass: 1 - frequency: 85 - resonance: 64 - id: 91 - - type: pan - parameters: - panning: 64 - stereo: 1 - id: 92 - - type: outaux - parameters: - outgain: 30 - auxgain: 100 - stereo: 1 - id: 93 - - type: loadnote - id: 94 - - type: envelope - parameters: - attack: 0 - gain: 128 - stereo: 0 - decay: 80 - sustain: 0 - release: 80 - id: 95 - - type: mulp - id: 96 - - type: sync - parameters: {} - id: 97 - - type: pop - parameters: {} - id: 98 - - numvoices: 1 - units: - - type: envelope - id: 99 - parameters: - attack: 16 - decay: 98 - gain: 7 - release: 98 - stereo: 0 - sustain: 0 - - type: send - parameters: - amount: 127 - port: 4 - sendpop: 0 - stereo: 0 - target: 99 - id: 100 - - type: push - id: 101 - - type: oscillator - parameters: - color: 110 - detune: 58 - gain: 2 - lfo: 0 - phase: 58 - shape: 110 - stereo: 1 - transpose: 64 - type: 1 - unison: 3 - id: 102 - - type: mulp - parameters: - stereo: 1 - id: 103 - - type: filter - parameters: - stereo: 1 - lowpass: 1 - frequency: 110 - resonance: 10 - id: 104 - - type: filter - parameters: - stereo: 1 - lowpass: 1 - frequency: 85 - resonance: 64 - id: 105 - - type: pan - parameters: - panning: 64 - stereo: 1 - id: 106 - - type: outaux - parameters: - outgain: 30 - auxgain: 100 - stereo: 1 - id: 107 - - type: loadnote - id: 108 - - type: envelope - parameters: - attack: 0 - gain: 128 - stereo: 0 - decay: 80 - sustain: 0 - release: 80 - id: 109 - - type: mulp - id: 110 - - type: sync - parameters: {} - id: 111 - - type: pop - parameters: {} - id: 112 - - numvoices: 1 - units: - - type: envelope - id: 113 - parameters: - attack: 16 - decay: 98 - gain: 7 - release: 98 - stereo: 0 - sustain: 0 - - type: send - parameters: - amount: 127 - port: 4 - sendpop: 0 - stereo: 0 - target: 113 - id: 114 - - type: push - id: 115 - - type: oscillator - parameters: - color: 110 - detune: 58 - gain: 2 - lfo: 0 - phase: 58 - shape: 110 - stereo: 1 - transpose: 64 - type: 1 - unison: 3 - id: 116 - - type: mulp - parameters: - stereo: 1 - id: 117 - - type: filter - parameters: - stereo: 1 - lowpass: 1 - frequency: 110 - resonance: 10 - id: 118 - - type: filter - parameters: - stereo: 1 - lowpass: 1 - frequency: 85 - resonance: 64 - id: 119 - - type: pan - parameters: - panning: 64 - stereo: 1 - id: 120 - - type: outaux - parameters: - outgain: 30 - auxgain: 100 - stereo: 1 - id: 121 - - type: loadnote - id: 122 - - type: envelope - parameters: - attack: 0 - gain: 128 - stereo: 0 - decay: 80 - sustain: 0 - release: 80 - id: 123 - - type: mulp - id: 124 - - type: sync - parameters: {} - id: 125 - - type: pop - parameters: {} - id: 126 - - numvoices: 1 - units: - - type: envelope - id: 127 parameters: attack: 0 decay: 73 @@ -1109,18 +938,18 @@ patch: port: 4 sendpop: 0 stereo: 0 - target: 127 - id: 128 + target: 82 + id: 83 - type: noise parameters: gain: 128 shape: 64 stereo: 0 - id: 129 + id: 84 - type: mulp parameters: stereo: 0 - id: 130 + id: 85 - type: filter parameters: bandpass: 1 @@ -1131,7 +960,7 @@ patch: neghighpass: 0 resonance: 100 stereo: 0 - id: 131 + id: 86 - type: envelope parameters: attack: 0 @@ -1140,17 +969,17 @@ patch: release: 32 stereo: 0 sustain: 0 - id: 132 + id: 87 - type: noise parameters: gain: 128 shape: 64 stereo: 0 - id: 133 + id: 88 - type: mulp parameters: stereo: 0 - id: 134 + id: 89 - type: filter parameters: bandpass: 1 @@ -1161,7 +990,7 @@ patch: neghighpass: 0 resonance: 100 stereo: 0 - id: 135 + id: 90 - type: envelope parameters: attack: 0 @@ -1170,17 +999,17 @@ patch: release: 32 stereo: 0 sustain: 0 - id: 136 + id: 91 - type: noise parameters: gain: 120 shape: 64 stereo: 0 - id: 137 + id: 92 - type: mulp parameters: stereo: 0 - id: 138 + id: 93 - type: filter parameters: bandpass: 1 @@ -1191,53 +1020,34 @@ patch: neghighpass: 0 resonance: 100 stereo: 0 - id: 139 + id: 94 - type: addp parameters: stereo: 0 - id: 140 + id: 95 - type: addp parameters: stereo: 0 - id: 141 + id: 96 - type: loadnote parameters: stereo: 0 - id: 142 + id: 97 - type: mulp parameters: stereo: 0 - id: 143 + id: 98 - type: pan parameters: panning: 64 stereo: 0 - id: 144 + id: 99 - type: outaux parameters: outgain: 74 auxgain: 30 stereo: 1 - id: 145 - - type: loadnote - id: 146 - - type: envelope - parameters: - attack: 0 - gain: 128 - stereo: 0 - decay: 80 - sustain: 0 - release: 80 - id: 147 - - type: mulp - id: 148 - - type: sync - parameters: {} - id: 149 - - type: pop - parameters: {} - id: 150 + id: 100 - numvoices: 1 units: - type: envelope @@ -1248,9 +1058,9 @@ patch: release: 85 stereo: 0 sustain: 60 - id: 151 + id: 101 - type: push - id: 152 + id: 102 - type: oscillator parameters: color: 120 @@ -1263,13 +1073,13 @@ patch: transpose: 64 type: 1 unison: 3 - id: 153 + id: 103 - type: mulp parameters: stereo: 1 - id: 154 + id: 104 - type: filter - id: 155 + id: 105 parameters: lowpass: 1 frequency: 28 @@ -1279,32 +1089,13 @@ patch: parameters: panning: 64 stereo: 1 - id: 156 + id: 106 - type: outaux parameters: outgain: 100 auxgain: 60 stereo: 1 - id: 157 - - type: loadnote - id: 158 - - type: envelope - parameters: - attack: 0 - gain: 128 - stereo: 0 - decay: 80 - sustain: 0 - release: 80 - id: 159 - - type: mulp - id: 160 - - type: sync - parameters: {} - id: 161 - - type: pop - parameters: {} - id: 162 + id: 107 - numvoices: 1 units: - type: envelope @@ -1315,9 +1106,9 @@ patch: release: 85 stereo: 0 sustain: 60 - id: 163 + id: 108 - type: push - id: 164 + id: 109 - type: oscillator parameters: color: 120 @@ -1330,13 +1121,13 @@ patch: transpose: 64 type: 1 unison: 3 - id: 165 + id: 110 - type: mulp parameters: stereo: 1 - id: 166 + id: 111 - type: filter - id: 167 + id: 112 parameters: lowpass: 1 frequency: 28 @@ -1346,32 +1137,13 @@ patch: parameters: panning: 64 stereo: 1 - id: 168 + id: 113 - type: outaux parameters: outgain: 100 auxgain: 60 stereo: 1 - id: 169 - - type: loadnote - id: 170 - - type: envelope - parameters: - attack: 0 - gain: 128 - stereo: 0 - decay: 80 - sustain: 0 - release: 80 - id: 171 - - type: mulp - id: 172 - - type: sync - parameters: {} - id: 173 - - type: pop - parameters: {} - id: 174 + id: 114 - numvoices: 1 units: - type: envelope @@ -1382,9 +1154,9 @@ patch: release: 85 stereo: 0 sustain: 60 - id: 175 + id: 115 - type: push - id: 176 + id: 116 - type: oscillator parameters: color: 120 @@ -1397,13 +1169,13 @@ patch: transpose: 64 type: 1 unison: 3 - id: 177 + id: 117 - type: mulp parameters: stereo: 1 - id: 178 + id: 118 - type: filter - id: 179 + id: 119 parameters: lowpass: 1 frequency: 28 @@ -1413,36 +1185,17 @@ patch: parameters: panning: 64 stereo: 1 - id: 180 + id: 120 - type: outaux parameters: outgain: 100 auxgain: 60 stereo: 1 - id: 181 - - type: loadnote - id: 182 - - type: envelope - parameters: - attack: 0 - gain: 128 - stereo: 0 - decay: 80 - sustain: 0 - release: 80 - id: 183 - - type: mulp - id: 184 - - type: sync - parameters: {} - id: 185 - - type: pop - parameters: {} - id: 186 + id: 121 - numvoices: 1 units: - type: envelope - id: 187 + id: 122 parameters: attack: 48 decay: 32 @@ -1462,52 +1215,33 @@ patch: transpose: 64 type: 1 unison: 3 - id: 188 + id: 123 - type: mulp parameters: stereo: 1 - id: 189 + id: 124 - type: filter parameters: stereo: 1 lowpass: 1 frequency: 110 resonance: 90 - id: 190 + id: 125 - type: pan parameters: panning: 64 stereo: 1 - id: 191 + id: 126 - type: outaux parameters: outgain: 120 auxgain: 48 stereo: 1 - id: 192 - - type: loadnote - id: 193 - - type: envelope - parameters: - attack: 0 - gain: 128 - stereo: 0 - decay: 80 - sustain: 0 - release: 80 - id: 194 - - type: mulp - id: 195 - - type: sync - parameters: {} - id: 196 - - type: pop - parameters: {} - id: 197 + id: 127 - numvoices: 1 units: - type: envelope - id: 198 + id: 128 parameters: attack: 48 decay: 32 @@ -1527,52 +1261,33 @@ patch: transpose: 64 type: 1 unison: 3 - id: 199 + id: 129 - type: mulp parameters: stereo: 1 - id: 200 + id: 130 - type: filter parameters: stereo: 1 lowpass: 1 frequency: 110 resonance: 90 - id: 201 + id: 131 - type: pan parameters: panning: 64 stereo: 1 - id: 202 + id: 132 - type: outaux parameters: outgain: 120 auxgain: 48 stereo: 1 - id: 203 - - type: loadnote - id: 204 - - type: envelope - parameters: - attack: 0 - gain: 128 - stereo: 0 - decay: 80 - sustain: 0 - release: 80 - id: 205 - - type: mulp - id: 206 - - type: sync - parameters: {} - id: 207 - - type: pop - parameters: {} - id: 208 + id: 133 - numvoices: 1 units: - type: envelope - id: 209 + id: 134 parameters: attack: 48 decay: 32 @@ -1592,55 +1307,36 @@ patch: transpose: 64 type: 1 unison: 3 - id: 210 + id: 135 - type: mulp parameters: stereo: 1 - id: 211 + id: 136 - type: filter parameters: stereo: 1 lowpass: 1 frequency: 110 resonance: 90 - id: 212 + id: 137 - type: pan parameters: panning: 64 stereo: 1 - id: 213 + id: 138 - type: outaux parameters: outgain: 120 auxgain: 48 stereo: 1 - id: 214 - - type: loadnote - id: 215 - - type: envelope - parameters: - attack: 0 - gain: 128 - stereo: 0 - decay: 80 - sustain: 0 - release: 80 - id: 216 - - type: mulp - id: 217 - - type: sync - parameters: {} - id: 218 - - type: pop - parameters: {} - id: 219 + id: 139 - numvoices: 1 units: - type: in parameters: channel: 2 stereo: 1 - id: 220 + id: 140 - type: delay parameters: damp: 64 @@ -1658,18 +1354,18 @@ patch: - 1492 - 1556 - 1618 - id: 221 + id: 141 - type: outaux parameters: auxgain: 0 outgain: 128 stereo: 1 - id: 222 + id: 142 - type: in parameters: channel: 0 stereo: 1 - id: 223 + id: 143 - type: compressor parameters: attack: 16 @@ -1678,14 +1374,14 @@ patch: release: 64 stereo: 1 threshold: 71 - id: 224 + id: 144 - type: mulp parameters: stereo: 1 - id: 225 + id: 145 - type: outaux parameters: auxgain: 0 outgain: 128 stereo: 1 - id: 226 + id: 146 diff --git a/tests/wasm_test_renderer.es6 b/tests/wasm_test_renderer.js similarity index 100% rename from tests/wasm_test_renderer.es6 rename to tests/wasm_test_renderer.js diff --git a/testwasm.mjs b/testwasm.mjs deleted file mode 100644 index 768e7ec..0000000 --- a/testwasm.mjs +++ /dev/null @@ -1,10 +0,0 @@ -import { readFile, writeFile } from 'fs/promises'; - -const wasm = (await readFile('./temp_song_file.wasm')); - -const mod = await WebAssembly.instantiate(wasm, { - -}); - -const mem = mod.instance.exports.m; -await writeFile('test.raw', new Uint8Array(mem.buffer,mod.instance.exports.s,mod.instance.exports.l)); \ No newline at end of file