maca-Scruby 0.0.8

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.
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
+