diff --git a/patch.go b/patch.go index bbabdd5..416d75b 100644 --- a/patch.go +++ b/patch.go @@ -319,7 +319,7 @@ var UnitTypes = map[string]UnitType{ Params: []UnitParameter{ {Name: "stereo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false}, {Name: "amount", MinValue: 0, Neutral: 64, Default: 64, MaxValue: 128, CanSet: true, CanModulate: true, DisplayFunc: func(v int) (string, string) { return formatFloat(float64(v)/64 - 1), "" }}, - {Name: "voice", MinValue: 0, MaxValue: 32, CanSet: true, CanModulate: false, DisplayFunc: func(v int) (string, string) { + {Name: "voice", MinValue: 0, MaxValue: 256, CanSet: true, CanModulate: false, DisplayFunc: func(v int) (string, string) { if v == 0 { return "default", "" } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index c5a0fa1..64149c7 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -174,6 +174,8 @@ regression_test(test_envelope_16bit ENVELOPE "" test_envelope "-i") regression_test(test_polyphony "ENVELOPE;VCO_SINE" POLYPHONY) regression_test(test_polyphony_init POLYPHONY) +regression_test(test_64_voices "ENVELOPE;POLYPHONY" VCO_SINE) + regression_test(test_chords "ENVELOPE;VCO_SINE") regression_test(test_speed "ENVELOPE;VCO_SINE") regression_test(test_sync "ENVELOPE" "" "" "-r") diff --git a/tests/expected_output/test_64_voices.raw b/tests/expected_output/test_64_voices.raw new file mode 100644 index 0000000..48239df Binary files /dev/null and b/tests/expected_output/test_64_voices.raw differ diff --git a/tests/test_64_voices.yml b/tests/test_64_voices.yml new file mode 100644 index 0000000..a13caef --- /dev/null +++ b/tests/test_64_voices.yml @@ -0,0 +1,743 @@ +bpm: 100 +rowsperbeat: 4 +score: + tracks: + - numvoices: 1 + order: [0] + patterns: [[64, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]] + - numvoices: 1 + order: [0] + patterns: [[1, 65, 0]] + - numvoices: 1 + order: [0] + patterns: [[1, 1, 66, 0]] + - numvoices: 1 + order: [0] + patterns: [[1, 1, 1, 67, 0]] + - numvoices: 1 + order: [0] + patterns: [[1, 1, 1, 1, 68, 0]] + - numvoices: 1 + order: [0] + patterns: [[1, 1, 1, 1, 1, 69, 0]] + - numvoices: 1 + order: [0] + patterns: [[1, 1, 1, 1, 1, 1, 70, 0]] + - numvoices: 1 + order: [0] + patterns: [[1, 1, 1, 1, 1, 1, 1, 71, 0]] + - numvoices: 1 + order: [0] + patterns: [[1, 1, 1, 1, 1, 1, 1, 1, 72, 0]] + - numvoices: 1 + order: [0] + patterns: [[1, 1, 1, 1, 1, 1, 1, 1, 1, 73, 0]] + - numvoices: 1 + order: [0] + patterns: [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 74, 0]] + - numvoices: 1 + order: [0] + patterns: [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 75, 0]] + - numvoices: 1 + order: [0] + patterns: [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 76, 0]] + - numvoices: 1 + order: [0] + patterns: [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 77, 0]] + - numvoices: 1 + order: [0] + patterns: [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 78, 0]] + - numvoices: 1 + order: [0, 1] + patterns: [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 79], [0]] + - numvoices: 1 + order: [-1, 0] + patterns: [[80, 0]] + - numvoices: 1 + order: [-1, 0] + patterns: [[1, 81, 0]] + - numvoices: 1 + order: [-1, 0] + patterns: [[1, 1, 82, 0]] + - numvoices: 1 + order: [-1, 0] + patterns: [[1, 1, 1, 83, 0]] + - numvoices: 1 + order: [-1, 0] + patterns: [[1, 1, 1, 1, 84, 0]] + - numvoices: 1 + order: [-1, 0] + patterns: [[1, 1, 1, 1, 1, 85, 0]] + - numvoices: 1 + order: [-1, 0] + patterns: [[1, 1, 1, 1, 1, 1, 86, 0]] + - numvoices: 1 + order: [-1, 0] + patterns: [[1, 1, 1, 1, 1, 1, 1, 87, 0]] + - numvoices: 1 + order: [-1, 0] + patterns: [[1, 1, 1, 1, 1, 1, 1, 1, 88, 0]] + - numvoices: 1 + order: [-1, 0] + patterns: [[1, 1, 1, 1, 1, 1, 1, 1, 1, 89, 0]] + - numvoices: 1 + order: [-1, 0] + patterns: [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 90, 0]] + - numvoices: 1 + order: [-1, 0] + patterns: [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 91, 0]] + - numvoices: 1 + order: [-1, 0] + patterns: [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 92, 0]] + - numvoices: 1 + order: [-1, 0] + patterns: [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 93, 0]] + - numvoices: 1 + order: [-1, 0] + patterns: [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 94, 0]] + - numvoices: 1 + order: [-1, 0] + patterns: [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 95]] + rowsperpattern: 16 + length: 2 +patch: + - numvoices: 2 + units: + - type: envelope + id: 385 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: envelope + id: 386 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: oscillator + id: 387 + parameters: {color: 96, detune: 64, gain: 128, lfo: 0, phase: 0, shape: 64, stereo: 0, transpose: 64, type: 0, unison: 0} + - type: oscillator + id: 388 + parameters: {color: 64, detune: 64, gain: 128, lfo: 0, phase: 64, shape: 96, stereo: 0, transpose: 72, type: 0, unison: 0} + - type: mulp + id: 389 + parameters: {stereo: 1} + - type: out + id: 390 + parameters: {gain: 128, stereo: 1} + - numvoices: 2 + units: + - type: envelope + id: 379 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: envelope + id: 380 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: oscillator + id: 381 + parameters: {color: 96, detune: 64, gain: 128, lfo: 0, phase: 0, shape: 64, stereo: 0, transpose: 64, type: 0, unison: 0} + - type: oscillator + id: 382 + parameters: {color: 64, detune: 64, gain: 128, lfo: 0, phase: 64, shape: 96, stereo: 0, transpose: 72, type: 0, unison: 0} + - type: mulp + id: 383 + parameters: {stereo: 1} + - type: out + id: 384 + parameters: {gain: 128, stereo: 1} + - numvoices: 2 + units: + - type: envelope + id: 373 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: envelope + id: 374 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: oscillator + id: 375 + parameters: {color: 96, detune: 64, gain: 128, lfo: 0, phase: 0, shape: 64, stereo: 0, transpose: 64, type: 0, unison: 0} + - type: oscillator + id: 376 + parameters: {color: 64, detune: 64, gain: 128, lfo: 0, phase: 64, shape: 96, stereo: 0, transpose: 72, type: 0, unison: 0} + - type: mulp + id: 377 + parameters: {stereo: 1} + - type: out + id: 378 + parameters: {gain: 128, stereo: 1} + - numvoices: 2 + units: + - type: envelope + id: 367 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: envelope + id: 368 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: oscillator + id: 369 + parameters: {color: 96, detune: 64, gain: 128, lfo: 0, phase: 0, shape: 64, stereo: 0, transpose: 64, type: 0, unison: 0} + - type: oscillator + id: 370 + parameters: {color: 64, detune: 64, gain: 128, lfo: 0, phase: 64, shape: 96, stereo: 0, transpose: 72, type: 0, unison: 0} + - type: mulp + id: 371 + parameters: {stereo: 1} + - type: out + id: 372 + parameters: {gain: 128, stereo: 1} + - numvoices: 2 + units: + - type: envelope + id: 361 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: envelope + id: 362 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: oscillator + id: 363 + parameters: {color: 96, detune: 64, gain: 128, lfo: 0, phase: 0, shape: 64, stereo: 0, transpose: 64, type: 0, unison: 0} + - type: oscillator + id: 364 + parameters: {color: 64, detune: 64, gain: 128, lfo: 0, phase: 64, shape: 96, stereo: 0, transpose: 72, type: 0, unison: 0} + - type: mulp + id: 365 + parameters: {stereo: 1} + - type: out + id: 366 + parameters: {gain: 128, stereo: 1} + - numvoices: 2 + units: + - type: envelope + id: 355 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: envelope + id: 356 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: oscillator + id: 357 + parameters: {color: 96, detune: 64, gain: 128, lfo: 0, phase: 0, shape: 64, stereo: 0, transpose: 64, type: 0, unison: 0} + - type: oscillator + id: 358 + parameters: {color: 64, detune: 64, gain: 128, lfo: 0, phase: 64, shape: 96, stereo: 0, transpose: 72, type: 0, unison: 0} + - type: mulp + id: 359 + parameters: {stereo: 1} + - type: out + id: 360 + parameters: {gain: 128, stereo: 1} + - numvoices: 2 + units: + - type: envelope + id: 349 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: envelope + id: 350 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: oscillator + id: 351 + parameters: {color: 96, detune: 64, gain: 128, lfo: 0, phase: 0, shape: 64, stereo: 0, transpose: 64, type: 0, unison: 0} + - type: oscillator + id: 352 + parameters: {color: 64, detune: 64, gain: 128, lfo: 0, phase: 64, shape: 96, stereo: 0, transpose: 72, type: 0, unison: 0} + - type: mulp + id: 353 + parameters: {stereo: 1} + - type: out + id: 354 + parameters: {gain: 128, stereo: 1} + - numvoices: 2 + units: + - type: envelope + id: 343 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: envelope + id: 344 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: oscillator + id: 345 + parameters: {color: 96, detune: 64, gain: 128, lfo: 0, phase: 0, shape: 64, stereo: 0, transpose: 64, type: 0, unison: 0} + - type: oscillator + id: 346 + parameters: {color: 64, detune: 64, gain: 128, lfo: 0, phase: 64, shape: 96, stereo: 0, transpose: 72, type: 0, unison: 0} + - type: mulp + id: 347 + parameters: {stereo: 1} + - type: out + id: 348 + parameters: {gain: 128, stereo: 1} + - numvoices: 2 + units: + - type: envelope + id: 337 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: envelope + id: 338 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: oscillator + id: 339 + parameters: {color: 96, detune: 64, gain: 128, lfo: 0, phase: 0, shape: 64, stereo: 0, transpose: 64, type: 0, unison: 0} + - type: oscillator + id: 340 + parameters: {color: 64, detune: 64, gain: 128, lfo: 0, phase: 64, shape: 96, stereo: 0, transpose: 72, type: 0, unison: 0} + - type: mulp + id: 341 + parameters: {stereo: 1} + - type: out + id: 342 + parameters: {gain: 128, stereo: 1} + - numvoices: 2 + units: + - type: envelope + id: 331 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: envelope + id: 332 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: oscillator + id: 333 + parameters: {color: 96, detune: 64, gain: 128, lfo: 0, phase: 0, shape: 64, stereo: 0, transpose: 64, type: 0, unison: 0} + - type: oscillator + id: 334 + parameters: {color: 64, detune: 64, gain: 128, lfo: 0, phase: 64, shape: 96, stereo: 0, transpose: 72, type: 0, unison: 0} + - type: mulp + id: 335 + parameters: {stereo: 1} + - type: out + id: 336 + parameters: {gain: 128, stereo: 1} + - numvoices: 2 + units: + - type: envelope + id: 325 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: envelope + id: 326 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: oscillator + id: 327 + parameters: {color: 96, detune: 64, gain: 128, lfo: 0, phase: 0, shape: 64, stereo: 0, transpose: 64, type: 0, unison: 0} + - type: oscillator + id: 328 + parameters: {color: 64, detune: 64, gain: 128, lfo: 0, phase: 64, shape: 96, stereo: 0, transpose: 72, type: 0, unison: 0} + - type: mulp + id: 329 + parameters: {stereo: 1} + - type: out + id: 330 + parameters: {gain: 128, stereo: 1} + - numvoices: 2 + units: + - type: envelope + id: 319 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: envelope + id: 320 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: oscillator + id: 321 + parameters: {color: 96, detune: 64, gain: 128, lfo: 0, phase: 0, shape: 64, stereo: 0, transpose: 64, type: 0, unison: 0} + - type: oscillator + id: 322 + parameters: {color: 64, detune: 64, gain: 128, lfo: 0, phase: 64, shape: 96, stereo: 0, transpose: 72, type: 0, unison: 0} + - type: mulp + id: 323 + parameters: {stereo: 1} + - type: out + id: 324 + parameters: {gain: 128, stereo: 1} + - numvoices: 2 + units: + - type: envelope + id: 313 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: envelope + id: 314 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: oscillator + id: 315 + parameters: {color: 96, detune: 64, gain: 128, lfo: 0, phase: 0, shape: 64, stereo: 0, transpose: 64, type: 0, unison: 0} + - type: oscillator + id: 316 + parameters: {color: 64, detune: 64, gain: 128, lfo: 0, phase: 64, shape: 96, stereo: 0, transpose: 72, type: 0, unison: 0} + - type: mulp + id: 317 + parameters: {stereo: 1} + - type: out + id: 318 + parameters: {gain: 128, stereo: 1} + - numvoices: 2 + units: + - type: envelope + id: 307 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: envelope + id: 308 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: oscillator + id: 309 + parameters: {color: 96, detune: 64, gain: 128, lfo: 0, phase: 0, shape: 64, stereo: 0, transpose: 64, type: 0, unison: 0} + - type: oscillator + id: 310 + parameters: {color: 64, detune: 64, gain: 128, lfo: 0, phase: 64, shape: 96, stereo: 0, transpose: 72, type: 0, unison: 0} + - type: mulp + id: 311 + parameters: {stereo: 1} + - type: out + id: 312 + parameters: {gain: 128, stereo: 1} + - numvoices: 2 + units: + - type: envelope + id: 301 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: envelope + id: 302 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: oscillator + id: 303 + parameters: {color: 96, detune: 64, gain: 128, lfo: 0, phase: 0, shape: 64, stereo: 0, transpose: 64, type: 0, unison: 0} + - type: oscillator + id: 304 + parameters: {color: 64, detune: 64, gain: 128, lfo: 0, phase: 64, shape: 96, stereo: 0, transpose: 72, type: 0, unison: 0} + - type: mulp + id: 305 + parameters: {stereo: 1} + - type: out + id: 306 + parameters: {gain: 128, stereo: 1} + - numvoices: 2 + units: + - type: envelope + id: 391 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: envelope + id: 392 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: oscillator + id: 393 + parameters: {color: 96, detune: 64, gain: 128, lfo: 0, phase: 0, shape: 64, stereo: 0, transpose: 64, type: 0, unison: 0} + - type: oscillator + id: 394 + parameters: {color: 64, detune: 64, gain: 128, lfo: 0, phase: 64, shape: 96, stereo: 0, transpose: 72, type: 0, unison: 0} + - type: mulp + id: 395 + parameters: {stereo: 1} + - type: out + id: 396 + parameters: {gain: 128, stereo: 1} + - numvoices: 2 + units: + - type: envelope + id: 397 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: envelope + id: 398 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: oscillator + id: 399 + parameters: {color: 96, detune: 64, gain: 128, lfo: 0, phase: 0, shape: 64, stereo: 0, transpose: 64, type: 0, unison: 0} + - type: oscillator + id: 400 + parameters: {color: 64, detune: 64, gain: 128, lfo: 0, phase: 64, shape: 96, stereo: 0, transpose: 72, type: 0, unison: 0} + - type: mulp + id: 401 + parameters: {stereo: 1} + - type: out + id: 402 + parameters: {gain: 128, stereo: 1} + - numvoices: 2 + units: + - type: envelope + id: 403 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: envelope + id: 404 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: oscillator + id: 405 + parameters: {color: 96, detune: 64, gain: 128, lfo: 0, phase: 0, shape: 64, stereo: 0, transpose: 64, type: 0, unison: 0} + - type: oscillator + id: 406 + parameters: {color: 64, detune: 64, gain: 128, lfo: 0, phase: 64, shape: 96, stereo: 0, transpose: 72, type: 0, unison: 0} + - type: mulp + id: 407 + parameters: {stereo: 1} + - type: out + id: 408 + parameters: {gain: 128, stereo: 1} + - numvoices: 2 + units: + - type: envelope + id: 409 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: envelope + id: 410 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: oscillator + id: 411 + parameters: {color: 96, detune: 64, gain: 128, lfo: 0, phase: 0, shape: 64, stereo: 0, transpose: 64, type: 0, unison: 0} + - type: oscillator + id: 412 + parameters: {color: 64, detune: 64, gain: 128, lfo: 0, phase: 64, shape: 96, stereo: 0, transpose: 72, type: 0, unison: 0} + - type: mulp + id: 413 + parameters: {stereo: 1} + - type: out + id: 414 + parameters: {gain: 128, stereo: 1} + - numvoices: 2 + units: + - type: envelope + id: 415 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: envelope + id: 416 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: oscillator + id: 417 + parameters: {color: 96, detune: 64, gain: 128, lfo: 0, phase: 0, shape: 64, stereo: 0, transpose: 64, type: 0, unison: 0} + - type: oscillator + id: 418 + parameters: {color: 64, detune: 64, gain: 128, lfo: 0, phase: 64, shape: 96, stereo: 0, transpose: 72, type: 0, unison: 0} + - type: mulp + id: 419 + parameters: {stereo: 1} + - type: out + id: 420 + parameters: {gain: 128, stereo: 1} + - numvoices: 2 + units: + - type: envelope + id: 421 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: envelope + id: 422 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: oscillator + id: 423 + parameters: {color: 96, detune: 64, gain: 128, lfo: 0, phase: 0, shape: 64, stereo: 0, transpose: 64, type: 0, unison: 0} + - type: oscillator + id: 424 + parameters: {color: 64, detune: 64, gain: 128, lfo: 0, phase: 64, shape: 96, stereo: 0, transpose: 72, type: 0, unison: 0} + - type: mulp + id: 425 + parameters: {stereo: 1} + - type: out + id: 426 + parameters: {gain: 128, stereo: 1} + - numvoices: 2 + units: + - type: envelope + id: 427 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: envelope + id: 428 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: oscillator + id: 429 + parameters: {color: 96, detune: 64, gain: 128, lfo: 0, phase: 0, shape: 64, stereo: 0, transpose: 64, type: 0, unison: 0} + - type: oscillator + id: 430 + parameters: {color: 64, detune: 64, gain: 128, lfo: 0, phase: 64, shape: 96, stereo: 0, transpose: 72, type: 0, unison: 0} + - type: mulp + id: 431 + parameters: {stereo: 1} + - type: out + id: 432 + parameters: {gain: 128, stereo: 1} + - numvoices: 2 + units: + - type: envelope + id: 433 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: envelope + id: 434 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: oscillator + id: 435 + parameters: {color: 96, detune: 64, gain: 128, lfo: 0, phase: 0, shape: 64, stereo: 0, transpose: 64, type: 0, unison: 0} + - type: oscillator + id: 436 + parameters: {color: 64, detune: 64, gain: 128, lfo: 0, phase: 64, shape: 96, stereo: 0, transpose: 72, type: 0, unison: 0} + - type: mulp + id: 437 + parameters: {stereo: 1} + - type: out + id: 438 + parameters: {gain: 128, stereo: 1} + - numvoices: 2 + units: + - type: envelope + id: 439 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: envelope + id: 440 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: oscillator + id: 441 + parameters: {color: 96, detune: 64, gain: 128, lfo: 0, phase: 0, shape: 64, stereo: 0, transpose: 64, type: 0, unison: 0} + - type: oscillator + id: 442 + parameters: {color: 64, detune: 64, gain: 128, lfo: 0, phase: 64, shape: 96, stereo: 0, transpose: 72, type: 0, unison: 0} + - type: mulp + id: 443 + parameters: {stereo: 1} + - type: out + id: 444 + parameters: {gain: 128, stereo: 1} + - numvoices: 2 + units: + - type: envelope + id: 445 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: envelope + id: 446 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: oscillator + id: 447 + parameters: {color: 96, detune: 64, gain: 128, lfo: 0, phase: 0, shape: 64, stereo: 0, transpose: 64, type: 0, unison: 0} + - type: oscillator + id: 448 + parameters: {color: 64, detune: 64, gain: 128, lfo: 0, phase: 64, shape: 96, stereo: 0, transpose: 72, type: 0, unison: 0} + - type: mulp + id: 449 + parameters: {stereo: 1} + - type: out + id: 450 + parameters: {gain: 128, stereo: 1} + - numvoices: 2 + units: + - type: envelope + id: 451 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: envelope + id: 452 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: oscillator + id: 453 + parameters: {color: 96, detune: 64, gain: 128, lfo: 0, phase: 0, shape: 64, stereo: 0, transpose: 64, type: 0, unison: 0} + - type: oscillator + id: 454 + parameters: {color: 64, detune: 64, gain: 128, lfo: 0, phase: 64, shape: 96, stereo: 0, transpose: 72, type: 0, unison: 0} + - type: mulp + id: 455 + parameters: {stereo: 1} + - type: out + id: 456 + parameters: {gain: 128, stereo: 1} + - numvoices: 2 + units: + - type: envelope + id: 457 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: envelope + id: 458 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: oscillator + id: 459 + parameters: {color: 96, detune: 64, gain: 128, lfo: 0, phase: 0, shape: 64, stereo: 0, transpose: 64, type: 0, unison: 0} + - type: oscillator + id: 460 + parameters: {color: 64, detune: 64, gain: 128, lfo: 0, phase: 64, shape: 96, stereo: 0, transpose: 72, type: 0, unison: 0} + - type: mulp + id: 461 + parameters: {stereo: 1} + - type: out + id: 462 + parameters: {gain: 128, stereo: 1} + - numvoices: 2 + units: + - type: envelope + id: 463 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: envelope + id: 464 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: oscillator + id: 465 + parameters: {color: 96, detune: 64, gain: 128, lfo: 0, phase: 0, shape: 64, stereo: 0, transpose: 64, type: 0, unison: 0} + - type: oscillator + id: 466 + parameters: {color: 64, detune: 64, gain: 128, lfo: 0, phase: 64, shape: 96, stereo: 0, transpose: 72, type: 0, unison: 0} + - type: mulp + id: 467 + parameters: {stereo: 1} + - type: out + id: 468 + parameters: {gain: 128, stereo: 1} + - numvoices: 2 + units: + - type: envelope + id: 469 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: envelope + id: 470 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: oscillator + id: 471 + parameters: {color: 96, detune: 64, gain: 128, lfo: 0, phase: 0, shape: 64, stereo: 0, transpose: 64, type: 0, unison: 0} + - type: oscillator + id: 472 + parameters: {color: 64, detune: 64, gain: 128, lfo: 0, phase: 64, shape: 96, stereo: 0, transpose: 72, type: 0, unison: 0} + - type: mulp + id: 473 + parameters: {stereo: 1} + - type: out + id: 474 + parameters: {gain: 128, stereo: 1} + - numvoices: 2 + units: + - type: envelope + id: 475 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: envelope + id: 476 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: oscillator + id: 477 + parameters: {color: 96, detune: 64, gain: 128, lfo: 0, phase: 0, shape: 64, stereo: 0, transpose: 64, type: 0, unison: 0} + - type: oscillator + id: 478 + parameters: {color: 64, detune: 64, gain: 128, lfo: 0, phase: 64, shape: 96, stereo: 0, transpose: 72, type: 0, unison: 0} + - type: mulp + id: 479 + parameters: {stereo: 1} + - type: out + id: 480 + parameters: {gain: 128, stereo: 1} + - numvoices: 2 + units: + - type: envelope + id: 481 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: envelope + id: 482 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: oscillator + id: 483 + parameters: {color: 96, detune: 64, gain: 128, lfo: 0, phase: 0, shape: 64, stereo: 0, transpose: 64, type: 0, unison: 0} + - type: oscillator + id: 484 + parameters: {color: 64, detune: 64, gain: 128, lfo: 0, phase: 64, shape: 96, stereo: 0, transpose: 72, type: 0, unison: 0} + - type: mulp + id: 485 + parameters: {stereo: 1} + - type: out + id: 486 + parameters: {gain: 128, stereo: 1} + - numvoices: 2 + units: + - type: envelope + id: 295 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: envelope + id: 296 + parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64} + - type: oscillator + id: 297 + parameters: {color: 96, detune: 64, gain: 128, lfo: 0, phase: 0, shape: 64, stereo: 0, transpose: 64, type: 0, unison: 0} + - type: oscillator + id: 298 + parameters: {color: 64, detune: 64, gain: 128, lfo: 0, phase: 64, shape: 96, stereo: 0, transpose: 72, type: 0, unison: 0} + - type: mulp + id: 299 + parameters: {stereo: 1} + - type: out + id: 300 + parameters: {gain: 128, stereo: 1} diff --git a/tests/test_oscillator_crash.c b/tests/test_oscillator_crash.c index ebe319b..e805662 100644 --- a/tests/test_oscillator_crash.c +++ b/tests/test_oscillator_crash.c @@ -30,7 +30,8 @@ int main(int argc, char* argv[]) memcpy(synth->Opcodes, opcodes, sizeof(opcodes)); memcpy(synth->Operands, operands, sizeof(operands)); synth->NumVoices = 3; - synth->Polyphony = 6; + memset(synth->Polyphony, 0, sizeof(synth->Polyphony)); + synth->Polyphony[0] = 6; synth->RandSeed = 1; synth->SampleOffsets[0].Start = 91507; synth->SampleOffsets[0].LoopStart = 5448; diff --git a/tests/test_render_samples.c b/tests/test_render_samples.c index 01fffdd..d0aa65f 100644 --- a/tests/test_render_samples.c +++ b/tests/test_render_samples.c @@ -23,7 +23,7 @@ void SU_CALLCONV su_render_song(float *buffer) memcpy(synth->Opcodes, opcodes, sizeof(opcodes)); memcpy(synth->Operands, operands, sizeof(operands)); synth->NumVoices = 1; - synth->Polyphony = 0; + memset(synth->Polyphony, 0, sizeof(synth->Polyphony)); synth->RandSeed = 1; // triger first voice synth->SynthWrk.Voices[0].Note = 64; diff --git a/tests/test_render_samples_api.c b/tests/test_render_samples_api.c index c1d5c6a..b47a436 100644 --- a/tests/test_render_samples_api.c +++ b/tests/test_render_samples_api.c @@ -32,7 +32,7 @@ int main(int argc, char *argv[]) memcpy(synth->Opcodes, opcodes, sizeof(opcodes)); memcpy(synth->Operands, operands, sizeof(operands)); synth->NumVoices = 1; - synth->Polyphony = 0; + memset(synth->Polyphony, 0, sizeof(synth->Polyphony)); synth->RandSeed = 1; // initialize Buffer buffer = (float *)malloc(2 * sizeof(float) * su_max_samples); diff --git a/tracker/derived.go b/tracker/derived.go index 2683288..1971d3b 100644 --- a/tracker/derived.go +++ b/tracker/derived.go @@ -212,7 +212,7 @@ func (m *Model) buildPatternUseCounts(track sointu.Track) []int { func (m *Model) updateRails() { type stackElem struct{ instr, unit int } - scratchArray := [32]stackElem{} + scratchArray := [256]stackElem{} scratch := scratchArray[:0] m.derived.railError = RailError{} for i, instr := range m.d.Song.Patch { diff --git a/vm/bytecode.go b/vm/bytecode.go index 7a57a4f..1402460 100644 --- a/vm/bytecode.go +++ b/vm/bytecode.go @@ -42,7 +42,7 @@ type ( // example, if first instrument has 3 voices, second instrument has 2 // voices, and third instrument four voices, the PolyphonyBitmask is: (MSB) // 110101110 (LSB) - PolyphonyBitmask uint32 + PolyphonyBitmask []byte // NumVoices is the total number of voices in the patch NumVoices uint32 @@ -69,8 +69,8 @@ type bytecodeBuilder struct { } func NewBytecode(patch sointu.Patch, featureSet FeatureSet, bpm int) (*Bytecode, error) { - if patch.NumVoices() > 32 { - return nil, fmt.Errorf("Sointu does not support more than 32 concurrent voices; patch uses %v", patch.NumVoices()) + if patch.NumVoices() > MAX_VOICES { + return nil, fmt.Errorf("Sointu does not support more than %d concurrent voices; patch uses %v", MAX_VOICES, patch.NumVoices()) } b := newBytecodeBuilder(patch, bpm) for instrIndex, instr := range patch { @@ -213,12 +213,13 @@ func NewBytecode(patch sointu.Patch, featureSet FeatureSet, bpm int) (*Bytecode, } func newBytecodeBuilder(patch sointu.Patch, bpm int) *bytecodeBuilder { - var polyphonyBitmask uint32 = 0 + var polyphonyBitmask []byte = make([]byte, (patch.NumVoices()+7)/8) // 1 bit per voice, rounded up to full bytes for _, instr := range patch { for j := 0; j < instr.NumVoices-1; j++ { - polyphonyBitmask = (polyphonyBitmask << 1) + 1 // for each instrument, NumVoices - 1 bits are ones + shiftLeftMask(polyphonyBitmask) + polyphonyBitmask[0] += 1 // for each instrument, NumVoices - 1 bits are ones } - polyphonyBitmask <<= 1 // ...and the last bit is zero, to denote "change instrument" + shiftLeftMask(polyphonyBitmask) // ...and the last bit is zero, to denote "change instrument" } delayTimesInt, delayIndices := constructDelayTimeTable(patch, bpm) delayTimesU16 := make([]uint16, len(delayTimesInt)) @@ -236,6 +237,13 @@ func newBytecodeBuilder(patch sointu.Patch, bpm int) *bytecodeBuilder { return &c } +func shiftLeftMask(b []byte) { + var carry byte = 0 + for i := range b { + carry, b[i] = b[i]&128, (b[i]<<1)+(carry>>7) + } +} + // 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)) diff --git a/vm/compiler/bridge/native_synth.go b/vm/compiler/bridge/native_synth.go index 9ffcd93..288593c 100644 --- a/vm/compiler/bridge/native_synth.go +++ b/vm/compiler/bridge/native_synth.go @@ -49,7 +49,6 @@ func Synth(patch sointu.Patch, bpm int) (*NativeSynth, error) { if len(comPatch.Opcodes) == 0 { s.Opcodes[0] = 0 s.NumVoices = 1 - s.Polyphony = 0 return &NativeSynth{csynth: *s}, nil } for i, v := range comPatch.Opcodes { @@ -67,7 +66,9 @@ func Synth(patch sointu.Patch, bpm int) (*NativeSynth, error) { s.SampleOffsets[i].LoopLength = (C.ushort)(v.LoopLength) } s.NumVoices = C.uint(comPatch.NumVoices) - s.Polyphony = C.uint(comPatch.PolyphonyBitmask) + for i, v := range comPatch.PolyphonyBitmask { + s.Polyphony[i] = (C.uchar)(v) + } s.RandSeed = 1 return &NativeSynth{csynth: *s}, nil } @@ -160,7 +161,6 @@ func (bridgesynth *NativeSynth) Update(patch sointu.Patch, bpm int) error { if len(comPatch.Opcodes) == 0 { s.Opcodes[0] = 0 s.NumVoices = 1 - s.Polyphony = 0 return nil } needsRefresh := false @@ -182,7 +182,9 @@ func (bridgesynth *NativeSynth) Update(patch sointu.Patch, bpm int) error { s.SampleOffsets[i].LoopLength = (C.ushort)(v.LoopLength) } s.NumVoices = C.uint(comPatch.NumVoices) - s.Polyphony = C.uint(comPatch.PolyphonyBitmask) + for i, v := range comPatch.PolyphonyBitmask { + s.Polyphony[i] = (C.uchar)(v) + } if needsRefresh { for i := range s.SynthWrk.Voices { // if any of the opcodes change, we retrigger all units diff --git a/vm/compiler/song_macros.go b/vm/compiler/song_macros.go index e47d5e4..e6e363b 100644 --- a/vm/compiler/song_macros.go +++ b/vm/compiler/song_macros.go @@ -6,7 +6,8 @@ import ( type SongMacros struct { Song *sointu.Song - VoiceTrackBitmask int + VoiceTrackBitmask []byte + HasVoiceTrack bool MaxSamples int } @@ -14,9 +15,13 @@ func NewSongMacros(s *sointu.Song) *SongMacros { maxSamples := s.SamplesPerRow() * s.Score.LengthInRows() p := SongMacros{Song: s, MaxSamples: maxSamples} trackVoiceNumber := 0 + p.VoiceTrackBitmask = make([]byte, (s.Score.NumVoices()+7)/8) for _, t := range s.Score.Tracks { + if t.NumVoices > 0 { + p.HasVoiceTrack = true + } for b := 0; b < t.NumVoices-1; b++ { - p.VoiceTrackBitmask += 1 << trackVoiceNumber + p.VoiceTrackBitmask[trackVoiceNumber/8] += 1 << (trackVoiceNumber % 8) trackVoiceNumber++ } trackVoiceNumber++ // set all bits except last one diff --git a/vm/compiler/templates/amd64-386/library.asm b/vm/compiler/templates/amd64-386/library.asm index 4f5eebe..ac64bb6 100644 --- a/vm/compiler/templates/amd64-386/library.asm +++ b/vm/compiler/templates/amd64-386/library.asm @@ -7,9 +7,9 @@ struc su_synth .sampleoffs resb su_sample_offset.size * 256 .randseed resd 1 .globaltime resd 1 - .opcodes resb 32 * 64 - .operands resb 32 * 64 * 8 - .polyphony resd 1 + .opcodes resb 256 * 64 + .operands resb 256 * 64 * 8 + .polyphony resb 32 .numvoices resd 1 endstruc @@ -68,8 +68,8 @@ su_render_samples_loop: inc dword [{{.Stack "BufSample"}}] ; samples++ mov {{.CX}}, [{{.Stack "SynthState"}}] {{.Push .AX "Sample"}} - mov eax, [{{.CX}} + su_synth.polyphony] - {{.Push .AX "PolyphonyBitmask"}} + lea {{.AX}}, [{{.CX}} + su_synth.polyphony] + {{.Push .AX "PolyphonyBitmaskAddr"}} mov eax, [{{.CX}} + su_synth.numvoices] {{.Push .AX "VoicesRemain"}} lea {{.DX}}, [{{.CX}}+ su_synth.synth_wrk] diff --git a/vm/compiler/templates/amd64-386/library.h b/vm/compiler/templates/amd64-386/library.h index 5a1d85e..7b72c66 100644 --- a/vm/compiler/templates/amd64-386/library.h +++ b/vm/compiler/templates/amd64-386/library.h @@ -23,11 +23,11 @@ typedef struct DelayWorkspace { } DelayWorkspace; typedef struct SynthWorkspace { - unsigned char Curvoices[32]; + unsigned char Curvoices[256]; float Left; float Right; float Aux[6]; - struct Voice Voices[32]; + struct Voice Voices[256]; } SynthWorkspace; typedef struct SampleOffset { @@ -43,9 +43,9 @@ typedef struct Synth { struct SampleOffset SampleOffsets[256]; unsigned int RandSeed; unsigned int GlobalTick; - unsigned char Opcodes[32 * 64]; - unsigned char Operands[32 * 64 * 8]; - unsigned int Polyphony; + unsigned char Opcodes[256 * 64]; + unsigned char Operands[256 * 64 * 8]; + unsigned char Polyphony[32]; unsigned int NumVoices; } Synth; #pragma pack(pop) diff --git a/vm/compiler/templates/amd64-386/patch.asm b/vm/compiler/templates/amd64-386/patch.asm index eded3d0..eba417e 100644 --- a/vm/compiler/templates/amd64-386/patch.asm +++ b/vm/compiler/templates/amd64-386/patch.asm @@ -63,7 +63,13 @@ su_run_vm_advance: mov [{{.Stack "Voice"}}], {{.WRK}} ; update the pointer in the stack to point to the new voice mov ecx, [{{.Stack "VoicesRemain"}}] ; ecx = how many voices remain to process dec ecx ; decrement number of voices to process - bt dword [{{.Stack "PolyphonyBitmask"}}], ecx ; if voice bit of su_polyphonism not set +{{- if .Library}} + mov {{.VAL}}, [{{.Stack "PolyphonyBitmaskAddr"}}] + bt dword [{{.VAL}}], ecx ; if voice bit of su_polyphonism not set +{{- else }} + {{- .Prepare "su_polyphony_bitmask" | indent 4}} + bt dword [{{.Use "su_polyphony_bitmask"}}], ecx ; if voice bit of su_polyphonism not set +{{- end}} jnc su_op_advance_next_instrument ; goto next_instrument mov {{.VAL}}, [{{.Stack "OperandStream"}}] ; if it was set, then repeat the opcodes for the current voice mov {{.COM}}, [{{.Stack "OpcodeStream"}}] diff --git a/vm/compiler/templates/amd64-386/player.asm b/vm/compiler/templates/amd64-386/player.asm index a52efcc..2a2fc93 100644 --- a/vm/compiler/templates/amd64-386/player.asm +++ b/vm/compiler/templates/amd64-386/player.asm @@ -44,9 +44,6 @@ extern syncBuf {{- end}} {{- end}} xor eax, eax - {{- if ne .VoiceTrackBitmask 0}} - {{.Push (.VoiceTrackBitmask | printf "%v") "VoiceTrackBitmask"}} - {{- end}} {{.Push "1" "RandSeed"}} {{.Push .AX "GlobalTick"}} su_render_rowloop: ; loop through every row in the song @@ -55,9 +52,6 @@ su_render_rowloop: ; loop through every row in the song xor eax, eax ; ecx is the current sample within row su_render_sampleloop: ; loop through every sample in the row {{.Push .AX "Sample"}} - {{- if .SupportsPolyphony}} - {{.Push (.PolyphonyBitmask | printf "%v") "PolyphonyBitmask"}} ; does the next voice reuse the current opcodes? - {{- 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_opcodes ; COM points to vm code @@ -68,9 +62,6 @@ su_render_sampleloop: ; loop through every sample in the row lea {{.WRK}}, [{{.DX}} + su_synthworkspace.voices] ; WRK points to the first voice {{.Call "su_run_vm"}} ; run through the VM code {{.Pop .AX}} - {{- if .SupportsPolyphony}} - {{.Pop .AX}} - {{- end}} {{- template "output_sound.asm" .}} ; *ptr++ = left, *ptr++ = right {{.Pop .AX}} inc dword [{{.Stack "GlobalTick"}}] ; increment global time, used by delays @@ -106,7 +97,7 @@ su_render_sampleloop: ; loop through every sample in the row ; Dirty: pretty much everything ;------------------------------------------------------------------------------- {{.Func "su_update_voices"}} -{{- if ne .VoiceTrackBitmask 0}} +{{- if .HasVoiceTrack}} ; The more complicated implementation: one track can trigger multiple voices xor edx, edx mov ebx, {{.PatternLength}} ; we could do xor ebx,ebx; mov bl,PATTERN_SIZE, but that would limit patternsize to 256... @@ -125,7 +116,8 @@ su_update_voices_trackloop: xor edx, edx ; edx=0 mov ecx, ebx ; ecx=first voice of the track to be done su_calculate_voices_loop: ; do { - bt dword [{{.Stack "VoiceTrackBitmask"}} + {{.PTRSIZE}}],ecx ; test voicetrack_bitmask// notice that the incs don't set carry + {{- .Prepare "su_voicetrack_bitmask" | indent 4}} + bt dword [{{.Use "su_voicetrack_bitmask"}}], ecx ; if voice bit of su_polyphonism not set inc edx ; edx++ // edx=numvoices inc ecx ; ecx++ // ecx=the first voice of next track jc su_calculate_voices_loop ; } while bit ecx-1 of bitmask is on @@ -249,6 +241,24 @@ su_update_voices_skipadd: {{.Data "su_patch_operands"}} db {{.Operands | toStrings | join ","}} +{{- if not .Library}} +{{- if .SupportsPolyphony}} +;------------------------------------------------------------------------------- +; PolyphonyBitmask +;------------------------------------------------------------------------------- +{{.Data "su_polyphony_bitmask"}} + db {{.PolyphonyBitmask | toStrings | join ","}} +{{- end}} +{{- end}} + +{{- if .HasVoiceTrack}} +;------------------------------------------------------------------------------- +; VoiceTrackBitmask +;------------------------------------------------------------------------------- +{{.Data "su_voicetrack_bitmask"}} + db {{.VoiceTrackBitmask | toStrings | join ","}} +{{- end}} + ;------------------------------------------------------------------------------- ; Constants ;------------------------------------------------------------------------------- diff --git a/vm/compiler/templates/amd64-386/sinks.asm b/vm/compiler/templates/amd64-386/sinks.asm index dc43c3e..6aea92d 100644 --- a/vm/compiler/templates/amd64-386/sinks.asm +++ b/vm/compiler/templates/amd64-386/sinks.asm @@ -94,6 +94,7 @@ su_op_aux_mono: test ah, 0x80 jz su_op_send_skipglobal mov {{.CX}}, [{{.Stack "Synth"}} + {{.PTRSIZE}}] + lea {{.CX}}, [{{.CX}} + su_synthworkspace.voices - su_unit.size] su_op_send_skipglobal: popf {{- end}} diff --git a/vm/compiler/templates/amd64-386/structs.asm b/vm/compiler/templates/amd64-386/structs.asm index ca9ee73..75d901b 100644 --- a/vm/compiler/templates/amd64-386/structs.asm +++ b/vm/compiler/templates/amd64-386/structs.asm @@ -23,11 +23,11 @@ endstruc ; synthworkspace struct ;------------------------------------------------------------------------------- struc su_synthworkspace - .curvoices resb 32 ; these are used by the multitrack player to store which voice is playing on which track + .curvoices resb 256 ; these are used by the multitrack player to store which voice is playing on which track .left resd 1 .right resd 1 .aux resd 6 ; 3 auxiliary signals - .voices resb 32 * su_voice.size + .voices resb 256 * su_voice.size .size: endstruc diff --git a/vm/go_synth.go b/vm/go_synth.go index 262d8ed..d196eb5 100644 --- a/vm/go_synth.go +++ b/vm/go_synth.go @@ -37,7 +37,7 @@ type ( } ) -const MAX_VOICES = 32 +const MAX_VOICES = 256 const MAX_UNITS = 63 type ( @@ -189,7 +189,7 @@ func (s *GoSynth) Render(buffer sointu.AudioBuffer, maxtime int) (samples int, r voices = voices[1:] units = voices[0].units[:] } - if mask := uint32(1) << uint32(voicesRemaining); s.bytecode.PolyphonyBitmask&mask == mask { + if mask := byte(1) << uint32(voicesRemaining&7); s.bytecode.PolyphonyBitmask[voicesRemaining>>3]&mask == mask { opcodes, operands = opcodesInstr, operandsInstr } else { opcodesInstr, operandsInstr = opcodes, operands