Skip to content
Browse files

refactored Server class, better spec coverage

  • Loading branch information...
1 parent 47fcf7e commit cccff37be969ef43adb56e1456ed6e33aa4931f3 @maca maca committed Jul 15, 2009
View
10 bin/livecode.rb
@@ -1,12 +1,8 @@
#!/usr/bin/env ruby
-live_session_dir = File.join( File.expand_path(File.dirname(__FILE__) ), '..', 'lib', 'live' )
+live_session_dir = File.dirname(__FILE__) + '/../lib/live'
+require 'rubygems'
require 'tempfile'
-require "#{live_session_dir}/session"
-
+require "#{ live_session_dir }/session"
Live::Session.new
-
-
-
-
View
39 lib/live/session.rb
@@ -1,17 +1,14 @@
require 'tempfile'
-require 'rubygems'
require 'highline'
-require 'parse_tree'
-require 'ruby2ruby'
module Kernel
alias :l :lambda
# Calls Kernel#eval with the given args but catches posible errors
- def resilient_eval( *args )
+ def resilient_eval *args
begin
begin
- eval( *args )
+ eval *args
rescue SyntaxError => e
e
end
@@ -20,7 +17,7 @@ def resilient_eval( *args )
end
end
- def p( obj ) #:nodoc:
+ def p obj #:nodoc:
puts obj.to_live_output
end
@@ -35,11 +32,11 @@ def to_live_output
"\e[41m\e[33m#{self.inspect}\e[0m"
when Numeric, Symbol, TrueClass, FalseClass, NilClass
"\e[35m#{self.inspect}\e[0m"
- when Notice
+ when Live::Notice
"\e[42m\e[30m#{self}\e[0m"
- when Warning
+ when Live::Warning
"\e[43m\e[30m#{self}\e[0m"
- when Special
+ when Live::Special
"\e[44m\e[37m#{self}\e[0m"
when String
"\e[32m#{self.inspect}\e[0m"
@@ -53,11 +50,12 @@ def to_live_output
end
end
-class Notice < String; end
-class Warning < String; end
-class Special < String; end
module Live
+ class Notice < String; end
+ class Warning < String; end
+ class Special < String; end
+
class Pipe < Tempfile
def make_tmpname( *args )
"ruby_live.pipe"
@@ -70,8 +68,7 @@ class Session
# Starts a live session using a named pipe to receive code from a remote source and evaluates it within a context, a bit like an IRB session but evaluates code sent from a text editor
def initialize
return p( Exception.new("Another session sems to be running: #{Dir.tmpdir}/ruby_live.pipe") ) if File.exist?( "#{Dir.tmpdir}/ruby_live.pipe" )
-
- p( Notice.new("Live Session") )
+ p Notice.new("Live Session")
get_binding
init_pipe
expect_input
@@ -103,15 +100,15 @@ def expect_input
end
# Expects a one char Symbol or String which will bind to a passed block so it can be called later with a keystroke
- def bind( key, &block )
+ def bind key, &block
@bindings = [] unless @bindings.instance_of?(Array)
block ||= Proc.new{}
@bindings[ key.to_s[0] ] = Ruby2Ruby.new.process( [:block, block.to_sexp.last] )
Notice.new( "Key '#{key}' is bound to an action")
end
# Evaluates a ruby expression within the @context Binding
- def evaluate( string = nil )
+ def evaluate string = nil
return resilient_eval( string, @context ) if string
end
@@ -123,20 +120,18 @@ def get_binding #:nodoc:
@context = binding
end
- def run_updates( code )
+ def run_updates code
source = ParseTree.new.parse_tree_for_string( code ).first
- final = []
+ final = []
while iter = source.assoc(:iter)
- source -= [iter]
+ source -= [iter]
final << [:block, iter.last] if iter[1].include?(:update)
end
evaluate( final.collect{ |exp| Ruby2Ruby.new.process(exp) }.join("\n") )
Notice.new('Update blocks evaluated')
end
- def update # Allmost a stub
- yield
- end
+ def update; yield end
alias :reaload! :get_binding
end
View
16 lib/scruby.rb
@@ -29,8 +29,14 @@ module Scruby
VERSION = '0.1'
end
-require "scruby/typed_array"
-require "scruby/extensions"
+require "scruby/core_ext/object"
+require "scruby/core_ext/array"
+require "scruby/core_ext/fixnum"
+require "scruby/core_ext/numeric"
+require "scruby/core_ext/proc"
+require "scruby/core_ext/string"
+require "scruby/core_ext/symbol"
+require "scruby/core_ext/typed_array"
require "scruby/audio/ugens/ugen"
require "scruby/audio/ugens/ugen_operations"
@@ -50,13 +56,13 @@ module Scruby
require "scruby/audio/node"
require "scruby/audio/synth"
+require "scruby/audio/buffer"
+
+
include Scruby
include Audio
include Ugens
-class Notice < String; end
-class Warning < String; end
-class Special < String; end
View
124 lib/scruby/audio/buffer.rb
@@ -0,0 +1,124 @@
+module Scruby
+ class Buffer
+
+
+ # allocReadChannel
+
+ # allocReadMsg
+ # alloc ReadCannelMsg
+ # read
+ # readChannel
+ # readNoUpdate
+ # readMsg
+ # readChannelMsg
+ # cueSoundFile
+ # cueSoundFilMsg
+ # loadCollection
+ # sendCollection
+ # streamCollection
+ # loadToFloatArray
+ # getToFloatArray
+ # write
+ # writeMsg
+ # free
+ # zero
+ # zeroMsg
+ # set
+ # setMsg
+ # setn
+ # setnMsgArgs
+ # setnMsg
+ # get
+ # getMsg
+ # getn
+ # getnMsg
+ # fill
+ # fillMsg
+ # normalize
+ # gen
+ # genMsg
+ # sine1
+ # ...
+ # copy
+ # copyData
+ # copyMsg
+ # close
+ # closeMsg
+ # query
+ # updateInfo
+ # cache
+ # uncache
+ # queryDone
+ # printOn
+ # play
+ # duration
+ # asUgenInput
+ # asControlInput
+ # asBufWithValues
+ # readMsg { arg argpath, fileStartFrame = 0, numFrames,
+ # bufStartFrame = 0, leaveOpen = false, completionMessage;
+ # path = argpath;
+ # ^["/b_read", bufnum, path, fileStartFrame, numFrames ? -1,
+ # bufStartFrame, leaveOpen.binaryValue, completionMessage.value(this)]
+ # // doesn't set my numChannels etc.
+ # }
+
+ attr_reader :server
+ attr_accessor :path, :frames, :channels, :rate
+
+ def initialize server, frames = -1, channels = 1
+ @server, @frames, @channels = server, frames, channels
+ @server.allocate_buffers self
+ end
+
+ def read path, file_start = 0, frames = -1, buf_start = 0, leave_open = false
+ message = Message.new "/b_read", bufnum, path, file_start, frames, buf_start, leave_open.to_i# , *Blob.new('/b_query', buf.bufnum)
+ self
+ end
+
+ def allocate &message
+ @server.send_message Message.new( '/b_alloc', bufnum, frames, channels, *Blob.new( message.call(self) ) )
+ end
+
+ def bufnum
+ @bufnum ||= @server.buffers.index self
+ end
+
+ # :nodoc:
+ def allocate_and_read path, start, frames, &completion
+ @path = path
+ @server.send "/b_allocRead", bufnum# , path, start, frames, yield(self)
+ self
+ end
+
+ class << self
+ def read server, path, start = 0, frames = -1, &action
+ buffer = new server, &action
+ buffer.allocate_and_read( path, start, frames ){ |buf| ["/b_query", buf.bufnum] }
+ end
+
+ def allocate server, frames = -1, channels = 1
+ buffer = new server, frames, channels
+ # buffer.rate = server.rate
+ buffer.alloc
+ end
+
+ named_arguments_for :read
+
+ # alloc
+ # allocConsecutive
+ # readChannel
+ # readNoUpdate
+ # cueSoundFile
+ # loadCollection
+ # sendCollection
+ # freeAllinitServerCache
+ # initServerCache
+ # clearServerCaches
+ # cachedBuffersDo
+ # cachedBufferAt
+ # loadDialog
+ end
+ end
+end
+
View
4 lib/scruby/audio/control_name.rb
@@ -19,10 +19,6 @@ def rate_from_name name
def non_control?
@rate == :noncontrol
end
-
- def valid_ugen_input?
- true
- end
end
end
end
View
12 lib/scruby/audio/env.rb
@@ -66,14 +66,14 @@ def to_array
end
def shape_numbers
- curves.collect do |curve|
- curve.valid_ugen_input? ? 5 : SHAPE_NAMES[curve]
+ curves.collect do |curve|
+ Ugen.valid_input?( curve ) ? 5 : SHAPE_NAMES[curve]
end
end
def curve_values
- curves.collect do |curve|
- curve.valid_ugen_input? ? curve : 0
+ curves.collect do |curve|
+ Ugen.valid_input?( curve ) ? curve : 0
end
end
@@ -85,10 +85,6 @@ def loop_node
@loop_node ||= -99
end
- def valid_ugen_input? #returns true
- true
- end
-
def collect_constants #:nodoc:
end
end
View
84 lib/scruby/audio/server.rb
@@ -4,11 +4,12 @@ module Scruby
module Audio
class UDPSender < OSC::UDPServer #:nodoc:
include Singleton
+ include OSC
alias :udp_send :send
def send command, host, port, *args
args = args.collect{ |arg| arg.kind_of?( Symbol ) ? arg.to_s : arg }
- udp_send OSC::Message.new( command, type_tag(args), *args ), 0, host, port
+ udp_send Message.new( command, type_tag(args), *args ), 0, host, port
end
def send_message message, host, port
@@ -17,52 +18,69 @@ def send_message message, host, port
def type_tag *args
args = *args
- args.collect{ |msg| OSC::Packet.tag msg }.to_s
+ args.collect{ |msg| Packet.tag msg }.to_s
end
end
$UDP_Sender = UDPSender.instance
class Server
- attr_reader :host, :port
- @@sc_path = '/Applications/SuperCollider/scsynth'
- @@servers = []
+ include OSC
+
+ attr_reader :host, :port, :path, :buffers
# Initializes and registers a new Server instance and sets the host and port for it.
# The server is a Ruby representation of scsynth which can be a local binary or a remote
# server already running.
# Server class keeps an array with all the instantiated servers
- def initialize host = 'localhost', port = 57111
- @host, @port = host, port
- @@servers << self
+ def initialize host = 'localhost', port = 57111, path = '/Applications/SuperCollider/scsynth'
+ @host = host
+ @port = port
+ @path = path
+ @buffers = []
+ self.class.all << self
end
+ named_arguments_for :initialize
# Boots the local binary of the scsynth forking a process, it will rise a SCError if the scsynth
# binary is not found in /Applications/SuperCollider/scsynth (default Mac OS path) or given path.
# The default path can be overriden using Server.scsynt_path=('path')
def boot
- raise SCError.new('Scsynth not found in the given path') unless File.exists? @@sc_path
- Thread.new do
- path = @@sc_path.scan(/[^\/]+/)
- @server_pipe = IO.popen( "cd /#{ path[0..-2].join('/') }; ./#{ path.last } -u #{ @port }" )
- loop { p Special.new(@server_pipe.gets.chomp) }
- end unless @server_pipe
- sleep 2 # TODO: There should be a better way to wait for the server to start
+ raise SCError.new('Scsynth not found in the given path') unless File.exists? @path
+ if running?
+ warn "Server on port #{ @port } allready running"
+ return self
+ end
+
+ ready = false
+ @thread = Thread.new do
+ IO.popen( "cd #{ File.dirname @path }; ./#{ File.basename @path } -u #{ @port }" ) do |pipe|
+ loop do
+ if response = pipe.gets
+ puts response
+ ready = true if response.match /ready/
+ end
+ end
+ end
+ end
+ sleep 0.1 until ready or !@thread.alive?
+ sleep 0.5 # just to be shure
send "/g_new", 1
self
end
+ def running?
+ @thread and @thread.alive? ? true : false
+ end
+
def stop
send "/g_freeAll", 0
send "/clearSched"
send "/g_new", 1
end
- # Sends the /quit OSC signal to the scsynth server and kills the forked process if the scsynth
- # server is running locally
+ # Sends the /quit OSC signal to the scsynth
def quit
send '/quit'
- Process.kill 'KILL', @server_pipe.pid if @server_pipe
- @server_pipe = nil
end
# Sends an OSC command to the scsyth server.
@@ -74,35 +92,32 @@ def send command, *args
# Encodes and sends a SynthDef to the scsynth server
def send_synth_def synth_def
- *blob = OSC::Blob.new( synth_def.encode ), 0
- def_message = OSC::Message.new( '/d_recv', $UDP_Sender.type_tag( blob ), *blob )
- send_message OSC::Bundle.new( nil, def_message )
+ blob = Blob.new( synth_def.encode ), 0
+ def_message = Message.new '/d_recv', $UDP_Sender.type_tag(blob), *blob
+ send_message Bundle.new nil, def_message
end
- private
def send_message message #:nodoc:
$UDP_Sender.send_message message, @host, @port
end
-
- public
- class << self
- # Specify the scsynth binary path
- def sc_path= path
- @@sc_path = path
- end
- # Get the scsynth path
- def sc_path
- @@sc_path
+ def allocate_buffers *buffers
+ buffers.peel!
+ if @buffers.compact.size + buffers.size > 1024
+ raise SCError, 'No more buffer numbers -- free some buffers before allocation more.'
end
+ @buffers += buffers
+ end
+ @@servers = []
+ class << self
# Returns an array with all the registered servers
def all
@@servers
end
# Clear the servers array
- def clear_servers
+ def clear
@@servers.clear
end
@@ -117,7 +132,6 @@ def []= index
@@servers.uniq!
end
end
-
end
class SCError < StandardError
View
1 lib/scruby/audio/synth.rb
@@ -2,6 +2,7 @@ module Scruby
class Synth < Node
def initialize name, opts = {}
+ raise ArgumentError, 'Second argument must be a Hash' unless opts.kind_of? Hash
super name, opts.delete(:servers)
@servers.each{ |s| s.send 9, @name, self.id, 0, 1, *opts.to_a.flatten } #Node?
end
View
8 lib/scruby/audio/ugens/ugen.rb
@@ -112,11 +112,17 @@ def output_specs #:nodoc:
end
class << self
+ def valid_input? obj
+ not [Ugen, ControlName, Env, UgenOperations].collect do |m|
+ true if obj.kind_of? m
+ end.compact.empty?
+ end
+
#:nodoc:
def new rate, *inputs
raise ArgumentError.new( "#{rate} not a defined rate") unless RATES.include?( rate.to_sym )
- inputs.each{ |i| raise ArgumentError.new( "#{i} is not a valid ugen input") unless i.valid_ugen_input? }
+ inputs.each{ |i| raise ArgumentError.new( "#{i} is not a valid ugen input") unless valid_input?(i) }
inputs.peel!
size = inputs.select{ |a| a.kind_of? Array }.map{ |a| a.size }.max || 1 #get the size of the largest array element if present
View
3 lib/scruby/audio/ugens/ugen_operations.rb
@@ -17,9 +17,6 @@ module UgenOperations
BINARY = operation_indices['binary']
SAFE_NAMES = { :+ => :plus, :- => :minus, :* => :mult, :/ => :div2, :<= => :less_than_or_eql, :>= => :more_than_or_eql }
- # true
- def valid_ugen_input?; true; end #TODO: Deprecate
-
def self.included klass
klass.send :include, BinaryOperations
klass.send :include, UnaryOperators if klass.ancestors.include? Ugen
View
48 lib/scruby/core_ext/array.rb
@@ -0,0 +1,48 @@
+class Array
+ #collect with index
+ def collect_with_index
+ self.zip( (0...self.size).map ).collect{ |element, index| yield element, index }
+ end
+
+ def wrap_to size
+ return self if size == self.size
+ self.dup.wrap_to! size
+ end
+
+ def wrap_to! size
+ return nil if size == self.size
+ original_size = self.size
+ size.times { |i| self[ i ] = self[ i % original_size ] }
+ self
+ end
+
+ def wrap_and_zip *args
+ max = args.map{ |a| instance_of?(Array) ? a.size : 0 }.max.max( self.size )
+ args = args.collect{ |a| a.to_array.wrap_to( max ) }
+ self.wrap_to( max ).zip( *args )
+ end
+
+ # Returns self
+ def to_array; self; end
+
+ def encode_floats #:nodoc:
+ [self.size].pack('n') + self.pack('g*') #TODO: Deprecate
+ end
+
+ def muladd mul, add #:nodoc:
+ self.collect{ |u| MulAdd.new( u, mul, add ) }
+ end
+
+ def peel!
+ self.replace self.first if self.first.kind_of? Array if self.size == 1
+ end
+
+ def peel
+ self.dup.peel! || self
+ end
+
+ private
+ def collect_constants #:nodoc:
+ self.collect{ |e| e.send( :collect_constants ) }
+ end
+end
View
8 lib/scruby/core_ext/fixnum.rb
@@ -0,0 +1,8 @@
+# Musical math
+class Fixnum
+ def freq
+ 440 * (2 ** ((self - 69) * 0.083333333333) )
+ end
+ #method next tone
+ # 1:1.05946
+end
View
25 lib/scruby/core_ext/numeric.rb
@@ -0,0 +1,25 @@
+class Numeric
+ # Rate is :scalar
+ def rate; :scalar; end
+
+ # Compares itself with +other+ and returns biggest
+ def max other
+ self > other ? self : other
+ end
+
+ # Compares itself with +other+ and returns smallest
+ def min other
+ self < other ? self : other
+ end
+
+ private
+ #:nodoc:
+ def collect_constants
+ self
+ end
+
+ #:nodoc:
+ def input_specs synthdef
+ [-1, synthdef.constants.index(self)]
+ end
+end
View
15 lib/scruby/core_ext/object.rb
@@ -0,0 +1,15 @@
+class Object
+ # Wraps self int an array, #to_a seems to be deprecated
+ def to_array
+ [*self]
+ end
+end
+
+
+class TrueClass
+ def to_i; 1; end
+end
+
+class FalseClass
+ def to_i; 0; end
+end
View
10 lib/scruby/core_ext/proc.rb
@@ -0,0 +1,10 @@
+class Proc
+ # Returns an array of symbols corresponding to the argument names
+ def arguments
+ case self.arity
+ when -1..0 then []
+ when 1 then self.to_sexp.assoc( :dasgn_curr )[1].to_array
+ else self.to_sexp[2][1][1..-1].collect{ |arg| arg[1] }
+ end
+ end
+end
View
5 lib/scruby/core_ext/string.rb
@@ -0,0 +1,5 @@
+class String
+ def encode #:nodoc:
+ [self.size & 255].pack('C*') + self[0..255]
+ end
+end
View
5 lib/scruby/core_ext/symbol.rb
@@ -0,0 +1,5 @@
+class Symbol
+ def to_proc
+ proc { |obj, *args| obj.send(self, *args) }
+ end
+end
View
54 lib/scruby/core_ext/typed_array.rb
@@ -0,0 +1,54 @@
+
+# Typed array is a kind of Array that only accepts elements of a given Class, it will raise a TypeError if an element of
+# diferent Class is passed to the operation methods or if an Array containing objects of a diferent class is concatenated.
+class TypedArray < Array
+ attr_reader :type
+
+ # +Type+ a Class or an instance, on the operation methods it will match the argument against the Class or instance's Class
+ def initialize type, elements = []
+ @type = type.instance_of?(Class) ? type : type.class
+ check_array_passed elements
+ check_types_for_array elements
+ super elements
+ end
+
+ # alias :old_plus :+ #:nodoc:
+ #
+ # def + array
+ # self.class.new @type, self.old_plus( array )
+ # end
+
+ def concat array
+ check_array_passed array
+ check_types_for_array array
+ super
+ end
+
+ def << e
+ check_type_for_obj e
+ super
+ end
+
+ def []= index, e
+ check_type_for_obj e
+ super
+ end
+
+ def push e
+ check_type_for_obj e
+ super
+ end
+
+ private
+ def check_array_passed obj
+ raise TypeError.new( "#{obj} is not Array" ) unless obj.instance_of? Array
+ end
+
+ def check_types_for_array array
+ raise TypeError.new("All elements of #{array} should be instance of #{@type}") unless array.reject{ |e| e.instance_of? @type }.empty?
+ end
+
+ def check_type_for_obj obj
+ raise TypeError.new("#{obj} is not instance of #{@type}") unless obj.instance_of? @type
+ end
+end
View
2 script/console
@@ -5,6 +5,6 @@ irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
libs = " -r irb/completion"
# Perhaps use a console_lib to store any extra methods I may want available in the cosole
# libs << " -r #{File.dirname(__FILE__) + '/../lib/console_lib/console_logger.rb'}"
-libs << " -r #{File.dirname(__FILE__) + '/../lib/Scruby.rb'}"
+libs << " -r #{File.dirname(__FILE__) + '/../lib/scruby.rb'}"
puts "Loading Scruby gem"
exec "#{irb} #{libs} --simple-prompt"
View
21 sesion 1.rb
@@ -0,0 +1,21 @@
+
+
+CSound
+SoundHack
+
+
+Técnicas de distorción FM, Waveshaping
+
+Csound
+PD
+SuperCollider
+Max MSP
+Turbosynth
+Open Music
+MetaSynth
+Modalys
+
+
+
+Music Tutorial
+Charles Dodge, Thomas Jerse - Computer Music
View
67 spec/audio/buffer_spec.rb
@@ -0,0 +1,67 @@
+require File.join( File.expand_path(File.dirname(__FILE__)), '..',"helper")
+
+require 'arguments'
+require 'tempfile'
+require 'osc'
+require 'scruby/core_ext/array'
+require "scruby/audio/buffer"
+require "scruby/audio/server"
+
+include Scruby
+include Audio
+
+class Scruby::Audio::Server
+ attr_reader :output
+ def puts string
+ @output ||= ""
+ @output << string
+ string
+ end
+end
+
+describe Buffer do
+ describe '#server buffer allocation' do
+ before do
+ @server = Server.new
+ end
+
+ it "should register itself in server" do
+ buffer = Buffer.new @server
+ @server.buffers.should include(buffer)
+ end
+
+ it "should allow less than 1024 buffers" do
+ @server.allocate_buffers( (1..1024).map{ mock(Buffer) } )
+ @server.buffers.size.should == 1024
+ end
+
+ it "should not allow more than 1024 buffers" do
+ lambda { @server.allocate_buffers( (1..1025).map{ mock(Buffer) } ) }.should raise_error(SCError)
+ end
+ end
+
+ describe "messaging" do
+ before :all do
+ @server = Server.new
+ @server.boot
+ 2.times do # ???
+ @server.send "/status"
+ sleep 0.2
+ @server.send "/dumpOSC", 1
+ end
+ end
+
+ after :all do
+ @server.quit
+ end
+
+ it "should send /b_allocRead message" do
+ buffer = Buffer.read @server, "sounds/a11wlk01-44_1.aiff"
+ buffer.should be_a(Buffer)
+ sleep 0.1
+ @server.output.should =~ %r{\[ "/b_allocRead", 1, "sounds/a11wlk01-44_1.aiff", 0, -1, DATA\[20\] \]}
+ end
+
+ end
+
+end
View
1 spec/audio/env_gen_spec.rb
@@ -1,5 +1,6 @@
require File.join( File.expand_path(File.dirname(__FILE__)), '..', "helper")
+require "scruby/audio/control_name"
require "scruby/audio/ugens/ugen"
require "scruby/audio/ugens/ugen_operations"
require "scruby/extensions"
View
4 spec/audio/in_out_spec.rb
@@ -1,5 +1,7 @@
require File.join( File.expand_path(File.dirname(__FILE__)),"../helper")
+require "scruby/audio/control_name"
+require "scruby/audio/env"
require "scruby/audio/ugens/ugen"
require "scruby/audio/ugens/ugen_operations"
require "scruby/extensions"
@@ -31,7 +33,7 @@ def self.ar freq = 440.0, phase = 0.0
@sdef = mock( 'ugen', :children => [] )
Ugen.should_receive( :synthdef ).at_least( :once ).and_return( @sdef )
- @proxy = mock('output proxy', :valid_ugen_input? => true )
+ @proxy = mock('output proxy' )
@proxies = (1..10).map{ @proxy }
OutputProxy.stub!(:new).and_return( @proxy )
View
12 spec/audio/multiout_ugen_spec.rb
@@ -1,5 +1,7 @@
require File.join( File.expand_path(File.dirname(__FILE__)), '..',"helper")
+require "scruby/audio/control_name"
+require "scruby/audio/env"
require "scruby/audio/ugens/ugen"
require "scruby/audio/ugens/ugen_operations"
require "scruby/extensions"
@@ -47,7 +49,7 @@
@proxy = mock('proxy', :instance_of_proxy? => true)
OutputProxy.stub!( :new ).and_return( @proxy )
- @names = Array.new( rand(7) + 3 ){ |i| mock('name', :rate => :audio, :valid_ugen_input? => true) }
+ @names = Array.new( rand(7) + 3 ){ |i| mock 'name', :rate => :audio }
@proxies = Control.new( :audio, *@names )
@control = sdef.children.first
end
@@ -84,11 +86,11 @@
@sdef = mock( 'sdef', :children => [] )
Ugen.stub!( :synthdef ).and_return( @sdef )
- @source = mock('source', :index => 0, :valid_ugen_input? => true )
- @name = mock('control name', :valid_ugen_input? => true)
- @output_index = mock('output_idex', :valid_ugen_input? => true)
+ @source = mock('source', :index => 0 )
+ @name = mock('control name' )
+ @output_index = mock('output_idex' )
- @names = [mock('name', :rate => :audio, :valid_ugen_input? => true)]
+ @names = [mock('name', :rate => :audio )]
end
View
10 spec/audio/operation_ugens_spec.rb
@@ -1,5 +1,7 @@
require File.join( File.expand_path(File.dirname(__FILE__)), '..',"helper")
+require "scruby/audio/control_name"
+require "scruby/audio/env"
require "scruby/audio/ugens/ugen"
require "scruby/audio/ugens/ugen_operations"
require "scruby/extensions"
@@ -13,10 +15,10 @@
::RATES = :scalar, :demand, :control, :audio
before do
- @scalar = mock 'ugen', :rate => :scalar, :valid_ugen_input? => true
- @demand = mock 'ugen', :rate => :demand, :valid_ugen_input? => true
- @control = mock 'ugen', :rate => :control, :valid_ugen_input? => true
- @audio = mock 'ugen', :rate => :audio, :valid_ugen_input? => true
+ @scalar = mock 'ugen', :rate => :scalar
+ @demand = mock 'ugen', :rate => :demand
+ @control = mock 'ugen', :rate => :control
+ @audio = mock 'ugen', :rate => :audio
end
describe UnaryOpUGen do
View
102 spec/audio/server_spec.rb
@@ -1,65 +1,87 @@
require File.join( File.expand_path(File.dirname(__FILE__)), '..',"helper")
+require 'arguments'
require 'tempfile'
require 'osc'
+require 'scruby/core_ext/typed_array'
+require 'scruby/audio/buffer'
require "scruby/audio/server"
+
include Scruby
include Audio
+Thread.abort_on_exception = true
-describe Server, 'instantiation and booting' do
-
- before do
- @server = Server.new
+class Scruby::Audio::Server
+ attr_reader :output
+
+ def puts string
+ @output ||= ""
+ @output << string
+ string
end
+end
- it "should not rise scynth not found error" do
- File.stub!( :exists ).and_return( true )
- lambda{ @server = Server.new; @server.boot; @server.stop }.should_not raise_error(Server::SCError)
- end
+describe Server do
+
+ describe "booting" do
+ before do
+ @server = Server.new
+ end
- it "should not reboot" do
- @server.boot
- Thread.should_not_receive(:new)
- @server.boot
- @server.stop
- end
+ after do
+ @server.quit
+ end
- it "should raise scsynth not found error" do
- Server.sc_path = '/Applications/SuperCollider/not_scsynth'
- lambda{ @server = Server.new; @server.boot }.should raise_error(Server::SCError)
- end
+ it "should not rise scynth not found error" do
+ lambda{ @server.boot }.should_not raise_error(Server::SCError)
+ end
- it "should add self to a list of servers" do
- s = Server.new
- Server.all.should include(s)
+ it "should not reboot" do
+ @server.boot
+ Thread.should_not_receive(:new)
+ @server.boot
+ end
+
+ it "should raise scsynth not found error" do
+ lambda{ @server = Server.new(:path => '/not_scsynth'); @server.boot }.should raise_error(Server::SCError)
+ end
+
+ it "should add self to a list of servers" do
+ s = Server.new
+ Server.all.should include(s)
+ end
end
describe 'sending OSC' do
-
+
before :all do
- Server.sc_path = '/Applications/SuperCollider/scsynth'
-
- encoded = "SCgf\000\000\000\001\000\001\003out\000\002C\334\000\000\000\000\000\000\000\000\000\000\000\002\006SinOsc\002\000\002\000\001\000\000\377\377\000\000\377\377\000\001\002\003Out\002\000\002\000\000\000\000\377\377\000\001\000\000\000\000\000\000"
- @sdef = mock('sdef', :encode => encoded)
-
@server = Server.new
- # @server.boot
+ @server.boot
+ 2.times do # ???
+ @server.send "/status"
+ sleep 0.2
+ @server.send "/dumpOSC", 1
+ end
end
-
- after do
- # @server.stop
+
+ after :all do
+ @server.quit
+ end
+
+ it "should send dump" do
+ @server.send "/dumpOSC", 1
+ sleep 0.1
+ @server.output.should =~ %r{/dumpOSC}
+ end
+
+ it "should send synthdef" do
+ sdef = mock 'sdef', :encode => [ 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*')
+ @server.send_synth_def sdef
+ sleep 0.1
+ @server.output.should =~ %r{\[ "#bundle", 1, \n\s*\[ "/d_recv", DATA\[56\], 0 \]\n\]}
end
-
- it "should send message" # do
- # @server.send_synth_def( @sdef )
- #
- # # blob = [OSC::Blob.new( @sdef.encode ), 0]
- #
- # end
-
-
end
end
View
5 spec/audio/synth_spec.rb
@@ -25,6 +25,10 @@
s.servers.should == @servers
end
+ it do
+ lambda { Synth.new 'synth', :hola }.should raise_error(ArgumentError)
+ end
+
it "should initialize not passing servers and have default servers" do
Server.should_receive(:all).and_return(@servers)
s = Synth.new( 'synth' )
@@ -37,6 +41,7 @@
s = Synth.new( :synth, :attack => 10, :servers => servers )
end
+
it "should send set message and return self" do
s = mock('server')
s.should_receive(:send).with( 15, 2002, :attack, 20 )
View
5 spec/audio/synthdef_spec.rb
@@ -1,5 +1,6 @@
require File.join( File.expand_path(File.dirname(__FILE__)), '..',"helper")
+require "scruby/audio/env"
require "scruby/audio/ugens/ugen"
require "scruby/audio/ugens/ugen_operations"
require "scruby/extensions"
@@ -262,9 +263,7 @@ def self.ar freq = 440.0, phase = 0.0 #not interested in muladd
Server.should_receive(:all).and_return([@server])
@sdef.send
end
-
- end
-
+ end
end
View
2 spec/audio/ugen_operations_spec.rb
@@ -1,6 +1,8 @@
require File.join( File.expand_path(File.dirname(__FILE__)), '..',"helper")
require 'yaml'
+require "scruby/audio/control_name"
+require "scruby/audio/env"
require "scruby/audio/ugens/ugen"
require "scruby/audio/ugens/operation_ugens"
require "scruby/audio/ugens/ugen_operations"
View
145 spec/audio/ugen_spec.rb
@@ -1,6 +1,8 @@
require File.join( File.expand_path(File.dirname(__FILE__)), '..',"helper")
require 'yaml'
-
+
+require "scruby/audio/control_name"
+require "scruby/audio/env"
require "scruby/audio/ugens/ugen"
require "scruby/audio/ugens/ugen_operations"
require "scruby/extensions"
@@ -9,15 +11,14 @@
include Audio
include Ugens
-
class SinOsc < Ugen
class << self
- def ar( freq=440.0, phase=0.0 ) #not interested in muladd
- new(:audio, freq, phase)
+ def ar freq = 440.0, phase = 0.0 #not interested in muladd by now
+ new :audio, freq, phase
end
- def kr( freq=440.0, phase=0.0 )
- new(:control, freq, phase)
+ def kr freq = 440.0, phase = 0.0
+ new :control, freq, phase
end
end
end
@@ -26,18 +27,24 @@ def kr( freq=440.0, phase=0.0 )
describe Ugen do
before do
- @sdef = mock( 'sdef', :children => [] )
+ @sdef = mock 'sdef', :children => []
end
it "should set constants " do
UgenOperations::UNARY.should_not be_nil
UgenOperations::BINARY.should_not be_nil
Ugen::RATES.should_not be_nil
end
+
+ it "should tell if valid input" do
+ Ugen.valid_input?( Ugen.new(:audio) ).should be_true
+ Ugen.valid_input?( Env.asr ).should be_true
+ Ugen.valid_input?( 'string' ).should be_false
+ end
describe 'attributes' do
before do
- @ugen = Ugen.new( :audio, 1 )
+ @ugen = Ugen.new :audio, 1
end
it do
@@ -51,14 +58,14 @@ def kr( freq=440.0, phase=0.0 )
describe 'operations' do
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 )
+ @op_ugen = mock( 'op_ugen' )
+ ::BinaryOpUGen = mock 'bynary_op_ugen', :new => @op_ugen
+ UnaryOpUGen = mock 'unary_op_ugen', :new => @op_ugen
end
before do
- @ugen = Ugen.new( :audio, 1, 2 )
- @ugen2 = Ugen.new( :audio, 1, 2 )
+ @ugen = Ugen.new :audio, 1, 2
+ @ugen2 = Ugen.new :audio, 1, 2
end
it do #this specs all binary operations
@@ -126,7 +133,7 @@ def kr( freq=440.0, phase=0.0 )
end
- describe 'initialization' do
+ describe 'initialization and inputs' do
before do
@ugen = Ugen.new(:audio, 1, 2, 3)
end
@@ -261,67 +268,65 @@ def kr( freq=440.0, phase=0.0 )
@ugen.muladd(1, 1).should be_nil
end
end
-
-end
+ describe Ugen, 'encoding' do
+ before do
+ args = [400.0, 0.0]
+ @sin = SinOsc.kr *args
+ @synthdef = mock 'synthdef', :constants => args
+ @sin.stub!( :index ).and_return 1 #as if was the first child of a synthdef
+ @sin.stub!( :synthdef ).and_return @synthdef
-describe Ugen, 'encoding' do
-
- before do
- args = [400.0, 0.0]
- @sin = SinOsc.kr *args
- @synthdef = mock 'synthdef', :constants => args
- @sin.stub!( :index ).and_return 1 #as if was the first child of a synthdef
- @sin.stub!( :synthdef ).and_return @synthdef
-
- @encoded = [6, 83, 105, 110, 79, 115, 99, 1, 0, 2, 0, 1, 0, 0, -1, -1, 0, 0, -1, -1, 0, 1, 1].pack('C*')
- end
-
- it "should stub synthdef" do
- @sin.send( :synthdef ).should == @synthdef
- end
-
- it "should encode have 0 as special index" do
- @sin.send(:special_index).should == 0
- end
-
- it "should encode have 0 as output index" do
- @sin.send(:output_index).should == 0
- end
-
- it "should encode have [1] as output index" do
- @sin.send(:channels).should == [1]
- end
-
- it "should return input_specs" do
- @sin.send( :input_specs, nil ).should == [1,0]
- end
-
- it "should collect input_specs" do
- @sin.send(:collect_input_specs).should == [[-1, 0], [-1, 1]]
- end
-
- # it "should collect input_specs" do
- # @sin.send(:collect_input_specs).flatten.collect { |e| e.encode }
- # end
-
- it "should encode class name" do
- @sin.encode[0..6].should == @encoded[0..6]
- end
-
- it "should encode classname, rate" do
- @sin.encode[0..7].should == @encoded[0..7]
- end
-
- it "should encode cn, rt, inputs, channels, special_index" do
- @sin.encode[0..13].should == @encoded[0..13]
+ @encoded = [6, 83, 105, 110, 79, 115, 99, 1, 0, 2, 0, 1, 0, 0, -1, -1, 0, 0, -1, -1, 0, 1, 1].pack('C*')
+ end
+
+ it "should stub synthdef" do
+ @sin.send( :synthdef ).should == @synthdef
+ end
+
+ it "should encode have 0 as special index" do
+ @sin.send(:special_index).should == 0
+ end
+
+ it "should encode have 0 as output index" do
+ @sin.send(:output_index).should == 0
+ end
+
+ it "should encode have [1] as output index" do
+ @sin.send(:channels).should == [1]
+ end
+
+ it "should return input_specs" do
+ @sin.send( :input_specs, nil ).should == [1,0]
+ end
+
+ it "should collect input_specs" do
+ @sin.send(:collect_input_specs).should == [[-1, 0], [-1, 1]]
+ end
+
+ # it "should collect input_specs" do
+ # @sin.send(:collect_input_specs).flatten.collect { |e| e.encode }
+ # end
+
+ it "should encode class name" do
+ @sin.encode[0..6].should == @encoded[0..6]
+ end
+
+ it "should encode classname, rate" do
+ @sin.encode[0..7].should == @encoded[0..7]
+ end
+
+ it "should encode cn, rt, inputs, channels, special_index" do
+ @sin.encode[0..13].should == @encoded[0..13]
+ end
+
+ it "should encode cn, rt, in, out, si, collect_input_specs" do
+ @sin.encode.should == @encoded
+ end
end
- it "should encode cn, rt, in, out, si, collect_input_specs" do
- @sin.encode.should == @encoded
- end
-
end
+
View
43 test.live.rb
@@ -0,0 +1,43 @@
+load File.expand_path( File.dirname( __FILE__ ) + '/../scruby.rb' )
+
+
+# Lamonte Young - Just in tone afination
+# Nan Carrow
+44100
+
+s = Server.new('localhost', 57140)
+s.boot
+
+s.send "/dumpOSC", 1
+
+clear
+
+# Síntesis aditiva
+SynthDef.new :add do |gate|
+ freqs = 1100, 1320, 1540, 1980
+ amps = 0.5, 0.5, 0.5, 0.5
+ env = EnvGen.kr Env.adsr(0.9, 0.1, 1, 0.5), gate, :doneAction => 2
+ sig = freqs.zip(amps).inject SinOsc.ar(220) do |sum, args|
+ sum + SinOsc.ar( args.first, :mul => args.last )
+ end
+ Out.ar 0, [sig * env, sig * env]
+end.send
+
+test = Synth.new :add, :gate => 1
+
+s.quit
+
+
+Buffer.read s, "sounds/robot.aiff"
+
+1
+
+
+class Smock
+ def encode
+ [ 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*')
+ end
+end
+
+s.send_synth_def Smock.new
+

0 comments on commit cccff37

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