The CuePlayer is useful for real-time and mixed electronic works (possibly involving acoustic instruments) when the composer wishes to build a series of processes (cues) and execute them one after another during the course of a piece. The cues are initially organised into an Array, and later on they may be triggered via code, a GUI window or any device/software which outputs midi/osc data, such as a footpedal or a Digital Audio Workstation.
There are lots of features which make the CuePlayer useful for composing in-studio and performing on-stage electroacoustic works using SuperCollider. Please read below and go through this short CuePlayerTutorial for more information.
Create a new CuePlayer instance
Returns the global clock. See useGlobalClock.
Set the tempo. Processes may be evaluated with reference to this clock.
bpm |
Beats per minute. |
Put cue at cue-number, replacing what is there.
This allows explicitly to create a cue at a specific cue-number. Simply construct your cue as a function and then assign it to a cue-number; (think of the cue-number as the index of the cue-list which holds all processes).
cueNumber |
The cue-number to register the function. |
function |
A compatible cue object; a Function, a CueInfo, or a String representing the path of an scd file returning one of the compatible objects. |
timeline |
An instance of Array with time - function pairs, (time is in beats or optionally in seconds). Alternatively a String representing the path of an scd file. The file must return an Array of time - function pairs, like [ 0, { }, 1, { } ]. See Timeline and the examples at the end of this document. |
timelineOptions |
An event of timeline options. See Timeline. x // This is how to make cues at specific cue-numbers. a = CuePlayer.new; // Create a new CuePlayer instance a.put(1, { "do something".postln }); // Define 1st cue. a.put(2, { "this is the 2nd cue".postln }); // Define 2nd cue. a.put(5, { "& this is the 5th cue".postln }); // Define 5th cue. |
Add a cue at the end of the cue-list.
function |
A compatible cue object; a Function, a CueInfo, or a String representing the path of an scd file returning one of the compatible objects. |
timeline |
An instance of Array with time - function pairs, (time is in beats or optionally in seconds). Alternatively a String representing the path of an scd file. The file must return an Array of time - function pairs, like [ 0, { }, 1, { } ]. See Timeline and the examples at the end of this document. |
timelineOptions |
An event of timeline options. See Timeline. |
Trigger a cue.
cueNumber |
An integer which corresponds to the function (cue) to evaluate. xxxxxxxxxx a = CuePlayer.new; // Create a new CuePlayer instance // Define cues 1 & 2 a.put(1, { "this is cue one".postln }); a.put(2, { "this is cue two".postln }); // Trigger cues a.trigger(1); // trigger cue 1 a.trigger(2); // trigger cue 2 |
Filter out triggers that occur too fast.
When the CuePlayer receives a new trigger within less time than the blockTrigger's value, it neglects it. This avoids the piece moving forward by mistake, for example when a footpedal is rapidly pressed twice by accident.
interval |
A number. Default is 0.3 secs. |
Trigger next cue.
Register a function to be avaluated right before triggering a new cue. The function is passed in the cuePlayer as an argument.
xxxxxxxxxx
b = CuePlayer.new;
b.hook = {arg cueplayer; cueplayer.current.postln; }
Create a GUI window for the CuePlayer.
This method brings up a convenient window allowing the user to control the CuePlayer from a Graphic User Interface. Through the window the user can monitor input/output buses, trigger cues, use a timer and a metronome and control the server's level.
The CueInfo object is used to add descriptive text to cues (if needed) which may be subsequently displayed on screen using the gui method.
monitorInChannels |
An integer (0 - 8) for creating input level meters. |
monitorOutChannels |
An integer (1 - 48) for creating output level meters. |
options |
An event of one or more options. xxxxxxxxxx b = CuePlayer.new; // Create a new CuePlayer instance // Bring up the CuePlayer window. b.gui( monitorInChannels: 5, // Monitor 5 input channels monitorOutChannels: 24, // Monitor 24 output channels options: ( monitorInOffset: 2, // Offset input monitoring by 2; (hence monitor inputs 3,4,5,6,7 here) largeDisplay: true, // Show/hide the big window displaying current cue-number. Useful for the performers on stage. largeDisplayBounds: Rect(600, 300, 450, 450), // Set bounds of the big window. infoDisplay: true, // Show/hide the cue-title. left: 1200, // Left bound of the CuePlayer window. top: 300, // Top bound of the CuePlayer window. timer: true, // Show/hide timer metronome: true, // Show/hide metronome serverControls: true, // Show/hide server controls: mute-button, volume-slider, Peak CPU, Number of Synths shortcuts: false // Use shortcuts; default is false // spacebar: trigger next cue // b: focus on bpm box // c: focus on cue-number box // p: start/pause timer // s: stop timer // P: plot current timeline // m: mute server // M: toggle metronome ) ); |
Set up a midi-trigger on a given note and channel to trigger the next cue. This allows to evaluate sequential cues upon receiving a midi-note through a specified midi-channel. Default note is 60 (middle C) transmitted via channel 15. Bear in mind that the CuePlayer starts counting midi-channels from 1, (as opposed to 0). See also the CuePlayerTutorial.
note |
The midi-note which the CuePlayer listens to in order to trigger the next cue. |
channel |
The midi-channel. xxxxxxxxxx // Create a new CuePlayer instance & bring up the GUI a = CuePlayer.new; a.gui; // Connect all midi devices & set up a midi-trigger for the CuePlayer MIDIIn.connectAll; a.midiTriggerNoteOn(note: 60, channel: 15); // Ready to trigger cues from an external midi-device hooked up on channel 15 upon sending note 60. |
Set up a midi-trigger on a given note and channel to trigger a cue based on the note's velocity value. This allows to evaluate specific cues upon receiving a midi-note; the velocity (1-127) controls the cue-number. Default note is 60 (middle C) transmitted via channel 16. Bear in mind that the CuePlayer starts counting midi-channels from 1, (as opposed to 0). See also the CuePlayerTutorial.
note |
The midi-note which the CuePlayer listens to. |
channel |
The midi-channel. |
offset |
Add a constant to the specified cue-number. Useful when more than 127 cues are needed. xxxxxxxxxx // Create a new CuePlayer instance & bring up the GUI a = CuePlayer.new; a.gui; // Connect all midi devices & set up a midi-trigger for the CuePlayer MIDIIn.connectAll; a.midiTriggerVelocity(note: 60, channel: 16, offset: 0); /* Ready to trigger cues from an external midi-device hooked up on channel 16 based on the note's velocity value. */ |
Set up a midi-trigger on a given value of a midi-controller to trigger the next cue. This allows to evaluate sequential cues upon receiving a midi-control message from an external device (such as a foot-pedal) through a specified midi-channel. Default value is 0, controller-number is 64, transmitted via channel 1. Bear in mind that the CuePlayer starts counting midi-channels from 1 (as opposed to 0).
value |
The value of the midi-controller which will trigger the next cue. |
ccNum |
The controller's number. |
channel |
The midi-channel. xxxxxxxxxx // Create a new CuePlayer instance & bring up the GUI a = CuePlayer.new; a.gui; // Connect all midi devices & set up a trigger which will respond to midi-control messages MIDIIn.connectAll; a.midiTriggerControl(value: 127, ccNum: 64, channel: 1) // Ready to trigger cues from midi-controller 64 hooked up on channel 1 upon sending the value 127 |
Clear all MIDI functions defined with midiTriggerNoteOn and midiTriggerVelocity.
Set up an Open Sound Control trigger. This allows to evaluate a cue upon receiving an OSC message. Default path is '/cueTrigger'. Default message is -1 which will trigger the next cue; any other positive integer will trigger the respective cue. See also the CuePlayerTutorial.
path |
A Symbol indicating the path of the OSC address. xxxxxxxxxx // Create a new CuePlayer instance & bring up the GUI a = CuePlayer.new; a.gui; // Define cues 1, 2 & 3 a.put(1, { "this is cue 1".postln }); a.put(2, { "this is cue 2".postln }); a.put(3, { "this is cue 3".postln }); // An OSC responder a.oscTrigger // Test it m = NetAddr("127.0.0.1", NetAddr.langPort); // Create a net address m.sendMsg("/cueTrigger", -1); // Send a message to trigger next cue m.sendMsg("/cueTrigger", -1); // Trigger next cue m.sendMsg("/cueTrigger", -1); // Trigger next cue m.sendMsg("/cueTrigger", 2); // Trigger cue 2 m.sendMsg("/cueTrigger", 3); // Trigger cue 3 |
Free the OSC trigger mechanism.
Send an open sound control message to a network address. See also the CuePlayerTutorial.
ip |
The IP number, like "127.0.0.1". |
port |
The port number, like 57110. |
msg |
The message, like ["/play", 1]. xxxxxxxxxx a = CuePlayer.new; // Create a new CuePlayer instance // Send messages (possibly to control a DAW). // ip/port/message need to be adjusted to match the software's specs. a.sendOSC("127.0.0.1", 8000, ["/play", 1]); a.sendOSC("127.0.0.1", 8000, ["/pause", 1]); |
Use the common clock. This is a TempoClock used by all CuePlayer instances. Useful when multiple synced CuePlayers are needed.
The timelines are stored in a Dictionary that you can access from your CuePlayer instance using the cue number as the key.
xxxxxxxxxx
a = CuePlayer.new;
a.timelineRegister; // the dictionary
// to access the TimeLine of a specific cue
a.timelineRegister[\3]; // timeline of cue 3
Provides a visual representation of the selected timeline items. It is applicable only when using timelines. See put and add methods.
cueNumber |
An integer. If a timeline is provided, it plots the items in the selected cue-number. |
Return the instnace of CuePlayerGUI used by this CuePlayer.
xxxxxxxxxx
/* ************************************************************************ */
// Using few basic methods
// Define a SynthDef to play with
(
SynthDef(\fsosynth, {
arg fundamental = 120, harmonics = #[0.5, 1.19, 1.5, 4], dec = 4;
var signal, envelope, delay;
signal = Mix.ar( FSinOsc.ar( fundamental * harmonics, mul: 0.07) );
delay = DelayN.ar(signal, delaytime: SinOsc.kr(15, mul: 25/SampleRate.ir, add: 50/SampleRate.ir ));
envelope = EnvGen.kr(Env.perc(attackTime:0.1,releaseTime: dec), 1, doneAction: 2);
Out.ar( [0,1], (signal + delay) * envelope)
}
).store;
)
// Create a new CuePlayer instance & set its tempo
a = CuePlayer.new;
a.tempo_(130);
// Build the cues
(
// Define cue-1
a.put(1, {
Synth(\fsosynth, [\fundamental, 146]);
});
// Define cue-2
a.put(2, {
Synth(\fsosynth, [\fundamental, 97, \harmonics, #[0.5, 1.19, 1.5, 8] ]);
});
// Define cue-3
a.put(3, {
Pdef(\pattern, Pbind(\instrument, \fsosynth, \fundamental, 110, \dec, 0.5, \dur, 1 )).play(a.clock, quant:[1]);
// Play the pattern at the CuePlayer's clock
});
// Add a cue at the end of the cue-list, (here it equates with cue-4)
a.add({
Pdef(\pattern).clear;
});
)
// Now, evaluate one by one
a.trigger(1); // trigger cue 1
a.trigger(3); // trigger cue 3
a.tempo_(100); // change the tempo
a.setCurrent(1); // set current cue to 1 ...
a.next; // trigger next cue (i.e cue-2)
a.trigger(4); // trigger cue 4
/* ************************************************************************ */
// Using the GUI
// Bring up the window and control the CuePlayer from its GUI
(
a.gui(
monitorInChannels: 4, // Monitor 4 input channels
monitorOutChannels: 16, // Monitor 16 output channels
options: (
infoDisplay: true, // Show the cue-title field.
largeDisplay: true, // Show the big window displaying current cue-number.
// Useful for the performers on stage.
left: 1300, // Left bound of the CuePlayer window.
top: 300, // Top bound of the CuePlayer window.
)
));
/* ************************************************************************ */
// Attaching text to a cue
// Define cue-5, & add text information using the CueInfo object
(
a.put(5,
CueInfo(
cueTitle: "play a C", // this will be projected on the cueplayer window
largeDisplayInfo: "performer's info", // ... and this on the large display
function: { Synth(\fsosynth, [\fundamental, 130]); }
))
);
a.trigger(5); // trigger cue 5
// "cueTitle" appears on the cueplayer gui & "largeDisplayInfo" on a second window for the performer.
/* ************************************************************************ */
// Using a timeline
// Put a timeline at cue-6
a.put(6,
{"a timeline".postln},
timeline: [
1, {Synth(\fsosynth, [\fundamental, 174, \dec, 0.4 ])},
2, {Synth(\fsosynth, [\fundamental, 220, \dec, 0.4 ])},
3, {Synth(\fsosynth, [\fundamental, 130, \dec, 0.4 ])},
4, {Synth(\fsosynth, [\fundamental, 146, \dec, 0.4 ])},
4.5, {Synth(\fsosynth, [\fundamental, 174, \dec, 0.4 ])},
5, {Synth(\fsosynth, [\fundamental, 220, \dec, 0.4 ])},
5.5, {Synth(\fsosynth, [\fundamental, 130, \dec, 0.4 ])},
6, {Synth(\fsosynth, [\fundamental, 146, \dec, 1 ])},
8,{Synth(\fsosynth, [\fundamental, 293, \dec, 3 ])}
],
timelineOptions: (quant: 1)
);
// Trigger cue-6 with the following code or via the GUI
a.trigger(6);
// Plot the timeline's events
a.plot(6);
// Alternatively you may save the timeline (as an Array of time - function pairs) in an scd file and point to its path.
a.put(7,
{"read timeline from an scd file".postln},
timeline: PathName(CuePlayer.class.filenameSymbol.asString).parentPath +/+ "HelpSource/Classes/timeline" +/+ "score.scd",
timelineOptions: (quant: 1)
);
a.trigger(7);
/* ************************************************************************ */