170 lines
4.7 KiB
Text
170 lines
4.7 KiB
Text
|
#lang scribble/manual
|
||
|
@(require (for-label racket))
|
||
|
|
||
|
@title{DiskOut}
|
||
|
Record to a soundfile to disk.@section{related}
|
||
|
Classes/RecordBuf, Classes/DiskIn
|
||
|
@section{categories}
|
||
|
UGens>InOut, UGens>Buffer
|
||
|
|
||
|
@section{description}
|
||
|
|
||
|
Record to a soundfile to disk. Uses a link::Classes/Buffer::.
|
||
|
|
||
|
See link::Classes/RecordBuf:: for recording into a buffer in memory.
|
||
|
|
||
|
@section{subsection}
|
||
|
Disk recording procedure
|
||
|
|
||
|
Recording to disk involves several steps, which should be taken in the right order. link::Classes/Server#-record:: performs these steps for you. To record arbitrary buses using DiskOut explicitly, make sure to do the following:
|
||
|
|
||
|
@section{numberedlist}
|
||
|
|
||
|
## Define a DiskOut link::Classes/SynthDef::, as shown in the example below.
|
||
|
## Allocate a link::Classes/Buffer:: for recording.
|
||
|
@section{list}
|
||
|
|
||
|
## The buffer size should be a power of two.
|
||
|
## A duration of at least one second is recommended:
|
||
|
@racketblock[s.sampleRate.nextPowerOfTwo::.
|
||
|
## Do not allocate the buffer inside the SynthDef.
|
||
|
## Keep the buffer in a variable.
|
||
|
::
|
||
|
## Specify the file path and recording format using link::Classes/Buffer#-write::, with the teletype::leaveOpen:: flag set to ]
|
||
|
|
||
|
@racketblock[true::. This is the only way to set the file path and recording format.
|
||
|
## Create a link::Classes/Synth:: node to run the DiskOut UGen.
|
||
|
## When recording is finished, stop the DiskOut synth.
|
||
|
## Close the buffer: ]
|
||
|
|
||
|
@racketblock[b.close::. This step updates the recorded file's audio header. Without it, the file will be unusable.
|
||
|
## Free the buffer: ]
|
||
|
|
||
|
@racketblock[b.free::.
|
||
|
::
|
||
|
|
||
|
These steps are illustrated in the Examples section. In general, only the "Object Style" approach is needed. ("Messaging Style" is provided as a historical reference, but it isn't needed for typical use.)
|
||
|
|
||
|
]
|
||
|
@section{classmethods}
|
||
|
|
||
|
@section{private}
|
||
|
categories
|
||
|
|
||
|
@section{method}
|
||
|
ar
|
||
|
|
||
|
@section{argument}
|
||
|
bufnum
|
||
|
The number of the buffer to write to (prepared with /b-write or
|
||
|
Buffer.write)
|
||
|
@section{Note}
|
||
|
The Buffer's numFrames must be a power of two and is recommended to be at least 65536 -- preferably 131072 or 262144. Smaller buffer sizes mean more frequent disk access, which can cause glitches. ::
|
||
|
|
||
|
@section{argument}
|
||
|
channelsArray
|
||
|
The Array of channels to write to the file.
|
||
|
@section{Note}
|
||
|
The number of channels in the buffer and the channelsArray must be the same, otherwise DiskOut will fail silently (and not write anything to your file). ::
|
||
|
|
||
|
@section{returns}
|
||
|
The number of frames written to disk.
|
||
|
|
||
|
@section{instancemethods}
|
||
|
|
||
|
@section{private}
|
||
|
checkInputs
|
||
|
|
||
|
@section{Examples}
|
||
|
|
||
|
|
||
|
@racketblock[
|
||
|
s.boot; // start the server
|
||
|
(
|
||
|
// something to record
|
||
|
SynthDef("bubbles", {
|
||
|
var f, zout;
|
||
|
f = LFSaw.kr(0.4, 0, 24, LFSaw.kr([8,7.23], 0, 3, 80)).midicps; // glissando function
|
||
|
zout = CombN.ar(SinOsc.ar(f, 0, 0.04), 0.2, 0.2, 4); // echoing sine wave
|
||
|
Out.ar(0, zout);
|
||
|
}).add;
|
||
|
|
||
|
// this will record to the disk
|
||
|
SynthDef("help-Diskout", {arg bufnum;
|
||
|
DiskOut.ar(bufnum, In.ar(0,2));
|
||
|
}).add;
|
||
|
|
||
|
// this will play it back
|
||
|
SynthDef("help-Diskin-2chan", { arg bufnum = 0;
|
||
|
Out.ar(0, DiskIn.ar(2, bufnum));
|
||
|
}).add;
|
||
|
)
|
||
|
::
|
||
|
|
||
|
]
|
||
|
@section{subsection}
|
||
|
Object Style
|
||
|
|
||
|
@racketblock[
|
||
|
// start something to record
|
||
|
x = Synth.new("bubbles");
|
||
|
|
||
|
// allocate a disk i/o buffer
|
||
|
b= Buffer.alloc(s, 65536, 2);
|
||
|
|
||
|
// create an output file for this buffer, leave it open
|
||
|
b.write("~/diskouttest.aiff".standardizePath, "aiff", "int16", 0, 0, true);
|
||
|
// create the diskout node; making sure it comes after the source
|
||
|
d = Synth.tail(nil, "help-Diskout", ["bufnum", b]);
|
||
|
// stop recording
|
||
|
d.free;
|
||
|
// stop the bubbles
|
||
|
x.free;
|
||
|
// close the buffer and the soundfile
|
||
|
b.close;
|
||
|
// free the buffer
|
||
|
b.free;
|
||
|
|
||
|
// play it back
|
||
|
(
|
||
|
x = Synth.basicNew("help-Diskin-2chan");
|
||
|
m = { arg buf; x.addToHeadMsg(nil, [\bufnum,buf])};
|
||
|
|
||
|
b = Buffer.cueSoundFile(s,"~/diskouttest.aiff".standardizePath, 0, 2, completionMessage: m);
|
||
|
)
|
||
|
x.free; b.close; b.free; // cleanup
|
||
|
::
|
||
|
|
||
|
]
|
||
|
@section{subsection}
|
||
|
Messaging Style
|
||
|
|
||
|
@racketblock[
|
||
|
// The same thing done in Messaging Style (less overhead but without the convenience of objects)
|
||
|
// This does nothing different from the Messaging Style example.
|
||
|
// If any of the following is confusing, stick to Object Style
|
||
|
// and ignore this part.
|
||
|
|
||
|
// start something to record
|
||
|
s.sendMsg("/s_new", "bubbles", 2003, 1, 1);
|
||
|
|
||
|
// allocate a disk i/o buffer
|
||
|
s.sendMsg("/b_alloc", 0, 65536, 2); // Buffer number is 0
|
||
|
|
||
|
// create an output file for this buffer, leave it open
|
||
|
s.sendMsg("/b_write", 0, "~/diskouttest.aiff".standardizePath, "aiff", "int16", 0, 0, 1);
|
||
|
|
||
|
// create the diskout node
|
||
|
s.sendMsg("/s_new", "help-Diskout", 2004, 3, 2003, "bufnum", 0);
|
||
|
|
||
|
s.sendMsg("/n_free", 2004); // stop recording
|
||
|
s.sendMsg("/n_free", 2003); // stop the bubbles
|
||
|
|
||
|
s.sendMsg("/b_close", 0); // close the file.
|
||
|
s.sendMsg("/b_free", 0);
|
||
|
::
|
||
|
|
||
|
]
|
||
|
|
||
|
|