Skip to content
Browse files

refactored ugen operations

  • Loading branch information...
1 parent 26b0dee commit 72b30a5ab501f91cfb67b1615d11c9b07dd0eb8f @maca committed Jul 7, 2009
View
2 Manifest.txt
@@ -29,7 +29,7 @@ doc/classes/Scruby/Audio/Ugens/OperationUgens.html
doc/classes/Scruby/Audio/Ugens/OperationUgens/BasicOpUgen.html
doc/classes/Scruby/Audio/Ugens/OperationUgens/BinaryOpUGen.html
doc/classes/Scruby/Audio/Ugens/OperationUgens/MulAdd.html
-doc/classes/Scruby/Audio/Ugens/OperationUgens/UnaryOpUgen.html
+doc/classes/Scruby/Audio/Ugens/OperationUgens/UnaryOpUGen.html
doc/classes/Scruby/Audio/Ugens/Out.html
doc/classes/Scruby/Audio/Ugens/OutputProxy.html
doc/classes/Scruby/Audio/Ugens/Ugen.html
View
4 lib/scruby.rb
@@ -34,13 +34,12 @@ module Scruby
require "scruby/typed_array"
require "scruby/extensions"
-require "scruby/audio/ugens/ugen_operations"
require "scruby/audio/ugens/ugen"
+require "scruby/audio/ugens/ugen_operations"
require "scruby/audio/ugens/multi_out_ugens"
require "scruby/audio/ugens/in_out"
require "scruby/audio/ugens/operation_ugens"
-require "scruby/audio/ugens/ugen"
require "scruby/audio/ugens/ugens"
require "scruby/audio/control_name"
@@ -56,7 +55,6 @@ module Scruby
include Scruby
include Audio
include Ugens
-include OperationUgens
class Notice < String; end
class Warning < String; end
View
91 lib/scruby/audio/ugens/operation_ugens.rb
@@ -1,66 +1,65 @@
module Scruby
module Audio
module Ugens
- module OperationUgens
- class BasicOpUgen < Ugen #:nodoc:
- attr_accessor :operator
+
+ class BasicOpUgen < Ugen #:nodoc:
+ attr_accessor :operator
- class << self
- def new operator, *inputs #:nodoc:
- obj = super get_rate(inputs), *inputs
- set_operator_for obj, operator
- obj
- end
-
- private
- #:nodoc:
- def set_operator_for input, operator
- input.kind_of?(Array) ? input.map{ |element| set_operator_for element, operator } : input.operator = operator
- end
-
- #:nodoc:
- def get_rate *inputs
- max_index = inputs.flatten.collect{ |ugen| Ugen::RATES.index ugen.rate }.max
- Ugen::RATES[max_index]
- end
+ class << self
+ def new operator, *inputs
+ obj = super get_rate(inputs), *inputs
+ set_operator_for obj, operator
+ obj
end
- end
- class UnaryOpUgen < BasicOpUgen
- def self.new operator, input
- super
+ private
+ #:nodoc:
+ def set_operator_for input, operator
+ input.kind_of?(Array) ? input.map{ |element| set_operator_for element, operator } : input.operator = operator
end
- def special_index
- UgenOperations::UNARY[ operator.to_sym ]
+ #:nodoc:
+ def get_rate *inputs
+ max_index = inputs.flatten.collect{ |ugen| Ugen::RATES.index ugen.rate }.max
+ Ugen::RATES[max_index]
end
end
+ end
- class BinaryOpUGen < BasicOpUgen
- def self.new operator, left, right
- super
- end
+ class UnaryOpUGen < BasicOpUgen
+ def self.new operator, input
+ super
+ end
- def special_index
- UgenOperations::BINARY[ operator.to_sym ]
- end
+ def special_index
+ UgenOperations::UNARY[operator.to_sym]
end
+ end
- class MulAdd < Ugen
- def self.new input, mul, add
- no_mul = ( mul == 1.0 )
- minus = ( mul == -1.0 )
- return add if mul == 0
- return input if no_mul and add == 0
- return input.neg if minus and add == 0
- return input * mul if add == 0
- return add - input if minus
- return input + add if no_mul
+ class BinaryOpUGen < BasicOpUgen
+ def self.new operator, left, right
+ super
+ end
- super input.rate, input, mul, add
- end
+ def special_index
+ UgenOperations::BINARY[operator.to_sym]
end
end
+
+ class MulAdd < Ugen
+ def self.new input, mul, add
+ no_mul = mul == 1.0
+ minus = mul == -1.0
+ return add if mul == 0
+ return input if no_mul and add == 0
+ return input.neg if minus and add == 0
+ return input * mul if add == 0
+ return add - input if minus
+ return input + add if no_mul
+ super input.rate, input, mul, add
+ end
+ end
+
end
end
end
View
5 lib/scruby/audio/ugens/ugen.rb
@@ -60,8 +60,6 @@ class Ugen
E_RATES = [ :scalar, :control, :audio, :demand ]
@@synthdef = nil
- include UgenOperations
-
def initialize rate, *inputs
@rate, @inputs = rate, inputs.compact
@@ -82,9 +80,6 @@ def to_s
"#{self.class.to_s.split('::').last}"
end
- # True
- def ugen?; true; end
-
def encode
self.class.to_s.split('::').last.encode + [ E_RATES.index(rate) ].pack('w') +
[ inputs.size, channels.size, special_index, collect_input_specs ].flatten.pack('n*') +
View
4 lib/scruby/audio/ugens/ugen_defs.yaml
@@ -737,14 +737,14 @@ Demand:
-
- - :reset
-
- - - :demandUGens
+ - - :demandUgens
-
:audio:
- - :trig
-
- - :reset
-
- - - :demandUGens
+ - - :demandUgens
-
DemandEnvGen:
:control:
View
62 lib/scruby/audio/ugens/ugen_operations.rb
@@ -12,55 +12,51 @@ module Ugens
# neg, bitNot, abs, asFloat, ceil, floor, frac, sign, squared, cubed, sqrt, exp, reciprocal, midicps, cpsmidi, midiratio, ratiomidi, dbamp, ampdb, octcps, cpsoct, log, log2, log10, sin, cos, tam, asin, acos, atan, sinh, cosh, tanh, rand, rand2, linrand, bilinrand, sum3rand, distort, softclip, coin, rectWindow, hanWindow, welWindow, triWindow, ramp and scurve
#
module UgenOperations
- operation_indices = YAML::load( File.open( "#{SCRUBY_DIR}/audio/ugens/operation_indices.yaml" ) )
- UNARY = operation_indices['unary']
- BINARY = operation_indices['binary']
- OP_SYMBOLS = { :+ => :plus, :- => :minus, :* => :mult, :/ => :div2, :<= => :less_than_or_eql, :>= => :more_than_or_eql }
+ operation_indices = YAML::load File.open("#{SCRUBY_DIR}/audio/ugens/operation_indices.yaml")
+ UNARY = operation_indices['unary']
+ BINARY = operation_indices['binary']
+ SAFE_NAMES = { :+ => :plus, :- => :minus, :* => :mult, :/ => :div2, :<= => :less_than_or_eql, :>= => :more_than_or_eql }
- def valid_ugen_input?
- true
- end
+ # true
+ def valid_ugen_input?; true; end #TODO: Deprecate
def self.included klass
klass.send :include, BinaryOperations
- begin; klass.send( :include, UnaryOperators ) if klass.new.ugen?; rescue; end
-
- BINARY.each_key do |operator|
- override = OP_SYMBOLS[operator] || operator #can't name a method ugen_+ so use OP_SYMBOLS hash to get a 'safe' name
- begin; klass.send :alias_method, "original_#{override}", operator; rescue; end #if there is an original operator method make an alias with the prefix 'original' so it may be called latter
- klass.send :alias_method, operator, "ugen_#{override}" #alias the newly added operator method with the name of the operator( +, -, mod, etc...)
- end
+ klass.send :include, UnaryOperators if klass.ancestors.include? Ugen
end
module BinaryOperations
BINARY.each_key do |op|
- method_name = OP_SYMBOLS[op] || op #get a 'safe' method name for the method to add
- eval "def ugen_#{method_name}( input )
- return BinaryOpUGen.new(:#{op}, self, input) if input.ugen? or (self.kind_of?( Ugen ) and (input.kind_of?( Numeric ) or input.kind_of?( Array )))
- return self.original_#{method_name}( input ) if self.respond_to?( :original_#{method_name} )
- raise ArgumentError.new( %(Expected \#\{input\} to be an Ugen) )
- end"
+ method_name = SAFE_NAMES[op] || op
+ define_method "__ugen_#{ method_name }" do |input|
+ case input
+ when Ugen
+ BinaryOpUGen.new op, self, input
+ when UgenOperations
+ kind_of?( Ugen ) ? BinaryOpUGen.new( op, self, input ) : __send__( "__original_#{ method_name }", input )
+ else
+ raise ArgumentError.new( "Expected `#{ input.inspect }` to be a valid Ugen input" )
+ end
+ end
+ end
+
+ def self.included klass
+ BINARY.each_key do |operator|
+ safe_name = SAFE_NAMES[operator] || operator
+ klass.send( :alias_method, "__original_#{ safe_name }", operator ) rescue nil
+ klass.send( :alias_method, operator, "__ugen_#{ safe_name }" )
+ end
end
end
module UnaryOperators
- UNARY.each_key do |op|
- eval "def #{op}; UnaryOpUgen.new(:#{op}, self); end"
- end
+ UNARY.each_key{ |op| define_method(op){ UnaryOpUGen.new op, self } }
end
end
+
+ [Ugen, ::Fixnum, ::Float, ::Array].each{ |k| k.send :include, UgenOperations }
end
end
end
-class Fixnum
- include Scruby::Audio::Ugens::UgenOperations
-end
-class Float
- include Scruby::Audio::Ugens::UgenOperations
-end
-
-class Array
- include Scruby::Audio::Ugens::UgenOperations
-end
View
3 lib/scruby/extensions.rb
@@ -6,9 +6,6 @@ def to_array
[*self]
end
- # TODO : deprecate
- def ugen?; false; end
-
def valid_ugen_input? #:nodoc:
false
end
View
13 spec/audio/integration_spec.rb
@@ -5,7 +5,6 @@
include Scruby
include Audio
include Ugens
-include OperationUgens
describe "synthdef examples" do
@@ -70,15 +69,15 @@
end
it "should encode 'complex' sdef" do
- sdef = SynthDef.new( :am ) do |gate, portadora, moduladora, amp|
- modulacion=SinOsc.kr(moduladora,0,0.5,0.5)
- sig=SinOsc.ar(portadora,0,modulacion)
- env=EnvGen.kr(Env.asr(2,1,2),gate, :doneAction => 2)
- Out.ar(0,sig*env);
+ sdef = SynthDef.new :am do |gate, portadora, moduladora, amp|
+ mod = SinOsc.kr moduladora, 0, 0.5, 0.5
+ sig = SinOsc.ar portadora, 0, mod
+ env = EnvGen.kr Env.asr(2, 1, 2), gate, :doneAction => 2
+ Out.ar 0, sig*env
end
+
sdef.children.should have(8).children
sdef.constants.should == [0, 0.5, 1, 2, -99, 5, -4]
-
expected = [ 83, 67, 103, 102, 0, 0, 0, 1, 0, 1, 2, 97, 109, 0, 7, 0, 0, 0, 0, 63, 0, 0, 0, 63, -128, 0, 0, 64, 0, 0, 0, -62, -58, 0, 0, 64, -96, 0, 0, -64, -128, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 103, 97, 116, 101, 0, 0, 9, 112, 111, 114, 116, 97, 100, 111, 114, 97, 0, 1, 10, 109, 111, 100, 117, 108, 97, 100, 111, 114, 97, 0, 2, 3, 97, 109, 112, 0, 3, 0, 8, 7, 67, 111, 110, 116, 114, 111, 108, 1, 0, 0, 0, 4, 0, 0, 1, 1, 1, 1, 6, 83, 105, 110, 79, 115, 99, 1, 0, 2, 0, 1, 0, 0, 0, 0, 0, 2, -1, -1, 0, 0, 1, 6, 77, 117, 108, 65, 100, 100, 1, 0, 3, 0, 1, 0, 0, 0, 1, 0, 0, -1, -1, 0, 1, -1, -1, 0, 1, 1, 6, 83, 105, 110, 79, 115, 99, 2, 0, 2, 0, 1, 0, 0, 0, 0, 0, 1, -1, -1, 0, 0, 2, 12, 66, 105, 110, 97, 114, 121, 79, 112, 85, 71, 101, 110, 2, 0, 2, 0, 1, 0, 2, 0, 3, 0, 0, 0, 2, 0, 0, 2, 6, 69, 110, 118, 71, 101, 110, 1, 0, 17, 0, 1, 0, 0, 0, 0, 0, 0, -1, -1, 0, 2, -1, -1, 0, 0, -1, -1, 0, 2, -1, -1, 0, 3, -1, -1, 0, 0, -1, -1, 0, 3, -1, -1, 0, 2, -1, -1, 0, 4, -1, -1, 0, 2, -1, -1, 0, 3, -1, -1, 0, 5, -1, -1, 0, 6, -1, -1, 0, 0, -1, -1, 0, 3, -1, -1, 0, 5, -1, -1, 0, 6, 1, 12, 66, 105, 110, 97, 114, 121, 79, 112, 85, 71, 101, 110, 2, 0, 2, 0, 1, 0, 2, 0, 4, 0, 0, 0, 5, 0, 0, 2, 3, 79, 117, 116, 2, 0, 2, 0, 0, 0, 0, -1, -1, 0, 0, 0, 6, 0, 0, 0, 0 ].pack('c*')
sdef.encode.should == expected
end
View
35 spec/audio/operation_ugens_spec.rb
@@ -9,9 +9,8 @@
include Scruby
include Audio
include Ugens
-include OperationUgens
-describe UnaryOpUgen do
+describe UnaryOpUGen do
::RATES = :scalar, :demand, :control, :audio
before do
@@ -21,44 +20,44 @@
@audio = mock 'ugen', :rate => :audio, :valid_ugen_input? => true
end
- describe UnaryOpUgen do
+ describe UnaryOpUGen do
before do
- @op = UnaryOpUgen.new( :neg, @audio )
+ @op = UnaryOpUGen.new( :neg, @audio )
end
it "should return special index" do
- UnaryOpUgen.new( :neg, @audio ).special_index.should == 0
- UnaryOpUgen.new( :bitNot, @audio ).special_index.should == 4
- UnaryOpUgen.new( :abs, @audio ).special_index.should == 5
- UnaryOpUgen.new( :asFloat, @audio ).special_index.should == 6
+ UnaryOpUGen.new( :neg, @audio ).special_index.should == 0
+ UnaryOpUGen.new( :bitNot, @audio ).special_index.should == 4
+ UnaryOpUGen.new( :abs, @audio ).special_index.should == 5
+ UnaryOpUGen.new( :asFloat, @audio ).special_index.should == 6
end
it "should accept just one input" do
- lambda{ UnaryOpUgen.new(:neg, @audio, @demand) }.should raise_error ArgumentError
+ lambda{ UnaryOpUGen.new(:neg, @audio, @demand) }.should raise_error( ArgumentError )
end
it "should just accept defined operators" # do
- # lambda{ UnaryOpUgen.new(:not_operator, @audio) }.should raise_error( ArgumentError )
+ # lambda{ UnaryOpUGen.new(:not_operator, @audio) }.should raise_error( ArgumentError )
# end
it "should get max rate" do
- UnaryOpUgen.send(:get_rate, @scalar, @demand ).should == :demand
- UnaryOpUgen.send(:get_rate, @scalar, @demand, @audio ).should == :audio
- UnaryOpUgen.send(:get_rate, @scalar, [@demand, [@control, @audio]] ).should == :audio
+ UnaryOpUGen.send(:get_rate, @scalar, @demand ).should == :demand
+ UnaryOpUGen.send(:get_rate, @scalar, @demand, @audio ).should == :audio
+ UnaryOpUGen.send(:get_rate, @scalar, [@demand, [@control, @audio]] ).should == :audio
end
it do
- UnaryOpUgen.new(:neg, @audio).should be_instance_of(UnaryOpUgen)
+ UnaryOpUGen.new(:neg, @audio).should be_instance_of(UnaryOpUGen)
end
it "should set rate" do
- UnaryOpUgen.new(:neg, @audio).rate.should == :audio
- UnaryOpUgen.new(:neg, @scalar).rate.should == :scalar
+ UnaryOpUGen.new(:neg, @audio).rate.should == :audio
+ UnaryOpUGen.new(:neg, @scalar).rate.should == :scalar
end
it "should set operator" do
- UnaryOpUgen.new(:neg, @audio).operator.should == :neg
+ UnaryOpUGen.new(:neg, @audio).operator.should == :neg
end
end
@@ -92,7 +91,7 @@
BinaryOpUGen.new(:+, @audio, [@audio, @scalar] ).should be_instance_of(Array)
end
- it "should return an array of UnaryOpUgens" do
+ it "should return an array of UnaryOpUGens" do
@op_arr.flatten.map { |op| op.should be_instance_of(BinaryOpUGen) }
end
View
122 spec/audio/ugen_operations_spec.rb
@@ -1,144 +1,104 @@
require File.join( File.expand_path(File.dirname(__FILE__)), '..',"helper")
require 'yaml'
+require "#{SCRUBY_DIR}/audio/ugens/ugen"
+require "#{SCRUBY_DIR}/audio/ugens/operation_ugens"
require "#{SCRUBY_DIR}/audio/ugens/ugen_operations"
-require "#{SCRUBY_DIR}/audio/ugens/ugen"
require "#{SCRUBY_DIR}/extensions"
include Scruby
include Audio
include Ugens
-
-describe UgenOperations, 'loading module' do
-
- before :all do
- class ::BinaryOpUGen
- attr_accessor :inputs, :operator
- def initialize(op, *args)
- @operator = op
- @inputs = args
- end
- end
- @ugen = mock( 'ugen', :ugen? => true)
- end
+describe UgenOperations do
before do
- Object.remove_const Klass rescue nil
- class Klass; end
+ @ugen = Ugen.new :audio
+ @ugen2 = Ugen.new :audio
end
-
- describe 'module inclusion' do
-
- it "should receive #included" do
- UgenOperations.should_receive( :included ).with( Klass )
- Klass.send( :include, UgenOperations )
- end
-
- it "should include module" do
- Klass.send( :include, UgenOperations )
- Klass.included_modules.should include( UgenOperations )
- end
-
- it "should include InstanceMethods" do
- Klass.send( :include, UgenOperations )
- Klass.included_modules.should include( UgenOperations::BinaryOperations )
- end
-
- it 'should respond to +' do
- Klass.send( :include, UgenOperations )
- Klass.new.should respond_to( :+ )
- end
-
+
+ describe 'binary operations' do
it "should sum" do
- Klass.send( :include, UgenOperations )
- (Klass.new + @ugen).should be_instance_of(BinaryOpUGen)
+ sum = @ugen + @ugen2
+ sum.should be_instance_of(BinaryOpUGen)
end
it 'should sum integer' do
- Klass.send( :include, UgenOperations )
- lambda{ Klass.new + 1 }.should raise_error(ArgumentError)
+ sum = @ugen + 1.0
+ sum.should be_instance_of(BinaryOpUGen)
end
it "respond to #ugen_sum (it will override #+ but can't name a method old_+)" do
- Klass.send( :include, UgenOperations )
- Klass.new.should respond_to( :ugen_plus )
+ @ugen.should respond_to( :__ugen_plus )
end
- it "should call the original #+" do
- class Klass; def +( input ); end; end
- Klass.send( :include, UgenOperations )
- (Klass.new + Klass.new).should be_nil
+ it "should raise argument error" do
+ lambda { @ugen + :hola }.should raise_error( ArgumentError )
end
end
- describe Numeric do
- before do
- @ugen = mock( 'ugen', :ugen? => true )
- end
+ describe 'unary operations' do
+ it "should do unary op" do
+ op = @ugen.distort
+ op.should be_instance_of(UnaryOpUGen)
+ op.inputs.should == [@ugen]
+ end
+ end
+
+ describe Numeric do
it do
1.should respond_to( :ring4 )
- 1.should respond_to( :ugen_plus )
+ 1.should respond_to( :__ugen_plus )
end
it do
1.2.should respond_to( :ring4 )
end
- it "should sum with overriden method #sum" do
- (1 + 1 ).should == 2
+ it "should use original +" do
+ sum = 1 + 1
+ sum.should == 2
end
it "should return a BinarayOpUgen when adding an Ugen" do
- (1 + @ugen).should be_instance_of( BinaryOpUGen )
+ sum = 1 + @ugen
+ sum.should be_instance_of(BinaryOpUGen)
end
it "should set the correct inputs and operator for the binopugen" do
- (1.0 + @ugen).inputs.should == [1.0, @ugen]
- (1 + @ugen).operator.should == :+
+ sum = 1.0 + @ugen
+ sum.inputs.should == [1.0, @ugen]
+ sum.operator.should == :+
end
it "ugen should sum numeric" do
- ugen = Ugen.new( :audio )
- sum = (ugen + 1)
+ sum = @ugen + 1
sum.should be_kind_of(BinaryOpUGen)
- sum.inputs.should == [ugen, 1]
+ sum.inputs.should == [@ugen, 1]
end
it 'ugen should sum array' do
- ugen = Ugen.new( :audio )
- sum = (ugen + [1,2])
- sum.should be_kind_of(BinaryOpUGen)
- sum.inputs.should == [ugen, [1,2]]
+ sum = @ugen + [1,2]
+ sum.should have(2).ugens
+ sum.first.inputs.should == [@ugen, 1]
+ sum.last.inputs.should == [@ugen, 2]
end
end
describe Array do
-
- before :all do
- Ugen = mock( 'Ugen' )
- end
-
- before do
- Klass.send( :include, UgenOperations )
- @ugen = mock( 'ugen', :ugen? => true )
- @ugen.stub!( :instance_of? ).with( Ugen ).and_return( true )
- @ugen.stub!( :instance_of? ).with( Ugen ).and_return( true )
- @ugen.should be_instance_of( Ugen )
- end
-
it do
[].should respond_to( :ring4 )
- [].should respond_to( :ugen_plus )
+ [].should respond_to( :__ugen_plus )
end
it "should sum an ugen" do
[] + @ugen
end
it "should sum arrays as expected" do
- ([1,2] + [3]).should == [1,2,3]
+ sum = [1,2] + [3]
+ sum.should == [1,2,3]
end
it "should return" do
View
2 spec/audio/ugen_spec.rb
@@ -58,7 +58,7 @@ def kr( freq=440.0, phase=0.0 )
before :all do
@op_ugen = mock( 'op_ugen', :ugen? => true )
::BinaryOpUGen = mock( 'bynary_op_ugen', :new => @op_ugen )
- UnaryOpUgen = mock( 'unary_op_ugen', :new => @op_ugen )
+ UnaryOpUGen = mock( 'unary_op_ugen', :new => @op_ugen )
end
before do

0 comments on commit 72b30a5

Please sign in to comment.
Something went wrong with that request. Please try again.