CtkBuffer a note prototyping system
Part of the CompositionToolKit (Ctk) system. See Ctk help for more details
CtkBuffers can be used for both real-time and non-real-time (NRT) purposes, and can be used for soundfile playback, DiskIn allocation and to allocate empty buffer space.
Class Methods
*new(path, size, startFrame, numFrames, numChannels, bufnum, server, channels) -
bufnum - defaults to nil. If nil, a buffer id will be allocated for you.
server - defaults to Server.default.
Depending on the parameters passed to the new method, different kinds buffers will be allocated. There are also creation methods for the more commonly used buffer types.
if path is given
the soundfile will be completely loaded into a CtkBuffer for use in UGens such as PlayBuf or BufRd. Size and
numChannels will be calculated for you with the SoundFile class. startFrame default to 0 and numFrames
defaults to 0 (the entire file is read in). Channels can be a single or an Array of channels to read. Nil (the
default) reads all channels.
if path and size is given
A CtkBuffer suitable for use with DiskIn is allocated. The buffer is left open and will be closed when the buffer
is freed. Size should be a power of 2 (see the DiskIn file for). startFrame defaults to 0, numFrames defaults to
the buffer size. Channels can be a single or an Array of channels to read. Nil (the default) reads all channels.
if only size is given
An empty buffer is allocated of size. numChannels defaults to 1.
*diskin(path, size, startFrame, server, channels) - create a CtkBuffer suitable for DiskIn usage. size defaults
to 32768. Channels can be nil (read all channels), a single number (read only 1 channel) or and Array
of channels.
*playbuf(path, startFrame, numFrames, server, channels) - create a CtkBuffer suitable for PlayBuf usage.
Channels can be nil (read all channels), a single number (read only 1 channel) or and Array of channels.
*buffer(size, numChannels, server) - create a CtkBuffer of empty size and numChannels.
*env(size, env, wavetable, server) - createa a CtkBuffer of size, filled with values from Env. 'wavetable' is a
flag where 0 (the default) fills the CtkBuffer with a Signal, if 1 then a Wavetable is used.
load(time, sync) - for real-time uses, load the file to the server in 'time' seconds. time defaults to 0.0. sync
defaults to false. If true, a messages will post to let you know the buffer has been allocated. If other
methods have been applied to a CtkBuffer (Wave fill commands or other fill or zero commands), these
will be sent after the CtkBuffer has been loaded to the server and the message's time parameter
is ignored. If you want to schedule something for the future, do it AFTER calling the load method on
free(time) - for real-time use, frees and, if necessary, closes the instance of CtkBuffer in 'time' seconds. time
defaults to 0.0.
set(time, startPos, values) - set a value or an Array of values to a CtkBuffer. If using in real-time, the CtkBuffer
must be loaded first.
zero(time) - zero the values in the buffer out.
write(time, path, headerFormat, sampleFormat, numberOfFrames, startingFrame) - write a buffer to a file
at path. sampleFormat defaults to 'aiff', sampleFormat to 'int16', numberOfFrames to -1 and startingFrame
to 0.
openWrite(time, path, headerFormat, sampleFormat, numberOfFrames, startingFrame) - write a buffer to
file at path. sampleFormat defaults to 'aiff', sampleFormat to 'int16', numberOfFrames to -1 and
startingFrame to 0. This file is left open for use by DiskOut, and will need to have the closeWrite method
applied to the CtkBuffer.
closeWrite(time) - close and write the header for a file that had been created and let open with openWrite.
fill(time, newValue, start, numSamples) - fill a buffer with newValue starting at sample start for numSamples.
From the Server-Command-Reference: " This is only meant for setting a few samples, not whole buffers or
large sections"
addTo(CtkScore) - add this instance of CtkBuffer to a CtkScore for playing or NRT rendering.
*All buffers are allocated at the beginning of the score. If a CtkScore is played, all CtkBuffers are loaded
to the server before performance begins and may cause a delay. All CtkBuffers are freed when
performance of a CtkScore is finished.
numChannels - return the number of channels in a CtkBuffer
duration - return the duration of the buffer, in seconds.
Wave File Commands
gen(time, cmd, normalize, wavetable, clear ... args) - See the Wave Fill Commands for more in
Server-Command-Reference for more details. This is the basic template used for the following standard
b_gen commands. cmd is one of \sine1, \sine2, \sine3, or \cheby. 'normalize' defaults to 0 (don't normalize,
1 to normalize), 'wavetable' specifies whether or not the buffer should use Wavetable format (defaults to
0, set to 1 for Wavetables) and clear specifies if the buffer should be cleared before values are set or if
new values should add to values previously in the buffer (defaults to 1 to clear values, 0 to add to old
ones). The format of args is dependent on the wave command (see more below)
sine1(time, normalize, wavetable, clear ... args) - args are individual floats that are applied to harmonic
partials of a sine wave and can vary in size.
e.g. args = 1 - create a wave with only a fundamental frequency.
e.g. args = 0.2, 1, 0.5, 0.2 - four partials, fundamental has an amplitude of 0.2, first partial's is 1, second
partial's is 0.5, and the third partial's is 0.2.
sine2(time, normalize, wavetable, clear ... args) - args are pairs where the first float specifies the frequency
of a partial (where 1 is the base frequency of the buffer) and the second value is its amplitude.
e.g. args = 1, 0.5, 4, 0.2 - fundamental has a strength of 0.5, and the third partial has a strength of 0.2.
sine3(time, normalize, wavetable, clear ... args) - args are sets of three values (similar to above) that
correspond to partial frequency, amplitude and phase.
cheby(time, normalize, wavetable, clear ... args) - args can be a series of floats that correspond to a series
of chebyshev polynomials. The first float is for n = 1, where:
cheby(n) = amplitude * cos(n * acos(x))
fillWithEnv(time, env, wavetable) - converts an instance of Env into a Signal or Wavetable, and loads its
values to the CtkBuffer. The wavetable parameter is a flag. If 0, the values are written as a Signal, if 1,
they are written in Wavetable format.
Real-time uses
s = Server.internal.boot;
Server.default = s;
//for use with PlayBuf
a = CtkBuffer("sounds/a11wlk01-44_1.aiff").load(sync: true); // load and sync with the server
b = {PlayBuf.ar(1, a)}.play(s);
b.free;
a.free;
// for use with DiskIn
a = CtkBuffer("sounds/a11wlk01-44_1.aiff", 32768).load(sync: true); // load and sync with the server
b = {DiskIn.ar(1, a)}.play(s);
b.free;
a.free;
// for use with delays
a = CtkBuffer("sounds/a11wlk01-44_1.aiff", 32768).load(sync: true); // load and sync with the server
b = CtkBuffer(size: 32768).load(sync: true); // load and sync with the server
c = {var play, del;
play = DiskIn.ar(1, a);
del = BufDelayN.ar(b, play, 0.25);
[play, del]
}.play(s);
c.free;
a.free;
b.free;
// allocating and setting values
a = CtkBuffer(size: 2048);
a.load(sync: true);
a.set(0.0, 0, Array.fill(1024, {-1.0.rrand(1.0)}));
b = {PlayBuf.ar(1, a, loop: 1)}.play(s);
// change the values in the buffer
a.set(0.0, 1024, Array.fill(1024, {-1.0.rrand(1.0)}));
// zero it out
a.zero;
// refill them
a.set(0.0, 0, Array.fill(1024, {-1.0.rrand(1.0)}));
a.set(0.0, 1024, Array.fill(1024, {0.0.rrand(1.0)}));
b.free;
a.free;
// with Osc, OscN and Shaper with the fill commands
a = CtkBuffer(size: 32768).load(sync: true);
a.sine1(0.0, 1, 1, 1, 0.3);
b = {Osc.ar(a, 440, mul: 0.5)}.play(s);
a.sine1(0.0, 1, 1, 1, 0.3, 0.2, 0.5);
a.sine3(0.0, 1, 1, 1, 1, 0.3, 0.0, 4, 0.2, 0.2, 9, 0.4, 0.5);
b.free;
a.free;
a = CtkBuffer.new(size: 32768).load(sync: true);
a.sine1(0.0, 1, 0, 1, 0.3);
b = {OscN.ar(a, 440, mul: 0.5)}.play(s);
a.sine1(0.0, 1, 0, 1, 0.3, 0.2, 0.5);
a.sine3(0.0, 1, 0, 1, 1, 0.3, 0.0, 4, 0.2, 0.2, 9, 0.4, 0.5);
b.free;
a.free;
a = CtkBuffer(size: 32768);
a.cheby(0.0, 1, 1, 1, 0.3, 0.2, 0.5);
a.load(sync: true);
s.scope;
b = {Shaper.ar(a, SinOsc.ar(440, 0, 0.5), mul: 0.5)}.play(s);
a.cheby(0.0, 1, 1, 1, 1.0, 0.5, 0.2);
a.cheby(0.0, 1, 1, 1, 0.1, 0.5, 1.0);
a.cheby(0.0, 1, 1, 1, 1.0);
b.free;
a.free;
// Test with DiskOut
a = CtkBuffer(size: 32768).load;
// open a file for writing with DiskOut
a.openWrite(0.0, "~/Desktop/test.aiff".standardizePath, 'aiff', 'int16', -1);
b = {DiskOut.ar(a, SinOsc.ar(440, 0, 0.2))}.play(s);
// let it run for a moment... then kill
b.free;
//close the file
a.closeWrite.free;
// test to make sure it worked
a = CtkBuffer("~/Desktop/test.aiff".standardizePath).load;
b = {PlayBuf.ar(1, a)}.play;
b.free; a.free;
// the fillWithEnv method.
a = CtkBuffer.new(size: 1024).fillWithEnv(env: Env([0, 1, 0], [0.5, 0.5], \sin)).load;
b = {SinOsc.ar(440, 0, 0.2) * BufRd.ar(1, a, Phasor.ar(0.0, 0.01, 0, 1024).poll)}.play(s)
b.free;
a.free;
Uses with CtkScore
(
var play, buf, score, playfun;
score = CtkScore.new;
play = CtkNoteObject(
SynthDef(\play, {arg buffer, rate = 1, dur, start;
OffsetOut.ar(0,
Pan2.ar(
PlayBuf.ar(1, buffer, BufRateScale.kr(buffer) * rate,
startPos: start * BufSampleRate.kr(buffer)) *
EnvGen.ar(
Env([0, 1, 0], [0.5, 0.5], \sin),
timeScale: dur)))
})
);
buf = CtkBuffer("sounds/a11wlk01-44_1.aiff").addTo(score);
//CtkBuffer(size: 1024).set(0.0, 0, Array.fill(1024, {-1.0.rrand(1.0)})).zero(1).addTo(score);
playfun = {arg starttime, gestdur, rateenv;
var note, now, ratio, rate;
now = 0;
while({
ratio = now / gestdur;
rate = rateenv[ratio];
play.new(now + starttime, 0.5)
.buffer_(buf) // the arg will parse the CtkBuffer and grab its bufnum
.rate_(CtkControl.env(Env([rate, 1], [1])))
.dur_(0.5)
.start_((buf.duration - (0.5 * rate)).rand)
.addTo(score);
now = now + 0.2;
now < gestdur;
});
};
playfun.value(0, 20, Env([0.5, 2.0, 1.0], [0.2, 0.8], [3, -5]));
// uncomment to play the score
//[score.notes, score.groups, score.controls, score.messages].postln;
score.play
// uncomment to save the score
//score.saveToFile("~/Desktop/test.sc".standardizePath);
// uncomment to write the score to a soundfile
//score.write("~/Desktop/test.aiff".standardizePath,
// options: ServerOptions.new.numOutputBusChannels_(2));
)