diff --git a/sound_algo/data_only/matrix.scd b/sound_algo/data_only/matrix.scd index 36bd5de..b9750aa 100644 --- a/sound_algo/data_only/matrix.scd +++ b/sound_algo/data_only/matrix.scd @@ -39,12 +39,12 @@ // -- default color defs reproduce the historical global variation table -- ~matDefaultColorDefs = { [ nil, - (stretch: 1.0, octave: 0, amp: 1.0, inst: nil, cutoff: nil, pan: nil), - (stretch: 0.5, octave: 0, amp: 1.0, inst: nil, cutoff: nil, pan: nil), - (stretch: 1.0, octave: 1, amp: 1.0, inst: nil, cutoff: nil, pan: nil), - (stretch: 2.0, octave: 0, amp: 1.0, inst: nil, cutoff: nil, pan: nil), - (stretch: 1.0, octave: -1, amp: 1.05, inst: nil, cutoff: nil, pan: nil), - (stretch: 0.5, octave: 0, amp: 1.2, inst: nil, cutoff: nil, pan: nil) ] + (stretch: 1.0, octave: 0, amp: 1.0, inst: nil, cutoff: nil, pan: nil, steps: Array.fill(16, nil)), + (stretch: 0.5, octave: 0, amp: 1.0, inst: nil, cutoff: nil, pan: nil, steps: Array.fill(16, nil)), + (stretch: 1.0, octave: 1, amp: 1.0, inst: nil, cutoff: nil, pan: nil, steps: Array.fill(16, nil)), + (stretch: 2.0, octave: 0, amp: 1.0, inst: nil, cutoff: nil, pan: nil, steps: Array.fill(16, nil)), + (stretch: 1.0, octave: -1, amp: 1.05, inst: nil, cutoff: nil, pan: nil, steps: Array.fill(16, nil)), + (stretch: 0.5, octave: 0, amp: 1.2, inst: nil, cutoff: nil, pan: nil, steps: Array.fill(16, nil)) ] }; ~matColorDefs = ~matColorDefs ? Array.fill(~matVoices.size, { ~matDefaultColorDefs.value }); @@ -435,6 +435,48 @@ File.exists(~matDir).not.if({ ("mkdir -p " ++ ~matDir.quote).systemCmd }); } }; +// -- ~matStepsEmpty : true when no step has a note (all rests) -- +~matStepsEmpty = { |steps| steps.isNil or: { steps.every({ |s| s.isNil }) } }; + +// -- ~matSetStep : write one step (degree \rest/nil clears), re-source, echo -- +~matSetStep = { |vi, color, stepIdx, degree, vel| + ((vi >= 0 and: { vi < ~matVoices.size }) and: { color >= 1 and: { color <= 6 } } + and: { stepIdx >= 0 and: { stepIdx < 16 } }).if({ + var steps = ~matColorDefs[vi][color][\steps]; + ((degree == \rest) or: { degree.isNil }).if({ + steps[stepIdx] = nil + }, { + steps[stepIdx] = (degree: degree.asInteger, vel: vel.asFloat.clip(0, 1)) + }); + ~matLastColor[vi] = -1; + (~lp[\matPlaying] and: { ~matApplyBar.notNil }).if({ ~matApplyBar.(~lp[\matBar]) }); + ~matStepsPush.(vi, color) + }) +}; + +// -- ~matStepsPush : send one color's 16 steps (degree, vel); rest -> (-99, 0) -- +~matStepsPush = { |vi, color| + ~toscSend !? { + var flat = ~matColorDefs[vi][color][\steps].collect({ |s| + s.isNil.if({ [-99, 0] }, { [s[\degree], s[\vel]] }) + }).flatten; + ~toscSend.valueArray(["/matrix/steps", vi, color] ++ flat) + } +}; + +OSCdef(\mat_step, { |msg, time, addr| + var deg; + ~toscTouch !? { ~toscTouch.(addr) }; + deg = ((msg[4] ? -99) == -99).if({ \rest }, { msg[4] }); + ~matSetStep.((msg[1] ? 0).asInteger, (msg[2] ? 1).asInteger, (msg[3] ? 0).asInteger, + deg, (msg[5] ? 0)) +}, '/matrix/step'); + +OSCdef(\mat_steps_get, { |msg, time, addr| + ~toscTouch !? { ~toscTouch.(addr) }; + (1..6).do { |c| ~matStepsPush.((msg[1] ? 0).asInteger, c) } +}, '/matrix/steps/get'); + // -- ~matModPush : send 16 mod triples (source,target,depth) flattened -- ~matModPush = { ~toscSend !? { diff --git a/sound_algo/data_only/test/test_matrix.scd b/sound_algo/data_only/test/test_matrix.scd index 3524a83..602e3c1 100644 --- a/sound_algo/data_only/test/test_matrix.scd +++ b/sound_algo/data_only/test/test_matrix.scd @@ -365,6 +365,25 @@ pass = pass and: { ~matColorDefs[6][2][\inst] == \do_strike }; pass = pass and: { ~matVariation.(\acid, 1, 5).asStream.next(()).notNil }; +// --- Step sequencer state (Task 1) --- +pass = pass and: { ~matStepsEmpty.notNil and: { ~matSetStep.notNil and: { ~matStepsPush.notNil } } }; +// default: every color's steps is a 16-slot all-nil array -> empty +pass = pass and: { ~matColorDefs[5][2][\steps].size == 16 }; +pass = pass and: { ~matStepsEmpty.(~matColorDefs[5][2][\steps]) }; +// set a step, then not empty; step holds degree+vel +~trigLog = nil; +~toscSend = { |path ...args| ~trigLog = ([path] ++ args) }; +~matSetStep.(5, 2, 3, 7, 0.8); +pass = pass and: { ~matColorDefs[5][2][\steps][3][\degree] == 7 }; +pass = pass and: { ~matColorDefs[5][2][\steps][3][\vel] == 0.8 }; +pass = pass and: { ~matStepsEmpty.(~matColorDefs[5][2][\steps]).not }; +pass = pass and: { ~trigLog[0] == "/matrix/steps" and: { ~trigLog[1] == 5 } }; +pass = pass and: { ~trigLog.size == 35 }; // path + vi + color + 32 vals +// rest clears the step +~matSetStep.(5, 2, 3, \rest, 0); +pass = pass and: { ~matColorDefs[5][2][\steps][3].isNil }; +pass = pass and: { ~matStepsEmpty.(~matColorDefs[5][2][\steps]) }; + pass.if( { "TEST PASS".postln }, { "TEST FAIL".postln }