1 <!DOCTYPE html PUBLIC
"-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
4 <meta http-equiv=
"Content-Type" content=
"text/html; charset=UTF-8">
5 <meta http-equiv=
"Content-Style-Type" content=
"text/css">
7 <meta name=
"Generator" content=
"Cocoa HTML Writer">
8 <meta name=
"CocoaVersion" content=
"824.44">
9 <style type=
"text/css">
10 p
.p1
{margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Helvetica
}
11 p
.p2
{margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica
; min-height: 14.0px}
12 p
.p3
{margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica
}
13 p
.p4
{margin: 0.0px 0.0px 0.0px 0.0px; font: 14.0px Helvetica
}
14 p
.p5
{margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco
; min-height: 12.0px}
15 p
.p6
{margin: 0.0px 0.0px 0.0px 57.0px; text-indent: -57.0px; font: 9.0px Monaco
}
16 p
.p7
{margin: 0.0px 0.0px 0.0px 57.0px; text-indent: -57.0px; font: 9.0px Monaco
; color: #902a19}
17 p
.p8
{margin: 0.0px 0.0px 0.0px 57.0px; text-indent: -57.0px; font: 9.0px Monaco
; min-height: 12.0px}
18 p
.p9
{margin: 0.0px 0.0px 0.0px 85.0px; text-indent: -85.0px; font: 9.0px Monaco
; color: #902a19}
19 p
.p10
{margin: 0.0px 0.0px 0.0px 85.0px; text-indent: -85.0px; font: 9.0px Monaco
; color: #606060}
20 p
.p11
{margin: 0.0px 0.0px 0.0px 85.0px; text-indent: -85.0px; font: 9.0px Monaco
; min-height: 12.0px}
21 p
.p12
{margin: 0.0px 0.0px 0.0px 85.0px; text-indent: -85.0px; font: 9.0px Monaco
}
22 p
.p13
{margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco
; color: #091fb1}
23 p
.p14
{margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco
; color: #902a19}
24 p
.p15
{margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco
}
25 p
.p16
{margin: 0.0px 0.0px 0.0px 0.0px; font: 14.0px Helvetica
; min-height: 17.0px}
26 p
.p17
{margin: 0.0px 0.0px 0.0px 57.0px; text-indent: -57.0px; font: 9.0px Monaco
; color: #606060}
27 p
.p18
{margin: 0.0px 0.0px 0.0px 85.0px; text-indent: -85.0px; font: 12.0px Helvetica
; min-height: 14.0px}
28 p
.p19
{margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco
; color: #606060}
29 p
.p20
{margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica
; color: #0016e6}
30 span
.s1
{color: #0018f7}
31 span
.s2
{color: #000000}
32 span
.s3
{color: #091fb1}
33 span
.s4
{color: #902a19}
34 span
.s5
{color: #606060}
35 span
.s6
{color: #456c20}
36 span
.s7
{font: 12.0px Helvetica
; color: #000000}
37 span
.s8
{font: 12.0px Helvetica
}
38 span
.s9
{text-decoration: underline
}
39 span
.Apple-tab-span
{white-space:pre
}
43 <p class=
"p1"><b>Buffers
</b></p>
44 <p class=
"p2"><br></p>
45 <p class=
"p3">Buffers represent server buffers, which are ordered arrays of floats on the server. 'float' is short for floating point number, which means a number with a decimal point, like
1.3. This is in contrast to integers, which are positive or negative whole numbers (or zero), and are written without decimal points. So
1 is an integer, but
1.0 is a float.
</p>
46 <p class=
"p2"><br></p>
47 <p class=
"p3">Server buffers can be single or multichannel, and are the usual way of storing data server-side. Their most common use is to hold soundfiles in memory, but any sort of data that can be represented by floats can be stored in a buffer.
</p>
48 <p class=
"p2"><br></p>
49 <p class=
"p3">Like busses, the number of buffers is set before you boot a server (using
<a href=
"../../ServerArchitecture/ServerOptions.html"><span class=
"s1">ServerOptions
</span></a>), but before buffers can be used, you need to allocate memory to them, which is an asynchronous step. Also like busses, buffers are numbered, starting from
0. Using Buffer takes care of allocating numbers, and avoids conflicts.
</p>
50 <p class=
"p2"><br></p>
51 <p class=
"p3">You can think of buffers as the server-side equivalent of an Array, but without all the elegant OOP functionality. Luckily with Buffer, and the ability to manipulate data in the client app when needed, you can do almost anything you want with buffer data. A server's buffers are global, which is to say that they can be accessed by any synth, and by more than one at a time. They can be written to or even changed in size,
<i>while
</i> they are being read from.
</p>
52 <p class=
"p2"><br></p>
53 <p class=
"p3">Many of Buffer's methods have numerous arguments. Needless to say, for full information see the
<a href=
"../../ServerArchitecture/Buffer.html"><span class=
"s1">Buffer
</span></a> help file.
</p>
54 <p class=
"p2"><br></p>
55 <p class=
"p4"><b>Making a Buffer Object and Allocating Memory
</b></p>
56 <p class=
"p2"><br></p>
57 <p class=
"p3">Making a Buffer object and allocating the necessary memory in the server app is quite easy. You can do it all in one step with Buffer's alloc method:
</p>
58 <p class=
"p5"><br></p>
59 <p class=
"p6"><span class=
"Apple-tab-span"> </span>s.boot;
</p>
60 <p class=
"p7"><span class=
"s2"><span class=
"Apple-tab-span"> </span>b =
</span><span class=
"s3">Buffer
</span><span class=
"s2">.alloc(s,
100,
2);
<span class=
"Apple-tab-span"> </span></span>// allocate
2 channels, and
100 frames
<span class=
"Apple-converted-space"> </span></p>
61 <p class=
"p7"><span class=
"s2"><span class=
"Apple-tab-span"> </span>b.free;
<span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></span>// free the memory (when you're finished using it)
</p>
62 <p class=
"p8"><br></p>
63 <p class=
"p3">The example above allocates a
2 channel buffer with
100 frames. The actual number of values stored is numChannels * numFrames, so in this case there will be
200 floats. So each frame is in this case a pair of values.
</p>
64 <p class=
"p2"><br></p>
65 <p class=
"p3">If you'd like to allocate in terms of seconds, rather than frames, you can do so like this:
</p>
66 <p class=
"p5"><span class=
"Apple-tab-span"> </span></p>
67 <p class=
"p6"><span class=
"Apple-tab-span"> </span>b =
<span class=
"s3">Buffer
</span>.alloc(s, s.sampleRate *
8.0,
2);
<span class=
"s4">// an
8 second stereo buffer
</span></p>
68 <p class=
"p6"><span class=
"s4"><span class=
"Apple-tab-span"> </span></span>b.free;
</p>
69 <p class=
"p2"><br></p>
70 <p class=
"p3">Buffer's 'free' method frees the memory on the server, and returns the Buffer's number for reallocation. You should not use a Buffer object after doing this.
</p>
71 <p class=
"p2"><br></p>
72 <p class=
"p4"><b>Using Buffers with Sound Files
</b></p>
73 <p class=
"p2"><span class=
"Apple-converted-space"> </span></p>
74 <p class=
"p3">Buffer has another class method called 'read', which reads a sound file into memory, and returns a Buffer object. Using the UGen PlayBuf, we can play the file.
</p>
75 <p class=
"p2"><br></p>
76 <p class=
"p9"><span class=
"s2"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></span>// read a soundfile
</p>
77 <p class=
"p10"><span class=
"s2"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>b =
</span><span class=
"s3">Buffer
</span><span class=
"s2">.read(s,
</span>"sounds/a11wlk01.wav"<span class=
"s2">);
</span></p>
78 <p class=
"p11"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></p>
79 <p class=
"p9"><span class=
"s2"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></span>// now play it
</p>
80 <p class=
"p12"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>(
</p>
81 <p class=
"p12"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>x =
<span class=
"s3">SynthDef
</span>(
<span class=
"s5">"tutorial-PlayBuf"</span>,{
<span class=
"s3">arg
</span> out =
0, bufnum;
</p>
82 <p class=
"p12"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"s3">Out
</span>.ar( out,
</p>
83 <p class=
"p12"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"s3">PlayBuf
</span>.ar(
1, bufnum,
<span class=
"s3">BufRateScale
</span>.kr(bufnum))
</p>
84 <p class=
"p12"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>)
</p>
85 <p class=
"p12"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>}).play(s,[
<span class=
"s6">\bufnum
</span>, b]);
</p>
86 <p class=
"p12"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>)
</p>
87 <p class=
"p12"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>x.free; b.free;
</p>
88 <p class=
"p11"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></p>
89 <p class=
"p3">PlayBuf.ar has a number of arguments which allow you to control various aspects of how it works. Take a look at the
<a href=
"../../UGens/Playback and Recording/PlayBuf.html"><span class=
"s1">PlayBuf
</span></a> helpfile for details of them all, but for now lets just concern ourselves with the first three, used in the example above.
</p>
90 <p class=
"p2"><br></p>
91 <p class=
"p13"><span class=
"s7"><span class=
"Apple-tab-span"> </span></span>PlayBuf
<span class=
"s2">.ar(
</span></p>
92 <p class=
"p14"><span class=
"s2"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>1,
<span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></span>// number of channels
</p>
93 <p class=
"p14"><span class=
"s2"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>bufnum,
<span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></span>// number of buffer to play
</p>
94 <p class=
"p14"><span class=
"s2"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></span><span class=
"s3">BufRateScale
</span><span class=
"s2">.kr(bufnum)
<span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></span>// rate of playback
</p>
95 <p class=
"p15"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>)
</p>
96 <p class=
"p2"><br></p>
97 <p class=
"p3">Number of channels: When working with PlayBuf you must let it know how many channels any buffer it will read in will have.
<i>You cannot make this an argument in the SynthDef and change it later
</i>. Why? Remember that SynthDefs must have a fixed number of output channels. So a one channel PlayBuf is
<i>always
</i> a one channel PlayBuf. If you need versions that can play varying numbers of channels then make multiple SynthDefs or use Function-play.
</p>
98 <p class=
"p2"><br></p>
99 <p class=
"p3">Bufffer Number: As noted above, Buffers are numbered, starting from zero. You can get a Buffer's number using its
<b>bufnum
</b> method, but you will not normally need to do this, since Buffer objects can be passed directly as UGen inputs or Synth args.
</p>
100 <p class=
"p2"><br></p>
101 <p class=
"p3">Rate of Playback: A rate of
1 would be normal speed,
2 twice as fast, etc. But here we see a UGen called BufRateScale. What this does is check the samplerate of the the buffer (this is set to correspond to that of the soundfile when it is loaded) and outputs the rate which would correspond to normal speed. This is useful because the soundfile we loaded (a11wlk01.wav) actually has a samplerate of
11025 Hz. With a rate of
1, PlayBuf would play it back using the sampling rate of the server, which is usually
44100 Hz, or four times as fast! BufRateScale thus brings things back to normal.
<span class=
"Apple-converted-space"> </span></p>
102 <p class=
"p2"><br></p>
103 <p class=
"p4"><b>Streaming a File in From Disk
</b></p>
104 <p class=
"p16"><br></p>
105 <p class=
"p3">In some cases, for instance when working with very large files, you might not want to load a sound completely into memory. Instead, you can stream it in from disk a bit at a time, using the UGen DiskIn, and Buffer's 'cueSoundFile' method:
</p>
106 <p class=
"p2"><br></p>
107 <p class=
"p12"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>(
</p>
108 <p class=
"p10"><span class=
"s2"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></span><span class=
"s3">SynthDef
</span><span class=
"s2">(
</span>"tutorial-Buffer-cue"<span class=
"s2">,{
</span><span class=
"s3">arg
</span><span class=
"s2"> out=
0,bufnum;
</span></p>
109 <p class=
"p12"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"s3">Out
</span>.ar(out,
</p>
110 <p class=
"p12"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"s3">DiskIn
</span>.ar(
1, bufnum )
</p>
111 <p class=
"p12"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>)
</p>
112 <p class=
"p12"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>}).send(s);
</p>
113 <p class=
"p12"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>)
</p>
114 <p class=
"p11"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></p>
115 <p class=
"p12"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>b =
<span class=
"s3">Buffer
</span>.cueSoundFile(s,
<span class=
"s5">"sounds/a11wlk01-44_1.aiff"</span>,
0,
1);
</p>
116 <p class=
"p10"><span class=
"s2"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>y =
</span><span class=
"s3">Synth
</span><span class=
"s2">.new(
</span>"tutorial-Buffer-cue",
<span class=
"s2">[
</span><span class=
"s6">\bufnum
</span><span class=
"s2">,b], s);
</span></p>
117 <p class=
"p11"><br></p>
118 <p class=
"p12"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>b.free; y.free;
</p>
119 <p class=
"p2"><br></p>
120 <p class=
"p3">This is not as flexible as PlayBuf (no rate control), but can save memory.
</p>
121 <p class=
"p16"><br></p>
122 <p class=
"p4"><b>More on Instance Variables and Action Functions
</b></p>
123 <p class=
"p16"><br></p>
124 <p class=
"p3">Now a little more OOP. Remember that individual Objects store data in
<i>instance variables
</i>. Some instance variables have what are called getter or setter methods, which allow you to get or set their values. We've already seen this in action with Buffer's 'bufnum' method, which is a getter for its buffer number instance variable.
</p>
125 <p class=
"p2"><br></p>
126 <p class=
"p3">Buffer has a number of other instance variables with getters which can provide helpful information. The ones we're interested in at the moment are numChannels, numFrames, and sampleRate. These can be particularly useful when working with sound files, as we may not have all this information at our fingertips before loading the file.
</p>
127 <p class=
"p2"><br></p>
128 <p class=
"p7"><span class=
"s2"><span class=
"Apple-tab-span"> </span></span>// watch the post window
</p>
129 <p class=
"p17"><span class=
"s2"><span class=
"Apple-tab-span"> </span>b =
</span><span class=
"s3">Buffer
</span><span class=
"s2">.read(s,
</span>"sounds/a11wlk01.wav"<span class=
"s2">);
</span></p>
130 <p class=
"p6"><span class=
"Apple-tab-span"> </span>b.bufnum;
</p>
131 <p class=
"p6"><span class=
"Apple-tab-span"> </span>b.numFrames;
</p>
132 <p class=
"p6"><span class=
"Apple-tab-span"> </span>b.numChannels;
</p>
133 <p class=
"p6"><span class=
"Apple-tab-span"> </span>b.sampleRate;
</p>
134 <p class=
"p6"><span class=
"Apple-tab-span"> </span>b.free;
</p>
135 <p class=
"p8"><br></p>
136 <p class=
"p3">Now (like with the example using an action function in our Bus-get example; see
<b>[Busses]
</b>) because of the small messaging latency between client and server, instance variables will not be immediately updated when you do something like read a file into a buffer. For this reason, many methods in Buffer take action functions as arguments. Remember that an action function is just a Function that will be evaluated after the client has received a reply, and has updated the Buffer's vars. It is passed the Buffer object as an argument.
</p>
137 <p class=
"p2"><br></p>
138 <p class=
"p9"><span class=
"s2"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></span>// with an action function
</p>
139 <p class=
"p9"><span class=
"s2"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></span>// note that the vars are not immediately up-to-date
</p>
140 <p class=
"p12"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>(
</p>
141 <p class=
"p12"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>b =
<span class=
"s3">Buffer
</span>.read(s,
<span class=
"s5">"sounds/a11wlk01.wav"</span>, action: {
<span class=
"s3">arg
</span> buffer;
<span class=
"Apple-converted-space"> </span></p>
142 <p class=
"p12"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>(
<span class=
"s5">"numFrames after update:"</span> + buffer.numFrames).postln;
</p>
143 <p class=
"p12"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>x = {
<span class=
"s3">PlayBuf
</span>.ar(
1, buffer,
<span class=
"s3">BufRateScale
</span>.kr(buffer)) }.play;
</p>
144 <p class=
"p12"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>});
</p>
145 <p class=
"p11"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></p>
146 <p class=
"p9"><span class=
"s2"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></span>// Note that the next line will execute BEFORE the action function
</p>
147 <p class=
"p12"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>(
<span class=
"s5">"numFrames before update:"</span> + b.numFrames).postln;
</p>
148 <p class=
"p12"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>)
</p>
149 <p class=
"p12"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>x.free; b.free;
</p>
150 <p class=
"p2"><br></p>
151 <p class=
"p3">In the example above, the client sends the read command to the server app, along with a request for the necessary information to update the Buffer's instance variables. It then cues the action function to be executed when it receives the reply, and continues executing the block of code. That's why the 'Before update...' line executes first.
</p>
152 <p class=
"p16"><br></p>
153 <p class=
"p4"><b>Recording into Buffers
</b></p>
154 <p class=
"p16"><br></p>
155 <p class=
"p3">In addition to PlayBuf, there's a UGen called RecordBuf, which lets you record into a buffer.
</p>
156 <p class=
"p2"><br></p>
157 <p class=
"p15"><span class=
"Apple-tab-span"> </span>b =
<span class=
"s3">Buffer
</span>.alloc(s, s.sampleRate *
5,
1);
<span class=
"s4">// a
5 second
1 channel Buffer
</span></p>
158 <p class=
"p5"><span class=
"Apple-tab-span"> </span></p>
159 <p class=
"p14"><span class=
"s2"><span class=
"Apple-tab-span"> </span></span>// record for four seconds
</p>
160 <p class=
"p15"><span class=
"Apple-tab-span"> </span>(
</p>
161 <p class=
"p15"><span class=
"Apple-tab-span"> </span>x =
<span class=
"s3">SynthDef
</span>(
<span class=
"s5">"tutorial-RecordBuf"</span>,{
<span class=
"s3">arg
</span> out=
0,bufnum=
0;
</p>
162 <p class=
"p15"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"s3">var
</span> noise;
</p>
163 <p class=
"p14"><span class=
"s2"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>noise =
</span><span class=
"s3">PinkNoise
</span><span class=
"s2">.ar(
0.3);
<span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></span>// record some PinkNoise
</p>
164 <p class=
"p14"><span class=
"s2"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></span><span class=
"s3">RecordBuf
</span><span class=
"s2">.ar(noise, bufnum);
<span class=
"Apple-tab-span"> </span></span>// by default this loops
</p>
165 <p class=
"p15"><span class=
"Apple-tab-span"> </span>}).play(s,[
<span class=
"s6">\out
</span>,
0,
<span class=
"s6">\bufnum
</span>, b]);
</p>
166 <p class=
"p15"><span class=
"Apple-tab-span"> </span>)
</p>
167 <p class=
"p5"><span class=
"Apple-tab-span"> </span></p>
168 <p class=
"p14"><span class=
"s2"><span class=
"Apple-tab-span"> </span></span>// free the record synth after a few seconds
</p>
169 <p class=
"p15"><span class=
"Apple-tab-span"> </span>x.free;
</p>
170 <p class=
"p5"><span class=
"Apple-tab-span"> </span></p>
171 <p class=
"p14"><span class=
"s2"><span class=
"Apple-tab-span"> </span></span>// play it back
</p>
172 <p class=
"p15"><span class=
"Apple-tab-span"> </span>(
</p>
173 <p class=
"p15"><span class=
"Apple-tab-span"> </span><span class=
"s3">SynthDef
</span>(
<span class=
"s5">"tutorial-playback"</span>,{
<span class=
"s3">arg
</span> out=
0,bufnum=
0;
</p>
174 <p class=
"p15"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"s3">var
</span> playbuf;
</p>
175 <p class=
"p15"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>playbuf =
<span class=
"s3">PlayBuf
</span>.ar(
1,bufnum);
</p>
176 <p class=
"p14"><span class=
"s2"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></span><span class=
"s3">FreeSelfWhenDone
</span><span class=
"s2">.kr(playbuf);
</span>// frees the synth when the PlayBuf has played through once
</p>
177 <p class=
"p15"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"s3">Out
</span>.ar(out, playbuf);
</p>
178 <p class=
"p15"><span class=
"Apple-tab-span"> </span>}).play(s,[
<span class=
"s6">\out
</span>,
0,
<span class=
"s6">\bufnum
</span>, b]);
</p>
179 <p class=
"p15"><span class=
"Apple-tab-span"> </span>)
</p>
180 <p class=
"p15"><span class=
"Apple-tab-span"> </span>b.free;
</p>
181 <p class=
"p5"><span class=
"Apple-tab-span"> </span></p>
182 <p class=
"p3">See the
<a href=
"../../UGens/Playback and Recording/RecordBuf.html"><span class=
"s1">RecordBuf
</span></a> help file for details on all of its options.
</p>
183 <p class=
"p16"><br></p>
184 <p class=
"p4"><b>Accessing Data
</b></p>
185 <p class=
"p16"><br></p>
186 <p class=
"p3">Buffer has a number of methods to allow you to get or set values in a buffer. Buffer-get and Buffer-set are straightforward to use and take an index as an argument. Multichannel buffers interleave their data, so for a two channel buffer index
0 = frame1-chan1, index
1 = frame1-chan2, index
2 = frame2-chan1, and so on. 'get' takes an action function.
</p>
187 <p class=
"p2"><br></p>
188 <p class=
"p12"><span class=
"Apple-tab-span"> </span>b =
<span class=
"s3">Buffer
</span>.alloc(s,
8,
1);
</p>
189 <p class=
"p9"><span class=
"s2"><span class=
"Apple-tab-span"> </span>b.set(
7,
0.5);
<span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></span>// set the value at
7 to
0.5</p>
190 <p class=
"p9"><span class=
"s2"><span class=
"Apple-tab-span"> </span>b.get(
7, {
</span><span class=
"s3">|msg|
</span><span class=
"s2"> msg.postln});
<span class=
"Apple-tab-span"> </span></span>// get the value at
7 and post it when the reply is received
</p>
191 <p class=
"p12"><span class=
"Apple-tab-span"> </span>b.free;
<span class=
"Apple-tab-span"> </span></p>
192 <p class=
"p11"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></p>
193 <p class=
"p3">The methods 'getn' and 'setn' allow you to get and set ranges of adjacent values. 'setn' takes a starting index and an array of values to set, 'getn' takes a starting index, the number of values to get, and an action function.
</p>
194 <p class=
"p11"><br></p>
195 <p class=
"p12"><span class=
"Apple-tab-span"> </span>b =
<span class=
"s3">Buffer
</span>.alloc(s,
16);
</p>
196 <p class=
"p12"><span class=
"Apple-tab-span"> </span>b.setn(
0, [
1,
2,
3]);
<span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"s4">// set the first
3 values
</span></p>
197 <p class=
"p12"><span class=
"Apple-tab-span"> </span>b.getn(
0,
3, {
<span class=
"s3">|msg|
</span> msg.postln});
<span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"s4">// get them
</span></p>
198 <p class=
"p12"><span class=
"Apple-tab-span"> </span>b.setn(
0,
<span class=
"s3">Array
</span>.fill(b.numFrames, {
1.0.rand}));
<span class=
"Apple-tab-span"> </span><span class=
"s4">// fill the buffer with random values
</span></p>
199 <p class=
"p12"><span class=
"Apple-tab-span"> </span>b.getn(
0, b.numFrames, {
<span class=
"s3">|msg|
</span> msg.postln});
<span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"s4">// get them
</span></p>
200 <p class=
"p12"><span class=
"Apple-tab-span"> </span>b.free;
</p>
201 <p class=
"p18"><br></p>
202 <p class=
"p3">There is an upper limit on the number of values you can get or set at a time (usually
1633 when using UDP, the default). This is because of a limit on network packet size. To overcome this Buffer has two methods, 'loadCollection' and 'loadToFloatArray' which allow you to set or get large amounts of data by writing it to disk and then loading to client or server as appropriate.
</p>
203 <p class=
"p2"><br></p>
204 <p class=
"p15"><span class=
"Apple-tab-span"> </span>(
</p>
205 <p class=
"p14"><span class=
"s2"><span class=
"Apple-tab-span"> </span></span>// make some white noise
</p>
206 <p class=
"p15"><span class=
"Apple-tab-span"> </span>v =
<span class=
"s3">FloatArray
</span>.fill(
44100, {
1.0.rand2});
</p>
207 <p class=
"p15"><span class=
"Apple-tab-span"> </span>b =
<span class=
"s3">Buffer
</span>.alloc(s,
44100);
</p>
208 <p class=
"p15"><span class=
"Apple-tab-span"> </span>)
</p>
209 <p class=
"p15"><span class=
"Apple-tab-span"> </span>(
</p>
210 <p class=
"p14"><span class=
"s2"><span class=
"Apple-tab-span"> </span></span>// load the FloatArray into b, then play it
</p>
211 <p class=
"p15"><span class=
"Apple-tab-span"> </span>b.loadCollection(v, action: {
<span class=
"s3">|buf|
</span><span class=
"Apple-converted-space"> </span></p>
212 <p class=
"p15"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>x = {
<span class=
"s3">PlayBuf
</span>.ar(buf.numChannels, buf,
<span class=
"s3">BufRateScale
</span>.kr(buf), loop:
1)
<span class=
"Apple-converted-space"> </span></p>
213 <p class=
"p15"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>*
0.2 }.play;
</p>
214 <p class=
"p15"><span class=
"Apple-tab-span"> </span>});
</p>
215 <p class=
"p15"><span class=
"Apple-tab-span"> </span>)
</p>
216 <p class=
"p15"><span class=
"Apple-tab-span"> </span>x.free;
</p>
217 <p class=
"p5"><span class=
"Apple-tab-span"> </span></p>
218 <p class=
"p14"><span class=
"s2"><span class=
"Apple-tab-span"> </span></span>// now get the FloatArray back, and compare it to v; this posts 'true'
</p>
219 <p class=
"p14"><span class=
"s2"><span class=
"Apple-tab-span"> </span></span>// the args
0, -
1 mean start from the beginning and load the whole buffer
</p>
220 <p class=
"p15"><span class=
"Apple-tab-span"> </span>b.loadToFloatArray(
0, -
1, {
<span class=
"s3">|floatArray|
</span> (floatArray == v).postln });
</p>
221 <p class=
"p15"><span class=
"Apple-tab-span"> </span>b.free;
</p>
222 <p class=
"p2"><br></p>
223 <p class=
"p3">A FloatArray is just a subclass of Array which can only contain floats.
</p>
224 <p class=
"p16"><br></p>
225 <p class=
"p4"><b>Plotting and Playing
</b></p>
226 <p class=
"p16"><br></p>
227 <p class=
"p3">Buffer has two useful convenience methods: 'plot' and 'play'.
</p>
228 <p class=
"p2"><br></p>
229 <p class=
"p14"><span class=
"s2"><span class=
"Apple-tab-span"> </span></span>// see the waveform
</p>
230 <p class=
"p19"><span class=
"s2"><span class=
"Apple-tab-span"> </span>b =
</span><span class=
"s3">Buffer
</span><span class=
"s2">.read(s,
</span>"sounds/a11wlk01.wav"<span class=
"s2">);
</span></p>
231 <p class=
"p15"><span class=
"Apple-tab-span"> </span>b.plot;
</p>
232 <p class=
"p5"><span class=
"Apple-tab-span"> </span></p>
233 <p class=
"p14"><span class=
"s2"><span class=
"Apple-tab-span"> </span></span>// play the contents
</p>
234 <p class=
"p14"><span class=
"s2"><span class=
"Apple-tab-span"> </span></span>// this takes one arg: loop. If false (the default) the resulting synth is
</p>
235 <p class=
"p14"><span class=
"s2"><span class=
"Apple-tab-span"> </span></span>// freed automatically
</p>
236 <p class=
"p14"><span class=
"s2"><span class=
"Apple-tab-span"> </span>b.play;
<span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></span>// frees itself
</p>
237 <p class=
"p14"><span class=
"s2"><span class=
"Apple-tab-span"> </span>x = b.play(
</span><span class=
"s3">true
</span><span class=
"s2">);
<span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></span>// loops so doesn't free
</p>
238 <p class=
"p15"><span class=
"Apple-tab-span"> </span>x.free; b.free;
</p>
239 <p class=
"p2"><span class=
"Apple-tab-span"> </span></p>
240 <p class=
"p4"><b>Other Uses For Buffers
</b></p>
241 <p class=
"p2"><br></p>
242 <p class=
"p3">In addition to being used for loading in sound files, buffers are also useful for any situation in which you need large and/or globally accessible data sets on the server. One example of another use for them is as a lookup table for waveshaping.
<span class=
"Apple-converted-space"> </span></p>
243 <p class=
"p2"><br></p>
244 <p class=
"p15"><span class=
"Apple-tab-span"> </span>b =
<span class=
"s3">Buffer
</span>.alloc(s,
512,
1);
</p>
245 <p class=
"p15"><span class=
"Apple-tab-span"> </span>b.cheby([
1,
0,
1,
1,
0,
1]);
</p>
246 <p class=
"p15"><span class=
"Apple-tab-span"> </span>(
</p>
247 <p class=
"p15"><span class=
"Apple-tab-span"> </span>x = play({
<span class=
"Apple-converted-space"> </span></p>
248 <p class=
"p15"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"s3">Shaper
</span>.ar(
</p>
249 <p class=
"p15"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>b,
<span class=
"Apple-converted-space"> </span></p>
250 <p class=
"p15"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"s3">SinOsc
</span>.ar(
300,
0,
<span class=
"s3">Line
</span>.kr(
0,
1,
6)),
</p>
251 <p class=
"p15"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>0.5</p>
252 <p class=
"p15"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>)
<span class=
"Apple-converted-space"> </span></p>
253 <p class=
"p15"><span class=
"Apple-tab-span"> </span>});
</p>
254 <p class=
"p15"><span class=
"Apple-tab-span"> </span>)
</p>
255 <p class=
"p15"><span class=
"Apple-tab-span"> </span>x.free; b.free;
<span class=
"s8"><span class=
"Apple-tab-span"> </span></span></p>
256 <p class=
"p2"><br></p>
257 <p class=
"p3">The Shaper UGen performs waveshaping on an input source. The method 'cheby' fills the buffer with a series of chebyshev polynomials, which are needed for this. (Don't worry if you don't understand all this.) Buffer has many similar methods for filling a buffer with different waveforms.
</p>
258 <p class=
"p2"><br></p>
259 <p class=
"p3">There are numerous other uses to which buffers can be put. You'll encounter them throughout the documentation.
</p>
260 <p class=
"p2"><br></p>
261 <p class=
"p3">For more information see:
<b><span class=
"Apple-converted-space"> </span></b></p>
262 <p class=
"p2"><br></p>
263 <p class=
"p20"><span class=
"s9"><a href=
"../../ServerArchitecture/Buffer.html">Buffer
</a></span><span class=
"s2"><b> </b><a href=
"../../UGens/Playback and Recording/PlayBuf.html"><span class=
"s8">PlayBuf
</span></a><b> </b><a href=
"../../UGens/Playback and Recording/RecordBuf.html"><span class=
"s8">RecordBuf
</span></a><b> </b><a href=
"../../ServerArchitecture/SynthDef.html"><span class=
"s8">SynthDef
</span></a><b> </b><a href=
"../../UGens/Info/BufRateScale.html"><span class=
"s8">BufRateScale
</span></a><b> </b><a href=
"../../UGens/Oscillators/Shaper.html"><span class=
"s8">Shaper
</span></a></span></p>
264 <p class=
"p2"><br></p>
265 <p class=
"p3">____________________
</p>
266 <p class=
"p2"><br></p>
267 <p class=
"p3">This document is part of the tutorial
<b>Getting Started With SuperCollider
</b>.
</p>
268 <p class=
"p2"><br></p>
269 <p class=
"p3">Click here to return to the table of Contents:
<a href=
"Getting Started With SC.html"><span class=
"s1">Getting Started With SC
</span></a></p>