Top Level Namespace
Defined Under Namespace
Classes: Patch, Resample, Sox
Constant Summary
collapse
- INIT_PATCH =
YAML.load "---\nversion: 1\npatch:\n id: 2aedc73c-4095-4d1b-ab1b-2121ea9ac19d\n pan:\n x: 0.0\n y: 0.0\n zoom: 1.0\n nodes: []\n wires: []\n"
- LIGHT_NODE =
YAML.load "---\ntype: Light\nid: b264602f-365b-48a2-9d25-9b95055a2c34\nposition:\n x: 0.0\n y: 0.0\n"
- TRIGGER_NODE =
JSON.parse "{\n \"type\": \"Trigger\",\n \"id\": \"3e8e612d-3b7a-4c6d-a2ea-2e5f1a00161d\",\n \"position\": {\n \"x\": 0,\n \"y\": 0\n },\n \"toggle\": false,\n \"state\": false\n}\n"
- INPUT_NODE =
JSON.parse "{\n \"type\": \"Input\",\n \"id\": \"3e8e612d-3b7a-4c6d-a2ea-2e5f1a00161d\",\n \"position\": {\n \"x\": 0,\n \"y\": 0\n },\n \"exposedPosition\": {\n \"x\": 0,\n \"y\": 0\n },\n \"name\": \"input\"\n}\n"
- SUBPATCH_NODE =
JSON.parse "{\n \"type\": \"Patch\",\n \"id\": \"0fe72e0e-2616-4366-8036-f852398d1c73\",\n \"position\": {\n \"x\": -33.04297,\n \"y\": -44.77734\n },\n \"subPatch\": {\n \"id\": \"0e096166-2c2d-4c0e-bce3-f9c5f42ce5c5\",\n \"pan\": {\n \"x\": 0,\n \"y\": 0\n },\n \"zoom\": 1,\n \"nodes\": [],\n \"wires\": []\n }\n}\n"
- CLOCK_NODE =
JSON.parse(File.read(File.join(File.dirname(__FILE__), 'clock.json')))
- VIA_NODE =
Instance Method Summary
collapse
-
#add_node(patch, node) ⇒ Object
-
#add_nodes(patch, nodes) ⇒ Object
-
#build_clock_node ⇒ Object
-
#build_demux_node ⇒ Object
-
#build_expr_node(expr) ⇒ Object
-
#build_init_doc ⇒ Object
-
#build_input_node ⇒ Object
-
#build_knob_node ⇒ Object
-
#build_light_node ⇒ Object
-
#build_mux_node ⇒ Object
-
#build_output_node ⇒ Object
-
#build_patch_from_samples(samples, title1, title2, output_path) ⇒ Object
Given a set of samples, build the Audulus wavetable node.
-
#build_patch_from_wav_file(path) ⇒ Object
Given a path to a single-cycle-waveform wav file, generate an Audulus wavetable node.
-
#build_sample_and_hold_node ⇒ Object
-
#build_simple_node(type) ⇒ Object
-
#build_subpatch_node ⇒ Object
-
#build_text_node(text) ⇒ Object
-
#build_trigger_node ⇒ Object
-
#build_uuid_map(node) ⇒ Object
-
#build_via_node ⇒ Object
-
#clone_node(node) ⇒ Object
-
#clone_node_helper(node, uuid_map) ⇒ Object
-
#command(argv) ⇒ Object
-
#expose_node(node, x, y) ⇒ Object
-
#make_parabolic_samples(count) ⇒ Object
Make a set of samples conforming to a parabola.
-
#make_random_samples(count) ⇒ Object
Make a set of random samples.
-
#make_subpatch(subpatch) ⇒ Object
-
#move_node(node, x, y) ⇒ Object
-
#scan_uuids(node) ⇒ Object
-
#usage ⇒ Object
-
#uuid?(string) ⇒ Boolean
-
#wire_output_to_input(patch, source_node, source_output, destination_node, destination_input) ⇒ Object
Instance Method Details
#add_node(patch, node) ⇒ Object
59
60
61
62
|
# File 'lib/audulus.rb', line 59
def add_node(patch, node)
patch['nodes'] << node
patch
end
|
#add_nodes(patch, nodes) ⇒ Object
64
65
66
67
68
|
# File 'lib/audulus.rb', line 64
def add_nodes(patch, nodes)
nodes.each do |node|
add_node(patch, node)
end
end
|
#build_clock_node ⇒ Object
123
124
125
|
# File 'lib/audulus.rb', line 123
def build_clock_node
clone_node(CLOCK_NODE)
end
|
#build_demux_node ⇒ Object
160
161
162
|
# File 'lib/audulus.rb', line 160
def build_demux_node
build_simple_node("Demux8")
end
|
#build_expr_node(expr) ⇒ Object
164
165
166
167
168
|
# File 'lib/audulus.rb', line 164
def build_expr_node(expr)
result = build_simple_node('Expr')
result['expr'] = expr
result
end
|
#build_init_doc ⇒ Object
95
96
97
98
|
# File 'lib/audulus.rb', line 95
def build_init_doc
result = clone_node(INIT_PATCH)
result
end
|
131
132
133
|
# File 'lib/audulus.rb', line 131
def build_input_node
clone_node(INPUT_NODE)
end
|
#build_knob_node ⇒ Object
141
142
143
144
145
146
147
148
149
150
|
# File 'lib/audulus.rb', line 141
def build_knob_node
result = build_simple_node("Knob")
result['knob'] = {
'value' => 0.5,
'min' => 0.0,
'max' => 1.0,
}
expose_node(result, 0, 0)
result
end
|
#build_light_node ⇒ Object
110
111
112
|
# File 'lib/audulus.rb', line 110
def build_light_node
clone_node(LIGHT_NODE)
end
|
#build_mux_node ⇒ Object
156
157
158
|
# File 'lib/audulus.rb', line 156
def build_mux_node
build_simple_node("Mux8")
end
|
#build_output_node ⇒ Object
135
136
137
138
139
|
# File 'lib/audulus.rb', line 135
def build_output_node
result = build_simple_node("Output")
result['name'] = "Output"
result
end
|
#build_patch_from_samples(samples, title1, title2, output_path) ⇒ Object
Given a set of samples, build the Audulus wavetable node
259
260
261
262
|
# File 'lib/build_audulus_wavetable_node.rb', line 259
def build_patch_from_samples(samples, title1, title2, output_path)
puts "building #{output_path}"
File.write(output_path, JSON.generate(make_subpatch(Patch.build_patch(samples, title1, title2)['patch'])))
end
|
#build_patch_from_wav_file(path) ⇒ Object
Given a path to a single-cycle-waveform wav file, generate an Audulus wavetable node
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
|
# File 'lib/build_audulus_wavetable_node.rb', line 216
def build_patch_from_wav_file(path)
parent, file = path.split("/")[-2..-1]
samples = Sox.load_samples(path)
basename = File.basename(file, ".wav")
puts "building #{basename}.audulus"
audulus_patch_name = "#{basename}.audulus"
base_patch = Patch.build_patch(samples, parent, basename)['patch']
final_patch = make_subpatch(base_patch)
File.write(audulus_patch_name, JSON.generate(final_patch))
end
|
#build_sample_and_hold_node ⇒ Object
152
153
154
|
# File 'lib/audulus.rb', line 152
def build_sample_and_hold_node
build_simple_node("Sample & Hold")
end
|
#build_simple_node(type) ⇒ Object
176
177
178
179
180
181
182
183
184
185
|
# File 'lib/audulus.rb', line 176
def build_simple_node(type)
clone_node({
"type" => type,
"id" => "7e5486fc-994c-44f0-ae83-5ebba54d7e3b",
"position" => {
"x" => 0,
"y" => 0
}
})
end
|
#build_subpatch_node ⇒ Object
118
119
120
|
# File 'lib/audulus.rb', line 118
def build_subpatch_node
clone_node(SUBPATCH_NODE)
end
|
#build_text_node(text) ⇒ Object
170
171
172
173
174
|
# File 'lib/audulus.rb', line 170
def build_text_node(text)
result = build_simple_node("Text")
result['text'] = text
result
end
|
#build_trigger_node ⇒ Object
114
115
116
|
# File 'lib/audulus.rb', line 114
def build_trigger_node
clone_node(TRIGGER_NODE)
end
|
#build_uuid_map(node) ⇒ Object
27
28
29
30
31
32
33
|
# File 'lib/audulus.rb', line 27
def build_uuid_map(node)
existing_uuids = scan_uuids(node)
existing_uuids.reduce({}) {|h, uuid|
h[uuid] = SecureRandom.uuid()
h
}
end
|
#build_via_node ⇒ Object
127
128
129
|
# File 'lib/audulus.rb', line 127
def build_via_node
clone_node(VIA_NODE)
end
|
#clone_node(node) ⇒ Object
35
36
37
38
|
# File 'lib/audulus.rb', line 35
def clone_node(node)
uuid_map = build_uuid_map(node)
clone_node_helper(node, uuid_map)
end
|
#clone_node_helper(node, uuid_map) ⇒ Object
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
|
# File 'lib/audulus.rb', line 40
def clone_node_helper(node, uuid_map)
case node
when Hash
Hash[node.map {|key, elem|
if uuid?(elem)
[key, uuid_map[elem]]
else
[key, clone_node_helper(elem, uuid_map)]
end
}]
when Array
node.map {|elem|
clone_node_helper(elem, uuid_map)
}
else
node
end
end
|
#command(argv) ⇒ Object
272
273
274
275
276
277
278
279
280
281
282
283
284
|
# File 'lib/build_audulus_wavetable_node.rb', line 272
def command(argv)
if argv.count != 1
puts usage
else
path = argv[0]
unless File.exist?(path)
puts "Cannot find WAV file at #{path}"
exit(1)
end
build_patch_from_wav_file(path)
end
end
|
#expose_node(node, x, y) ⇒ Object
78
79
80
81
82
83
84
|
# File 'lib/audulus.rb', line 78
def expose_node(node, x, y)
node['exposedPosition'] = {
'x' => x,
'y' => y,
}
node
end
|
#make_parabolic_samples(count) ⇒ Object
Make a set of samples conforming to a parabola. This method would be used in place of loading the WAV file.
249
250
251
252
253
254
255
256
|
# File 'lib/build_audulus_wavetable_node.rb', line 249
def make_parabolic_samples(count)
f = ->(x) { -4*x**2 + 4*x }
count.times.map {|index|
index.to_f / (count-1)
}.map(&f).map {|sample|
sample*2-1
}
end
|
#make_random_samples(count) ⇒ Object
Make a set of random samples. Useful for generating a cyclic noise wavetable. This method would be used in place of loading the WAV file.
241
242
243
244
245
|
# File 'lib/build_audulus_wavetable_node.rb', line 241
def make_random_samples(count)
count.times.map {
rand*2-1
}
end
|
#make_subpatch(subpatch) ⇒ Object
100
101
102
103
104
105
106
107
108
|
# File 'lib/audulus.rb', line 100
def make_subpatch(subpatch)
doc = build_init_doc
patch = doc['patch']
subpatch_node = build_subpatch_node
subpatch_node['subPatch'] = subpatch
add_node(patch, subpatch_node)
doc
end
|
#move_node(node, x, y) ⇒ Object
70
71
72
73
74
75
76
|
# File 'lib/audulus.rb', line 70
def move_node(node, x, y)
node['position'] = {
'x' => x,
'y' => y,
}
node
end
|
#scan_uuids(node) ⇒ Object
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
# File 'lib/audulus.rb', line 10
def scan_uuids(node)
case node
when Hash
node.map {|key, elem|
if uuid?(elem)
elem
else
scan_uuids(elem)
end
}.flatten
when Array
node.map {|elem| scan_uuids(elem)}.flatten
else
[]
end
end
|
#usage ⇒ Object
264
265
266
267
268
269
270
|
# File 'lib/build_audulus_wavetable_node.rb', line 264
def usage
"Usage: build_audulus_wavetable_node <wav_file>\n\nOutputs an audulus patch built from the <wav_file>. Assumes the input is monophonic, containing a single-cycle waveform.\n END\nend\n"
|
#uuid?(string) ⇒ Boolean
5
6
7
|
# File 'lib/audulus.rb', line 5
def uuid?(string)
string.kind_of?(String) && /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/ =~ string
end
|
86
87
88
89
90
91
92
93
|
# File 'lib/audulus.rb', line 86
def wire_output_to_input(patch, source_node, source_output, destination_node, destination_input)
patch['wires'] << {
"from" => source_node['id'],
"output" => source_output,
"to" => destination_node['id'],
"input": destination_input
}
end
|