Author |
Message |
fadeddata
Joined: Dec 27, 2004 Posts: 43 Location: Nashville TN
|
Posted: Fri Feb 06, 2009 11:42 pm Post subject:
Converting control rate to audio rate |
 |
|
I've been using Supercollider and a MOTU Ultralite with my modular and have had some very exciting results (http://fadeddata.com/?action=view&url=supercollider-and-motu). I feel as if I'm just barely scratching the surface.
Basically the MOTU Ultralite has DC Coupled outputs which allows you to use the device as a generic 4 volt signal generator.
I'm very interested in using Supercolliders Streams and Patterns utilities to create sequences and the like. I've played around EnvGen.ar and have had some success with creating sequences but I would much rather convert Streams and Patterns to audio rate information. K2A seems like the right thing...
Any thoughts or ideas?
Thanks,
-dustin |
|
Back to top
|
|
 |
dewdrop_world

Joined: Aug 28, 2006 Posts: 858 Location: Guangzhou, China
Audio files: 4
|
Posted: Sat Feb 07, 2009 8:53 pm Post subject:
|
 |
|
Streams and patterns don't run at audio rate but it should be pretty straightforward to run a control signal through to the audio outs. I think you'd need a SynthDef to receive the values from Control inputs, convert to ar (K2A.ar) and output them to hardware out buses.
Something like:
Code: | // 8 because the MOTU has 8 audio outs
SynthDef(\ctlX8, { |out, gate=1, ctl0, ctl1, ctl2, ctl3, ctl4, ctl5, ctl6, ctl7|
FreeSelf.kr(gate <= 0);
Out.ar(out, K2A.ar([ctl0, ctl1, ctl2, ctl3, ctl4, ctl5, ctl6, ctl7]));
}).memStore; |
The gate is there because that's what the next thing needs to terminate the Synth when the pattern is over. The next thing is Pmono, which is like Pbind except that it runs one Synth, changing its parameters with each event instead of creating a new note.
Code: | p = Pmono(\ctlX8,
\ctl0, Pwhite(0.0, 1.0, inf),...
\delta, 0.25
).play; |
Note that you'll have to scale the values in the pattern to the range -1.0 .. 1.0.
We could have some more fun and write a function whose input is the number of controls you want the Synth to process. Don't worry if this doesn't make much sense right away -- it's a bit advanced. Basically, it's duplicating in code the process that's used to make the Controls automatically out of the SynthDef function arguments. (See the Env and Control help files for more information about this technique.)
Code: | // or, build the controls dynamically
f = { |numCtls = 8|
SynthDef("ctlX" ++ numCtls, {
var ctlNames = Array(numCtls+2).add(\out).add(\gate),
out, gate, controls;
numCtls.do { |i|
ctlNames.add(("ctl" ++ i).asSymbol);
};
#out, gate ... controls = Control.names(ctlNames).kr((0 ! (numCtls+2)).put(1, 1));
FreeSelf.kr(gate <= 0);
Out.ar(out, K2A.ar(controls));
}).memStore;
}; |
Hope that helps--
James _________________ ddw online: http://www.dewdrop-world.net
sc3 online: http://supercollider.sourceforge.net |
|
Back to top
|
|
 |
fadeddata
Joined: Dec 27, 2004 Posts: 43 Location: Nashville TN
|
Posted: Sun Feb 08, 2009 1:50 pm Post subject:
|
 |
|
Hey James,
Thanks for the info! Here is a sequencer I built that is working somwhat well...
Code: |
var freq_arr, slider_arr, dur, wave_arr, w_slider_arr, dur_arr, d_slider_arr, sequ;
dur_arr=Array.with(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1);
freq_arr=Array.newClear(16);
wave_arr=Array.with([0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]);
w_slider_arr = Array.newClear(16);
d_slider_arr = Array.newClear(16);
slider_arr=Array.newClear(16);
w=Window.new("Sequencer", Rect(20,20, 1000,420)).front;
w.view.decorator = FlowLayout(w.view.bounds);
v=CompositeView(w, Rect(5,5,290,390));
v.background = Color.rand;
v.decorator = FlowLayout(v.bounds);
t=CompositeView(w, Rect(205,5,290,390));
t.background = Color.rand;
t.decorator = FlowLayout(t.bounds);
s=CompositeView(w, Rect(405,5,290,390));
s.background = Color.rand;
s.decorator = FlowLayout(s.bounds);
16.do({
arg i;
slider_arr.put(i, Slider(v, 280@20));
slider_arr[i].action = { freq_arr.put(i, slider_arr[i].value); };
});
16.do({
arg i;
d_slider_arr.put(i, Slider(t, 280@20));
d_slider_arr[i].value = 1;
d_slider_arr[i].action = { dur_arr.put(i, d_slider_arr[i].value); };
});
16.do({
arg i;
w_slider_arr.put(i, Slider2D(s,58@58).background_(Color.rand).x_(0).y_(0));
w_slider_arr[i].action = { wave_arr.put(i, [(w_slider_arr[i].x), (w_slider_arr[i].y)]); };
});
x=Synth.new("DCout");
x.play;
sequ = Routine {
var i=0, step=0, old_color;
loop {
i = i + 1;
step = i%16;
x.set("arg_0", freq_arr[step]);
x.set("arg_1", wave_arr[step][0]);
x.set("arg_2", wave_arr[step][1]);
(dur_arr[step]/4).wait;
}
}.play;
b = Button(v, 180@20)
.states_([
["Off", Color.black, Color.red],
["On", Color.white, Color.black]
])
.action_({ arg butt;
if(butt.value == 0,{sequ.stop},{sequ.resume});
});
|
I use the following SynthDef with it:
Code: |
s = Server.local;
SynthDef("DCout",
{ arg arg_0, arg_1, arg_2, arg_3, arg_4, arg_5, arg_6, arg_7;
Out.ar(0, K2A.ar([arg_0, arg_1, arg_2, arg_3, arg_4, arg_5, arg_6, arg_7]));
}).send(s)
|
The only thing not working is the On Off button....
-dustin |
|
Back to top
|
|
 |
dewdrop_world

Joined: Aug 28, 2006 Posts: 858 Location: Guangzhou, China
Audio files: 4
|
|
Back to top
|
|
 |
fadeddata
Joined: Dec 27, 2004 Posts: 43 Location: Nashville TN
|
Posted: Tue Feb 10, 2009 11:18 pm Post subject:
|
 |
|
Hey James,
Easy question, hopefully.
When I instantiate a Routine how often does it's lambda/block get called? Is it based on the default TempoClock? Or the SystemClock? I'm wanting to put a bunch of stuff in sync.
Also what do you recommend I do for putting out a pulse (something similar to what Blip puts out) on the beat of the clock?
Thanks,
-dustin |
|
Back to top
|
|
 |
fadeddata
Joined: Dec 27, 2004 Posts: 43 Location: Nashville TN
|
Posted: Tue Feb 10, 2009 11:59 pm Post subject:
|
 |
|
Hey James,
No worries about the clock I think I've got it figured now...
Code: |
SynthDef("clock",
{
Out.ar(0, Impulse.ar(0));
}).send(s);
Pbind(\instrument, \clock, \dur, 2.0).play;
TempoClock.default.tempo = 240/60;
|
|
|
Back to top
|
|
 |
dewdrop_world

Joined: Aug 28, 2006 Posts: 858 Location: Guangzhou, China
Audio files: 4
|
Posted: Thu Feb 12, 2009 11:50 am Post subject:
|
 |
|
Hmm... I expect that would pile up synths on the server because nothing releases them.
For this, I would probably use a trigger control and Pmono. Then it will use just 1 synth, and Pmono always cleans up after itself.
Code: | SynthDef(\clock, { |t_trig, out|
Out.ar(out, K2A.ar(t_trig))
}).memStore;
// \trig is not a typo: it still maps onto t_trig in the Synth
c = Pmono(\clock, \trig, 1, \delta, 2.0).play; |
Also, when using patterns, don't use send(s) - use memStore instead. It's to make sure the synth arguments work properly.
James _________________ ddw online: http://www.dewdrop-world.net
sc3 online: http://supercollider.sourceforge.net |
|
Back to top
|
|
 |
fadeddata
Joined: Dec 27, 2004 Posts: 43 Location: Nashville TN
|
Posted: Fri Feb 13, 2009 10:58 pm Post subject:
|
 |
|
James,
Thanks so much for the info. Are there more of these "special" variables? How do I find them? I see "dur" everywhere does it relate to something server side?
Thanks,
-dustin |
|
Back to top
|
|
 |
|