368 lines
8.5 KiB
Text
368 lines
8.5 KiB
Text
|
#lang scribble/manual
|
||
|
@(require (for-label racket))
|
||
|
|
||
|
@title{Score}
|
||
|
score of timed OSC commands@section{related}
|
||
|
Guides/Non-Realtime-Synthesis
|
||
|
@section{categories}
|
||
|
Control, Server>NRT, External Control>OSC
|
||
|
|
||
|
@section{description}
|
||
|
|
||
|
Score encapsulates a list of timed OSC commands and provides some methods for using it, as well as support for the creation of binary OSC files for non-realtime synthesis. See link::Guides/Non-Realtime-Synthesis:: for more details.
|
||
|
|
||
|
The list should be in the following format, with times in ascending order. Bundles are okay.
|
||
|
|
||
|
|
||
|
@racketblock[
|
||
|
[
|
||
|
[beat1, [OSCcmd1]],
|
||
|
[beat2, [OSCcmd2], [OSCcmd3]],
|
||
|
...
|
||
|
[beat_n, [OSCcmdn]],
|
||
|
[beatToEndNRT, [\c_set, 0, 0]] // finish
|
||
|
]
|
||
|
::
|
||
|
|
||
|
For NRT synthesis the final event should a dummy event, after which synthesis will cease. It is thus important that this event be timed to allow previous events to complete.
|
||
|
|
||
|
Score scheduling defaults to link::Classes/TempoClock::. A setting of ]
|
||
|
|
||
|
@racketblock[TempoClock.default.tempo = 1 :: (60 beats per minute), may be used to express score events in seconds if desired.
|
||
|
|
||
|
]
|
||
|
@section{ClassMethods}
|
||
|
|
||
|
|
||
|
@section{private}
|
||
|
initClass
|
||
|
|
||
|
@section{method}
|
||
|
new
|
||
|
returns a new Score object with the supplied list.
|
||
|
|
||
|
@section{argument}
|
||
|
list
|
||
|
can be an link::Classes/Array::, a link::Classes/@section{List}
|
||
|
, or similar object.
|
||
|
|
||
|
@section{method}
|
||
|
newFromFile
|
||
|
as link::#*new::, but reads the list in from a text file.
|
||
|
|
||
|
@section{argument}
|
||
|
path
|
||
|
a link::Classes/String:: indicating the path of the file. The file must contain a valid SC expression.
|
||
|
|
||
|
@section{method}
|
||
|
play
|
||
|
as link::#*new:: but immediately plays it. (See also the instance method below.)
|
||
|
|
||
|
@section{argument}
|
||
|
list
|
||
|
the list.
|
||
|
|
||
|
@section{argument}
|
||
|
server
|
||
|
If no value is supplied it will play on the default link::Classes/Server::.
|
||
|
|
||
|
@section{method}
|
||
|
playFromFile
|
||
|
as link::#*play::, but reads the list from a file.
|
||
|
|
||
|
@section{method}
|
||
|
write
|
||
|
a convenience method to create a binary OSC file for NRT synthesis. Does not create an instance.
|
||
|
|
||
|
@section{argument}
|
||
|
list
|
||
|
the list.
|
||
|
|
||
|
@section{argument}
|
||
|
oscFilePath
|
||
|
a link::Classes/String:: containing the desired path of the OSC file.
|
||
|
|
||
|
@section{argument}
|
||
|
clock
|
||
|
Use clock as a tempo base.
|
||
|
@racketblock[TempoClock.default:: is used if clock is nil.
|
||
|
|
||
|
]
|
||
|
@section{method}
|
||
|
writeFromFile
|
||
|
as link::#*write:: but reads the list from a file.
|
||
|
|
||
|
@section{argument}
|
||
|
path
|
||
|
a path to a file with a list.
|
||
|
|
||
|
@section{argument}
|
||
|
oscFilePath
|
||
|
a link::Classes/String:: containing the desired path of the OSC file.
|
||
|
|
||
|
@section{argument}
|
||
|
clock
|
||
|
Use clock as a tempo base.
|
||
|
@racketblock[TempoClock.default:: is used if clock is nil.
|
||
|
|
||
|
]
|
||
|
@section{method}
|
||
|
recordNRT
|
||
|
a convenience method to synthesize strong@section{list}
|
||
|
in non-realtime. This method writes an OSC file to strong::oscFilePath:: (you have to do your own cleanup if desired) and then starts a server app to synthesize it. For details on valid headerFormats and sampleFormats see link::Classes/SoundFile::. Use
|
||
|
@racketblock[TempoClock.default:: as a tempo base. Does not return an instance.
|
||
|
|
||
|
]
|
||
|
@section{argument}
|
||
|
list
|
||
|
the list.
|
||
|
|
||
|
@section{argument}
|
||
|
oscFilePath
|
||
|
the path to which the binary OSC file will be written.
|
||
|
|
||
|
@section{argument}
|
||
|
outputFilePath
|
||
|
the path of the resultant soundfile.
|
||
|
|
||
|
@section{argument}
|
||
|
inputFilePath
|
||
|
an optional path for an input soundfile.
|
||
|
|
||
|
@section{argument}
|
||
|
sampleRate
|
||
|
the sample rate at which synthesis will occur.
|
||
|
|
||
|
@section{argument}
|
||
|
headerFormat
|
||
|
the header format of the output file. The default is 'AIFF'.
|
||
|
|
||
|
@section{argument}
|
||
|
sampleFormat
|
||
|
the sample format of the output file. The default is 'int16'.
|
||
|
|
||
|
@section{argument}
|
||
|
options
|
||
|
an instance of link::Classes/ServerOptions::. If not supplied the options of the default link::Classes/Server:: will be used.
|
||
|
|
||
|
@section{argument}
|
||
|
completionString
|
||
|
|
||
|
@section{argument}
|
||
|
duration
|
||
|
|
||
|
@section{argument}
|
||
|
action
|
||
|
A function to be evaluated once the NRT server has finished rendering its score.
|
||
|
|
||
|
@section{InstanceMethods}
|
||
|
|
||
|
|
||
|
@section{method}
|
||
|
play
|
||
|
play the list on strong::server::, use strong::clock:: as a tempo base and quantize start time to strong::quant::. If strong::server:: is nil, then on the default server.
|
||
|
@racketblock[TempoClock.default:: if strong::clock:: is nil. now if strong::quant:: is 0.
|
||
|
|
||
|
]
|
||
|
@section{method}
|
||
|
stop
|
||
|
stop playing.
|
||
|
|
||
|
@section{method}
|
||
|
write
|
||
|
create a binary OSC file for NRT synthesis from the list. Use strong::clock:: as a tempo base.
|
||
|
@racketblock[TempoClock.default:: if strong::clock:: is nil.
|
||
|
|
||
|
]
|
||
|
@section{method}
|
||
|
score
|
||
|
get or set the list.
|
||
|
|
||
|
@section{method}
|
||
|
add
|
||
|
adds bundle to the list.
|
||
|
|
||
|
@section{method}
|
||
|
sort
|
||
|
sort the score time order. This is recommended to do strong::before recordNRT or write:: when you are not sure about the packet order.
|
||
|
|
||
|
@section{method}
|
||
|
recordNRT
|
||
|
synthesize the score in non-realtime. For details of the arguments see link::#*recordNRT:: above.
|
||
|
|
||
|
@section{method}
|
||
|
saveToFile
|
||
|
save the score list as a text file to strong::path::.
|
||
|
|
||
|
@section{Examples}
|
||
|
|
||
|
|
||
|
@section{subsection}
|
||
|
NRT Examples
|
||
|
|
||
|
|
||
|
@racketblock[
|
||
|
// A sample synthDef
|
||
|
(
|
||
|
SynthDef("helpscore",{ arg freq = 440;
|
||
|
Out.ar(0,
|
||
|
SinOsc.ar(freq, 0, 0.2) * Line.kr(1, 0, 0.5, doneAction: Done.freeSelf)
|
||
|
)
|
||
|
}).add;
|
||
|
)
|
||
|
|
||
|
// write a sample file for testing
|
||
|
(
|
||
|
var f, g;
|
||
|
TempoClock.default.tempo = 1;
|
||
|
g = [
|
||
|
[0.1, [\s_new, \helpscore, 1000, 0, 0, \freq, 440]],
|
||
|
[0.2, [\s_new, \helpscore, 1001, 0, 0, \freq, 660]],
|
||
|
[0.3, [\s_new, \helpscore, 1002, 0, 0, \freq, 220]],
|
||
|
[1, [\c_set, 0, 0]] // finish
|
||
|
];
|
||
|
f = File("score-test","w");
|
||
|
f.write(g.asCompileString);
|
||
|
f.close;
|
||
|
)
|
||
|
|
||
|
//convert it to a binary OSC file for use with NRT
|
||
|
Score.writeFromFile("score-test", "test.osc");
|
||
|
::
|
||
|
|
||
|
From the command line, the file can then be rendered from within the build directory:
|
||
|
|
||
|
]
|
||
|
|
||
|
@racketblock[
|
||
|
./scsynth -N test.osc _ test.aif 44100 AIFF int16 -o 1
|
||
|
::
|
||
|
|
||
|
Score also provides methods to do all this more directly:
|
||
|
|
||
|
]
|
||
|
|
||
|
@racketblock[
|
||
|
(
|
||
|
var f, o;
|
||
|
g = [
|
||
|
[0.1, [\s_new, \helpscore, 1000, 0, 0, \freq, 440]],
|
||
|
[0.2, [\s_new, \helpscore, 1001, 0, 0, \freq, 660],
|
||
|
[\s_new, \helpscore, 1002, 0, 0, \freq, 880]],
|
||
|
[0.3, [\s_new, \helpscore, 1003, 0, 0, \freq, 220]],
|
||
|
[1, [\c_set, 0, 0]] // finish
|
||
|
];
|
||
|
o = ServerOptions.new.numOutputBusChannels = 1; // mono output
|
||
|
Score.recordNRT(g, "help-oscFile", "helpNRT.aiff", options: o); // synthesize
|
||
|
)
|
||
|
::
|
||
|
|
||
|
]
|
||
|
@section{subsection}
|
||
|
Real-time Examples
|
||
|
|
||
|
|
||
|
@racketblock[
|
||
|
s.boot; // boot the default server
|
||
|
|
||
|
// A sample synthDef
|
||
|
(
|
||
|
SynthDef("helpscore",{ arg freq = 440;
|
||
|
Out.ar(0,
|
||
|
SinOsc.ar(freq, 0, 0.2) * Line.kr(1, 0, 0.5, doneAction: Done.freeSelf)
|
||
|
)
|
||
|
}).add;
|
||
|
)
|
||
|
|
||
|
// write a sample file for testing
|
||
|
(
|
||
|
var f, g;
|
||
|
TempoClock.default.tempo = 1;
|
||
|
g = [
|
||
|
[0.1, [\s_new, \helpscore, 1000, 0, 0, \freq, 440]],
|
||
|
[0.2, [\s_new, \helpscore, 1001, 0, 0, \freq, 660],
|
||
|
[\s_new, \helpscore, 1002, 0, 0, \freq, 880]],
|
||
|
[0.3, [\s_new, \helpscore, 1003, 0, 0, \freq, 220]],
|
||
|
[1, [\c_set, 0, 0]] // finish
|
||
|
];
|
||
|
f = File("score-test","w");
|
||
|
f.write(g.asCompileString);
|
||
|
f.close;
|
||
|
)
|
||
|
|
||
|
z = Score.newFromFile("score-test");
|
||
|
|
||
|
// play it on the default server
|
||
|
z.play;
|
||
|
|
||
|
// change the list
|
||
|
(
|
||
|
x = [
|
||
|
[0.0, [ \s_new, \helpscore, 1000, 0, 0, \freq, 1413 ]],
|
||
|
[0.1, [ \s_new, \helpscore, 1001, 0, 0, \freq, 712 ]],
|
||
|
[0.2, [ \s_new, \helpscore, 1002, 0, 0, \freq, 417 ]],
|
||
|
[0.3, [ \s_new, \helpscore, 1003, 0, 0, \freq, 1238 ]],
|
||
|
[0.4, [ \s_new, \helpscore, 1004, 0, 0, \freq, 996 ]],
|
||
|
[0.5, [ \s_new, \helpscore, 1005, 0, 0, \freq, 1320 ]],
|
||
|
[0.6, [ \s_new, \helpscore, 1006, 0, 0, \freq, 864 ]],
|
||
|
[0.7, [ \s_new, \helpscore, 1007, 0, 0, \freq, 1033 ]],
|
||
|
[0.8, [ \s_new, \helpscore, 1008, 0, 0, \freq, 1693 ]],
|
||
|
[0.9, [ \s_new, \helpscore, 1009, 0, 0, \freq, 410 ]],
|
||
|
[1.0, [ \s_new, \helpscore, 1010, 0, 0, \freq, 1349 ]],
|
||
|
[1.1, [ \s_new, \helpscore, 1011, 0, 0, \freq, 1449 ]],
|
||
|
[1.2, [ \s_new, \helpscore, 1012, 0, 0, \freq, 1603 ]],
|
||
|
[1.3, [ \s_new, \helpscore, 1013, 0, 0, \freq, 333 ]],
|
||
|
[1.4, [ \s_new, \helpscore, 1014, 0, 0, \freq, 678 ]],
|
||
|
[1.5, [ \s_new, \helpscore, 1015, 0, 0, \freq, 503 ]],
|
||
|
[1.6, [ \s_new, \helpscore, 1016, 0, 0, \freq, 820 ]],
|
||
|
[1.7, [ \s_new, \helpscore, 1017, 0, 0, \freq, 1599 ]],
|
||
|
[1.8, [ \s_new, \helpscore, 1018, 0, 0, \freq, 968 ]],
|
||
|
[1.9, [ \s_new, \helpscore, 1019, 0, 0, \freq, 1347 ]],
|
||
|
[2.0, [\c_set, 0, 0]] // finish
|
||
|
];
|
||
|
|
||
|
z.score_(x);
|
||
|
)
|
||
|
|
||
|
// play it
|
||
|
z.play;
|
||
|
|
||
|
// play and stop after one second
|
||
|
(
|
||
|
z.play;
|
||
|
SystemClock.sched(1.0, {z.stop;});
|
||
|
)
|
||
|
::
|
||
|
|
||
|
]
|
||
|
@section{subsection}
|
||
|
creating Score from a pattern
|
||
|
|
||
|
|
||
|
@racketblock[
|
||
|
SynthDescLib.read;
|
||
|
|
||
|
// new pattern
|
||
|
(
|
||
|
p = Pbind(
|
||
|
\dur, Prand([0.3, 0.5], inf),
|
||
|
\freq, Prand([200, 300, 500],inf)
|
||
|
);
|
||
|
)
|
||
|
|
||
|
// make a score from the pattern, 4 beats long
|
||
|
z = p.asScore(4.0);
|
||
|
|
||
|
z.score.postcs;
|
||
|
z.play;
|
||
|
|
||
|
// rendering a pattern to sound file directly:
|
||
|
|
||
|
// render the pattern to aiff (4 beats)
|
||
|
|
||
|
p.render("asScore-Help.aif", 4.0);
|
||
|
::
|
||
|
]
|
||
|
|
||
|
|