Last active
January 1, 2016 01:19
-
-
Save iani/8071915 to your computer and use it in GitHub Desktop.
Live Hardware Coding basic idea, in SuperCollider
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| // synth definition already written in SynthDef.synthDefDir | |
| ( | |
| SynthDef(\LHCV, { | out=0, clk=1, vclk=2, id=0, step=0, resetVal=0| | |
| var clock, varclock, latch; | |
| clock = LFPulse.kr(clk); | |
| varclock = LFPulse.kr(vclk); | |
| latch = Latch.kr(Stepper.kr(varclock, step: step, resetval: resetVal), clock); | |
| Out.kr(out, SendTrig.kr(Changed.kr(latch), id, latch)) | |
| }).writeOnce; | |
| ) | |
| */ | |
| /* | |
| TODO: | |
| - There is a problem in the initial output of the counter? (must be zero) | |
| - The secondary GUI (Slider) has a problem with it's flashDisplay and the initial position of the slider (though works OK). | |
| - There are 2 dependants: | |
| * see var <>updater | |
| * I suppose it is feasible to have only one update method .. | |
| - I have to fix the getter, setter vars | |
| - ... and embed the slider to the main window !! | |
| */ | |
| /* | |
| a = LHCV().start // see LHC example for musical example | |
| a.counterOut // returns the current value of the Counter | |
| a.vclk // returns the current value of the Var Clk rate (in Hz) | |
| a.counterIn // returns the current input | |
| // set main clk (latched) | |
| a.setClk_(value) | |
| */ | |
| LHCV : LHC { | |
| var <>clk=1, <>vclk=1; | |
| var <>synth; | |
| var <>counterIn=0, <>counterOut=0; | |
| var <>input=0; | |
| var osc; | |
| var <>binaryString; | |
| // the variables for the slider of the Var Clk rate | |
| var <>model, <>setValueFunction, <>bounds, <>windowVClk, <>numberboxVClk, <>sliderVClk, <>updater; | |
| var <posedgeDisplayVClk, <routineFlash; | |
| var <>monitor; | |
| var <x, <y; | |
| *new { | player | | |
| ^super.new.init(player); | |
| } | |
| init { | player | | |
| this.makeFsmDecoder; | |
| this.addPlayer(player); | |
| } | |
| start { | x, y | | |
| this.ugenconstr; | |
| this.oscrespond; | |
| this.makeWindow; | |
| this.makeRoutine; | |
| this.makeSlider; | |
| this.startMonitor; | |
| } | |
| ugenconstr { | clock=1, vclock=1, step=1, resetVal=0 | | |
| Server.default.waitForBoot { | |
| synth = Synth(\LHCV, [clk: clock, vclk: vclock, step: step, resetVal: resetVal]); | |
| } | |
| } | |
| oscrespond { | |
| osc = OSCFunc.newMatching({ arg msg, time; | |
| [time, msg].postln; | |
| counterOut = msg[3]; | |
| counterOut.asInteger.asBinaryString(3).postln; | |
| },'/tr', Server.default.addr); | |
| } | |
| startMonitor { | x, y | | |
| monitor = LHCVmonitor.new(x, y); | |
| } | |
| setInput_ { | value | | |
| input = value; | |
| synth.set(\step, input); | |
| } | |
| setClk_ { | value | | |
| clk = value; | |
| synth.set(\clk, clk); | |
| } | |
| setVClk_ { | value | | |
| vclk = value; | |
| synth.set(\vclk, vclk); | |
| } | |
| makeRoutine { | |
| if (routine.isNil) { | |
| routine = { | |
| loop { | |
| this.flashPositiveEdgeDisplay; | |
| counterIn = ([bit0.value, bit1.value, bit2.value] * [1, 2, 4]).sum; | |
| if (resetbutton.value > 0) { | |
| counterOut = 0; | |
| fsmDecoder.changed(\reset); | |
| "fsmDecoder should now broadcast change RESET".postln; | |
| }{ | |
| // change step in Stepper | |
| this.setInput_(counterIn); | |
| fsmDecoder.changed(\counter, counterOut); | |
| }; | |
| counterDisplay.value = counterOut; | |
| this.calculateFSMstate(counterOut); | |
| // clk is reciprocal because it's value is in Hz | |
| clk.reciprocal.wait; | |
| } | |
| }.fork(AppClock); | |
| } | |
| } | |
| windowClosed { | |
| window = nil; | |
| this.stopSynthsAndProcesses; | |
| fsmDecoder.releaseDependants; | |
| model.releaseDependants; | |
| } | |
| stopSynthsAndProcesses { | |
| routine.stop; | |
| routine = 0; | |
| synth.free; | |
| osc.free; | |
| } | |
| flashPositiveEdgeDisplay { | |
| { | |
| positiveEdgeDisplay.value = 1; | |
| (clk / 3).wait; | |
| positiveEdgeDisplay.value = 0; | |
| (clk / 3).wait; | |
| }.fork(AppClock); | |
| } | |
| calculateFSMstate { | counter | | |
| // current state + input = next state + output | |
| { | |
| counter.asInteger.asBinaryString(3) do: { | digit | | |
| fsmDecoder input: (digit == $1).binaryValue; | |
| // clk is reciprocal because it's value is in Hz (see SynthDef(\LHCV,...) | |
| (clk.reciprocal / 3).wait; | |
| }; | |
| }.fork(AppClock); | |
| } | |
| makeSlider { | |
| if (windowVClk.isNil) { this.prMakeSlider } { windowVClk.front }; | |
| } | |
| prMakeSlider { | |
| this.flashDisplayVClk; | |
| //model | |
| model = (myValue: this.vclk); | |
| setValueFunction = {|value| | |
| model [\myValue] = value; | |
| model.changed(\value, value); | |
| }; | |
| //bounds | |
| bounds = ControlSpec(0.01, 50, \linear, 0.01); // min, max, mapping, step | |
| //view | |
| windowVClk = Window("slider for LHCV", Rect(600,200, 280, 70)); | |
| posedgeDisplayVClk = Button(windowVClk, Rect(10, 20, 18, 18)) | |
| .states_([[" ", Color.black, Color.black], [" ", Color.yellow, Color.yellow]]); | |
| numberboxVClk = NumberBox(windowVClk, Rect(30, 20, 40, 20)) | |
| .value_(model[\myValue]) | |
| .action_({|view| setValueFunction.value(bounds.map(view.value)) }); | |
| sliderVClk = Slider(windowVClk, Rect(73, 20, 200, 20)) | |
| .value_(model[\myValue]) | |
| .action_({|view| setValueFunction.value(bounds.map(view.value)) }); | |
| windowVClk.front; | |
| windowVClk.onClose_({model.removeDependant(updater)}); | |
| //updater | |
| updater = {|theChanger, what, val| | |
| { | |
| if(what == \value, { | |
| numberboxVClk.value_(val); | |
| sliderVClk.value_(bounds.unmap(val)); | |
| // | |
| "VClk = ".post; val.value.postln; | |
| this.setVClk_(val.value); | |
| }); | |
| }.defer; | |
| }; | |
| model.addDependant(updater); | |
| } | |
| // the flasher for the Variable Clock rate | |
| // you can not run 2 different routines into the same Class? | |
| flashDisplayVClk { | |
| if ((routineFlash.isNil)&&(vclk.notNil)) { | |
| routineFlash = { | |
| loop { | |
| posedgeDisplayVClk.value = 1; | |
| vclk.reciprocal.wait; | |
| posedgeDisplayVClk.value = 0; | |
| vclk.reciprocal.wait; | |
| } | |
| }.fork(AppClock); | |
| } | |
| } | |
| update { | who, what, value | | |
| // postf("% updated: % to: %\n", who, what, value); | |
| switch (what, | |
| \symbol, { encoderDisplay.string = value.asString }, | |
| \state, { } | |
| ); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment