scruby 0.2.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. data/.gitignore +5 -0
  2. data/.rspec +1 -0
  3. data/Gemfile +4 -0
  4. data/Gemfile.lock +53 -0
  5. data/README.rdoc +65 -0
  6. data/Rakefile +10 -0
  7. data/TODO.markdown +3 -0
  8. data/examples/example.rb +73 -0
  9. data/lib/scruby/buffer.rb +153 -0
  10. data/lib/scruby/bus.rb +67 -0
  11. data/lib/scruby/control_name.rb +29 -0
  12. data/lib/scruby/core_ext/array.rb +44 -0
  13. data/lib/scruby/core_ext/delegator_array.rb +44 -0
  14. data/lib/scruby/core_ext/fixnum.rb +8 -0
  15. data/lib/scruby/core_ext/numeric.rb +25 -0
  16. data/lib/scruby/core_ext/object.rb +23 -0
  17. data/lib/scruby/core_ext/proc.rb +11 -0
  18. data/lib/scruby/core_ext/string.rb +5 -0
  19. data/lib/scruby/core_ext/symbol.rb +5 -0
  20. data/lib/scruby/core_ext/typed_array.rb +54 -0
  21. data/lib/scruby/env.rb +93 -0
  22. data/lib/scruby/group.rb +24 -0
  23. data/lib/scruby/node.rb +102 -0
  24. data/lib/scruby/server.rb +182 -0
  25. data/lib/scruby/synth.rb +50 -0
  26. data/lib/scruby/synthdef.rb +109 -0
  27. data/lib/scruby/ticker.rb +92 -0
  28. data/lib/scruby/ugens/buffer_read_write.rb +98 -0
  29. data/lib/scruby/ugens/demand.rb +9 -0
  30. data/lib/scruby/ugens/disk_in_out.rb +33 -0
  31. data/lib/scruby/ugens/env_gen.rb +38 -0
  32. data/lib/scruby/ugens/in_out.rb +46 -0
  33. data/lib/scruby/ugens/multi_out.rb +53 -0
  34. data/lib/scruby/ugens/operation_indices.yaml +92 -0
  35. data/lib/scruby/ugens/operation_ugens.rb +63 -0
  36. data/lib/scruby/ugens/panner.rb +137 -0
  37. data/lib/scruby/ugens/ugen.rb +173 -0
  38. data/lib/scruby/ugens/ugen_defs.yaml +3123 -0
  39. data/lib/scruby/ugens/ugen_operations.rb +57 -0
  40. data/lib/scruby/ugens/ugens.rb +95 -0
  41. data/lib/scruby/version.rb +3 -0
  42. data/lib/scruby.rb +65 -0
  43. data/scruby.gemspec +27 -0
  44. data/spec/buffer_read_write_spec.rb +333 -0
  45. data/spec/buffer_spec.rb +199 -0
  46. data/spec/bus_spec.rb +184 -0
  47. data/spec/core_ext/core_ext_spec.rb +120 -0
  48. data/spec/core_ext/delegator_array_spec.rb +144 -0
  49. data/spec/core_ext/typed_array_spec.rb +95 -0
  50. data/spec/demand_spec.rb +81 -0
  51. data/spec/disk_in_out_spec.rb +138 -0
  52. data/spec/env_gen_spec.rb +23 -0
  53. data/spec/env_spec.rb +73 -0
  54. data/spec/group_spec.rb +71 -0
  55. data/spec/helper.rb +20 -0
  56. data/spec/in_out_spec.rb +127 -0
  57. data/spec/integration_spec.rb +88 -0
  58. data/spec/multiout_ugen_spec.rb +86 -0
  59. data/spec/node_spec.rb +112 -0
  60. data/spec/operation_ugens_spec.rb +196 -0
  61. data/spec/panner_spec.rb +271 -0
  62. data/spec/server.rb +12 -0
  63. data/spec/server_spec.rb +198 -0
  64. data/spec/synth_spec.rb +103 -0
  65. data/spec/synthdef_spec.rb +267 -0
  66. data/spec/ugen_operations_spec.rb +100 -0
  67. data/spec/ugen_spec.rb +356 -0
  68. data/spec/ugens_spec.rb +65 -0
  69. metadata +207 -0
@@ -0,0 +1,173 @@
1
+ module Scruby
2
+ module Ugens
3
+ # All ugens inherit from this "abstract" class
4
+ #
5
+ # == Creation
6
+ #
7
+ # Ugens are usually instantiated inside an "ugen graph" or the block passed when creating a SynthDef
8
+ # using either the ar, kr, ir or new methods wich will determine the rate.
9
+ # * ar: audio rate
10
+ # * kr: control rate
11
+ # * ir: scalar rate
12
+ # * new: demand rate
13
+ #
14
+ # Not all the ugens provide all the rates
15
+ #
16
+ # Two ugens inside an ugen graph:
17
+ # SynthDef.new('simple'){ Out.ar(0, SinOsc.ar) }
18
+ # # Out and SinOsc are both ugens
19
+ #
20
+ #
21
+ # == Passing arguments when creating
22
+ #
23
+ # Usually when instantiating an ugen the arguments can be passed in order:
24
+ # Pitch.kr(0, 220, 80, ...)
25
+ #
26
+ # Or using a hash where the keys are symbols corresponding to the argument name.
27
+ # Pitch.kr( :initFreq => 220, :execFreq => 300 )
28
+ #
29
+ # Or a combination of both ways:
30
+ # Pitch.kr(0, 220, :execFreq => 300)
31
+ #
32
+ # Arguments not passed in either way will resort to default
33
+ #
34
+ #
35
+ # == Defining ugens
36
+ #
37
+ # This named arguments functionality is provided for all the default Ugens but can be provided when defining a new Ugen by calling
38
+ # <tt>#named_arguments_for</tt> passing a symbol with the name of a defined method:
39
+ #
40
+ # class Umaguma < Ugen
41
+ # class << self
42
+ # def ar(karma = 200, pitch = 20, rate = 200)
43
+ # ...
44
+ # end
45
+ # named_arguments_for :ar
46
+ # end
47
+ #
48
+ # end
49
+ #
50
+ # For more info and limitations on named arguments check the gem: http://github.com/maca/arguments
51
+ #
52
+ # Otherwise usage is pretty the same as in SuperCollider
53
+ #
54
+ # TODO: Provide a way of getting the argument names and default values
55
+ class Ugen
56
+ attr_reader :inputs, :rate, :index, :special_index, :output_index, :channels
57
+
58
+ RATES = :scalar, :trigger, :demand, :control, :audio
59
+ E_RATES = :scalar, :control, :audio, :demand
60
+ VALID_INPUTS = Numeric, Array, Ugen, Env, ControlName
61
+ @@synthdef = nil
62
+
63
+
64
+ def initialize rate, *inputs
65
+ @rate, @inputs = rate, inputs.compact
66
+ @special_index ||= 0
67
+ @output_index ||= 0
68
+ @channels ||= [1]
69
+ @index = add_to_synthdef || 0
70
+ end
71
+
72
+ # Instantiate a new MulAdd passing self and the multiplication and addition arguments
73
+ def muladd mul, add
74
+ MulAdd.new self, mul, add
75
+ end
76
+
77
+ def encode
78
+ self.class.to_s.split('::').last.encode + [ E_RATES.index(rate) ].pack('w') +
79
+ [ inputs.size, channels.size, special_index, collect_input_specs ].flatten.pack('n*') +
80
+ output_specs.pack('w*')
81
+ end
82
+
83
+ private
84
+ def synthdef #:nodoc:
85
+ @synthdef ||= Ugen.synthdef
86
+ end
87
+
88
+ def add_to_synthdef #:nodoc:
89
+ (synthdef.children << self).size - 1 if synthdef
90
+ end
91
+
92
+ def collect_constants #:nodoc:
93
+ @inputs.send( :collect_constants )
94
+ end
95
+
96
+ def input_specs synthdef #:nodoc:
97
+ [index, output_index]
98
+ end
99
+
100
+ def collect_input_specs #:nodoc:
101
+ @inputs.collect{ |i| i.send :input_specs, synthdef }
102
+ end
103
+
104
+ def output_specs #:nodoc:
105
+ [E_RATES.index(rate)]
106
+ end
107
+
108
+ public
109
+ def == other
110
+ self.class == other.class and
111
+ self.rate == other.rate and
112
+ self.inputs == other.inputs and
113
+ self.channels == other.channels
114
+ end
115
+
116
+ class << self
117
+ #:nodoc:
118
+ private
119
+ def new rate, *inputs
120
+ if rate.kind_of? Array
121
+ rate = RATES.slice rate.collect { |rate| # get the highest rate, raise error if rate is not defined
122
+ rate = rate.to_sym
123
+ raise ArgumentError.new( "#{rate} not a defined rate") unless RATES.include? rate
124
+ RATES.index rate
125
+ }.max
126
+ else
127
+ raise ArgumentError.new( "#{rate} not a defined rate") unless RATES.include? rate.to_sym
128
+ end
129
+
130
+ size = 1 # Size of the largest multichannel input (Array)
131
+ inputs.peel! # First input if input is Array and size is 1
132
+ inputs.map! do |input|
133
+ input = input.as_ugen_input if input.respond_to?(:as_ugen_input) # Convert input to prefered form
134
+ raise ArgumentError.new( "#{ input.inspect } is not a valid ugen input") unless valid_input? input
135
+ size = input.size if input.size > size if input.kind_of? Array
136
+ input
137
+ end
138
+
139
+ return super( rate, *inputs.flatten ) unless size > 1 #return an Ugen if no array was passed as an input
140
+
141
+ inputs.map! do |input|
142
+ Array === input ? input.wrap_to!(size) : input = Array.new(size, input)
143
+ input
144
+ end
145
+ output = inputs.transpose
146
+ output.map! do |new_inputs| new rate, *new_inputs end
147
+ output.to_da
148
+ end
149
+
150
+ public
151
+ def valid_input? obj
152
+ case obj
153
+ when *VALID_INPUTS then true
154
+ else false
155
+ end
156
+ end
157
+
158
+ def synthdef #:nodoc:
159
+ @@synthdef
160
+ end
161
+
162
+ def synthdef= synthdef #:nodoc:
163
+ @@synthdef = synthdef
164
+ end
165
+
166
+ def params
167
+ {}
168
+ end
169
+
170
+ end
171
+ end
172
+ end
173
+ end