AudioMulchClock clock that slaves to AudioMulch over network
See also: ClockAudioMulch
Use this class to receive sync and have SuperCollider act as a slave.
AudioMulch is a program written by Ross Bencina. http://www.audiomulch.com/
AudioMulchClock is a SuperCollider class for synchronising playback with this program via network sync.
This clock has no notion of time in seconds. Rather time advances in ticks and each incoming network sync message includes a tick counter. There are 24 ticks per beat and 96 per bar (assuming 4/4 - change beatsPerBar to use something different).
A tick is roughly 1/24 seconds long at tempo 60bpm. Though network jitter will add and subtract to this value.
Sub tick accurate scheduling (precision lower than 1/24th of a beat) is also possible.
Network setup:
In AudioMulch's preference panel under the Network Sync tab, set the Send to address to 127.0.0.1 and the corresponding UDP Port to 57120. Activate Generate Network Sync under the Control meny.
Known issues:
pbind legato does not behave correctly - scale it with beat duration.
*new
creates a new clock.
*default
returns the default clock. It is created the first time you try to access it and is permanent.
play(task, quant)
schedules a function to be evaluated at some future beat - usually the next beat or next 4 beats (bar).
task - a Function. The function is passed tick, time and clock as first three arguments.
quant - 1 plays on the next beat, 4 on the next bar etc. The default is 1.
Also fractions of beats are possible.
schedAbs(tick, item)
schedules a function to be evaluated at a certain tick.
tick - use .tick to find the current tick and then add an offset in ticks to that.
Also fractions of ticks are possible for sub tick accuracy.
item - a Function. The function is passed tick, time and clock as first three arguments.
if the function returns a number, it will be rescheduled in that amount of beats (yes, not ticks).
sched(delta, item)
schedules a function to be evaluated at some future beat.
delta - 1 here means the next upcoming beat.
Also fractions of beats are possible as well as sub tick accuracy (1<24th of a beat).
item - a Function. The function is passed tick, time and clock as first three arguments.
if the function returns a number, it will be rescheduled in that amount of beats.
nextTimeOnGrid(quant, phase)
used for finding out at which tick in the future the next beat or bar will occur.
quant - if 1 then return the tick for the next tick%24==0. If 4 then the tick for the next tick%96==0 etc.
phase - adds to the quant. e.g. quant 4 and phase 2 will return the tick at the next bar + two beats.
clear
stops the clock and removes all tasks from the scheduling queue.
beatDur
return the average beat duration in seconds.
Note: this value will fluctuate because of network jitter.
beats
return the current beat.
<running
A Boolean that is set when either a \t_start or a \t_pulse message is received.
It is cleard when a \t_stop message is received or the clock is cleared.
<tick
An Integer that counts up indefinitely.
<>shift
an Integer specifying latency compentation in ticks. If negative items will be scheduled slightly early.
<>beatsPerBar
an Integer that should match the number of beats in a bar. Used when restarting after a t_stop.
<permanent
a Boolean. If true then the clock will continue to run after a CmdPeriod.
The user is responsible for clearing permanent clocks with the clear method.
<tempo
A Float that represents the average tempo in beats per minutes.
Note: this value will fluctuate because of network jitter.
<>startAction
a Function that is evaluated when the external clock is started (a \t_start is received).
<>stopAction
a Function that is evaluated when the external clock is stopped (a \t_stop is received).
s.latency= 0.05;
s.boot;
a= AudioMulchClock.new;
//now press play in AudioMulch - make sure 'Generate Network Sync' is set under the control menu.
a.beatDur //will fluctuate because of network jitter
a.beats
a.tempo //will fluctuate because of network jitter
a.tick
//--patterns - note that legato needs to be scaled down - still not working properly
b= Pbind(\degree, Pseq([0, 5, 2, 1, 0, 5, 2, 1, 0, -1], inf), \dur, Pseq([1, 1, 1, 1, 0.25, 0.25, 0.5, 1, 1, 1], inf), \legato, Pfunc({a.beatDur})).play(a, quant:4)
a.shift= -3; //latency compenstation. 3 ticks early
//now try changing tempo in AudioMulch
b.stop
a.clear
//--show manual scheduling in beats
a= AudioMulchClock.new;
(
a.sched(3.5, {|tick, time, clock|
("3.5 beats later - relative to now"+tick+time+clock).postln;
nil;
})
)
(
//note: schedAbs works in ticks so you need to scale with ticks per beat (24)
a.schedAbs(a.tick+(2*24), {|tick, time, clock|
("2 beats later (48 ticks) - absolute time"+tick+time+clock).postln;
nil;
})
)
(
//schedules a synth at half a beat after the beginning of the next bar
a.schedAbs(a.nextTimeOnGrid(4, 0.5), {|tick, time, clock|
var syn= Synth(\default);
a.sched(1, {
syn.release;
nil;
});
4; //reschedule every 4 beat
})
)
a.clear
//--two pbinds on the same clock
(
SynthDef(\audiomulchclock, {|out= 0, atk= 0.01, rel= 0.2, gate= 1, freq= 400, pan= 0, amp= 1|
var env= EnvGen.kr(Env.asr(atk, amp, rel), gate, doneAction:2);
var src= MoogFF.ar(
Pulse.ar(freq-(amp-env*50), env*0.25+0.5, env),
env.lag(2).exprange(freq*0.5, freq*2),
3
);
Out.ar(out, Pan2.ar(src, pan));
}).add;
)
a= AudioMulchClock.new;
a.shift= -4;
b= Pbind(\instrument, \audiomulchclock, \degree, Pseq([0, 5, 2, 1, 0, 5, 2, 1], inf)*[1, 0.5], \strum, 0.2, \dur, 0.5, \pan, [0.5, -0.5], \amp, cos(Ptime()*0.3), \legato, Pfunc({a.beatDur})).play(a, quant:4);
c= Pbind(\instrument, \audiomulchclock, \degree, Pn(Pshuf([0, 5, 2, 1, 0, 5, 2, 1], 4), inf)*[1, 0.5], \strum, 0.1, \dur, 0.5, \pan, [-0.5, 0.5], \amp, cos(Ptime()*0.2), \legato, Pfunc({a.beatDur}), \octave, 7).play(a, quant:4);
c.stop
b.stop
a.clear