scruby 0.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +5 -0
- data/.rspec +1 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +53 -0
- data/README.rdoc +65 -0
- data/Rakefile +10 -0
- data/TODO.markdown +3 -0
- data/examples/example.rb +73 -0
- data/lib/scruby/buffer.rb +153 -0
- data/lib/scruby/bus.rb +67 -0
- data/lib/scruby/control_name.rb +29 -0
- data/lib/scruby/core_ext/array.rb +44 -0
- data/lib/scruby/core_ext/delegator_array.rb +44 -0
- data/lib/scruby/core_ext/fixnum.rb +8 -0
- data/lib/scruby/core_ext/numeric.rb +25 -0
- data/lib/scruby/core_ext/object.rb +23 -0
- data/lib/scruby/core_ext/proc.rb +11 -0
- data/lib/scruby/core_ext/string.rb +5 -0
- data/lib/scruby/core_ext/symbol.rb +5 -0
- data/lib/scruby/core_ext/typed_array.rb +54 -0
- data/lib/scruby/env.rb +93 -0
- data/lib/scruby/group.rb +24 -0
- data/lib/scruby/node.rb +102 -0
- data/lib/scruby/server.rb +182 -0
- data/lib/scruby/synth.rb +50 -0
- data/lib/scruby/synthdef.rb +109 -0
- data/lib/scruby/ticker.rb +92 -0
- data/lib/scruby/ugens/buffer_read_write.rb +98 -0
- data/lib/scruby/ugens/demand.rb +9 -0
- data/lib/scruby/ugens/disk_in_out.rb +33 -0
- data/lib/scruby/ugens/env_gen.rb +38 -0
- data/lib/scruby/ugens/in_out.rb +46 -0
- data/lib/scruby/ugens/multi_out.rb +53 -0
- data/lib/scruby/ugens/operation_indices.yaml +92 -0
- data/lib/scruby/ugens/operation_ugens.rb +63 -0
- data/lib/scruby/ugens/panner.rb +137 -0
- data/lib/scruby/ugens/ugen.rb +173 -0
- data/lib/scruby/ugens/ugen_defs.yaml +3123 -0
- data/lib/scruby/ugens/ugen_operations.rb +57 -0
- data/lib/scruby/ugens/ugens.rb +95 -0
- data/lib/scruby/version.rb +3 -0
- data/lib/scruby.rb +65 -0
- data/scruby.gemspec +27 -0
- data/spec/buffer_read_write_spec.rb +333 -0
- data/spec/buffer_spec.rb +199 -0
- data/spec/bus_spec.rb +184 -0
- data/spec/core_ext/core_ext_spec.rb +120 -0
- data/spec/core_ext/delegator_array_spec.rb +144 -0
- data/spec/core_ext/typed_array_spec.rb +95 -0
- data/spec/demand_spec.rb +81 -0
- data/spec/disk_in_out_spec.rb +138 -0
- data/spec/env_gen_spec.rb +23 -0
- data/spec/env_spec.rb +73 -0
- data/spec/group_spec.rb +71 -0
- data/spec/helper.rb +20 -0
- data/spec/in_out_spec.rb +127 -0
- data/spec/integration_spec.rb +88 -0
- data/spec/multiout_ugen_spec.rb +86 -0
- data/spec/node_spec.rb +112 -0
- data/spec/operation_ugens_spec.rb +196 -0
- data/spec/panner_spec.rb +271 -0
- data/spec/server.rb +12 -0
- data/spec/server_spec.rb +198 -0
- data/spec/synth_spec.rb +103 -0
- data/spec/synthdef_spec.rb +267 -0
- data/spec/ugen_operations_spec.rb +100 -0
- data/spec/ugen_spec.rb +356 -0
- data/spec/ugens_spec.rb +65 -0
- metadata +207 -0
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
scruby (0.2.7)
|
5
|
+
arguments (~> 0.6)
|
6
|
+
live (~> 0.1)
|
7
|
+
ruby-osc (~> 0.3)
|
8
|
+
|
9
|
+
GEM
|
10
|
+
remote: http://rubygems.org/
|
11
|
+
specs:
|
12
|
+
ParseTree (3.0.7)
|
13
|
+
RubyInline (>= 3.7.0)
|
14
|
+
sexp_processor (>= 3.0.0)
|
15
|
+
RubyInline (3.9.0)
|
16
|
+
ZenTest (~> 4.3)
|
17
|
+
ZenTest (4.5.0)
|
18
|
+
arguments (0.6)
|
19
|
+
ParseTree (>= 3.0.3)
|
20
|
+
ruby2ruby (= 1.1.9)
|
21
|
+
ruby_parser (>= 2.0.2)
|
22
|
+
diff-lcs (1.1.2)
|
23
|
+
eventmachine (0.12.10)
|
24
|
+
highline (1.6.1)
|
25
|
+
hoe (2.9.1)
|
26
|
+
rake (>= 0.8.7)
|
27
|
+
live (0.1.2)
|
28
|
+
highline
|
29
|
+
rake (0.8.7)
|
30
|
+
rspec (2.5.0)
|
31
|
+
rspec-core (~> 2.5.0)
|
32
|
+
rspec-expectations (~> 2.5.0)
|
33
|
+
rspec-mocks (~> 2.5.0)
|
34
|
+
rspec-core (2.5.1)
|
35
|
+
rspec-expectations (2.5.0)
|
36
|
+
diff-lcs (~> 1.1.2)
|
37
|
+
rspec-mocks (2.5.0)
|
38
|
+
ruby-osc (0.3.2)
|
39
|
+
eventmachine (>= 0.12.8)
|
40
|
+
ruby2ruby (1.1.9)
|
41
|
+
ParseTree
|
42
|
+
hoe (>= 1.5.3)
|
43
|
+
ruby_parser (2.0.6)
|
44
|
+
sexp_processor (~> 3.0)
|
45
|
+
sexp_processor (3.0.5)
|
46
|
+
|
47
|
+
PLATFORMS
|
48
|
+
ruby
|
49
|
+
|
50
|
+
DEPENDENCIES
|
51
|
+
bundler
|
52
|
+
rspec
|
53
|
+
scruby!
|
data/README.rdoc
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
== Scruby
|
2
|
+
|
3
|
+
Is a bare-bones SuperCollider livecoding library for Ruby, it provides comunication with a remote or local scsynth server and SynthDef creation with a
|
4
|
+
in a similar way to Sclang.
|
5
|
+
|
6
|
+
SynthDef creation and sending is robust but some features are not implemented such as SynthDef variations and others I may not be aware of.
|
7
|
+
|
8
|
+
livecode.rb executable is located in the bin directory and a TextMate bundle included in extras permits livecoding from TextMate, comunication is
|
9
|
+
thrugh *nix pipes. Similar functionality shouldn't be too dificult to implement from Emacs or Vim.
|
10
|
+
|
11
|
+
== INSTALL
|
12
|
+
|
13
|
+
$ [sudo] gem install scruby
|
14
|
+
|
15
|
+
|
16
|
+
== USAGE
|
17
|
+
|
18
|
+
require 'scruby'
|
19
|
+
|
20
|
+
s = Server.new
|
21
|
+
s.boot
|
22
|
+
|
23
|
+
SynthDef.new :fm do |freq, amp, dur|
|
24
|
+
mod_env = EnvGen.kr Env.new( d(600, 200, 100), d(0.7,0.3) ), 1, :timeScale => dur
|
25
|
+
mod = SinOsc.ar freq * 1.4, :mul => mod_env
|
26
|
+
sig = SinOsc.ar freq + mod
|
27
|
+
env = EnvGen.kr Env.new( d(0, 1, 0.6, 0.2, 0.1, 0), d(0.001, 0.005, 0.3, 0.5, 0.7) ), 1, :timeScale => dur, :doneAction => 2
|
28
|
+
sig = sig * amp * env
|
29
|
+
Out.ar 0, [sig, sig]
|
30
|
+
end.send
|
31
|
+
|
32
|
+
Synth.new :fm, :freq => 220, :amp => 0.4, :dur => 1
|
33
|
+
|
34
|
+
|
35
|
+
To start a live coding session:
|
36
|
+
|
37
|
+
$ live
|
38
|
+
|
39
|
+
See http://github.com/maca/live
|
40
|
+
|
41
|
+
|
42
|
+
== TODO
|
43
|
+
|
44
|
+
Receive OSC messages from SuperCollider
|
45
|
+
|
46
|
+
== LICENSE:
|
47
|
+
|
48
|
+
Copyright (c) 2008 Macario Ortega
|
49
|
+
|
50
|
+
This program is free software: you can redistribute it and/or modify
|
51
|
+
it under the terms of the GNU General Public License as published by
|
52
|
+
the Free Software Foundation, either version 3 of the License, or
|
53
|
+
(at your option) any later version.
|
54
|
+
|
55
|
+
This program is distributed in the hope that it will be useful,
|
56
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
57
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
58
|
+
GNU General Public License for more details.
|
59
|
+
|
60
|
+
You should have received a copy of the GNU General Public License
|
61
|
+
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
62
|
+
|
63
|
+
|
64
|
+
|
65
|
+
|
data/Rakefile
ADDED
data/TODO.markdown
ADDED
data/examples/example.rb
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
scruby = "#{File.expand_path( File.join( File.dirname( __FILE__), '..', 'scruby' ) )}"
|
2
|
+
require scruby
|
3
|
+
s = Server.new('localhost', 57140)
|
4
|
+
s.boot
|
5
|
+
require File.expand_path( File.join( File.dirname(__FILE__),'..','..', '..', 'Sequentiable', 'lib', 'metro' ) )
|
6
|
+
require File.expand_path( File.join( File.dirname(__FILE__),'..','..', '..', 'HumanGenome', 'lib', 'human_genome' ) )
|
7
|
+
|
8
|
+
sdef = SynthDef.new :melo, :values => [456, 0.34, 0.45] do |freq, amp, a, b, c|
|
9
|
+
gate = EnvGen.kr( Env.perc(0, 0.2) )
|
10
|
+
sig = SinOsc.ar( [freq, freq * 1.01], :mul => SinOsc.kr(40) * amp * 0.7, :add => SinOsc.kr(0.5, :mul => 2.5) ) * EnvGen.kr( Env.asr(2, 1, 3), gate, :doneAction => 2 )
|
11
|
+
sig = SinOsc.ar( [freq, freq * 1.01], :mul => SinOsc.kr(8) * amp * 0.3, :add => SinOsc.kr(0.5, :mul => 2.5) ) * EnvGen.kr( Env.asr(2, 1, 2), gate ) + sig
|
12
|
+
sig = SinOsc.ar( [freq * 0.25, freq * 0.251], :mul => SinOsc.kr(30) * amp * 0.3 ) * EnvGen.kr( Env.asr(2, 1, 3), gate ) + sig
|
13
|
+
sig = SinOsc.ar( freq * 2, :mul => SinOsc.kr(500, :mul => 0.1) * amp * 0.1 ) * EnvGen.kr( Env.asr(0, 1, 2), gate ) + sig
|
14
|
+
sig = SinOsc.ar( freq * 0.25, :mul => amp * 0.2 ) * EnvGen.kr( Env.asr(0, 1, 0.4), gate ) + sig
|
15
|
+
res = Resonz.ar( sig, EnvGen.kr( Env.asr(0.5, 3,c*2) )* a * 10000 )
|
16
|
+
Out.ar( 0, [res[0] * 6 + sig[1] * 0.8]*2 )
|
17
|
+
end
|
18
|
+
sdef.send
|
19
|
+
sleep 0.05
|
20
|
+
test = Synth.new :melo, :freq => 220, :amp => 0.5
|
21
|
+
|
22
|
+
# [1] * 2 = [1,1]
|
23
|
+
|
24
|
+
s.stop
|
25
|
+
|
26
|
+
|
27
|
+
sdef = SynthDef.new :perc, :values => [456, 0.34, 0.45] do |freq, amp, a, b|
|
28
|
+
dur = a
|
29
|
+
amp = amp * 0.25
|
30
|
+
freq = freq * 0.05
|
31
|
+
sig = SinOsc.ar( Line.kr( freq * 1.5, freq * 1.1, dur ), Math::PI/2, amp * 0.2 * SinOsc.kr(10) )
|
32
|
+
# sig = Resonz.ar( sig, EnvGen.kr( Env.asr(0.5, 3, 2) ) * 120, 0.5 )
|
33
|
+
# sig = LPF.ar( sig, 120 )
|
34
|
+
sig = HPF.ar( WhiteNoise.ar( amp * 0.1 ), freq * 10 ) * b * 0.8 + sig
|
35
|
+
# sig = Pan2.ar( sig, 0)
|
36
|
+
env = EnvGen.kr Env.perc( 0, dur ), :doneAction => 2
|
37
|
+
Out.ar 0, [sig*env]*2
|
38
|
+
end
|
39
|
+
sdef.send
|
40
|
+
sleep 0.05
|
41
|
+
test = Synth.new :perc, :freq => 1000, :amp => 0.5, :dur => rand
|
42
|
+
|
43
|
+
sdef = SynthDef.new :perc, :values => [456, 0.34, 0.45] do |freq, amp, a, b|
|
44
|
+
dur = a
|
45
|
+
amp = amp
|
46
|
+
freq = freq * 0.1
|
47
|
+
sig = SinOsc.ar( Line.kr( freq * 1.5, freq * 1.1, dur ), Math::PI/2, amp * 0.2 * SinOsc.kr(10) )
|
48
|
+
sig = HPF.ar( WhiteNoise.ar( amp * 0.1 ), freq * 10 ) * 0.8 + sig
|
49
|
+
env = EnvGen.kr Env.perc( 0, dur ), :doneAction => 2
|
50
|
+
Out.ar 0, [sig*env]*2
|
51
|
+
end
|
52
|
+
sdef.send
|
53
|
+
sleep 0.05
|
54
|
+
test = Synth.new :perc, :freq => 1000, :amp => 0.5, :dur => rand
|
55
|
+
|
56
|
+
sdef = SynthDef.new :perc, :values => [456, 0.34, 0.45] do |freq, amp, a, b|
|
57
|
+
gate = EnvGen.kr Env.perc(0,0.1)
|
58
|
+
env = EnvGen.kr Env.asr( 0.1, 4, 1 ), gate, :doneAction => 2
|
59
|
+
sig = DelayC.ar( SinOsc.ar(freq), 4, SinOsc.ar( SinOsc.ar( SinOsc.ar( 2 ) ) ) )
|
60
|
+
Out.ar( 0, [sig * env]*2 )
|
61
|
+
end
|
62
|
+
sdef.send
|
63
|
+
sleep 0.05
|
64
|
+
test = Synth.new :perc, :freq => 1000, :amp => 0.5, :dur => rand
|
65
|
+
# sleep 0.8
|
66
|
+
|
67
|
+
s.stop
|
68
|
+
|
69
|
+
sleep 0.05
|
70
|
+
test = Synth.new :test, :freq => 20, :amp => 1
|
71
|
+
|
72
|
+
|
73
|
+
|
@@ -0,0 +1,153 @@
|
|
1
|
+
module Scruby
|
2
|
+
def expand_path path
|
3
|
+
path = "~/Scruby/#{ path }" unless path.match %r{^(?:/|~)}
|
4
|
+
File.expand_path path
|
5
|
+
end
|
6
|
+
|
7
|
+
class Buffer
|
8
|
+
# readNoUpdate
|
9
|
+
# loadCollection
|
10
|
+
# sendCollection
|
11
|
+
# streamCollection
|
12
|
+
# loadToFloatArray
|
13
|
+
# getToFloatArray
|
14
|
+
# set
|
15
|
+
# setn
|
16
|
+
# get
|
17
|
+
# getn
|
18
|
+
# fill
|
19
|
+
# normalize
|
20
|
+
# gen
|
21
|
+
# sine1
|
22
|
+
# ...
|
23
|
+
# copy
|
24
|
+
# copyData
|
25
|
+
# query
|
26
|
+
# updateInfo
|
27
|
+
# queryDone
|
28
|
+
# printOn
|
29
|
+
# play
|
30
|
+
# duration
|
31
|
+
# asBufWithValues
|
32
|
+
|
33
|
+
attr_reader :server
|
34
|
+
attr_accessor :path, :frames, :channels, :rate
|
35
|
+
|
36
|
+
def read path, file_start = 0, frames = -1, buff_start = 0, leave_open = false, &message
|
37
|
+
# @on_info = message
|
38
|
+
message ||= ["/b_query", buffnum]
|
39
|
+
@server.send "/b_read", buffnum, expand_path(path), file_start, frames, buff_start, leave_open, message.value(self)
|
40
|
+
self
|
41
|
+
end
|
42
|
+
|
43
|
+
def read_channel path, file_start = 0, frames = -1, buff_start = 0, leave_open = false, channels = [], &message
|
44
|
+
message ||= 0
|
45
|
+
@server.send *(["/b_ReadChannel", buffnum, expand_path(path), start, frames, buff_start, leave_open] + channels << message.value(self))
|
46
|
+
self
|
47
|
+
end
|
48
|
+
|
49
|
+
def close &message
|
50
|
+
message ||= 0
|
51
|
+
@server.send '/b_close', buffnum, message.value(self)
|
52
|
+
self
|
53
|
+
end
|
54
|
+
|
55
|
+
def zero &message
|
56
|
+
message ||= 0
|
57
|
+
@server.send '/b_zero', buffnum, message.value(self)
|
58
|
+
self
|
59
|
+
end
|
60
|
+
|
61
|
+
def cue_sound_file path, start = 0, &message
|
62
|
+
message ||= 0
|
63
|
+
@server.send "/b_read", buffnum, expand_path(path), start, @frames, 0, 1, message.value(self)
|
64
|
+
self
|
65
|
+
end
|
66
|
+
|
67
|
+
def write path = nil, format = 'aiff', sample_format = 'int24', frames = -1, start = 0, leave_open = false, &message
|
68
|
+
message ||= 0
|
69
|
+
path ||= "#{ DateTime.now }.#{ format }"
|
70
|
+
@server.send "/b_write", buffnum, expand_path(path), format, sample_format, frames, start, leave_open, message.value(self)
|
71
|
+
self
|
72
|
+
end
|
73
|
+
|
74
|
+
def initialize server, frames = -1, channels = 1
|
75
|
+
@server, @frames, @channels = server, frames, channels
|
76
|
+
end
|
77
|
+
|
78
|
+
def allocate &message
|
79
|
+
message ||= 0
|
80
|
+
@server.allocate :buffers, self
|
81
|
+
@server.send '/b_alloc', buffnum, frames, channels, message.value(self)
|
82
|
+
self
|
83
|
+
end
|
84
|
+
|
85
|
+
def buffnum
|
86
|
+
@server.buffers.index self
|
87
|
+
end
|
88
|
+
alias :as_ugen_input :buffnum
|
89
|
+
alias :index :buffnum
|
90
|
+
# alias :as_control_input :buffnum
|
91
|
+
|
92
|
+
def free &message
|
93
|
+
message ||= 0
|
94
|
+
@server.send "/b_free", buffnum, message.value(self)
|
95
|
+
@server.buffers.delete self
|
96
|
+
end
|
97
|
+
|
98
|
+
# :nodoc:
|
99
|
+
def allocate_and_read path, start, frames, &message
|
100
|
+
@server.allocate :buffers, self
|
101
|
+
message ||= ["/b_query", buffnum]
|
102
|
+
@server.send "/b_allocRead", buffnum, @path = expand_path(path), start, frames, message.value(self)
|
103
|
+
self
|
104
|
+
end
|
105
|
+
|
106
|
+
def allocate_read_channel path, start, frames, channels, &message
|
107
|
+
@server.allocate :buffers, self
|
108
|
+
message ||= ["/b_query", buffnum]
|
109
|
+
@server.send *(["/b_allocReadChannel", buffnum, expand_path(path), start, frames] + channels << message.value(self))
|
110
|
+
self
|
111
|
+
end
|
112
|
+
|
113
|
+
class << self
|
114
|
+
def allocate server, frames = -1, channels = 1, &message
|
115
|
+
new(server, frames, channels).allocate &message
|
116
|
+
end
|
117
|
+
|
118
|
+
def cue_sound_file server, path, start, channels = 2, buff_size = 32768, &message
|
119
|
+
allocate server, buff_size, channels do |buffer|
|
120
|
+
message ||= 0
|
121
|
+
['/b_read', buffer.buffnum, expand_path(path), start, buff_size, 0, true, message.value(buffer)]
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
# Allocate a buffer and immediately read a soundfile into it.
|
126
|
+
def read server, path, start = 0, frames = -1, &message
|
127
|
+
buffer = new server, &message
|
128
|
+
buffer.allocate_and_read expand_path(path), start, frames
|
129
|
+
end
|
130
|
+
|
131
|
+
def read_channel server, path, start = 0, frames = -1, channels = [], &message
|
132
|
+
new(server, frames, channels).allocate_read_channel expand_path(path), start, frames, channels, &message
|
133
|
+
end
|
134
|
+
|
135
|
+
def alloc_consecutive buffers, server, frames = -1, channels = 1, &message
|
136
|
+
buffers = Array.new(buffers){ new server, frames, channels }
|
137
|
+
server.allocate :buffers, buffers
|
138
|
+
message ||= 0
|
139
|
+
buffers.each do |buff|
|
140
|
+
server.send '/b_alloc', buff.buffnum, frames, channels, message.value(buff)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
named_arguments_for :allocate, :read, :cue_sound_file, :alloc_consecutive, :read_channel
|
145
|
+
|
146
|
+
# readNoUpdate
|
147
|
+
# loadCollection
|
148
|
+
# sendCollection
|
149
|
+
# loadDialog
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
data/lib/scruby/bus.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
module Scruby
|
2
|
+
|
3
|
+
class Bus
|
4
|
+
attr_reader :server, :rate, :channels, :main_bus
|
5
|
+
|
6
|
+
def initialize server, rate, channels = 1, main_bus = self, hardware_out = false
|
7
|
+
@server, @rate, @channels, @main_bus, @hardware_out = server, rate, channels, main_bus, hardware_out
|
8
|
+
end
|
9
|
+
|
10
|
+
def index
|
11
|
+
@index ||= @server.__send__("#{ @rate }_buses").index(self)
|
12
|
+
end
|
13
|
+
|
14
|
+
def free
|
15
|
+
@index = nil
|
16
|
+
@server.__send__("#{ @rate }_buses").delete(self)
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_map
|
20
|
+
raise SCError, 'Audio buses cannot be mapped' if rate == :audio
|
21
|
+
"c#{ index }"
|
22
|
+
end
|
23
|
+
|
24
|
+
def audio_out?
|
25
|
+
index < @server.instance_variable_get(:@opts)[:audio_outputs]
|
26
|
+
end
|
27
|
+
|
28
|
+
# Messaging
|
29
|
+
def set *args
|
30
|
+
args.flatten!
|
31
|
+
message_args = []
|
32
|
+
(index...channels).to_a.zip(args) do |chan, val|
|
33
|
+
message_args.push(chan).push(val) if chan and val
|
34
|
+
end
|
35
|
+
if args.size > channels
|
36
|
+
warn "You tried to set #{ args.size } values for bus #{ index } that only has #{ channels } channels, extra values are ignored."
|
37
|
+
end
|
38
|
+
@server.send '/c_set', *message_args
|
39
|
+
end
|
40
|
+
|
41
|
+
def fill value, channels = @channels
|
42
|
+
if channels > @channels
|
43
|
+
warn "You tried to set #{ channels } values for bus #{ index } that only has #{ @channels } channels, extra values are ignored."
|
44
|
+
end
|
45
|
+
@server.send '/c_fill', index, channels.min(@channels), value
|
46
|
+
end
|
47
|
+
|
48
|
+
class << self
|
49
|
+
private :new
|
50
|
+
|
51
|
+
def control server, channels = 1
|
52
|
+
buses = [new(server, :control, channels)]
|
53
|
+
buses.push new(server, :control, channels, buses.first) while buses.size < channels
|
54
|
+
server.allocate :control_buses, buses
|
55
|
+
buses.first
|
56
|
+
end
|
57
|
+
|
58
|
+
def audio server, channels = 1
|
59
|
+
buses = [new(server, :audio, channels)]
|
60
|
+
buses.push new(server, :audio, channels, buses.first) while buses.size < channels
|
61
|
+
server.allocate :audio_buses, buses
|
62
|
+
buses.first
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Scruby
|
2
|
+
class ControlName #:nodoc:
|
3
|
+
attr_accessor :name, :value, :rate, :index
|
4
|
+
RATES = { 'n_' => :noncontrol, 'i_' => :scalar, 'k_' => :control, 't_' => :trigger }
|
5
|
+
|
6
|
+
def initialize name, value, rate, index
|
7
|
+
@name, @value, @rate, @index = name.to_s, value.to_f, set_rate( name, rate ), index
|
8
|
+
end
|
9
|
+
|
10
|
+
def set_rate name, rate
|
11
|
+
RATES.has_value?( rate ) ? rate : rate_from_name( name )
|
12
|
+
end
|
13
|
+
|
14
|
+
def rate_from_name name
|
15
|
+
RATES[ name.to_s[0..1] ] || :control
|
16
|
+
end
|
17
|
+
|
18
|
+
def non_control?
|
19
|
+
@rate == :noncontrol
|
20
|
+
end
|
21
|
+
|
22
|
+
def == other
|
23
|
+
@name == other.name and
|
24
|
+
@value == other.value and
|
25
|
+
@rate == other.rate and
|
26
|
+
@index == other.index
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
class Array
|
2
|
+
#collect with index
|
3
|
+
def collect_with_index
|
4
|
+
self.zip( (0...self.size).map ).collect{ |element, index| yield element, index }
|
5
|
+
end
|
6
|
+
|
7
|
+
def wrap_to size
|
8
|
+
return self if size == self.size
|
9
|
+
self.dup.wrap_to! size
|
10
|
+
end
|
11
|
+
|
12
|
+
def wrap_to! size
|
13
|
+
return nil if size == self.size
|
14
|
+
original_size = self.size
|
15
|
+
size.times { |i| self[ i ] = self[ i % original_size ] }
|
16
|
+
self
|
17
|
+
end
|
18
|
+
|
19
|
+
def wrap_and_zip *args
|
20
|
+
max = args.map{ |a| instance_of?(Array) ? a.size : 0 }.max.max( self.size )
|
21
|
+
args = args.collect{ |a| a.to_array.wrap_to( max ) }
|
22
|
+
self.wrap_to( max ).zip( *args )
|
23
|
+
end
|
24
|
+
|
25
|
+
# Returns self
|
26
|
+
def to_array; self; end
|
27
|
+
|
28
|
+
def encode_floats #:nodoc:
|
29
|
+
[self.size].pack('n') + self.pack('g*') #TODO: Deprecate
|
30
|
+
end
|
31
|
+
|
32
|
+
def peel!
|
33
|
+
self.replace self.first if self.first.kind_of? Array if self.size == 1
|
34
|
+
end
|
35
|
+
|
36
|
+
def peel
|
37
|
+
self.dup.peel! || self
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
def collect_constants #:nodoc:
|
42
|
+
self.collect{ |e| e.send( :collect_constants ) }
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
class DelegatorArray < Array
|
2
|
+
|
3
|
+
def method_missing meth, *args, &block
|
4
|
+
return self.map! { |item| item.send meth, *args, &block }
|
5
|
+
end
|
6
|
+
|
7
|
+
def to_da; self; end
|
8
|
+
def to_a; Array.new self; end
|
9
|
+
|
10
|
+
[:*, :+, :-, :/].each do |meth|
|
11
|
+
define_method meth do |args|
|
12
|
+
binary_op meth, args
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
def binary_op op, inputs
|
18
|
+
return method_missing(op, inputs) unless inputs.kind_of? Array
|
19
|
+
|
20
|
+
results = self.class.new
|
21
|
+
self.zip(inputs).collect_with_index do |pair, index|
|
22
|
+
left, right = pair
|
23
|
+
next results.push(right) if index + 1 > self.size
|
24
|
+
next results.push(left) if index + 1 > inputs.size
|
25
|
+
results.push left.send(op, right)
|
26
|
+
end
|
27
|
+
results
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class Array
|
32
|
+
def to_da
|
33
|
+
DelegatorArray.new self
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
module Kernel
|
38
|
+
def d *args
|
39
|
+
args.peel!
|
40
|
+
darray = DelegatorArray.new
|
41
|
+
darray.push *args
|
42
|
+
darray
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
class Numeric
|
2
|
+
# Rate is :scalar
|
3
|
+
def rate; :scalar; end
|
4
|
+
|
5
|
+
# Compares itself with +other+ and returns biggest
|
6
|
+
def max other
|
7
|
+
self > other ? self : other
|
8
|
+
end
|
9
|
+
|
10
|
+
# Compares itself with +other+ and returns smallest
|
11
|
+
def min other
|
12
|
+
self < other ? self : other
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
#:nodoc:
|
17
|
+
def collect_constants
|
18
|
+
self
|
19
|
+
end
|
20
|
+
|
21
|
+
#:nodoc:
|
22
|
+
def input_specs synthdef
|
23
|
+
[-1, synthdef.constants.index(self)]
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class Object
|
2
|
+
# Wraps self int an array, #to_a seems to be deprecated
|
3
|
+
def to_array
|
4
|
+
[*self]
|
5
|
+
end
|
6
|
+
|
7
|
+
def to_proc
|
8
|
+
Proc.new{ self }
|
9
|
+
end
|
10
|
+
|
11
|
+
def value *args
|
12
|
+
self
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
class TrueClass
|
18
|
+
def to_i; 1; end
|
19
|
+
end
|
20
|
+
|
21
|
+
class FalseClass
|
22
|
+
def to_i; 0; end
|
23
|
+
end
|