Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

working on buffer, added buffnum allocate_and_read, read, cue_sound_file

  • Loading branch information...
commit 92fc776917c7a3f9ad20ba018dd23b6e68c06b77 1 parent 5b3868b
@maca authored
View
59 lib/scruby/audio/buffer.rb
@@ -1,6 +1,5 @@
module Scruby
class Buffer
-
# allocReadChannel
# allocReadMsg
# alloc ReadCannelMsg
@@ -50,16 +49,10 @@ class Buffer
# 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
@@ -69,45 +62,49 @@ def initialize server, frames = -1, channels = 1
@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) ) )
+ message ||= 0
+ @server.send '/b_alloc', buffnum, frames, channels, message.value(self)
+ self
end
-
- def bufnum
- @bufnum ||= @server.buffers.index self
+
+ def buffnum
+ @server.buffers.index self
end
+ alias :as_ugen_input :buffnum
+ # alias :as_control_input :buffnum
# :nodoc:
- def allocate_and_read path, start, frames, &completion
- @path = path
- @server.send "/b_allocRead", bufnum, path, start, frames, Message.new("/b_query", bufnum)
+ def allocate_and_read path, start, frames, &message
+ message ||= ["/b_query", buffnum]
+ @server.send "/b_allocRead", buffnum, @path = path, start, frames, message.value(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] }
+ # Allocate a buffer and immediately read a soundfile into it.
+ def read server, path, start = 0, frames = -1, &message
+ buffer = new server, &message
+ buffer.allocate_and_read path, start, frames
+ end
+
+ def cue_sound_file server, path, start, channels = 2, buff_size = 32768, &message
+ allocate server, buff_size, channels do |buffer|
+ message ||= 0
+ ['/b_read', buffer.buffnum, path, start, buff_size, 0, true, message.value(buffer)]
+ end
end
- def allocate server, frames = -1, channels = 1
+ def allocate server, frames = -1, channels = 1, &message
buffer = new server, frames, channels
- # buffer.rate = server.rate
- buffer.alloc
+ buffer.allocate &message
end
- named_arguments_for :read
+ named_arguments_for :allocate, :read, :cue_sound_file
- # alloc
# allocConsecutive
# readChannel
# readNoUpdate
- # cueSoundFile
# loadCollection
# sendCollection
# freeAllinitServerCache
View
2  lib/scruby/audio/env.rb
@@ -18,6 +18,8 @@ class Env
}
def initialize levels, times, curves = :lin, release_node = nil, loop_node = nil
+ #times should be one less than levels size
+ # raise( ArgumentError, 'levels and times must be array')
@levels, @times, @curves, @release_node, @loop_node = levels, times, curves.to_array, release_node, loop_node
raise ArgumentError, "levels and times should be array" unless levels.instance_of?(Array) and times.instance_of?(Array)
end
View
41 lib/scruby/audio/server.rb
@@ -7,6 +7,18 @@ module Audio
class Message < OSC::Message
def initialize command, *args
args.peel!
+ args.collect! do |arg|
+ case arg
+ when Array
+ Blob.new self.class.new(*arg).encode
+ when true
+ 1
+ when false
+ 0
+ else
+ arg
+ end
+ end
super command, type_tags(args), *args
end
@@ -39,10 +51,10 @@ class Server
# server already running.
# Server class keeps an array with all the instantiated servers
def initialize host = 'localhost', port = 57111, path = '/Applications/SuperCollider/scsynth'
- @host = host
- @port = port
- @path = path
- @buffers = []
+ @host = host
+ @port = port
+ @path = path
+ @buffers = []
self.class.all << self
end
@@ -89,20 +101,21 @@ def quit
send '/quit'
end
- # Sends an OSC command to the scsyth server.
- # E.g. <tt>server.send('/dumpOSC', 1)</tt>
- def send command, *args
- $UDP_Sender.send command, @host, @port, *args
+ # Sends an OSC command or +Message+ to the scsyth server.
+ # E.g. +server.send('/dumpOSC', 1)+
+ def send message, *args
+ case message
+ when Bundle, Message
+ $UDP_Sender.send_message message, @host, @port
+ else
+ $UDP_Sender.send message, @host, @port, *args
+ end
self
end
# Encodes and sends a SynthDef to the scsynth server
def send_synth_def synth_def
- send_message Bundle.new nil, Message.new( '/d_recv', Blob.new(synth_def.encode), 0 )
- end
-
- def send_message message #:nodoc:
- $UDP_Sender.send_message message, @host, @port
+ send Bundle.new( nil, Message.new( '/d_recv', Blob.new(synth_def.encode), 0 ) )
end
def allocate_buffers *buffers
@@ -112,7 +125,7 @@ def allocate_buffers *buffers
end
@buffers += buffers
end
-
+
@@servers = []
class << self
# Returns an array with all the registered servers
View
11 lib/scruby/audio/ugens/ugen.rb
@@ -108,9 +108,14 @@ class << self
#: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 valid_input?(i) }
+
inputs.peel!
+ inputs.collect! do |input|
+ input = input.as_ugen_input if input.respond_to?(:as_ugen_input)
+ raise ArgumentError.new( "#{ input.inspect } is not a valid ugen input") unless valid_input? input
+ input
+ end
+
size = inputs.select{ |a| a.kind_of? Array }.map{ |a| a.size }.max || 1 #get the size of the largest array element if present
inputs.flatten! if size == 1 #if there is one or more arrays with just one element flatten the input array
@@ -137,7 +142,7 @@ def synthdef= synthdef #:nodoc:
end
def valid_input? obj
- not [Ugen, ControlName, Env, UgenOperations].collect do |m|
+ not [Ugen, ControlName, Env, UgenOperations, Buffer].collect do |m|
true if obj.kind_of? m
end.compact.empty?
end
View
4 lib/scruby/audio/ugens/ugen_operations.rb
@@ -47,7 +47,9 @@ def self.included klass
end
module UnaryOperators
- UNARY.each_key{ |op| define_method(op){ UnaryOpUGen.new op, self } }
+ UNARY.each_key do |op|
+ define_method(op){ UnaryOpUGen.new op, self }
+ end
end
end
View
8 lib/scruby/core_ext/object.rb
@@ -3,6 +3,14 @@ class Object
def to_array
[*self]
end
+
+ def to_proc
+ Proc.new{ self }
+ end
+
+ def value *args
+ self
+ end
end
View
2  lib/scruby/core_ext/proc.rb
@@ -7,4 +7,6 @@ def arguments
else self.to_sexp[2][1][1..-1].collect{ |arg| arg[1] }
end
end
+
+ alias :value :call
end
View
50 spec/audio/buffer_spec.rb
@@ -53,14 +53,52 @@ def puts string
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", 0, "sounds/a11wlk01-44_1.aiff", 0, -1, DATA\[20\] \]}
+
+ describe 'Buffer.read' do
+ before do
+ @buffer = Buffer.read @server, "sounds/a11wlk01-44_1.aiff"
+ sleep 0.1
+ end
+
+ it "should instantiate and send /b_allocRead message" do
+ @buffer.should be_a(Buffer)
+ @server.output.should =~ %r{\[ "/b_allocRead", #{ @buffer.buffnum }, "sounds/a11wlk01-44_1.aiff", 0, -1, DATA\[20\] \]}
+ @server.output.should =~ /00 00 00 14 2f 62 5f 71 75 65 72 79 00 00 00 00/
+ end
+
+ it "should allow passing a completion message"
end
+ describe 'Buffer.allocate' do
+ before do
+ @buffer = Buffer.allocate @server, 44100 * 8.0, 2
+ sleep 0.1
+ end
+
+ it "should call allocate and send /b_alloc message" do
+ @buffer.should be_a(Buffer)
+ @server.output.should =~ %r{\[ "/b_alloc", #{ @buffer.buffnum }, 352800, 2, 0 \]}
+ @server.output.should =~ /69 00 00 00 00 00 00 00 00 44 ac 48 00 00 00 02/
+ end
+
+ it "should allow passing a completion message"
+ end
+
+ describe 'Buffer.cueSoundFile' do
+ before do
+ @buffer = Buffer.cue_sound_file @server, "sounds/a11wlk01-44_1.aiff", 0, 1
+ sleep 0.1
+ end
+
+ it "should send /b_alloc message and instantiate" do
+ @buffer.should be_a(Buffer)
+ @server.output.should =~ %r{\[ "/b_alloc", #{ @buffer.buffnum }, 32768, 1, DATA\[72\] \]}
+ @server.output.should =~ /64 73 2f 61 31 31 77 6c 6b 30 31 2d 34 34 5f 31/
+ @server.output.should =~ /2e 61 69 66 66 00 00 00 00 00 00 00 00 00 80 00/
+ end
+
+ it "should allow passing a completion message"
+ end
end
end
View
4 spec/audio/node_spec.rb
@@ -1,7 +1,9 @@
require File.join( File.expand_path(File.dirname(__FILE__)), '..',"helper")
require "scruby/core_ext/typed_array"
-require "scruby/audio/node"
+require "scruby/audio/node"
+require 'osc'
+require 'scruby/audio/server'
class Server; end
include Scruby
View
12 spec/audio/server_spec.rb
@@ -3,6 +3,7 @@
require 'arguments'
require 'tempfile'
require 'osc'
+require 'scruby/audio/node'
require 'scruby/core_ext/array'
require 'scruby/core_ext/typed_array'
require 'scruby/audio/buffer'
@@ -24,6 +25,13 @@ def puts string
end
end
+describe Message do
+ it "should encode array as Message Blob" do
+ m = Message.new "/b_allocRead", 1, "path", 1, -1, ["/b_query", 1]
+ p m.encode
+ end
+end
+
describe Server do
describe "booting" do
@@ -56,8 +64,6 @@ def puts string
end
describe 'sending OSC' do
-
-
before :all do
@server = Server.new
@server.boot
@@ -84,7 +90,7 @@ def puts string
sleep 0.1
@server.output.should =~ %r{\[ "#bundle", 1, \n\s*\[ "/d_recv", DATA\[56\], 0 \]\n\]}
end
-
end
+
end
View
1  spec/audio/synth_spec.rb
@@ -40,7 +40,6 @@
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
11 spec/audio/ugen_spec.rb
@@ -26,6 +26,10 @@ def kr freq = 440.0, phase = 0.0
end
end
end
+
+class Scruby::Audio::Buffer
+ def as_ugen_input; 0; end
+end
describe Ugen do
@@ -43,8 +47,13 @@ def kr freq = 440.0, phase = 0.0
it "should tell if valid input" do
Ugen.send( :valid_input?, SinOsc.ar ).should be_true
Ugen.send( :valid_input?, Env.asr ).should be_true
+ Ugen.send( :valid_input?, Buffer.new ).should be_true
Ugen.send( :valid_input?, 'string' ).should be_false
end
+
+ it "should use buffnum as input when a buffer is passed" do
+ Ugen.new( :audio, Buffer.new ).inputs.should == [0]
+ end
describe 'attributes' do
before do
@@ -182,7 +191,7 @@ def kr freq = 440.0, phase = 0.0
it "should have empty inputs" do
Ugen.new( :audio ).inputs.should == []
- Ugen.new( :audio, [nil] ).inputs.should == []
+ Ugen.new( :audio, [] ).inputs.should == []
end
end
View
57 test.live.rb
@@ -8,12 +8,13 @@
s = Server.new('localhost', 57140)
s.boot
-s.send "/dumpOSC", 1
+s.send "/dumpOSC", 0
clear
-# Síntesis aditiva
-SynthDef.new :add do |gate|
+# Síntesis aditiva básica
+SynthDef.new :add do
+ gate = EnvGen.kr( Env.perc(0, 0.2) )
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
@@ -25,19 +26,55 @@
test = Synth.new :add, :gate => 1
-s.quit
-Buffer.read s, "sounds/robot.aiff"
+# Síntesis aditiva básica 2
+SynthDef.new :dos do |dur, freq|
+ gate = EnvGen.kr( Env.perc(0, 0.2) )
+ freq_env = EnvGen.kr Env.new( [100, 500*freq, 400*freq, 600*freq, 300*freq], [dur*3/4, dur*3/4, dur*3/4, dur*3/4] ), gate
+ amp_env = EnvGen.kr Env.new( [0, 1, 0.8, 1, 0], [dur*3/4, dur*3/4, dur*3/4, dur*3/4] ), gate, :doneAction => 2
+ Out.ar( 0, SinOsc.ar( freq_env) * amp_env )
+end.send
+
+test = Synth.new :dos, :dur => 5, :freq => 1
+test = Synth.new :dos, :dur => 5, :freq => 1.7
+test = Synth.new :dos, :dur => 5, :freq => 1.6
+test = Synth.new :dos, :dur => 5, :freq => 1.3
+
+s.stop
+
+SynthDef.new :simple do |freq, mul, dur|
+ gate = EnvGen.kr( Env.perc(0, 0.2) )
+ env = EnvGen.kr Env.asr(dur * 0.01, dur * 0.2, dur * 0.1), gate, :doneAction => 2
+ sig = SinOsc.ar(freq) * env * mul
+ Out.ar 0, [sig, sig]
+end.send
+
+Synth.new :simple, :freq => 200, :amp => 1, :dur => 1
-1
+freqs = 100, 300, 500, 700, 900, 1100, 1300, 1500, 1700, 1900, 2100, 2300, 2500, 2700, 2900
+amps = 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31
+durs = 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 24, 25, 26, 27, 28
-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*')
+run = true
+while run
+ freqs.zip amps, durs do |arr|
+ freq, amp, dur = arr
+ Synth.new :simple, :freq => freq * 1.2 * rand, :mul => 1.0/amp * 0.1 * rand, :dur => dur * 1 * rand
+ Synth.new :simple, :freq => freq * 0.9 * rand, :mul => 1.0/amp * 0.2 * rand, :dur => dur * 1 * rand
+ Synth.new :simple, :freq => freq * 0.6 * rand, :mul => 1.0/amp * 0.3 * rand, :dur => dur * 1 * rand
end
+ sleep 0.2
end
-s.send_synth_def Smock.new
+run = false
+
+p Node.base_id
+
+s.quit
+
+
+Buffer.read s, "sounds/robot.aiff"
+
Please sign in to comment.
Something went wrong with that request. Please try again.