diff --git a/tests/test_render_samples.c b/tests/test_render_samples.c index 165a605..01fffdd 100644 --- a/tests/test_render_samples.c +++ b/tests/test_render_samples.c @@ -7,21 +7,21 @@ void SU_CALLCONV su_render_song(float *buffer) { Synth *synth; - const unsigned char commands[] = {SU_ENVELOPE_ID, // MONO - SU_ENVELOPE_ID, // MONO - SU_OUT_ID + 1, // STEREO - SU_ADVANCE_ID}; // MONO - const unsigned char values[] = {64, 64, 64, 80, 128, // envelope 1 - 95, 64, 64, 80, 128, // envelope 2 - 128}; + const unsigned char opcodes[] = {SU_ENVELOPE_ID, // MONO + SU_ENVELOPE_ID, // MONO + SU_OUT_ID + 1, // STEREO + SU_ADVANCE_ID}; // MONO + const unsigned char operands[] = {64, 64, 64, 80, 128, // envelope 1 + 95, 64, 64, 80, 128, // envelope 2 + 128}; int retval; int samples; int time; // initialize Synth synth = (Synth *)malloc(sizeof(Synth)); memset(synth, 0, sizeof(Synth)); - memcpy(synth->Commands, commands, sizeof(commands)); - memcpy(synth->Values, values, sizeof(values)); + memcpy(synth->Opcodes, opcodes, sizeof(opcodes)); + memcpy(synth->Operands, operands, sizeof(operands)); synth->NumVoices = 1; synth->Polyphony = 0; synth->RandSeed = 1; diff --git a/tests/test_render_samples_api.c b/tests/test_render_samples_api.c index 393f792..c1d5c6a 100644 --- a/tests/test_render_samples_api.c +++ b/tests/test_render_samples_api.c @@ -14,13 +14,13 @@ int main(int argc, char *argv[]) { Synth *synth; float *buffer; - const unsigned char commands[] = {SU_ENVELOPE_ID, // MONO - SU_ENVELOPE_ID, // MONO - SU_OUT_ID + 1, // STEREO - SU_ADVANCE_ID}; // MONO - const unsigned char values[] = {64, 64, 64, 80, 128, // envelope 1 - 95, 64, 64, 80, 128, // envelope 2 - 128}; + const unsigned char opcodes[] = {SU_ENVELOPE_ID, // MONO + SU_ENVELOPE_ID, // MONO + SU_OUT_ID + 1, // STEREO + SU_ADVANCE_ID}; // MONO + const unsigned char operands[] = {64, 64, 64, 80, 128, // envelope 1 + 95, 64, 64, 80, 128, // envelope 2 + 128}; int errcode; int time; int samples; @@ -29,8 +29,8 @@ int main(int argc, char *argv[]) // initialize Synth synth = (Synth *)malloc(sizeof(Synth)); memset(synth, 0, sizeof(Synth)); - memcpy(synth->Commands, commands, sizeof(commands)); - memcpy(synth->Values, values, sizeof(values)); + memcpy(synth->Opcodes, opcodes, sizeof(opcodes)); + memcpy(synth->Operands, operands, sizeof(operands)); synth->NumVoices = 1; synth->Polyphony = 0; synth->RandSeed = 1; diff --git a/vm/bytecode.go b/vm/bytecode.go index dd4de28..8c36c87 100644 --- a/vm/bytecode.go +++ b/vm/bytecode.go @@ -11,15 +11,16 @@ type ( // Bytecode is the Sointu VM bytecode & data (delay times, sample offsets) // which is executed by the synthesizer. It is generated from a Sointu patch. Bytecode struct { - // Commands is the bytecode, which is a sequence of opcode bytes, one + // Opcodes is the bytecode, which is a sequence of opcode bytes, one // per unit in the patch. A byte of 0 denotes the end of an instrument, // at which point if that instrument has more than one voice, the - // commands are repeated for each voice. - Commands []byte + // opcodes are repeated for each voice. + Opcodes []byte - // Values are the operands of the opcodes. Every opcode reads 0 or more - // values from the value sequence. - Values []byte + // Operands are the operands of the opcodes. When executing the + // bytecodes, every opcode reads 0 or more operands from it and advances + // in the sequence. + Operands []byte // DelayTimes is a table of delay times in samples. The delay times are // used by the delay units in the patch. The delay unit only stores @@ -114,8 +115,8 @@ func Encode(patch sointu.Patch, featureSet FeatureSet, bpm int) (*Bytecode, erro flags += 0x08 } flags += p["unison"] - b.cmd(opcode + p["stereo"]) - b.vals(p["transpose"], p["detune"], p["phase"], color, p["shape"], p["gain"], flags) + b.op(opcode + p["stereo"]) + b.operand(p["transpose"], p["detune"], p["phase"], color, p["shape"], p["gain"], flags) case "delay": count := len(unit.VarArgs) if unit.Parameters["stereo"] == 1 { @@ -125,13 +126,13 @@ func Encode(patch sointu.Patch, featureSet FeatureSet, bpm int) (*Bytecode, erro continue // skip encoding delays without any delay lines } countTrack := count*2 - 1 + (unit.Parameters["notetracking"] & 1) // 1 means no note tracking and 1 delay, 2 means notetracking with 1 delay, 3 means no note tracking and 2 delays etc. - b.cmd(opcode + p["stereo"]) - b.defaultVals(unit) - b.vals(b.delayIndices[instrIndex][unitIndex], countTrack) + b.op(opcode + p["stereo"]) + b.defOperands(unit) + b.operand(b.delayIndices[instrIndex][unitIndex], countTrack) case "aux", "in": - b.cmd(opcode + p["stereo"]) - b.defaultVals(unit) - b.vals(unit.Parameters["channel"]) + b.op(opcode + p["stereo"]) + b.defOperands(unit) + b.operand(unit.Parameters["channel"]) case "filter": flags := 0 if unit.Parameters["lowpass"] == 1 { @@ -149,9 +150,9 @@ func Encode(patch sointu.Patch, featureSet FeatureSet, bpm int) (*Bytecode, erro if unit.Parameters["neghighpass"] == 1 { flags += 0x04 } - b.cmd(opcode + p["stereo"]) - b.defaultVals(unit) - b.vals(flags) + b.op(opcode + p["stereo"]) + b.defOperands(unit) + b.operand(flags) case "send": targetID := unit.Parameters["target"] targetInstrIndex, _, err := patch.FindSendTarget(targetID) @@ -164,8 +165,8 @@ func Encode(patch sointu.Patch, featureSet FeatureSet, bpm int) (*Bytecode, erro if unit.Parameters["sendpop"] == 1 { addr += 0x8 } - b.cmd(opcode + p["stereo"]) - b.defaultVals(unit) + b.op(opcode + p["stereo"]) + b.defOperands(unit) b.localIDRef(targetID, addr) } else { addr += 0x8000 @@ -177,8 +178,8 @@ func Encode(patch sointu.Patch, featureSet FeatureSet, bpm int) (*Bytecode, erro } addr += voiceStart * 0x400 for i := voiceStart; i < voiceEnd; i++ { - b.cmd(opcode + p["stereo"]) - b.defaultVals(unit) + b.op(opcode + p["stereo"]) + b.defOperands(unit) if i == voiceEnd-1 && unit.Parameters["sendpop"] == 1 { addr += 0x8 // when making multi unit send, only the last one should have POP bit set if popping } @@ -194,19 +195,19 @@ func Encode(patch sointu.Patch, featureSet FeatureSet, bpm int) (*Bytecode, erro if unit.Parameters["sendpop"] == 1 { addr |= 0x8 } - b.cmd(opcode + p["stereo"]) - b.defaultVals(unit) - b.Values = append(b.Values, byte(addr&255), byte(addr>>8)) + b.op(opcode + p["stereo"]) + b.defOperands(unit) + b.Operands = append(b.Operands, byte(addr&255), byte(addr>>8)) } default: - b.cmd(opcode + p["stereo"]) - b.defaultVals(unit) + b.op(opcode + p["stereo"]) + b.defOperands(unit) } if b.unitNo > 63 { return nil, fmt.Errorf(`Instrument %v has over 63 units`, instrIndex) } } - b.cmdFinish(instr) + b.opFinish(instr) } return &b.Bytecode, nil } @@ -235,34 +236,35 @@ func newBytecodeBuilder(patch sointu.Patch, bpm int) *bytecodeBuilder { return &c } -// cmd adds a command to the bytecode, and increments the unit number -func (b *bytecodeBuilder) cmd(opcode int) { - b.Commands = append(b.Commands, byte(opcode)) +// op adds a command to the bytecode, and increments the unit number +func (b *bytecodeBuilder) op(opcode int) { + b.Opcodes = append(b.Opcodes, byte(opcode)) b.unitNo++ } -// cmdFinish adds a command to the bytecode that marks the end of an instrument, resets the unit number and increments the voice number +// opFinish adds a command to the bytecode that marks the end of an instrument, resets the unit number and increments the voice number // local addresses are forgotten when instrument ends -func (b *bytecodeBuilder) cmdFinish(instr sointu.Instrument) { - b.Commands = append(b.Commands, 0) +func (b *bytecodeBuilder) opFinish(instr sointu.Instrument) { + b.Opcodes = append(b.Opcodes, 0) b.unitNo = 0 b.voiceNo += instr.NumVoices b.localAddrs = map[int]uint16{} b.localFixups = map[int]([]int){} } -// vals appends values to the value stream -func (b *bytecodeBuilder) vals(values ...int) { - for _, v := range values { - b.Values = append(b.Values, byte(v)) +// operand appends operands to the operand stream +func (b *bytecodeBuilder) operand(operands ...int) { + for _, v := range operands { + b.Operands = append(b.Operands, byte(v)) } } -// defaultVals appends the values to the value stream for all parameters that can be modulated and set -func (b *bytecodeBuilder) defaultVals(unit sointu.Unit) { +// defOperands appends the operands to the stream for all parameters that can be +// modulated and set +func (b *bytecodeBuilder) defOperands(unit sointu.Unit) { for _, v := range sointu.UnitTypes[unit.Type] { if v.CanModulate && v.CanSet { - b.Values = append(b.Values, byte(unit.Parameters[v.Name])) + b.Operands = append(b.Operands, byte(unit.Parameters[v.Name])) } } } @@ -272,9 +274,9 @@ func (b *bytecodeBuilder) localIDRef(id int, addr int) { if v, ok := b.localAddrs[id]; ok { addr += int(v) } else { - b.localFixups[id] = append(b.localFixups[id], len(b.Values)) + b.localFixups[id] = append(b.localFixups[id], len(b.Operands)) } - b.Values = append(b.Values, byte(addr&255), byte(addr>>8)) + b.Operands = append(b.Operands, byte(addr&255), byte(addr>>8)) } // globalIDRef adds a reference to a global id label to the value stream; if the targeted ID has not been seen yet, it is added to the fixup list @@ -282,9 +284,9 @@ func (b *bytecodeBuilder) globalIDRef(id int, addr int) { if v, ok := b.globalAddrs[id]; ok { addr += int(v) } else { - b.globalFixups[id] = append(b.globalFixups[id], len(b.Values)) + b.globalFixups[id] = append(b.globalFixups[id], len(b.Operands)) } - b.Values = append(b.Values, byte(addr&255), byte(addr>>8)) + b.Operands = append(b.Operands, byte(addr&255), byte(addr>>8)) } // idLabel adds a label to the value stream for the given id; all earlier references to the id are fixed up @@ -302,10 +304,10 @@ func (b *bytecodeBuilder) idLabel(id int) { // fixUp fixes up the references to the given id with the given delta func (b *bytecodeBuilder) fixUp(positions []int, delta uint16) { for _, pos := range positions { - orig := (uint16(b.Values[pos+1]) << 8) + uint16(b.Values[pos]) + orig := (uint16(b.Operands[pos+1]) << 8) + uint16(b.Operands[pos]) new := orig + delta - b.Values[pos] = byte(new & 255) - b.Values[pos+1] = byte(new >> 8) + b.Operands[pos] = byte(new & 255) + b.Operands[pos+1] = byte(new >> 8) } } diff --git a/vm/compiler/bridge/native_synth.go b/vm/compiler/bridge/native_synth.go index 3d3d365..8f37d70 100644 --- a/vm/compiler/bridge/native_synth.go +++ b/vm/compiler/bridge/native_synth.go @@ -32,17 +32,17 @@ func Synth(patch sointu.Patch, bpm int) (*NativeSynth, error) { if err != nil { return nil, fmt.Errorf("error compiling patch: %v", err) } - if len(comPatch.Commands) > 2048 { // TODO: 2048 could probably be pulled automatically from cgo - return nil, errors.New("bridge supports at most 2048 commands; the compiled patch has more") + if len(comPatch.Opcodes) > 2048 { // TODO: 2048 could probably be pulled automatically from cgo + return nil, errors.New("bridge supports at most 2048 opcodes; the compiled patch has more") } - if len(comPatch.Values) > 16384 { // TODO: 16384 could probably be pulled automatically from cgo - return nil, errors.New("bridge supports at most 16384 values; the compiled patch has more") + if len(comPatch.Operands) > 16384 { // TODO: 16384 could probably be pulled automatically from cgo + return nil, errors.New("bridge supports at most 16384 operands; the compiled patch has more") } - for i, v := range comPatch.Commands { - s.Commands[i] = (C.uchar)(v) + for i, v := range comPatch.Opcodes { + s.Opcodes[i] = (C.uchar)(v) } - for i, v := range comPatch.Values { - s.Values[i] = (C.uchar)(v) + for i, v := range comPatch.Operands { + s.Operands[i] = (C.uchar)(v) } for i, v := range comPatch.DelayTimes { s.DelayTimes[i] = (C.ushort)(v) @@ -124,21 +124,21 @@ func (bridgesynth *NativeSynth) Update(patch sointu.Patch, bpm int) error { if err != nil { return fmt.Errorf("error compiling patch: %v", err) } - if len(comPatch.Commands) > 2048 { // TODO: 2048 could probably be pulled automatically from cgo - return errors.New("bridge supports at most 2048 commands; the compiled patch has more") + if len(comPatch.Opcodes) > 2048 { // TODO: 2048 could probably be pulled automatically from cgo + return errors.New("bridge supports at most 2048 opcodes; the compiled patch has more") } - if len(comPatch.Values) > 16384 { // TODO: 16384 could probably be pulled automatically from cgo - return errors.New("bridge supports at most 16384 values; the compiled patch has more") + if len(comPatch.Operands) > 16384 { // TODO: 16384 could probably be pulled automatically from cgo + return errors.New("bridge supports at most 16384 operands; the compiled patch has more") } needsRefresh := false - for i, v := range comPatch.Commands { - if cmdChar := (C.uchar)(v); s.Commands[i] != cmdChar { - s.Commands[i] = cmdChar - needsRefresh = true // if any of the commands change, we retrigger all units + for i, v := range comPatch.Opcodes { + if cmdChar := (C.uchar)(v); s.Opcodes[i] != cmdChar { + s.Opcodes[i] = cmdChar + needsRefresh = true // if any of the opcodes change, we retrigger all units } } - for i, v := range comPatch.Values { - s.Values[i] = (C.uchar)(v) + for i, v := range comPatch.Operands { + s.Operands[i] = (C.uchar)(v) } for i, v := range comPatch.DelayTimes { s.DelayTimes[i] = (C.ushort)(v) @@ -152,7 +152,7 @@ func (bridgesynth *NativeSynth) Update(patch sointu.Patch, bpm int) error { s.Polyphony = C.uint(comPatch.PolyphonyBitmask) if needsRefresh { for i := range s.SynthWrk.Voices { - // if any of the commands change, we retrigger all units + // if any of the opcodes change, we retrigger all units // note that we don't change the notes or release states, just the units for j := range s.SynthWrk.Voices[i].Units { s.SynthWrk.Voices[i].Units[j] = C.Unit{} diff --git a/vm/compiler/templates/amd64-386/library.asm b/vm/compiler/templates/amd64-386/library.asm index 6d17cf7..4391331 100644 --- a/vm/compiler/templates/amd64-386/library.asm +++ b/vm/compiler/templates/amd64-386/library.asm @@ -7,8 +7,8 @@ struc su_synth .sampleoffs resb su_sample_offset.size * 256 .randseed resd 1 .globaltime resd 1 - .commands resb 32 * 64 - .values resb 32 * 64 * 8 + .opcodes resb 32 * 64 + .operands resb 32 * 64 * 8 .polyphony resd 1 .numvoices resd 1 endstruc @@ -73,8 +73,8 @@ su_render_samples_loop: mov eax, [{{.CX}} + su_synth.numvoices] {{.Push .AX "VoicesRemain"}} lea {{.DX}}, [{{.CX}}+ su_synth.synth_wrk] - lea {{.COM}}, [{{.CX}}+ su_synth.commands] - lea {{.VAL}}, [{{.CX}}+ su_synth.values] + lea {{.COM}}, [{{.CX}}+ su_synth.opcodes] + lea {{.VAL}}, [{{.CX}}+ su_synth.operands] lea {{.WRK}}, [{{.DX}} + su_synthworkspace.voices] lea {{.CX}}, [{{.CX}}+ su_synth.delay_wrks - su_delayline_wrk.filtstate] {{.Call "su_run_vm"}} diff --git a/vm/compiler/templates/amd64-386/library.h b/vm/compiler/templates/amd64-386/library.h index 6976065..1776c1c 100644 --- a/vm/compiler/templates/amd64-386/library.h +++ b/vm/compiler/templates/amd64-386/library.h @@ -43,8 +43,8 @@ typedef struct Synth { struct SampleOffset SampleOffsets[256]; unsigned int RandSeed; unsigned int GlobalTick; - unsigned char Commands[32 * 64]; - unsigned char Values[32 * 64 * 8]; + unsigned char Opcodes[32 * 64]; + unsigned char Operands[32 * 64 * 8]; unsigned int Polyphony; unsigned int NumVoices; } Synth; diff --git a/vm/compiler/templates/amd64-386/patch.asm b/vm/compiler/templates/amd64-386/patch.asm index 402682d..24f652d 100644 --- a/vm/compiler/templates/amd64-386/patch.asm +++ b/vm/compiler/templates/amd64-386/patch.asm @@ -5,15 +5,15 @@ ; su_synth_obj.right : Set to 0 before calling ; _CX : Pointer to delay workspace (if needed) ; _DX : Pointer to synth object -; COM : Pointer to command stream -; VAL : Pointer to value stream +; COM : Pointer to opcode stream +; VAL : Pointer to operand stream ; WRK : Pointer to the last workspace processed ; Output: su_synth_obj.left : left sample ; su_synth_obj.right : right sample ; Dirty: everything ;------------------------------------------------------------------------------- {{.Func "su_run_vm"}} - {{- .PushRegs .CX "DelayWorkSpace" .DX "Synth" .COM "CommandStream" .WRK "Voice" .VAL "ValueStream" | indent 4}} + {{- .PushRegs .CX "DelayWorkSpace" .DX "Synth" .COM "OpcodeStream" .WRK "Voice" .VAL "OperandStream" | indent 4}} {{- if .RowSync}} fild dword [{{.Stack "Sample"}}] {{.Int .Song.SamplesPerRow | .Prepare | indent 8}} @@ -33,13 +33,13 @@ su_run_vm_loop: ; loop until all voices done add {{.INP}}, su_voice.inputs xor ecx, ecx ; counter = 0 xor eax, eax ; clear out high bits of eax, as lodsb only sets al -su_transform_values_loop: +su_transform_operands_loop: {{- .Prepare "su_vm_transformcounts-1" | indent 4}} cmp cl, byte [{{.Use "su_vm_transformcounts-1"}}+{{.DI}}] ; compare the counter to the value in the param count table - je su_transform_values_out - lodsb ; load the byte value from VAL stream + je su_transform_operands_out + lodsb ; load the operand from VAL stream push {{.AX}} ; push it to memory so FPU can read it - fild dword [{{.SP}}] ; load the value to FPU stack + fild dword [{{.SP}}] ; load the operand value to FPU stack {{- .Prepare (.Float 0.0078125) | indent 4}} fmul dword [{{.Use (.Float 0.0078125)}}] ; divide it by 128 (0 => 0, 128 => 1.0) fadd dword [{{.WRK}}+su_unit.ports+{{.CX}}*4] ; add the modulations in the current workspace @@ -48,8 +48,8 @@ su_transform_values_loop: mov dword [{{.WRK}}+su_unit.ports+{{.CX}}*4], eax ; clear out the modulation ports pop {{.AX}} inc ecx - jmp su_transform_values_loop -su_transform_values_out: + jmp su_transform_operands_loop +su_transform_operands_out: popf ; pop flags for the carry bit = stereo bit {{- .SaveStack "Opcode"}} {{- $x := printf "su_vm_jumptable-%v" .PTRSIZE}} @@ -65,11 +65,11 @@ su_run_vm_advance: dec ecx ; decrement number of voices to process bt dword [{{.Stack "PolyphonyBitmask"}}], ecx ; if voice bit of su_polyphonism not set jnc su_op_advance_next_instrument ; goto next_instrument - mov {{.VAL}}, [{{.Stack "ValueStream"}}] ; if it was set, then repeat the opcodes for the current voice - mov {{.COM}}, [{{.Stack "CommandStream"}}] + mov {{.VAL}}, [{{.Stack "OperandStream"}}] ; if it was set, then repeat the opcodes for the current voice + mov {{.COM}}, [{{.Stack "OpcodeStream"}}] su_op_advance_next_instrument: - mov [{{.Stack "ValueStream"}}], {{.VAL}} ; save current VAL as a checkpoint - mov [{{.Stack "CommandStream"}}], {{.COM}} ; save current COM as a checkpoint + mov [{{.Stack "OperandStream"}}], {{.VAL}} ; save current VAL as a checkpoint + mov [{{.Stack "OpcodeStream"}}], {{.COM}} ; save current COM as a checkpoint su_op_advance_finish: mov [{{.Stack "VoicesRemain"}}], ecx jne su_run_vm_loop ; ZF was set by dec ecx @@ -95,7 +95,7 @@ su_op_advance_finish: ; su_nonlinear_map function: returns 2^(-24*x) of parameter number _AX ;------------------------------------------------------------------------------- ; Input: _AX : parameter number (e.g. for envelope: 0 = attac, 1 = decay...) -; INP : pointer to transformed values +; INP : pointer to transformed operands ; Output: st0 : 2^(-24*x), where x is the parameter in the range 0-1 ;------------------------------------------------------------------------------- {{.Func "su_nonlinear_map"}} diff --git a/vm/compiler/templates/amd64-386/player.asm b/vm/compiler/templates/amd64-386/player.asm index 111ef83..0267173 100644 --- a/vm/compiler/templates/amd64-386/player.asm +++ b/vm/compiler/templates/amd64-386/player.asm @@ -60,8 +60,8 @@ su_render_sampleloop: ; loop through every sample in the row {{- end}} {{.Push (.Song.Patch.NumVoices | printf "%v") "VoicesRemain"}} mov {{.DX}}, {{.PTRWORD}} su_synth_obj ; {{.DX}} points to the synth object - mov {{.COM}}, {{.PTRWORD}} su_patch_code ; COM points to vm code - mov {{.VAL}}, {{.PTRWORD}} su_patch_parameters ; VAL points to unit params + mov {{.COM}}, {{.PTRWORD}} su_patch_opcodes ; COM points to vm code + mov {{.VAL}}, {{.PTRWORD}} su_patch_operands ; VAL points to unit params {{- if .HasOp "delay"}} mov {{.CX}}, {{.PTRWORD}} su_synth_obj + su_synthworkspace.size - su_delayline_wrk.filtstate {{- end}} @@ -240,14 +240,14 @@ su_update_voices_skipadd: ;------------------------------------------------------------------------------- ; The code for this patch, basically indices to vm jump table ;------------------------------------------------------------------------------- -{{.Data "su_patch_code"}} - db {{.Commands | toStrings | join ","}} +{{.Data "su_patch_opcodes"}} + db {{.Opcodes | toStrings | join ","}} ;------------------------------------------------------------------------------- ; The parameters / inputs to each opcode ;------------------------------------------------------------------------------- -{{.Data "su_patch_parameters"}} - db {{.Values | toStrings | join ","}} +{{.Data "su_patch_operands"}} + db {{.Operands | toStrings | join ","}} ;------------------------------------------------------------------------------- ; Constants diff --git a/vm/compiler/templates/wasm/effects.wat b/vm/compiler/templates/wasm/effects.wat index af96370..7ab8a1e 100644 --- a/vm/compiler/templates/wasm/effects.wat +++ b/vm/compiler/templates/wasm/effects.wat @@ -115,7 +115,7 @@ (global.set $VAL (i32.sub (global.get $VAL) (i32.const 1))) )) {{- end}} - (local.set $flags (call $scanValueByte)) + (local.set $flags (call $scanOperand)) (local.set $freq (f32.mul (call $input (i32.const {{.InputNumber "filter" "frequency"}})) (call $input (i32.const {{.InputNumber "filter" "frequency"}})) @@ -252,16 +252,16 @@ (func $su_op_delay (param $stereo i32) (local $delayIndex i32) (local $delayCount i32) (local $output f32) (local $s f32) (local $filtstate f32) {{- if .Stereo "delay"}} (local $delayCountStash i32) {{- end}} {{- if or (.SupportsModulation "delay" "delaytime") (.SupportsParamValue "delay" "notetracking" 1)}} (local $delayTime f32) {{- end}} - (local.set $delayIndex (i32.mul (call $scanValueByte) (i32.const 2))) + (local.set $delayIndex (i32.mul (call $scanOperand) (i32.const 2))) {{- if .Stereo "delay"}} - (local.set $delayCountStash (call $scanValueByte)) + (local.set $delayCountStash (call $scanOperand)) (if (local.get $stereo)(then (call $su_op_xch (i32.const 0)) )) loop $stereoLoop (local.set $delayCount (local.get $delayCountStash)) {{- else}} - (local.set $delayCount (call $scanValueByte)) + (local.set $delayCount (call $scanOperand)) {{- end}} (local.set $output (f32.mul (call $input (i32.const {{.InputNumber "delay" "dry"}})) diff --git a/vm/compiler/templates/wasm/patch.wat b/vm/compiler/templates/wasm/patch.wat index d1c5813..08955ba 100644 --- a/vm/compiler/templates/wasm/patch.wat +++ b/vm/compiler/templates/wasm/patch.wat @@ -9,15 +9,15 @@ (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 + loop $transform_operands_loop {{- $addr := sub (index .Labels "su_vm_transformcounts") 1}} (if (i32.lt_u (local.get $paramNum) (i32.load8_u offset={{$addr}} (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={{index .Labels "su_transformedvalues"}} + (f32.store offset={{index .Labels "su_transformedoperands"}} (local.get $paramX4) (f32.add (f32.mul - (f32.convert_i32_u (call $scanValueByte)) + (f32.convert_i32_u (call $scanOperand)) (f32.const 0.0078125) ;; scale from 0-128 to 0.0 - 1.0 ) (f32.load offset=32 (local.get $WRKplusparam)) ;; add modulation @@ -26,7 +26,7 @@ (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 + br $transform_operands_loop ;; continue looping )) ;; paramNum was >= the number of parameters to transform, exiting loop end @@ -59,7 +59,7 @@ ;; The transformed values start at 512 (TODO: change magic constants somehow) ;;------------------------------------------------------------------------------- (func $input (param $inputNumber i32) (result f32) - (f32.load offset={{index .Labels "su_transformedvalues"}} (i32.mul (local.get $inputNumber) (i32.const 4))) + (f32.load offset={{index .Labels "su_transformedoperands"}} (i32.mul (local.get $inputNumber) (i32.const 4))) ) ;;------------------------------------------------------------------------------- diff --git a/vm/compiler/templates/wasm/player.wat b/vm/compiler/templates/wasm/player.wat index b901287..f1434e6 100644 --- a/vm/compiler/templates/wasm/player.wat +++ b/vm/compiler/templates/wasm/player.wat @@ -31,8 +31,8 @@ ; The code for this patch, basically indices to vm jump table ;------------------------------------------------------------------------------- */}} -{{- .SetDataLabel "su_patch_code"}} -{{- range .Commands}} +{{- .SetDataLabel "su_patch_opcodes"}} +{{- range .Opcodes}} {{- $.DataB .}} {{- end}} @@ -41,8 +41,8 @@ ; The parameters / inputs to each opcode ;------------------------------------------------------------------------------- */}} -{{- .SetDataLabel "su_patch_parameters"}} -{{- range .Values}} +{{- .SetDataLabel "su_patch_operands"}} +{{- range .Operands}} {{- $.DataB .}} {{- end}} @@ -79,11 +79,11 @@ {{- /* ;------------------------------------------------------------------------------- -; Allocate memory for transformed values. +; Allocate memory for transformed operands. ;------------------------------------------------------------------------------- */}} {{- .Align}} -{{- .SetBlockLabel "su_transformedvalues"}} +{{- .SetBlockLabel "su_transformedoperands"}} {{- .Block 32}} {{- /* @@ -193,7 +193,7 @@ local.get 0 ) -(func $scanValueByte (result i32) ;; scans positions $VAL for a byte, incrementing $VAL afterwards +(func $scanOperand (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++ ) @@ -211,8 +211,8 @@ (call $su_update_voices) (global.set $sample (i32.const 0)) loop $sample_loop - (global.set $COM (i32.const {{index .Labels "su_patch_code"}})) - (global.set $VAL (i32.const {{index .Labels "su_patch_parameters"}})) + (global.set $COM (i32.const {{index .Labels "su_patch_opcodes"}})) + (global.set $VAL (i32.const {{index .Labels "su_patch_operands"}})) {{- if .SupportsPolyphony}} (global.set $COM_instr_start (global.get $COM)) (global.set $VAL_instr_start (global.get $VAL)) diff --git a/vm/compiler/templates/wasm/sinks.wat b/vm/compiler/templates/wasm/sinks.wat index fce3635..290b13c 100644 --- a/vm/compiler/templates/wasm/sinks.wat +++ b/vm/compiler/templates/wasm/sinks.wat @@ -47,7 +47,7 @@ ;; Stereo: also add gain*ST1 to right port ;;------------------------------------------------------------------------------- (func $su_op_aux (param $stereo i32) (local $addr i32) - (local.set $addr (i32.add (i32.mul (call $scanValueByte) (i32.const 4)) (i32.const {{index .Labels "su_globalports"}}))) + (local.set $addr (i32.add (i32.mul (call $scanOperand) (i32.const 4)) (i32.const {{index .Labels "su_globalports"}}))) {{- if .Stereo "aux"}} loop $stereoLoop {{- end}} @@ -78,7 +78,7 @@ ;; 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)))) + (local.set $address (i32.add (call $scanOperand) (i32.shl (call $scanOperand) (i32.const 8)))) (if (i32.eqz (i32.and (local.get $address) (i32.const 8)))(then {{- if .Stereo "send"}} (if (local.get $stereo)(then diff --git a/vm/compiler/templates/wasm/sources.wat b/vm/compiler/templates/wasm/sources.wat index 236653f..5c7474e 100644 --- a/vm/compiler/templates/wasm/sources.wat +++ b/vm/compiler/templates/wasm/sources.wat @@ -118,7 +118,7 @@ (local.set $freqMod (f32.load offset={{.InputNumber "oscillator" "frequency" | mul 4 | add 32}} (global.get $WRK))) (f32.store offset={{.InputNumber "oscillator" "frequency" | mul 4 | add 32}} (global.get $WRK) (f32.const 0)) {{- end}} - (local.set $flags (call $scanValueByte)) + (local.set $flags (call $scanOperand)) (local.set $detune (call $inputSigned (i32.const {{.InputNumber "oscillator" "detune"}}))) {{- if .Stereo "oscillator"}} loop $stereoLoop @@ -197,7 +197,7 @@ {{- if .SupportsParamValueOtherThan "oscillator" "unison" 0}} (call $push (f32.add (call $pop) (call $pop))) (if (local.tee $unison (i32.sub (local.get $unison) (i32.const 1)))(then - (f32.store offset={{.InputNumber "oscillator" "phase" | mul 4 | add (index .Labels "su_transformedvalues")}} (i32.const 0) + (f32.store offset={{.InputNumber "oscillator" "phase" | mul 4 | add (index .Labels "su_transformedoperands")}} (i32.const 0) (f32.add (call $input (i32.const {{.InputNumber "oscillator" "phase"}})) (f32.const 0.08333333) ;; 1/12, add small phase shift so all oscillators don't start in phase @@ -341,7 +341,7 @@ ;; Stereo: also push the right channel (stack in l r order) ;;------------------------------------------------------------------------------- (func $su_op_in (param $stereo i32) (local $addr i32) - call $scanValueByte + call $scanOperand {{- if .Stereo "in"}} (i32.add (local.get $stereo)) ;; start from right channel if stereo {{- end}} diff --git a/vm/go_synth.go b/vm/go_synth.go index 1acd252..0014122 100644 --- a/vm/go_synth.go +++ b/vm/go_synth.go @@ -117,10 +117,10 @@ func (s *GoSynth) Update(patch sointu.Patch, bpm int) error { if err != nil { return fmt.Errorf("error compiling %v", err) } - needsRefresh := len(bytecode.Commands) != len(s.bytecode.Commands) + needsRefresh := len(bytecode.Opcodes) != len(s.bytecode.Opcodes) if !needsRefresh { - for i, c := range bytecode.Commands { - if s.bytecode.Commands[i] != c { + for i, c := range bytecode.Opcodes { + if s.bytecode.Opcodes[i] != c { needsRefresh = true break } @@ -151,16 +151,16 @@ func (s *GoSynth) Render(buffer sointu.AudioBuffer, maxtime int) (samples int, t stack = append(stack, []float32{0, 0, 0, 0}...) synth := &s.synth for time < maxtime && len(buffer) > 0 { - commandInstr := s.bytecode.Commands - valuesInstr := s.bytecode.Values - commands, values := commandInstr, valuesInstr + opcodesInstr := s.bytecode.Opcodes + operandsInstr := s.bytecode.Operands + opcodes, operands := opcodesInstr, operandsInstr delaylines := s.delaylines voicesRemaining := s.bytecode.NumVoices voices := s.synth.voices[:] units := voices[0].units[:] for voicesRemaining > 0 { - op := commands[0] - commands = commands[1:] + op := opcodes[0] + opcodes = opcodes[1:] channels := int((op & 1) + 1) stereo := channels == 2 opNoStereo := (op & 0xFE) >> 1 @@ -171,23 +171,23 @@ func (s *GoSynth) Render(buffer sointu.AudioBuffer, maxtime int) (samples int, t units = voices[0].units[:] } if mask := uint32(1) << uint32(voicesRemaining); s.bytecode.PolyphonyBitmask&mask == mask { - commands, values = commandInstr, valuesInstr + opcodes, operands = opcodesInstr, operandsInstr } else { - commandInstr, valuesInstr = commands, values + opcodesInstr, operandsInstr = opcodes, operands } continue } tcount := transformCounts[opNoStereo-1] - if len(values) < tcount { - return samples, time, errors.New("value stream ended prematurely") + if len(operands) < tcount { + return samples, time, errors.New("operand stream ended prematurely") } voice := &voices[0] unit := &units[0] - valuesAtTransform := values + operandsAtTransform := operands for i := 0; i < tcount; i++ { - params[i] = float32(values[0])/128.0 + unit.ports[i] + params[i] = float32(operands[0])/128.0 + unit.ports[i] unit.ports[i] = 0 - values = values[1:] + operands = operands[1:] } l := len(stack) switch opNoStereo { @@ -276,7 +276,7 @@ func (s *GoSynth) Render(buffer sointu.AudioBuffer, maxtime int) (samples int, t } case opAux: var channel byte - channel, values = values[0], values[1:] + channel, operands = operands[0], operands[1:] if stereo { synth.outputs[channel+1] += params[0] * stack[l-2] } @@ -290,7 +290,7 @@ func (s *GoSynth) Render(buffer sointu.AudioBuffer, maxtime int) (samples int, t stack = stack[:l-1] case opIn: var channel byte - channel, values = values[0], values[1:] + channel, operands = operands[0], operands[1:] if stereo { stack = append(stack, synth.outputs[channel+1]) synth.outputs[channel+1] = 0 @@ -368,7 +368,7 @@ func (s *GoSynth) Render(buffer sointu.AudioBuffer, maxtime int) (samples int, t } case opSend: var addrLow, addrHigh byte - addrLow, addrHigh, values = values[0], values[1], values[2:] + addrLow, addrHigh, operands = operands[0], operands[1], operands[2:] addr := (uint16(addrHigh) << 8) + uint16(addrLow) targetVoice := voice if addr&0x8000 == 0x8000 { @@ -408,7 +408,7 @@ func (s *GoSynth) Render(buffer sointu.AudioBuffer, maxtime int) (samples int, t freq2 := params[0] * params[0] res := params[1] var flags byte - flags, values = values[0], values[1:] + flags, operands = operands[0], operands[1:] for i := 0; i < channels; i++ { low, band := unit.state[0+i], unit.state[2+i] low += freq2 * band @@ -435,7 +435,7 @@ func (s *GoSynth) Render(buffer sointu.AudioBuffer, maxtime int) (samples int, t } case opOscillator: var flags byte - flags, values = values[0], values[1:] + flags, operands = operands[0], operands[1:] detuneStereo := params[1]*2 - 1 unison := flags & 3 for i := 0; i < channels; i++ { @@ -460,7 +460,7 @@ func (s *GoSynth) Render(buffer sointu.AudioBuffer, maxtime int) (samples int, t if flags&0x80 == 0x80 { // if this is a sample oscillator phase := *statevar phase += params[2] - sampleno := valuesAtTransform[3] // reuse color as the sample number + sampleno := operandsAtTransform[3] // reuse color as the sample number sampleoffset := s.bytecode.SampleOffsets[sampleno] sampleindex := int(phase*84.28074964676522 + 0.5) loopstart := int(sampleoffset.LoopStart) @@ -495,7 +495,7 @@ func (s *GoSynth) Render(buffer sointu.AudioBuffer, maxtime int) (samples int, t amplitude = 1 } case flags&0x4 == 0x4: // Gate - maskLow, maskHigh := valuesAtTransform[3], valuesAtTransform[4] + maskLow, maskHigh := operandsAtTransform[3], operandsAtTransform[4] gateBits := (int(maskHigh) << 8) + int(maskLow) amplitude = float32((gateBits >> (int(phase*16+.5) & 15)) & 1) g := unit.state[4+i] // warning: still fucks up with unison = 3 @@ -522,7 +522,7 @@ func (s *GoSynth) Render(buffer sointu.AudioBuffer, maxtime int) (samples int, t damp := params[3] feedback := params[2] var index, count byte - index, count, values = values[0], values[1], values[2:] + index, count, operands = operands[0], operands[1], operands[2:] t := uint16(s.synth.globalTime) stackIndex := l - channels for i := 0; i < channels; i++ {