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));

)