0% found this document useful (0 votes)
52 views7 pages

5.1 Buffers and Sound Files

Buffers are used in SuperCollider for sample playback and manipulation, streaming files from disk, and recording. The Buffer class handles memory buffers on the Server. There are 1024 buffers by default that are allocated as needed. Various UGens like PlayBuf, BufRd, and DiskIn can be used to work with samples in buffers, including reading entire files or streaming parts of files. Oscillators generally work by reading through short wavetables stored in buffers to generate waveforms at different frequencies.

Uploaded by

Manu Codjia
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
52 views7 pages

5.1 Buffers and Sound Files

Buffers are used in SuperCollider for sample playback and manipulation, streaming files from disk, and recording. The Buffer class handles memory buffers on the Server. There are 1024 buffers by default that are allocated as needed. Various UGens like PlayBuf, BufRd, and DiskIn can be used to work with samples in buffers, including reading entire files or streaming parts of files. Oscillators generally work by reading through short wavetables stored in buffers to generate waveforms at different frequencies.

Uploaded by

Manu Codjia
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 7

Buffers and Sound Files

Server.default=s=Server.local;
s.boot;

To do sample playback and manipulation, for streaming files off disk, for recording
and wavetables and many other processes, it is necessary to handle memory buffers
on the Server.

Note: SuperCollider versions from 3.5 on have the default sound files that come
with SuperCollider in a different location. You will see the path as:

Platform.resourceDir +/+ "sounds/a11wlk01.wav" //3.5 or later

Which is the version used in the examples in these tutorials. If you are on 3.4 or
earlier, the correct path is just:
"sounds/a11wlk01.wav"

Note that if you need a path for a sound file, you can drag and drop to the text
window in SuperCollider to get the path.

There are 1024 individual buffers by default. The Buffer memory is allocated as
needed from the operating system.

(Advanced: You can check defaults by looking at the ServerOptions class and
Main:startup. The Buffer memory is not the memSize option; memSize is just some
reserved memory for use by plug-ins like delay lines. So you should still set
memSize big because UGens like CombN or DelayN need to use it for their
allocations.
)

We'll deal with buffers using the convenience wrapper class appropriately called
Buffer.

//allocate a one channel buffer of 441000 sample frames (10 sec at standard
sampling rate)
b=Buffer.alloc(s, 10*44100, 1); // s= server, 10*44100 num frames, 1 = 1 channel,
i.e. mono

If you check scsynth's memory use in your operating system (e.g., for OS X use the
Terminal with the top command or Activity Monitor) before and after running this
line (top command would work) you should see it has gone up.

b.bufnum //which buffer are we using? This is an essential parameter to pass to


lots of UGens

//restore that memory and free that bufferID


b.free

To prepare buffers for playback by loopers or disk streamers, there are other
methods of the Buffer class you'll see called.

To work with sample playback there are a variety of possible UGens to use.

PlayBuf

(
//this loads into a buffer the default sound that comes with SuperCollider
//.read brings in the whole sound at once
b = Buffer.read(s,Platform.resourceDir +/+ "sounds/a11wlk01.wav"); //store handle
to Buffer in global variable b

SynthDef("playbuf",{ arg out=0,bufnum=0, rate=1, trigger=1, startPos=0, loop=1;


Out.ar(out,
Pan2.ar(PlayBuf.ar(1,bufnum, BufRateScale.kr(bufnum)*rate, trigger,
BufFrames.ir(bufnum)*startPos, loop),0.0)
)
}).add;
)

BufRateScale is vital because the soundfile I've loaded is actually at 11025Hz


sampling rate, and my audio output is at 44100Hz - so it adjusts for different
possible sampling rates. The BufFrames UGen returns, well, the number of frames in
the soundfile. But note the .ir - this is initialisation rate, i.e., the UGen only
runs once when first created, it doesn't need to be continually recalculated.

//note how even though the soundfile doesn't loop, the Synth is not deallocated
when done
//(it has no envelope function). you'll need to cmd+period to kill it
Synth(\playbuf, [\out, 0, \bufnum, b.bufnum]);

//play at half rate


Synth(\playbuf, [\out, 0, \bufnum, b.bufnum, \rate, 0.5]);

//Example with GUI controlling Synth


(
var w, rateslid, trigslid, startposslid, loopslid, a;

a=Synth(\playbuf, [\out, 0, \bufnum, b.bufnum]);

w=Window("PlayBuf Example",Rect(10,200,300,150));

w.front;

//control positioning of new GUI elements so I don't have to think too hard about
it
w.view.decorator= FlowLayout(w.view.bounds);

//James' shortcut slider class


//250@24 means a Point of size 250 by 24
//|ez| is the same as arg ez; - the EZSlider object is being passed into the
callback action function
rateslid= EZSlider(w, 250@24, "Rate", ControlSpec(0.5, 10, 'exponential', 0.1), {|
ez| a.set(\rate,ez.value)}, 1);

trigslid= EZSlider(w, 250@24, "Trigger", ControlSpec(0, 1, 'lin', 1), {|ez| a.set(\


trigger,ez.value)}, 1);

startposslid= EZSlider(w, 250@24, "StartPos", ControlSpec(0.0, 1.0, 'lin', 0.01),


{|ez| a.set(\startPos,ez.value)}, 0);

loopslid= EZSlider(w, 250@24, "Loop", ControlSpec(0, 1, 'lin', 0.1), {|ez| a.set(\


loop,ez.value)}, 1);

w.onClose_({a.free;});
)

BufRd

BufRd is similar to PlayBuf but lets you directly read from a buffer (note you
could also use this with non-soundfiles) via a phase argument. This is more
convenient for taking custom control of how you read through a sample.

(
//this loads into a buffer the default sound that comes with SuperCollider
//.read brings in the whole sound at once
b = Buffer.read(s,Platform.resourceDir +/+ "sounds/a11wlk01.wav");

//using Mouse to scrub through- X position is normalised position 0 to 1 phase


through the source file
SynthDef("bufrd",{ arg out=0,bufnum=0;
Out.ar(out,
Pan2.ar(BufRd.ar(1, bufnum,
K2A.ar(BufFrames.ir(b.bufnum)*MouseX.kr(0.0,1.0)).lag(MouseY.kr(0.0,1.0))),0.0)
)
}).play(s);
)

The K2A is needed to convert control rate Mouse to run at audio rate. This is
because the BufRd needs to know where it is reading for every sample.

.lag (which is a shortcut to get a Lag UGen) puts a smooth 'catch-up delay' (amount
controlled by MouseY) on the scratching.

[BufRd] //the help file has more examples


DiskIn

Here we only read a small part of the soundfile at a time; you would use this for
streaming a large file off disk.

(
//Prepare to stream. You can use a big file for streaming: replace the filename
here with one valid for your machine. Note that dragging and dropping a file into
the SC text editor posts the full path of that file as text for you to use in your
code.
b=Buffer.cueSoundFile(s,Platform.resourceDir +/+ "sounds/a11wlk01.wav",0, 1);
)

SynthDef(\diskin,{Out.ar(0,DiskIn.ar(1, b.bufnum))}).play(s);

You can only playback, you can't modulate the streaming rate in any way (there is a
more advanced UGen, VDiskIn, that allows some extra functionality here). But this
allows you to bring in files for any processing you desire to do.

[DiskIn] //help file- you will probably want to look at the 'Object messaging
style' further down the page, for now.

Wavetables and oscillators

The implementation of most oscillator UGens is to read sample values from a


wavetable. A short wavetable is read through again and again in a loop, at a
particular rate (giving a fixed pitch).

{SinOsc.ar(100)}.plot(0.05) //plot 5 cycles of a SinOsc sine oscillator: reads


through the sine wavetable 5 times

This is similar to sampling, just with small tables which are continuously reused
many times per second (as many times as the frequency). Scanning through a fixed
length table at variable rates means that you sometimes fall inbetween table
positions; this can be covered by interpolation, generating those inbetween values
on the fly.

You can specify the waveform shape for a wavetable yourself. SuperCollider has a
special efficient wavetable format to pack a buffer.
b = Buffer.alloc(s, 512, 1); //make a Buffer storage area

b.sine1(1.0/[1,2,3,4,5,6], true, false, true); //fill the Buffer with wavetable


data

b.plot; //stored shape (not in special SuperCollider Wavetable format, for clarity)

{OscN.ar(b,MouseX.kr(10,1000),0,0.1)}.play //OscN; N means non-interpolating

[Osc]
[OscN]

There are various other UGens that leverage buffers. You might try exploring the
help files for

[Index] //buffer as array of data for UGen

[Shaper] //buffer for wave shaping distortion/complex sound generation

[FFT] //buffer as complex Fourier data, gets passed through the phase
vocoder processing chain

Note that Shaper and FFT will re-appear in future weeks for effects and spectral
analysis discussions.

You'll probably see some other ways of using the Buffer class to set or get
information in server side Buffers from the language.

(Sometimes communication with buffers uses the messaging style: the exhaustive list
is here: [Server-Command-Reference] and is a more advanced topic. Just be
forewarned that some help file examples might show some explicit message passing to
handle buffers)

You might also like