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
@@ -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
|