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

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)

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.

if only size is given

An empty buffer is allocated of size. numChannels defaults to 1.

*diskin(path, size, startFrame, server) - create a CtkBuffer suitable for DiskIn usage. size defaults to 32768.

*playbuf(path, startFrame, numFrames, server) - create a CtkBuffer suitable for PlayBuf usage.

*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.

copy()

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

)