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=
"1038.29">
9 <style type=
"text/css">
10 p
.p1
{margin: 0.0px 0.0px 0.0px 0.0px; font: 12.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
; color: #0000ee}
13 p
.p4
{margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco
; min-height: 12.0px}
14 p
.p5
{margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco
; color: #606060}
15 p
.p6
{margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco
}
16 p
.p7
{margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco
; color: #ad140d}
17 p
.p8
{margin: 0.0px 0.0px 0.0px 0.0px; font: 14.0px Helvetica
}
18 p
.p9
{margin: 0.0px 0.0px 0.0px 46.0px; text-indent: -28.0px; font: 12.0px Helvetica
}
19 p
.p10
{margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco
; color: #001bb9}
20 span
.s1
{font: 18.0px Helvetica
}
21 span
.s2
{font: 9.0px Monaco
}
22 span
.s3
{color: #000000}
23 span
.s4
{text-decoration: underline
}
24 span
.s5
{color: #001bb9}
25 span
.s6
{color: #2c7014}
26 span
.s7
{color: #606060}
27 span
.Apple-tab-span
{white-space:pre
}
31 <p class=
"p1"><span class=
"s1"><b>SynthDesc
</b></span><span class=
"s2"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></span><b>description of a synth definition
</b></p>
32 <p class=
"p2"><br></p>
33 <p class=
"p2"><br></p>
34 <p class=
"p1">Contains a description of a SynthDef, including its name, control names and default values.
</p>
35 <p class=
"p1">Information is also stored on its outputs and inputs and whether it has a gate control.
</p>
36 <p class=
"p2"><br></p>
37 <p class=
"p3"><span class=
"s3">See also:
<a href=
"SynthDef.html"><span class=
"s4">SynthDef
</span></a>,
<a href=
"Synth.html"><span class=
"s4">Synth
</span></a></span></p>
38 <p class=
"p2"><br></p>
39 <p class=
"p2"><br></p>
40 <p class=
"p2"><br></p>
41 <p class=
"p1"><span class=
"Apple-tab-span"> </span><b>*read(path, keepDefs, dict)
</b></p>
42 <p class=
"p1"><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>adds all synthDescs in a path to a dict
<span class=
"Apple-converted-space"> </span></p>
43 <p class=
"p2"><br></p>
44 <p class=
"p1"><span class=
"Apple-tab-span"> </span>SynthDescs are created by
<b>SynthDescLib
</b>, by reading a compiled synth def file.
</p>
45 <p class=
"p4"><br></p>
46 <p class=
"p5"><span class=
"s3"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></span><span class=
"s5">SynthDescLib
</span><span class=
"s3">.global.read(
</span>"synthdefs/default.scsyndef"<span class=
"s3">);
</span></p>
47 <p class=
"p6"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"s5">SynthDescLib
</span>.global.synthDescs.at(
<span class=
"s6">\default
</span>)
</p>
48 <p class=
"p7"><span class=
"s3"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></span><span class=
"s5">SynthDescLib
</span><span class=
"s3">.global.at(
</span><span class=
"s6">\default
</span><span class=
"s3">)
</span>// shortcut, same as line above
</p>
49 <p class=
"p4"><br></p>
50 <p class=
"p1"><span class=
"Apple-tab-span"> </span><b>name
</b><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>returns the name of the SynthDef
</p>
51 <p class=
"p1"><b><span class=
"Apple-tab-span"> </span>controlNames
</b><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>returns an array of instances of ControlName, each of which
<span class=
"Apple-converted-space"> </span></p>
52 <p class=
"p1"><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>have the following fields: name, index, rate, defaultValue
</p>
53 <p class=
"p4"><span class=
"Apple-tab-span"> </span></p>
54 <p class=
"p6"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"s5">SynthDescLib
</span>.global.at(
<span class=
"s6">\default
</span>).controlNames.postln;
</p>
55 <p class=
"p4"><span class=
"Apple-tab-span"> </span></p>
56 <p class=
"p1"><span class=
"s2"><span class=
"Apple-tab-span"> </span></span><b>hasGate
</b><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>is true if the Synthdef has a gate input
</p>
57 <p class=
"p1"><span class=
"Apple-tab-span"> </span><b>canFreeSynth
</b><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>is true if the Synth can free itself (via some means, usually a doneAction)
</p>
58 <p class=
"p1"><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>This can be used to decide if to remove a Synth directly via free-message.
</p>
59 <p class=
"p2"><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></p>
60 <p class=
"p6"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"s5">SynthDescLib
</span>.global.at(
<span class=
"s6">\default
</span>).canFreeSynth;
</p>
61 <p class=
"p4"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></p>
62 <p class=
"p1"><span class=
"Apple-tab-span"> </span><b>msgFunc
</b><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>the function which is used to create an array of arguments for
</p>
63 <p class=
"p1"><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>playing a synth def in patterns
</p>
64 <p class=
"p2"><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></p>
65 <p class=
"p6"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"s5">SynthDescLib
</span>.global.synthDescs.at(
<span class=
"s6">\default
</span>).msgFunc.postcs;
</p>
66 <p class=
"p4"><span class=
"Apple-tab-span"> </span></p>
67 <p class=
"p4"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></p>
68 <p class=
"p2"><br></p>
69 <p class=
"p1">SynthDescs are needed by the event stream system, so when using
<b>Pbind
</b>, the instruments' default parameters are derived from the SynthDesc.
</p>
70 <p class=
"p4"><br></p>
71 <p class=
"p4"><br></p>
72 <p class=
"p1"><b>aSynthDef.store
</b> and
<b>aSynthDef.add
</b> also create a synthDesc in the global library.
<b>.store
</b> saves a synthdef file on disk (like .load);
<b>.add
</b> creates the synthDesc wholly in memory and sends the synthdef to registered servers.
</p>
73 <p class=
"p4"><br></p>
74 <p class=
"p4"><br></p>
75 <p class=
"p6"><span class=
"Apple-tab-span"> </span>(
</p>
76 <p class=
"p6"><span class=
"Apple-tab-span"> </span><span class=
"s5">SynthDef
</span>(
<span class=
"s7">"test"</span>, {
<span class=
"s5">arg
</span> out, freq, xFade;
<span class=
"Apple-converted-space"> </span></p>
77 <p class=
"p6"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"s5">XOut
</span>.ar(out, xFade,
<span class=
"s5">SinOsc
</span>.ar(freq))
<span class=
"Apple-converted-space"> </span></p>
78 <p class=
"p6"><span class=
"Apple-tab-span"> </span>}).store
</p>
79 <p class=
"p6"><span class=
"Apple-tab-span"> </span>);
</p>
80 <p class=
"p4"><br></p>
81 <p class=
"p7"><span class=
"s3"><span class=
"Apple-tab-span"> </span></span><span class=
"s5">SynthDescLib
</span><span class=
"s3">.global.browse;
</span>// browse the properties of SynthDescs
</p>
82 <p class=
"p4"><br></p>
83 <p class=
"p4"><br></p>
84 <p class=
"p8"><b>SynthDescs and SynthDef metadata
</b></p>
85 <p class=
"p2"><br></p>
86 <p class=
"p1">Metadata associated with a SynthDef consists of an event (a syntactically shorter form of an identity dictionary) containing information about the SynthDef that is useful to the client, and which cannot be inferred from the binary .scsyndef stream. For example, by listing argument names and ControlSpecs under the 'specs' key in the event, the client can use the specs to build a GUI allowing control over all the SynthDef's inputs, with sensible range mappings. (The
"window" button in the SynthDescLib browser does exactly this -- any ControlSpecs listed in the metadata will be used for the corresponding synth input's slider.)
</p>
87 <p class=
"p2"><br></p>
88 <p class=
"p1">Currently only the 'specs' key is reserved. Other keys may be used as needed for specific applications. As the use of SynthDef metadata evolves, other keys may be standardized.
</p>
89 <p class=
"p2"><br></p>
90 <p class=
"p1"><b>Creation and access:
</b> Metadata are specified when creating a SynthDef. If the SynthDef is .store'd (or .added'd) into a SynthDescLib, the metadata become part of the SynthDesc as well. Thereafter, the metadata can be accessed through SynthDescLib:
</p>
91 <p class=
"p2"><br></p>
92 <p class=
"p6"><span class=
"s5">SynthDescLib
</span>.global[
<span class=
"s6">\synthDefName
</span>].metadata
</p>
93 <p class=
"p2"><br></p>
94 <p class=
"p1"><b>Persistence and metadata plug-ins:
</b> Storing a SynthDef into the library with .store persists the SynthDef on disk. Metadata may also be persisted at the same time by using the appropriate metadata plug-in class. The plug-in is responsible for writing a separate metadata file into the synthdefs directory, and reading the file back at the same time that a SynthDesc is created for a .scsyndef file using SynthDesc.read or SynthDescLib.global.read.
</p>
95 <p class=
"p2"><br></p>
96 <p class=
"p1">The currently available plug-ins are:
</p>
97 <p class=
"p2"><br></p>
98 <p class=
"p9"><b>AbstractMDPlugin:
</b> A dummy plug-in, which writes no metadata. This is the default, so that users who are not interested in metadata will not find extra files in the synthdefs directory.
</p>
99 <p class=
"p9"><b>TextArchiveMDPlugin:
</b> Writes the metadata as a SuperCollider text archive -- metadata.writeArchive(path).
</p>
100 <p class=
"p2"><br></p>
101 <p class=
"p1">Other plug-ins may be written at a later date, to support sharing metadata with applications in other languages using formats like JSON (JavaScript Object Notation) or XML.
</p>
102 <p class=
"p2"><br></p>
103 <p class=
"p1">You may specify a global default metadata plug-in as follows:
</p>
104 <p class=
"p2"><br></p>
105 <p class=
"p6"><span class=
"s5">SynthDesc
</span>.mdPlugin = ... plug-in class name ...;
</p>
106 <p class=
"p2"><br></p>
107 <p class=
"p1">Metadata are not written when using SynthDef().load(server). This is because SynthDesc exists to describe a SynthDef to the client, whereas SynthDef is really just an abstraction to create a UGen graph for the server.
</p>
108 <p class=
"p2"><br></p>
109 <p class=
"p1">Automatic population: You may write a function to populate entries into the metadata automatically, based on the SynthDesc object. This function executes when reading a SynthDesc from disk, when using .add, and before writing a metadata file (in .store).
</p>
110 <p class=
"p2"><br></p>
111 <p class=
"p6"><span class=
"s5">SynthDesc
</span>.populateMetadataFunc = {
<span class=
"s5">|synthdesc|
</span></p>
112 <p class=
"p6"><span class=
"Apple-tab-span"> </span>... do work here ...
</p>
114 <p class=
"p2"><br></p>
115 <p class=
"p1"><b>Synchronization:
</b> Whenever a .scsyndef file is written, any existing metadata files will be deleted so that a new .scsyndef file will not exist on disk with out-of-date metadata.
</p>
116 <p class=
"p2"><br></p>
117 <p class=
"p1"><b>Reading:
</b> When reading a SynthDesc, metadata files will be checked and one will be read, regardless of format. (Even if the default SynthDesc.mdPlugin is different from the file format on disk, the disk file will be read using the appropriate plug-in anyway.) There should be only one metadata file at a time. However, in the case of conflicts, the default SynthDesc.mdPlugin will be preferred. The file extension identifies the format.
</p>
118 <p class=
"p2"><br></p>
119 <p class=
"p8"><b>Metadata Examples
</b></p>
120 <p class=
"p2"><br></p>
121 <p class=
"p6">s.boot;
</p>
122 <p class=
"p4"><br></p>
123 <p class=
"p10"><span class=
"s3">d =
</span>SynthDef
<span class=
"s3">(
</span><span class=
"s6">\mdDemo
</span><span class=
"s3">, {
</span>|out, freq, cutoff, volume, gate =
1|
</p>
124 <p class=
"p6"><span class=
"Apple-tab-span"> </span><span class=
"s5">var
</span><span class=
"Apple-tab-span"> </span>sig =
<span class=
"s5">LPF
</span>.ar(
<span class=
"s5">Saw
</span>.ar(freq, volume), cutoff),
</p>
125 <p class=
"p6"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>env =
<span class=
"s5">EnvGen
</span>.kr(
<span class=
"s5">Env
</span>.adsr, gate, doneAction:
2);
</p>
126 <p class=
"p6"><span class=
"Apple-tab-span"> </span><span class=
"s5">Out
</span>.ar(out, (sig * env) !
2)
</p>
127 <p class=
"p6">}).add;
</p>
128 <p class=
"p4"><br></p>
129 <p class=
"p6"><span class=
"s5">SynthDescLib
</span>.global[
<span class=
"s6">\mdDemo
</span>].makeWindow;
</p>
130 <p class=
"p4"><br></p>
131 <p class=
"p7">// Note in the resulting window that Freq has a slider, but Cutoff and Volume do not.
</p>
132 <p class=
"p7">// This is because there are no global specs for the argument names 'cutoff' and 'volume'.
</p>
133 <p class=
"p4"><br></p>
134 <p class=
"p4"><br></p>
135 <p class=
"p7">// Same SynthDef, but adding metadata
</p>
136 <p class=
"p7">// \freq and \amp exist in the global ControlSpec collection -- Spec.specs
</p>
137 <p class=
"p7">// They are converted to real ControlSpecs using .asSpec
</p>
138 <p class=
"p4"><br></p>
139 <p class=
"p10"><span class=
"s3">d =
</span>SynthDef
<span class=
"s3">(
</span><span class=
"s6">\mdDemo
</span><span class=
"s3">, {
</span>|out, freq, cutoff, volume, gate =
1|
</p>
140 <p class=
"p6"><span class=
"Apple-tab-span"> </span><span class=
"s5">var
</span><span class=
"Apple-tab-span"> </span>sig =
<span class=
"s5">LPF
</span>.ar(
<span class=
"s5">Saw
</span>.ar(freq, volume), cutoff),
</p>
141 <p class=
"p6"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>env =
<span class=
"s5">EnvGen
</span>.kr(
<span class=
"s5">Env
</span>.adsr, gate, doneAction:
2);
</p>
142 <p class=
"p6"><span class=
"Apple-tab-span"> </span><span class=
"s5">Out
</span>.ar(out, (sig * env) !
2)
</p>
143 <p class=
"p6">}, metadata: (specs: (cutoff:
<span class=
"s6">\freq
</span>, volume:
<span class=
"s6">\amp
</span>))).add;
</p>
144 <p class=
"p4"><br></p>
145 <p class=
"p6"><span class=
"s5">SynthDescLib
</span>.global[
<span class=
"s6">\mdDemo
</span>].makeWindow;
</p>
146 <p class=
"p4"><br></p>
147 <p class=
"p7">// Now cutoff has a slider for frequency and volume has amplitude scaling
</p>
148 <p class=
"p4"><br></p>
149 <p class=
"p4"><br></p>
150 <p class=
"p7">// Store the SynthDef along with metadata
</p>
151 <p class=
"p6">d.store(mdPlugin:
<span class=
"s5">TextArchiveMDPlugin
</span>);
</p>
152 <p class=
"p4"><br></p>
153 <p class=
"p6"><span class=
"s7">"ls %mdDemo.*"</span>.format(
<span class=
"s5">SynthDef
</span>.synthDefDir.escapeChar($ )).unixCmd;
</p>
154 <p class=
"p4"><br></p>
155 <p class=
"p7">// In addition to .scsyndef, there's also .txarcmeta -
"text archive metadata"</p>
156 <p class=
"p4"><br></p>
157 <p class=
"p7">// Load a fresh SynthDesc from disk for it
</p>
158 <p class=
"p7">// The SynthDesc.read interface is a bit weird - e will be a dictionary holding the SynthDesc
</p>
159 <p class=
"p6">e =
<span class=
"s5">SynthDesc
</span>.read(
<span class=
"s5">SynthDef
</span>.synthDefDir ++
<span class=
"s7">"mdDemo.scsyndef"</span>);
</p>
160 <p class=
"p4"><br></p>
161 <p class=
"p7">// Metadata have been successfully read from disk!
</p>
162 <p class=
"p7">// You could even do the above after recompiling and the MD would be there
</p>
163 <p class=
"p6">e[
<span class=
"s6">\mdDemo
</span>].metadata
</p>
164 <p class=
"p4"><br></p>
165 <p class=
"p6">e[
<span class=
"s6">\mdDemo
</span>].makeWindow;
</p>