ruby-audio-heroku 1.6.1

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.
@@ -0,0 +1,85 @@
1
+ module RubyAudio
2
+ # Class <code>Sound</code> wraps libsndfile to provide simple reading and
3
+ # writing for a wide variety of file formats
4
+ #
5
+ # Reading Example:
6
+ # RubyAudio::Sound.open('sound.wav') do |snd|
7
+ # buf = snd.read(:float, 100)
8
+ # puts buf.real_size #=> 100
9
+ # end
10
+ #
11
+ # Writing Example:
12
+ # buf = RubyAudio::Buffer.float(1000)
13
+ # out = nil
14
+ # ['snd1.wav', 'snd2.wav', 'snd3.wav'].each do |file|
15
+ # RubyAudio::Sound.open(file) do |snd|
16
+ # out = RubyAudio::Sound.open('out.wav', 'w', snd.info.clone) if out.nil?
17
+ #
18
+ # while snd.read(buf) != 0
19
+ # out.write(buf)
20
+ # end
21
+ # end
22
+ # end
23
+ # out.close if out
24
+ class Sound < CSound
25
+ # Creates a new <code>Sound</code> object for the audio file at the given path.
26
+ # Mode defaults to <code>"r"</code>, but valid modes are <code>"r"</code>,
27
+ # <code>"w"</code>, and <code>"rw"</code>.
28
+ #
29
+ # When creating a new sound, a valid <code>SoundInfo</code> object must be
30
+ # passed in, as libsndfile uses it to determine the output format.
31
+ # info = RubyAudio::SoundInfo.new :channels => 1, :samplerate => 48000, :format => RubyAudio::FORMAT_WAV|RubyAudio::FORMAT_PCM_16
32
+ # snd = RubyAudio::Sound.new "new.wav", 'r', info
33
+ def initialize(path, mode='r', info=nil)
34
+ info ||= SoundInfo.new
35
+ super(path, mode, info)
36
+ end
37
+
38
+ # Seeks to a given offset <i>anInteger</i> in the sound according to the value
39
+ # of <i>whence</i>:
40
+ #
41
+ # IO::SEEK_CUR | Seeks to _frames_ plus current position
42
+ # --------------+----------------------------------------------------
43
+ # IO::SEEK_END | Seeks to _frames_ plus end of stream (you probably
44
+ # | want a negative value for _frames_)
45
+ # --------------+----------------------------------------------------
46
+ # IO::SEEK_SET | Seeks to the absolute location given by _frames_
47
+ def seek(frames, whence=IO::SEEK_SET)
48
+ super(frames, whence)
49
+ end
50
+
51
+ # Reads a given number of frames from the sound into a buffer
52
+ #
53
+ # When given a buffer as the first argument, it reads data into that buffer
54
+ # reading an optional number of frames as the second argument. It returns
55
+ # the number of frames read.
56
+ #
57
+ # Example:
58
+ # buf = RubyAudio::Buffer.float(1000)
59
+ # snd.read(buf) #=> 1000
60
+ # snd.read(buf, 50) #=> 50
61
+ #
62
+ # When given a string or symbol as the first argument, it interprets this as
63
+ # the data type and creates a new buffer of the given size to read the data
64
+ # into. The buffer is correctly initialized with the proper number of channels
65
+ # to hold data from that sound.
66
+ #
67
+ # Example:
68
+ # buf = snd.read("int", 1000)
69
+ def read(*args)
70
+ case args[0]
71
+ when Buffer
72
+ buf = args[0]
73
+ size = args[1] || buf.size
74
+ return super(buf, size)
75
+ when Symbol, String
76
+ type = args[0]
77
+ buf = Buffer.new(type, args[1], info.channels)
78
+ super(buf, buf.size)
79
+ return buf
80
+ else
81
+ raise ArgumentError, "invalid arguments"
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,83 @@
1
+ module RubyAudio
2
+ # Class <code>SoundInfo</code> provides information about open sound files'
3
+ # format, length, samplerate, channels, and other things.
4
+ #
5
+ # Example:
6
+ # snd = RubyAudio::Sound.open("snd.wav")
7
+ # puts snd.info.channels #=> 2
8
+ # puts snd.info.samplerate #=> 48000
9
+ # snd.close
10
+ #
11
+ # In addition it can be used to specify the format of new sound files:
12
+ #
13
+ # info = RubyAudio::SoundInfo.new :channels => 1, :samplerate => 48000, :format => RubyAudio::FORMAT_WAV|RubyAudio::FORMAT_PCM_16
14
+ # snd = RubyAudio::Sound.open("new.wav", 'w', info)
15
+ class SoundInfo < CSoundInfo
16
+ # Creates a new SoundInfo object and populates it using the given data
17
+ #
18
+ # Example:
19
+ # info = RubyAudio::SoundInfo.new :channels => 1, :samplerate => 48000, :format => RubyAudio::FORMAT_WAV|RubyAudio::FORMAT_PCM_16
20
+ def initialize options={}
21
+ # Populate from options if given
22
+ unless options.empty?
23
+ options.each {|key,value| send("#{key}=", value)}
24
+ end
25
+ end
26
+
27
+ # Returns a new <code>SoundInfo</code> object that has the same channel
28
+ # count, sample rate, and format. This is useful in creating a new sound with
29
+ # the same format as an already existing sound.
30
+ #
31
+ # Example:
32
+ # snd1 = RubyAudio::Sound.open("snd.wav")
33
+ # snd2 = RubyAudio::Sound.open("snd2.wav", 'w', snd1.info.clone)
34
+ def clone
35
+ SoundInfo.new(:channels => channels, :samplerate => samplerate, :format => format)
36
+ end
37
+
38
+ alias_method :seekable?, :seekable
39
+
40
+ # Returns the main format constant as a string
41
+ #
42
+ # Example:
43
+ # info = RubyAudio::SoundInfo.new :channels => 1, :samplerate => 48000, :format => RubyAudio::FORMAT_WAV|RubyAudio::FORMAT_PCM_16
44
+ # info.main_format
45
+ # #=> "FORMAT_WAV"
46
+ def main_format
47
+ calculate_format if @main_format.nil?
48
+ @main_format
49
+ end
50
+
51
+ # Returns the sub format constant as a string
52
+ #
53
+ # Example:
54
+ # info = RubyAudio::SoundInfo.new :channels => 1, :samplerate => 48000, :format => RubyAudio::FORMAT_WAV|RubyAudio::FORMAT_PCM_16
55
+ # info.sub_format
56
+ # #=> "FORMAT_PCM_16"
57
+ def sub_format
58
+ calculate_format if @sub_format.nil?
59
+ @sub_format
60
+ end
61
+
62
+ # Returns the length of the audio file in seconds
63
+ def length
64
+ frames / samplerate.to_f
65
+ end
66
+
67
+ private
68
+ def calculate_format
69
+ RubyAudio.constants.grep(/FORMAT_/).map(&:to_s).each do |f|
70
+ next if f.include?('MASK') # Skip mask constants
71
+
72
+ val = RubyAudio.const_get(f)
73
+ if val > RubyAudio::FORMAT_SUBMASK
74
+ # Main format
75
+ @main_format = f if format & RubyAudio::FORMAT_TYPEMASK == val
76
+ else
77
+ # Sub format
78
+ @sub_format = f if format & RubyAudio::FORMAT_SUBMASK == val
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
data/lib/ruby-audio.rb ADDED
@@ -0,0 +1,10 @@
1
+ begin
2
+ # Fat binaries for Windows
3
+ RUBY_VERSION =~ /(\d+.\d+)/
4
+ require "#{$1}/rubyaudio_ext"
5
+ rescue LoadError
6
+ require "rubyaudio_ext"
7
+ end
8
+ require 'ruby-audio/buffer'
9
+ require 'ruby-audio/sound_info'
10
+ require 'ruby-audio/sound'
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = 'ruby-audio-heroku'
5
+ s.version = '1.6.1'
6
+ s.platform = Gem::Platform::RUBY
7
+ s.authors = ['Khurram Zaman']
8
+ s.email = ['khurram.zaman@gmail.com']
9
+ s.homepage = 'https://github.com/khurramzaman/ruby-audio-heroku'
10
+ s.summary = 'libsndfile wrapper for ruby that works on heroku'
11
+ s.description = 'ruby-audio-heroku wraps around libsndfile to provide simplified sound reading and writing support to ruby programs. it works on heroku.'
12
+
13
+ s.files = Dir['ruby-audio-heroku.gemspec', 'README.rdoc', 'LICENSE', 'Rakefile', 'lib/**/*.rb', 'spec/**/*.{rb,opts,wav,mp3}', 'ext/**/*.{c,h,rb}']
14
+ s.test_files = Dir['spec/**/*_spec.rb']
15
+ s.extensions = Dir["ext/**/extconf.rb"]
16
+
17
+ s.requirements << ''
18
+
19
+ s.has_rdoc = true
20
+ s.extra_rdoc_files = Dir['README.rdoc', 'ext/**/*.c']
21
+ s.rdoc_options = ['--line-numbers', '--main', 'README.rdoc']
22
+ end
@@ -0,0 +1,107 @@
1
+ require "spec_helper.rb"
2
+
3
+ describe RubyAudio::Buffer do
4
+ it "should initialize properly" do
5
+ buf = RubyAudio::Buffer.new('float', 100, 2)
6
+ buf.channels.should == 2
7
+ buf.size.should == 100
8
+ buf.real_size.should == 0
9
+ buf.type.should == :float
10
+ end
11
+
12
+ it "should support pretty typed constructors" do
13
+ lambda {
14
+ [:short, :int, :float, :double].each do |type|
15
+ buf = RubyAudio::Buffer.send(type, 100)
16
+ end
17
+ }.should_not raise_error
18
+ end
19
+
20
+ it "should allow [] access on integer single channel buffers" do
21
+ buf = RubyAudio::Buffer.int(100, 1)
22
+ buf[0] = 1.3
23
+ buf[0].should == 1
24
+
25
+ buf = RubyAudio::Buffer.short(100, 1)
26
+ buf[20] = 614
27
+ buf[20].should == 614
28
+ end
29
+
30
+ it "should allow [] access on floating point single channel buffers" do
31
+ buf = RubyAudio::Buffer.double(100, 1)
32
+ buf[30] = 1.375
33
+ buf[30].should == 1.375
34
+
35
+ buf = RubyAudio::Buffer.float(100, 1)
36
+ buf[12] = 5
37
+ buf[12].should == 5.0
38
+ end
39
+
40
+ it "should allow [] access on multi-channel buffers" do
41
+ buf = RubyAudio::Buffer.double(100, 2)
42
+ buf[0] = [0.5, 0.3]
43
+ buf[0].should == [0.5, 0.3]
44
+ end
45
+
46
+ it "should raise exception if channel count of set frame does not match buffer's" do
47
+ lambda {
48
+ buf = RubyAudio::Buffer.double(100, 2)
49
+ buf[0] = [0.4, 0.8, 0.8]
50
+ }.should raise_error(RubyAudio::Error, "array length must match channel count")
51
+ end
52
+
53
+ it "should return nil on out-of-bounds [] access" do
54
+ buf = RubyAudio::Buffer.float(100)
55
+ buf[101].should == nil
56
+ buf[-1].should == nil
57
+ end
58
+
59
+ it "should truncate invalid real size" do
60
+ buf = RubyAudio::Buffer.float(100)
61
+ buf.real_size = 101
62
+ buf.real_size.should == 100
63
+ end
64
+
65
+ it "should support cloning/duping" do
66
+ buf = RubyAudio::Buffer.int(100)
67
+ buf[4] = 100
68
+
69
+ buf2 = buf.dup
70
+ buf2.size.should == buf.size
71
+ buf2[4].should == 100
72
+
73
+ buf[4] = 140
74
+ buf2[4].should == 100
75
+ end
76
+
77
+ context ".each" do
78
+ before(:each) do
79
+ @buf = RubyAudio::Buffer.int(10, 2)
80
+ 10.times do |i|
81
+ @buf[i] = [i, i]
82
+ end
83
+ end
84
+
85
+ it "should yield the elements in order" do
86
+ i = 0
87
+ @buf.each do |left, right|
88
+ left.should == i
89
+ right.should == i
90
+ i += 1
91
+ end
92
+ end
93
+
94
+ it "shouldn't do anything on an empty buffer" do
95
+ buf = RubyAudio::Buffer.int(50, 2)
96
+
97
+ buf.each do
98
+ fail "This shouldn't be executed"
99
+ end
100
+ end
101
+
102
+ it "should support usage through returned enumerable" do
103
+ enum = @buf.each
104
+ enum.any? {|frame| frame[0] == 5}.should == true
105
+ end
106
+ end
107
+ end
Binary file
Binary file
Binary file
@@ -0,0 +1,55 @@
1
+ require "spec_helper.rb"
2
+
3
+ describe RubyAudio::SoundInfo do
4
+ it "should initialize with default properties" do
5
+ info = RubyAudio::SoundInfo.new
6
+ info.channels.should == 0
7
+ info.samplerate.should == 0
8
+ info.format.should == 0
9
+ end
10
+
11
+ it "should allow setting properties on initialize" do
12
+ info = RubyAudio::SoundInfo.new(:channels => 1, :samplerate => 48000, :format => RubyAudio::FORMAT_WAV|RubyAudio::FORMAT_PCM_16)
13
+ info.channels.should == 1
14
+ info.samplerate.should == 48000
15
+ info.format.should == RubyAudio::FORMAT_WAV|RubyAudio::FORMAT_PCM_16
16
+ end
17
+
18
+ it "should allow setting properties after initialize" do
19
+ info = RubyAudio::SoundInfo.new
20
+ info.channels = 3
21
+ info.channels.should == 3
22
+ end
23
+
24
+ it "should not be valid if properties invalid" do
25
+ info = RubyAudio::SoundInfo.new(:channels => 1, :samplerate => 48000, :format => RubyAudio::FORMAT_WAV)
26
+ info.valid?.should == false
27
+ info.format = RubyAudio::FORMAT_WAV|RubyAudio::FORMAT_PCM_16
28
+ info.valid?.should == true
29
+ end
30
+
31
+ it "should allow cloning" do
32
+ info = RubyAudio::SoundInfo.new(:channels => 1, :samplerate => 48000, :format => RubyAudio::FORMAT_WAV|RubyAudio::FORMAT_PCM_16)
33
+ info2 = info.clone
34
+ info.object_id.should_not == info2.object_id
35
+ info.channels.should == info2.channels
36
+ info.samplerate.should == info2.samplerate
37
+ info.format.should == info2.format
38
+ end
39
+
40
+ it "should calculate main and sub format from format" do
41
+ info = RubyAudio::SoundInfo.new(:format => RubyAudio::FORMAT_WAV|RubyAudio::FORMAT_PCM_16)
42
+ info.main_format.should == "FORMAT_WAV"
43
+ info.sub_format.should == "FORMAT_PCM_16"
44
+
45
+ info = RubyAudio::SoundInfo.new(:format => RubyAudio::FORMAT_WAVEX|RubyAudio::FORMAT_MS_ADPCM)
46
+ info.main_format.should == "FORMAT_WAVEX"
47
+ info.sub_format.should == "FORMAT_MS_ADPCM"
48
+ end
49
+
50
+ it "should return the length of an audio file" do
51
+ RubyAudio::Sound.open(fixture('what.wav')) do |snd|
52
+ snd.info.length.should == 26413 / 16000.0
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,220 @@
1
+ require "spec_helper.rb"
2
+
3
+ describe RubyAudio::Sound do
4
+ after :each do
5
+ File.delete(fixture('temp.wav')) if File.exists?(fixture('temp.wav'))
6
+ end
7
+
8
+ it "should open a standard wav without issues" do
9
+ lambda {
10
+ RubyAudio::Sound.open(fixture('what.wav'))
11
+ }.should_not raise_error
12
+ end
13
+
14
+ it "should open an IO conformer without issues" do
15
+ lambda {
16
+ RubyAudio::Sound.open(io_fixture('what.wav'))
17
+ }.should_not raise_error
18
+ end
19
+
20
+ it "should raise an exception if the mode is invalid" do
21
+ lambda {
22
+ RubyAudio::Sound.open(fixture('what.wav'), 'q')
23
+ }.should raise_error(ArgumentError, 'invalid access mode q')
24
+ end
25
+
26
+ it "should close the sound on block exit" do
27
+ s = nil
28
+ RubyAudio::Sound.open(fixture('what.wav')) do |snd|
29
+ snd.closed?.should be_false
30
+ s = snd
31
+ end
32
+ s.closed?.should be_true
33
+ end
34
+
35
+ it "should raise an exception for an unsupported file" do
36
+ lambda {
37
+ RubyAudio::Sound.open(fixture('what.mp3'))
38
+ }.should raise_error(RubyAudio::Error, "File contains data in an unknown format.")
39
+ end
40
+
41
+ it "should raise an exception if file does not exist" do
42
+ lambda {
43
+ RubyAudio::Sound.open(fixture('what.mp3')+'.not')
44
+ }.should raise_error(RubyAudio::Error, "System error : No such file or directory.")
45
+ end
46
+
47
+ it "should have the proper sound info" do
48
+ RubyAudio::Sound.open(fixture('what.wav')) do |snd|
49
+ snd.info.channels.should == 1
50
+ snd.info.samplerate.should == 16000
51
+ snd.info.format.should == RubyAudio::FORMAT_WAV|RubyAudio::FORMAT_PCM_16
52
+ end
53
+ end
54
+
55
+ it "should allow seeking" do
56
+ lambda {
57
+ RubyAudio::Sound.open(fixture('what.wav')) do |snd|
58
+ snd.seek(100)
59
+ buf = snd.read(:float, 100)
60
+ buf[0].should > 0
61
+ end
62
+ }.should_not raise_error
63
+ end
64
+
65
+ it "should allow seeking in IO conformers" do
66
+ lambda {
67
+ RubyAudio::Sound.open(io_fixture('what.wav')) do |snd|
68
+ snd.seek(100)
69
+ buf = snd.read(:float, 100)
70
+ buf[0].should > 0
71
+ end
72
+ }.should_not raise_error
73
+ end
74
+
75
+ it "should raise exceptions for invalid seeks" do
76
+ lambda {
77
+ RubyAudio::Sound.open(fixture('what.wav')) {|snd| snd.seek(-1)}
78
+ }.should raise_error(RubyAudio::Error, "invalid seek")
79
+ lambda {
80
+ RubyAudio::Sound.open(fixture('what.wav')) {|snd| snd.seek(1000000)}
81
+ }.should raise_error(RubyAudio::Error, "invalid seek")
82
+ end
83
+
84
+ it "should allow reading samples from the sound" do
85
+ RubyAudio::Sound.open(fixture('what2.wav')) do |snd|
86
+ buf = snd.read(:float, 1000)
87
+ buf.size.should == 1000
88
+ buf.real_size.should == 1000
89
+ buf[999].length.should == 2
90
+ end
91
+ end
92
+
93
+ it "should allow reading samples from IO conformers" do
94
+ RubyAudio::Sound.open(io_fixture('what2.wav')) do |snd|
95
+ buf = snd.read(:float, 1000)
96
+ buf.size.should == 1000
97
+ buf.real_size.should == 1000
98
+ buf[999].length.should == 2
99
+ end
100
+ end
101
+
102
+ it "should allow reading into an existing buffer" do
103
+ buf = RubyAudio::Buffer.float(1000)
104
+ buf.real_size.should == 0
105
+ RubyAudio::Sound.open(fixture('what.wav')) do |snd|
106
+ snd.read(buf)
107
+ end
108
+ buf.real_size.should == 1000
109
+ buf[99].should > 0
110
+ end
111
+
112
+ it "should allow reading into an existing buffer partially" do
113
+ buf = RubyAudio::Buffer.float(1000)
114
+ buf.real_size.should == 0
115
+ RubyAudio::Sound.open(fixture('what.wav')) do |snd|
116
+ snd.read(buf, 100)
117
+ end
118
+ buf.real_size.should == 100
119
+ buf[99].should > 0
120
+ buf[100].should == nil
121
+ end
122
+
123
+ it "should allow downmixing to mono on read" do
124
+ buf = RubyAudio::Buffer.int(100, 1)
125
+ buf2 = RubyAudio::Buffer.int(100, 2)
126
+ RubyAudio::Sound.open(fixture('what2.wav'), 'r') do |snd|
127
+ snd.read(buf)
128
+ snd.seek(0)
129
+ snd.read(buf2)
130
+
131
+ f = buf2[99]
132
+ buf[99].should == (f[0] + f[1]) / 2
133
+ end
134
+ end
135
+
136
+ it "should allow upmixing from mono on read" do
137
+ buf = RubyAudio::Buffer.int(100, 1)
138
+ buf2 = RubyAudio::Buffer.int(100, 2)
139
+ RubyAudio::Sound.open(fixture('what2.wav'), 'r') do |snd|
140
+ snd.read(buf2)
141
+ snd.seek(0)
142
+ snd.read(buf)
143
+
144
+ buf2[99].should == [buf[99], buf[99]]
145
+ end
146
+ end
147
+
148
+ it "should fail read on unsupported up/downmixing" do
149
+ buf = RubyAudio::Buffer.float(100, 5)
150
+ lambda {
151
+ RubyAudio::Sound.open(fixture('what2.wav')) do |snd|
152
+ snd.read(buf)
153
+ end
154
+ }.should raise_error(RubyAudio::Error, "unsupported mix from 5 to 2")
155
+ end
156
+
157
+ it "should allow writing to a new sound" do
158
+ in_buf = RubyAudio::Buffer.float(100)
159
+ out_buf = RubyAudio::Buffer.float(100)
160
+ out_info = nil
161
+ RubyAudio::Sound.open(fixture('what.wav')) do |snd|
162
+ snd.read(in_buf)
163
+ out_info = snd.info.clone
164
+ end
165
+
166
+ RubyAudio::Sound.open(fixture('temp.wav'), 'rw', out_info) do |snd|
167
+ snd.write(in_buf)
168
+ snd.seek(0)
169
+ snd.read(out_buf)
170
+ end
171
+
172
+ out_buf[50].should == in_buf[50]
173
+ end
174
+
175
+ it "should allow writing to an IO conformer" do
176
+ in_buf = RubyAudio::Buffer.float(100)
177
+ out_buf = RubyAudio::Buffer.float(100)
178
+ out_info = nil
179
+ RubyAudio::Sound.open(fixture('what.wav')) do |snd|
180
+ snd.read(in_buf)
181
+ out_info = snd.info.clone
182
+ end
183
+
184
+ RubyAudio::Sound.open(io_fixture, 'rw', out_info) do |snd|
185
+ snd.write(in_buf)
186
+ snd.seek(0)
187
+ snd.read(out_buf)
188
+ end
189
+
190
+ out_buf[50].should == in_buf[50]
191
+ end
192
+
193
+ it "should allow writing to a new sound using <<" do
194
+ in_buf = RubyAudio::Buffer.float(100)
195
+ out_buf = RubyAudio::Buffer.float(100)
196
+ out_info = nil
197
+ RubyAudio::Sound.open(fixture('what.wav')) do |snd|
198
+ snd.read(in_buf)
199
+ out_info = snd.info.clone
200
+ end
201
+
202
+ RubyAudio::Sound.open(fixture('temp.wav'), 'rw', out_info) do |snd|
203
+ snd << in_buf
204
+ snd.seek(0)
205
+ snd.read(out_buf)
206
+ end
207
+
208
+ out_buf[50].should == in_buf[50]
209
+ end
210
+
211
+ it "should fail write on channel mismatch" do
212
+ buf = RubyAudio::Buffer.float(100, 5)
213
+ info = RubyAudio::SoundInfo.new :channels => 2, :samplerate => 48000, :format => RubyAudio::FORMAT_WAV|RubyAudio::FORMAT_PCM_16
214
+ lambda {
215
+ RubyAudio::Sound.open(fixture('temp.wav'), 'w', info) do |snd|
216
+ snd.write(buf)
217
+ end
218
+ }.should raise_error(RubyAudio::Error, "channel count mismatch: 5 vs 2")
219
+ end
220
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1,2 @@
1
+ --colour
2
+ -f nested
@@ -0,0 +1,24 @@
1
+ begin
2
+ require 'spec'
3
+ rescue LoadError
4
+ require 'rubygems'
5
+ gem 'rspec'
6
+ require 'spec'
7
+ end
8
+ require 'spec/autorun'
9
+
10
+ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
11
+ require 'ruby-audio'
12
+
13
+ def fixture file_name
14
+ File.join(File.dirname(__FILE__), 'data', file_name)
15
+ end
16
+
17
+ def io_fixture file_name=nil
18
+ if file_name
19
+ path = fixture(file_name)
20
+ StringIO.new(File.read(path))
21
+ else
22
+ StringIO.new
23
+ end
24
+ end