maca-Scruby 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. data/README.rdoc +26 -0
  2. data/Rakefile +10 -0
  3. data/Scruby.gemspec +36 -0
  4. data/bin/live_session.rb +12 -0
  5. data/changes +1 -0
  6. data/lib/live/session.rb +144 -0
  7. data/lib/scruby.rb +60 -0
  8. data/lib/scruby/audio/control_name.rb +29 -0
  9. data/lib/scruby/audio/env.rb +97 -0
  10. data/lib/scruby/audio/node.rb +20 -0
  11. data/lib/scruby/audio/server.rb +112 -0
  12. data/lib/scruby/audio/synth.rb +15 -0
  13. data/lib/scruby/audio/synthdef.rb +114 -0
  14. data/lib/scruby/audio/ugens/env_gen.rb +18 -0
  15. data/lib/scruby/audio/ugens/in_out.rb +43 -0
  16. data/lib/scruby/audio/ugens/multi_out_ugens.rb +48 -0
  17. data/lib/scruby/audio/ugens/operation_indices.yaml +92 -0
  18. data/lib/scruby/audio/ugens/operation_ugens.rb +64 -0
  19. data/lib/scruby/audio/ugens/ugen.rb +154 -0
  20. data/lib/scruby/audio/ugens/ugen_defs.yaml +3421 -0
  21. data/lib/scruby/audio/ugens/ugen_operations.rb +44 -0
  22. data/lib/scruby/audio/ugens/ugens.rb +34 -0
  23. data/lib/scruby/control/metro.rb +6 -0
  24. data/lib/scruby/extensions.rb +109 -0
  25. data/lib/scruby/typed_array.rb +64 -0
  26. data/spec/audio/env_gen_specs.rb +25 -0
  27. data/spec/audio/in_out_spec.rb +107 -0
  28. data/spec/audio/integration_spec.rb +106 -0
  29. data/spec/audio/lib_spec.rb +14 -0
  30. data/spec/audio/multiout_ugen_spec.rb +112 -0
  31. data/spec/audio/node_spec.rb +60 -0
  32. data/spec/audio/operation_ugens_spec.rb +189 -0
  33. data/spec/audio/server_spec.rb +68 -0
  34. data/spec/audio/synth_spec.rb +46 -0
  35. data/spec/audio/synthdef_spec.rb +275 -0
  36. data/spec/audio/ugen_operations_spec.rb +146 -0
  37. data/spec/audio/ugen_spec.rb +333 -0
  38. data/spec/audio/ugens_spec.rb +61 -0
  39. data/spec/env_spec.rb +64 -0
  40. data/spec/extensions_spec.rb +133 -0
  41. data/spec/helper.rb +11 -0
  42. data/spec/typed_array_spec.rb +95 -0
  43. metadata +129 -0
@@ -0,0 +1,46 @@
1
+ require File.join( File.expand_path(File.dirname(__FILE__)), '..',"helper")
2
+ require 'yaml'
3
+ require 'named_arguments'
4
+
5
+
6
+ require "#{SCRUBY_DIR}/typed_array"
7
+ require "#{SCRUBY_DIR}/audio/node"
8
+ require "#{SCRUBY_DIR}/audio/synth"
9
+
10
+ include Scruby
11
+
12
+ describe Synth do
13
+
14
+ before :all do
15
+ Server = mock('server')
16
+ end
17
+
18
+ before do
19
+ Node.reset!
20
+ @servers = (0..3).map{ s = mock( 'server'); s.stub!(:send); s }
21
+ @synth = Synth.new( :synth, :attack => 10, :servers => @servers )
22
+ end
23
+
24
+ it "should initialize" do
25
+ s = Synth.new( 'synth', :attack => 10, :servers => @servers )
26
+ s.name.should == 'synth'
27
+ s.servers.should == @servers
28
+ end
29
+
30
+ it "should initialize not passing servers and have default servers" do
31
+ Server.should_receive(:all).and_return(@servers)
32
+ s = Synth.new( 'synth' )
33
+ s.servers.should == @servers
34
+ end
35
+
36
+ it "should send /s_new message" do
37
+ @servers.each{ |s| s.should_receive(:send).with( '/s_new', ['synth', 2002, 0, 1, :attack, 10] ) }
38
+ s = Synth.new( :synth, :attack => 10, :servers => @servers )
39
+ end
40
+
41
+ it "should send set message and return self" do
42
+ @servers.each{ |s| s.should_receive(:send).with( '/n_set', [2001, :attack, 20] ) }
43
+ @synth.set( :attack => 20 ).should == @synth
44
+ end
45
+
46
+ end
@@ -0,0 +1,275 @@
1
+ require File.join( File.expand_path(File.dirname(__FILE__)), '..',"helper")
2
+
3
+ require "#{SCRUBY_DIR}/audio/ugens/ugen_operations"
4
+ require "#{SCRUBY_DIR}/extensions"
5
+ require "#{SCRUBY_DIR}/audio/synthdef"
6
+ require "#{SCRUBY_DIR}/audio/ugens/ugen"
7
+ require "#{SCRUBY_DIR}/audio/ugens/multi_out_ugens"
8
+ require "#{SCRUBY_DIR}/typed_array"
9
+
10
+
11
+
12
+ include Scruby
13
+ include Audio
14
+ include Ugens
15
+
16
+ class ControlName
17
+ def self.new( *args )
18
+ args.flatten
19
+ end
20
+ end
21
+
22
+
23
+ describe SynthDef, 'instantiation' do
24
+
25
+ describe 'initialize' do
26
+ before do
27
+ @sdef = SynthDef.new( :name )
28
+ @sdef.stub!( :collect_control_names )
29
+ end
30
+
31
+ it "should instantiate" do
32
+ @sdef.should_not be_nil
33
+ @sdef.should be_instance_of( SynthDef )
34
+ end
35
+
36
+ it "should protect attributes" do
37
+ @sdef.should_not respond_to( :name= )
38
+ @sdef.should_not respond_to( :children= )
39
+ @sdef.should_not respond_to( :constants= )
40
+ @sdef.should_not respond_to( :control_names= )
41
+
42
+ @sdef.should respond_to( :name )
43
+ @sdef.should respond_to( :children )
44
+ @sdef.should respond_to( :constants )
45
+ @sdef.should respond_to( :control_names )
46
+ end
47
+
48
+ it "should accept name and set it as an attribute as string" do
49
+ @sdef.name.should eql( 'name' )
50
+ end
51
+
52
+ it "should initialize with an empty array for children" do
53
+ @sdef.children.should eql( [] )
54
+ end
55
+ end
56
+
57
+ describe "options" do
58
+ before do
59
+ @options = mock( Hash )
60
+ end
61
+
62
+ it "should accept options" do
63
+ sdef = SynthDef.new( :hola, :values => [] ){}
64
+ end
65
+
66
+ it "should use options" do
67
+ @options.should_receive(:delete).with( :values )
68
+ @options.should_receive(:delete).with( :rates )
69
+
70
+ sdef = SynthDef.new( :hola, @options ){}
71
+ end
72
+
73
+ it "should set default values if not provided"
74
+ it "should accept a graph function"
75
+
76
+ end
77
+
78
+ describe '#collect_control_names' do
79
+ before do
80
+ @sdef = SynthDef.new( :name ){}
81
+ @function = mock( "grap_function", :argument_names => [:arg1, :arg2, :arg3] )
82
+ end
83
+
84
+ it "should get the argument names for the provided function" do
85
+ @function.should_receive( :argument_names ).and_return( [] )
86
+ @sdef.send_msg( :collect_control_names, @function, [], [] )
87
+ end
88
+
89
+ it "should return empty array if the names are empty" do
90
+ @function.should_receive( :argument_names ).and_return( [] )
91
+ @sdef.send_msg( :collect_control_names, @function, [], [] ).should eql([])
92
+ end
93
+
94
+ it "should not return empty array if the names are not empty" do
95
+ @sdef.send_msg( :collect_control_names, @function, [], [] ).should_not eql([])
96
+ end
97
+
98
+ it "should instantiate and return a ControlName for each function name" do
99
+ c_name = mock( :control_name )
100
+ ControlName.should_receive( :new ).at_most(3).times.and_return( c_name )
101
+ control_names = @sdef.send_msg( :collect_control_names, @function, [1,2,3], [] )
102
+ control_names.size.should eql(3)
103
+ control_names.collect { |e| e.should == c_name }
104
+ end
105
+
106
+ it "should pass the argument value, the argument index and the rate(if provided) to the ControlName at instantiation" do
107
+ @sdef.send_msg( :collect_control_names, @function, [:a,:b,:c], [] ).should eql( [[:arg1, :a, nil, 0], [:arg2, :b, nil, 1], [:arg3, :c, nil, 2]])
108
+ @sdef.send_msg( :collect_control_names, @function, [:a,:b,:c], [:ir, :tr, :ir] ).should eql( [[:arg1, :a, :ir, 0], [:arg2, :b, :tr, 1], [:arg3, :c, :ir, 2]])
109
+ end
110
+
111
+ it "should not return more elements than the function argument number" do
112
+ c_name = mock( :control_name )
113
+ ControlName.should_receive( :new ).at_most(3).times.and_return( c_name )
114
+ @sdef.send_msg( :collect_control_names, @function, [:a, :b, :c, :d, :e], [] ).should have( 3 ).elements
115
+ end
116
+ end
117
+
118
+ describe '#build_controls' do
119
+
120
+ before :all do
121
+ Object.send(:remove_const, 'ControlName')
122
+ RATES = [:scalar, :trigger, :control]
123
+ require "#{SCRUBY_DIR}/audio/control_name"
124
+ end
125
+
126
+ before do
127
+ @sdef = SynthDef.new( :name ){}
128
+ @function = mock( "grap_function", :argument_names => [:arg1, :arg2, :arg3, :arg4] )
129
+ @control_names = Array.new( rand(10)+15 ) { |i| ControlName.new "arg#{i+1}".to_sym, i, RATES[ rand(3) ], i }
130
+ end
131
+
132
+ it "should call Control#and_proxies.." do
133
+ rates = @control_names.collect{ |c| c.rate }.uniq
134
+ Control.should_receive(:and_proxies_from).exactly( rates.size ).times
135
+ @sdef.send_msg( :build_controls, @control_names )
136
+ end
137
+
138
+ it "should call Control#and_proxies.. with args" do
139
+ Control.should_receive(:and_proxies_from).with( @control_names.select{ |c| c.rate == :scalar } ) unless @control_names.select{ |c| c.rate == :scalar }.empty?
140
+ Control.should_receive(:and_proxies_from).with( @control_names.select{ |c| c.rate == :trigger } ) unless @control_names.select{ |c| c.rate == :trigger }.empty?
141
+ Control.should_receive(:and_proxies_from).with( @control_names.select{ |c| c.rate == :control } ) unless @control_names.select{ |c| c.rate == :control }.empty?
142
+ @sdef.send_msg( :build_controls, @control_names )
143
+ end
144
+
145
+ it do
146
+ @sdef.send_msg( :build_controls, @control_names ).should be_instance_of(Array)
147
+ end
148
+
149
+ it "should return an array of OutputProxies" do
150
+ @sdef.send_msg( :build_controls, @control_names ).each { |e| e.should be_instance_of(OutputProxy) }
151
+ end
152
+
153
+ it "should return an array of OutputProxies sorted by ControlNameIndex" do
154
+ @sdef.send_msg( :build_controls, @control_names ).collect{ |p| p.control_name.index }.should == (0...@control_names.size).map
155
+ end
156
+
157
+ it "should call graph function with correct args" do
158
+ function = mock("function", :call => [] )
159
+ proxies = @sdef.send_msg( :build_controls, @control_names )
160
+ @sdef.stub!( :build_controls ).and_return( proxies )
161
+ function.should_receive( :call ).with( *proxies )
162
+ @sdef.send_msg( :build_ugen_graph, function, @control_names)
163
+ end
164
+
165
+ it "should set @sdef" do
166
+ function = lambda{}
167
+ Ugen.should_receive( :synthdef= ).with( @sdef )
168
+ Ugen.should_receive( :synthdef= ).with( nil )
169
+ @sdef.send_msg( :build_ugen_graph, function, [] )
170
+ end
171
+
172
+ it "should collect constants for simple children array" do
173
+ children = [Ugen.new(:audio, 100), Ugen.new(:audio, 200), Ugen.new(:audio, 100, 300)]
174
+ @sdef.send_msg( :collect_constants, children).should == [100.0, 200.0, 300.0]
175
+ end
176
+
177
+ it "should collect constants for children arrays" do
178
+ children = [ Ugen.new(:audio, 100), [ Ugen.new(:audio, 400), [ Ugen.new(:audio, 200), Ugen.new(:audio, 100, 300) ] ] ]
179
+ @sdef.send_msg( :collect_constants, children).should == [100.0, 400.0, 200.0, 300.0]
180
+ end
181
+
182
+ it "should remove nil from constants array"
183
+
184
+ end
185
+
186
+ end
187
+
188
+
189
+ describe "encoding" do
190
+
191
+ before :all do
192
+ class SinOsc < Ugen
193
+ def self.ar( freq=440.0, phase=0.0 ) #not interested in muladd
194
+ new(:audio, freq, phase)
195
+ end
196
+ end
197
+ end
198
+
199
+ before do
200
+ @sdef = SynthDef.new(:hola) { SinOsc.ar }
201
+ @encoded = [ 83, 67, 103, 102, 0, 0, 0, 1, 0, 1, 4, 104, 111, 108, 97, 0, 2, 67, -36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 6, 83, 105, 110, 79, 115, 99, 2, 0, 2, 0, 1, 0, 0, -1, -1, 0, 0, -1, -1, 0, 1, 2, 0, 0 ].pack('C*')
202
+ end
203
+
204
+ it "should get values" do
205
+ @sdef.values
206
+ end
207
+
208
+ it "should encode init stream" do
209
+ @sdef.encode[0..9].should == @encoded[0..9]
210
+ end
211
+
212
+ it "should encode is, name" do
213
+ @sdef.encode[0..14].should == @encoded[0..14]
214
+ end
215
+
216
+ it "should encode is, name, constants" do
217
+ @sdef.encode[0..24].should == @encoded[0..24]
218
+ end
219
+
220
+ it "should encode is, name, consts, values" do
221
+ @sdef.encode[0..26].should == @encoded[0..26]
222
+ end
223
+
224
+ it "should encode is, name, consts, values, controls" do
225
+ @sdef.encode[0..28].should == @encoded[0..28]
226
+ end
227
+
228
+ it "should encode is, name, consts, values, controls, children" do
229
+ @sdef.encode[0..53].should == @encoded[0..53]
230
+ end
231
+
232
+ it "should encode is, name, consts, values, controls, children, variants stub" do
233
+ @sdef.encode.should == @encoded
234
+ end
235
+
236
+ describe "sending" do
237
+
238
+ before :all do
239
+ @server = mock('server', :instance_of? => true, :send_synth_def => nil)
240
+ Server = mock('Server', :all => [@server])
241
+ end
242
+
243
+ before do
244
+ @servers = (0..3).map{ mock('server', :instance_of? => true, :send_synth_def => nil) }
245
+ @sdef = SynthDef.new(:hola) { SinOsc.ar }
246
+ end
247
+
248
+ it "should accept an array or several Servers" do
249
+ @sdef.send( @servers )
250
+ @sdef.send( *@servers )
251
+ end
252
+
253
+ it "should not accept non servers" do
254
+ lambda{ @sdef.send( [1,2] ) }.should raise_error(NoMethodError)
255
+ lambda{ @sdef.send( 1,2 ) }.should raise_error(NoMethodError)
256
+ end
257
+
258
+ it "should send self to each of the servers" do
259
+ @servers.each{ |s| s.should_receive(:send_synth_def).with(@sdef) }
260
+ @sdef.send( @servers )
261
+ end
262
+
263
+ it "should send to Server.all if not provided with a list of servers" do
264
+ @server.should_receive(:send_synth_def).with(@sdef)
265
+ Server.should_receive(:all).and_return([@server])
266
+ @sdef.send
267
+ end
268
+
269
+ end
270
+
271
+ end
272
+
273
+
274
+
275
+
@@ -0,0 +1,146 @@
1
+ require File.join( File.expand_path(File.dirname(__FILE__)), '..',"helper")
2
+ require 'yaml'
3
+
4
+ require "#{SCRUBY_DIR}/audio/ugens/ugen_operations"
5
+ require "#{SCRUBY_DIR}/extensions"
6
+
7
+ include Scruby
8
+ include Audio
9
+ include Ugens
10
+
11
+ Klass = nil
12
+
13
+ describe UgenOperations, 'loading module' do
14
+
15
+ before :all do
16
+ class BinaryOpUGen
17
+ attr_accessor :inputs, :operator
18
+ def initialize(op, *args)
19
+ @operator = op
20
+ @inputs = args
21
+ end
22
+ end
23
+ @ugen = mock( 'ugen', :ugen? => true)
24
+ end
25
+
26
+ before do
27
+ Object.send(:remove_const, 'Klass')
28
+ class Klass; end
29
+ end
30
+
31
+ describe 'module inclusion' do
32
+
33
+ it "should receive #included" do
34
+ UgenOperations.should_receive( :included ).with( Klass )
35
+ Klass.send( :include, UgenOperations )
36
+ end
37
+
38
+ it "should include module" do
39
+ Klass.send( :include, UgenOperations )
40
+ Klass.included_modules.should include( UgenOperations )
41
+ end
42
+
43
+ it "should include InstanceMethods" do
44
+ Klass.send( :include, UgenOperations )
45
+ Klass.included_modules.should include( UgenOperations::BinaryOperations )
46
+ end
47
+
48
+ it do
49
+ Klass.send( :include, UgenOperations )
50
+ Klass.new.should respond_to( :+ )
51
+ end
52
+
53
+ it "should sum" do
54
+ Klass.send( :include, UgenOperations )
55
+ (Klass.new + @ugen).should be_instance_of(BinaryOpUGen)
56
+ end
57
+
58
+ it do
59
+ Klass.send( :include, UgenOperations )
60
+ lambda{ Klass.new + 1 }.should raise_error(ArgumentError)
61
+ end
62
+
63
+ it "respond to #ugen_sum (it will override #+ but can't name a method old_+)" do
64
+ Klass.send( :include, UgenOperations )
65
+ Klass.new.should respond_to( :ugen_plus )
66
+ end
67
+
68
+ it "should call the original #+" do
69
+ Object.send(:remove_const, 'Klass')
70
+ class Klass; def +( input ); end; end
71
+ Klass.send( :include, UgenOperations )
72
+ (Klass.new + Klass.new).should be_nil
73
+ end
74
+ end
75
+
76
+ describe Numeric do
77
+ before do
78
+ @ugen = mock( 'ugen', :ugen? => true )
79
+ end
80
+
81
+ it do
82
+ 1.should respond_to( :ring4 )
83
+ 1.should respond_to( :ugen_plus )
84
+ end
85
+
86
+ it do
87
+ 1.2.should respond_to( :ring4 )
88
+ end
89
+
90
+ it "should sum with overriden method #sum" do
91
+ (1 + 1 ).should == 2
92
+ end
93
+
94
+ it "should return a BinarayOpUgen when adding an Ugen" do
95
+ (1 + @ugen).should be_instance_of( BinaryOpUGen )
96
+ end
97
+
98
+ it "should set the correct inputs and operator for the binopugen" do
99
+ (1.0 + @ugen).inputs.should == [1.0, @ugen]
100
+ (1 + @ugen).operator.should == :+
101
+ end
102
+ end
103
+
104
+ describe Array do
105
+
106
+ before :all do
107
+ Ugen = mock( 'Ugen' )
108
+ end
109
+
110
+ before do
111
+ Klass.send( :include, UgenOperations )
112
+ @ugen = mock( 'ugen', :ugen? => true )
113
+ @ugen.stub!( :instance_of? ).with( Ugen ).and_return( true )
114
+ @ugen.stub!( :instance_of? ).with( Ugen ).and_return( true )
115
+ @ugen.should be_instance_of( Ugen )
116
+ end
117
+
118
+ it do
119
+ [].should respond_to( :ring4 )
120
+ [].should respond_to( :ugen_plus )
121
+ end
122
+
123
+ it "should sum an ugen" do
124
+ [] + @ugen
125
+ end
126
+
127
+ it "should sum arrays as expected" do
128
+ ([1,2] + [3]).should == [1,2,3]
129
+ end
130
+
131
+ it "should return" do
132
+ BinaryOpUGen.should_receive( :new ).with( :*, [1,2], @ugen )
133
+ ([1, 2] * @ugen)
134
+ end
135
+ end
136
+
137
+ end
138
+
139
+
140
+ # methods overriden by UgenOperations inclusion:
141
+ # Fixnum#+ Fixnum#gcd Fixnum#/ Fixnum#round Fixnum#lcm Fixnum#div Fixnum#- Fixnum#>= Fixnum#* Fixnum#<=
142
+ # Float#+ Float#/ Float#round Float#div Float#- Float#>= Float#* Float#<=
143
+ # Array#+ Array#- Array#*
144
+ # changed max and min to maximum and minimum because the override Array#max and Array#min wich take no args
145
+
146
+