Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
norns engine switching test
-- engine switching test
-- key 2: select TestSine
-- key 3: select TestNoise
-- enc 2 up: auto-switch (as fast as possible)
-- enc 2 down: stop auto-switching
local engine_loading_flag = true
local autoswitch = false
function init()
engine_loading_flag = false
end
function engine_loaded()
engine_loading_flag = false
if autoswitch then
if engine.name == 'TestSine' then
load_engine('TestNoise')
else
load_engine('TestSine')
end
end -- autoswitch
end
local load_engine = function(name)
if engine_loading_flag then
print("---------------------------------")
print("--- engine is already loading ---")
print("---------------------------------")
else
engine_loading_flag = true
engine.load(name, engine_loaded)
engine.name = name
end
end
function key(n,z)
if z == 1 then
if n == 2 then
load_engine('TestSine')
end
if n == 3 then
load_engine('TestNoise')
end
end
end
function enc(n, z)
if n == 2 then
if z > 0 then
autoswitch = true
print("autoswitch on")
else
autoswitch = false
print("autoswitch off")
end
end
end
// CroneEngine_TestNoise
// variante of TestSine, for switching
// Inherit methods from CroneEngine
Engine_TestNoise : CroneEngine {
var <synth;
*new { arg context, doneCallback;
^super.new(context, doneCallback);
}
alloc {
synth = {
arg out, hz=220, amp=0.5, amplag=0.02, hzlag=0.01;
var amp_, hz_;
amp_ = Lag.ar(K2A.ar(amp), amplag);
hz_ = Lag.ar(K2A.ar(hz), hzlag);
Out.ar(out, (LPF.ar(WhiteNoise.ar, hz_) * amp_).dup);
}.play(args: [\out, context.out_b], target: context.xg);
this.addCommand("hz", "f", { arg msg;
synth.set(\hz, msg[1]);
});
this.addCommand("amp", "f", { arg msg;
synth.set(\amp, msg[1]);
});
}
free {
synth.free;
}
}
// CroneEngine_TestSine
// dumbest possible test: a single, mono sinewave
// Inherit methods from CroneEngine
Engine_TestSine : CroneEngine {
// Define a getter for the synth variable
var <synth;
// Define a class method when an object is created
*new { arg context, doneCallback;
// Return the object from the superclass (CroneEngine) .new method
^super.new(context, doneCallback);
}
// Rather than defining a SynthDef, use a shorthand to allocate a function and send it to the engine to play
// Defined as an empty method in CroneEngine
// https://github.com/monome/norns/blob/master/sc/core/CroneEngine.sc#L31
alloc {
// Define the synth variable, whichis a function
synth = {
// define arguments to the function
arg out, hz=220, amp=0.5, amplag=0.02, hzlag=0.01;
// initialize two local vars for Lag'd amp and hz
var amp_, hz_;
// Allow Lag (Slew in modular jargon) for amplitude and frequency
amp_ = Lag.ar(K2A.ar(amp), amplag);
hz_ = Lag.ar(K2A.ar(hz), hzlag);
// Create an output object with two copies of a SineOsc,
// passing the Lag'd amp and frequency as args
Out.ar(out, (SinOsc.ar(hz_) * amp_).dup);
// Send the synth function to the engine as a UGen graph.
// It seems like when an Engine is loaded it is passed an AudioContext
// that is used to define audio routing stuff (Busses and Groups in SC parlance)
// These methods are defined in
// https://github.com/monome/norns/blob/master/sc/core/CroneAudioContext.sc
// pass the CroneAudioContext method "out_b" as the value to the \out argument
// pass the CroneAudioContext method "xg" as the value to the target.
}.play(args: [\out, context.out_b], target: context.xg);
// Export argument symbols as modulatable paramaters
// This could be extended to control the Lag time as additional params
this.addCommand("hz", "f", { arg msg;
synth.set(\hz, msg[1]);
});
this.addCommand("amp", "f", { arg msg;
synth.set(\amp, msg[1]);
});
}
// define a function that is called when the synth is shut down
free {
synth.free;
}
}
@catfact

This comment has been minimized.

Copy link
Owner Author

@catfact catfact commented Jun 19, 2019

test switching norns engines within a script.

the supecollider classes can't handle the edge case of loading an engine before the previous one is done lodaing.

this demonstrates a workaround; lua tracks the state of engine loading and doesn't initiate a new load if one is pending.

keys 2, 3 select engines
encoder 2 engages / disengages 'autoswitch' mode, in which pressing k2 or k3 will begin toggling between the two engines as fast as possible. (this is not a pleasant sound.)

note that Engine_TestSine can't be duplicated, and is provided by the we repo already.
Engine_TestNoise is new here,

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment