waveinfo 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/COPYING ADDED
@@ -0,0 +1,56 @@
1
+ ruby-mpris is copyrighted free software by Nicholas J Humfrey <njh@aelius.com>.
2
+ You can redistribute it and/or modify it under either the terms of the GPL
3
+ version 2 (see the file GPL), or the conditions below:
4
+
5
+ 1. You may make and give away verbatim copies of the source form of the
6
+ software without restriction, provided that you duplicate all of the
7
+ original copyright notices and associated disclaimers.
8
+
9
+ 2. You may modify your copy of the software in any way, provided that
10
+ you do at least ONE of the following:
11
+
12
+ a) place your modifications in the Public Domain or otherwise
13
+ make them Freely Available, such as by posting said
14
+ modifications to Usenet or an equivalent medium, or by allowing
15
+ the author to include your modifications in the software.
16
+
17
+ b) use the modified software only within your corporation or
18
+ organization.
19
+
20
+ c) give non-standard binaries non-standard names, with
21
+ instructions on where to get the original software distribution.
22
+
23
+ d) make other distribution arrangements with the author.
24
+
25
+ 3. You may distribute the software in object code or binary form,
26
+ provided that you do at least ONE of the following:
27
+
28
+ a) distribute the binaries and library files of the software,
29
+ together with instructions (in the manual page or equivalent)
30
+ on where to get the original distribution.
31
+
32
+ b) accompany the distribution with the machine-readable source of
33
+ the software.
34
+
35
+ c) give non-standard binaries non-standard names, with
36
+ instructions on where to get the original software distribution.
37
+
38
+ d) make other distribution arrangements with the author.
39
+
40
+ 4. You may modify and include the part of the software into any other
41
+ software (possibly commercial). But some files in the distribution
42
+ are not written by the author, so that they are not under these terms.
43
+
44
+ For the list of those files and their copying conditions, see the
45
+ file LEGAL.
46
+
47
+ 5. The scripts and library files supplied as input to or produced as
48
+ output from the software do not automatically fall under the
49
+ copyright of the software, but belong to whomever generated them,
50
+ and may be sold commercially, and may be aggregated with this
51
+ software.
52
+
53
+ 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
54
+ IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
55
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
56
+ PURPOSE.
data/README ADDED
@@ -0,0 +1,43 @@
1
+ == waveinfo
2
+
3
+ waveinfo is a pure-ruby gem to get the information from the headers of Wave (.wav) files.
4
+
5
+ RubyForge Project Page http://rubyforge.org/projects/waveinfo/
6
+
7
+ == Installing
8
+
9
+ You may get the latest stable version from Rubyforge. Source gems are also available.
10
+
11
+ $ gem install waveinfo
12
+
13
+ == Synopsis
14
+
15
+ require 'rubygems'
16
+ require 'waveinfo'
17
+
18
+ wave = WaveInfo.new('example.wav')
19
+ puts "Channels: #{wave.channels}"
20
+ puts "Sample Rate: #{wave.sample_rate} Hz"
21
+ puts "Duration: #{wave.duration} secs"
22
+
23
+ == TODO
24
+
25
+ * Add support for the extensible format which uses GUIDs
26
+ * Inplement more validity checks
27
+ - file is shorter than reported chunk size
28
+ - file is longer than reported chunk size
29
+ * Implement more chunk types
30
+ - bext - Broadcast Wave Extention
31
+ - mext - MPEG audio extension chunk
32
+ - DISP - Title
33
+ - cart - CartChunk/aes46-2002
34
+ - LIST
35
+ * Test against more weird Wave files
36
+
37
+ == Contact
38
+
39
+ Author:: Nicholas J Humfrey
40
+ Email:: njh@aelius.com
41
+ Home Page:: http://www.aelius.com/njh/
42
+ License:: Distributes under the same terms as Ruby
43
+
@@ -0,0 +1,112 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/clean'
4
+ require 'rake/gempackagetask'
5
+ require 'rake/rdoctask'
6
+ require 'spec/rake/spectask'
7
+ require 'spec/rake/verify_rcov'
8
+
9
+
10
+ NAME = "waveinfo"
11
+ VERS = "0.0.1"
12
+ CLEAN.include ['pkg', 'rdoc']
13
+
14
+ spec = Gem::Specification.new do |s|
15
+ s.name = NAME
16
+ s.version = VERS
17
+ s.author = "Nicholas J Humfrey"
18
+ s.email = "njh@aelius.com"
19
+ s.homepage = "http://waveinfo.rubyforge.org"
20
+ s.platform = Gem::Platform::RUBY
21
+ s.summary = "Pure-ruby gem to get the information from the headers of Wave (.wav) files."
22
+ s.rubyforge_project = "waveinfo"
23
+ s.description = "waveinfo is a pure-ruby gem to get the information from the headers of Wave (.wav) files."
24
+ s.files = FileList["Rakefile", "lib/waveinfo.rb", "spec/*.rb", "samples/*.wav"]
25
+ s.executables = ['waveinfo']
26
+ s.require_path = "lib"
27
+
28
+ # rdoc
29
+ s.has_rdoc = true
30
+ s.extra_rdoc_files = ["README", "COPYING"]
31
+
32
+ # Build Dependencies
33
+ #s.add_dependency 'rake' '~> 0.8'
34
+ #s.add_dependency 'rspec', '~> 1.1'
35
+ #s.add_dependency 'rcov', '~> 0.8'
36
+ end
37
+
38
+ desc "Default: test the gem."
39
+ task :default => [:check_syntax, :rdoc]
40
+
41
+ task :build_package => [:repackage]
42
+ Rake::GemPackageTask.new(spec) do |pkg|
43
+ pkg.need_zip = false
44
+ pkg.need_tar = true
45
+ pkg.gem_spec = spec
46
+ end
47
+
48
+ desc "Run :package and install the resulting .gem"
49
+ task :install => :package do
50
+ sh %{sudo gem install --local pkg/#{NAME}-#{VERS}.gem}
51
+ end
52
+
53
+ desc "Run :clean and uninstall the .gem"
54
+ task :uninstall => :clean do
55
+ sh %{sudo gem uninstall #{NAME}}
56
+ end
57
+
58
+
59
+
60
+ ## Testing
61
+ desc "Run all the specification tests"
62
+ Spec::Rake::SpecTask.new(:spec) do |t|
63
+ t.spec_files = FileList['spec/*_spec.rb']
64
+ t.spec_opts = ["--colour"]
65
+ end
66
+
67
+ desc "Check the syntax of all ruby files"
68
+ task :check_syntax do
69
+ `find . -name "*.rb" |xargs -n1 ruby -c |grep -v "Syntax OK"`
70
+ puts "* Done"
71
+ end
72
+
73
+ namespace :spec do
74
+ desc "Generate RCov report"
75
+ Spec::Rake::SpecTask.new(:rcov) do |t|
76
+ t.spec_files = FileList['spec/*_spec.rb']
77
+ t.rcov = true
78
+ t.rcov_dir = 'coverage'
79
+ t.rcov_opts = ['--text-report', '--exclude', "spec/"]
80
+ end
81
+
82
+ desc "Generate specdoc"
83
+ Spec::Rake::SpecTask.new(:doc) do |t|
84
+ t.spec_files = FileList['spec/*_spec.rb']
85
+ t.spec_opts = ["--format", "specdoc"]
86
+ end
87
+
88
+ namespace :doc do
89
+ desc "Generate html specdoc"
90
+ Spec::Rake::SpecTask.new(:html) do |t|
91
+ t.spec_files = FileList['spec/*_spec.rb']
92
+ t.spec_opts = ["--format", "html:rspec_report.html", "--diff"]
93
+ end
94
+ end
95
+ end
96
+
97
+
98
+
99
+ ## Documentation
100
+ desc "Generate documentation for the library"
101
+ Rake::RDocTask.new("rdoc") { |rdoc|
102
+ rdoc.rdoc_dir = 'rdoc'
103
+ rdoc.title = "waveinfo Documentation"
104
+ rdoc.options << '--line-numbers' << '--inline-source'
105
+ rdoc.main = "README"
106
+ rdoc.rdoc_files.include("README", "COPYING", "lib/waveinfo.rb")
107
+ }
108
+
109
+ desc "Upload rdoc to rubyforge"
110
+ task :upload_rdoc => [:rdoc] do
111
+ sh %{/usr/bin/scp -r -p rdoc/* waveinfo.rubyforge.org:/var/www/gforge-projects/waveinfo}
112
+ end
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'waveinfo'
5
+
6
+ if (ARGV.size < 1)
7
+ puts "Usage: waveinfo <file.wav> [<file2.wav> ...]"
8
+ exit
9
+ end
10
+
11
+ ARGV.each do |arg|
12
+ wave = WaveInfo.new(arg)
13
+ puts "Filename : #{wave.filename}"
14
+ puts "Audio Format : #{wave.audio_format} " +
15
+ sprintf("(0x%2.2x)",wave.audio_format_id)
16
+ puts "Duration : " + sprintf("%2.2fs", wave.duration)
17
+ puts "Channels : #{wave.channels}"
18
+ puts "Sample Rate : #{wave.sample_rate}Hz"
19
+ puts "Bits per Sample : #{wave.bits_per_sample}"
20
+ puts "Bytes per Block : #{wave.block_align}"
21
+ puts "Byte rate : #{wave.byte_rate}"
22
+ puts "Sample Count : #{wave.samples}"
23
+ puts "Audio Length : #{wave.size} bytes"
24
+ puts
25
+ end
@@ -0,0 +1,186 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ class WaveInfo
4
+
5
+ # Create a new WaveInfo object to get information and metadata about a
6
+ # Wave file (.wav). 'file' can either be a filename or an IO object.
7
+ def initialize(file)
8
+
9
+ # Set default values
10
+ @audio_format_id = 0
11
+ @bits_per_sample = nil
12
+ @block_align = nil
13
+ @byte_rate = nil
14
+ @channels = nil
15
+ @data_size = nil
16
+ @sample_rate = nil
17
+ @samples = nil
18
+
19
+ # What was passed in to us?
20
+ if file.is_a?(String)
21
+ @io = File.new(file, 'rb')
22
+ @filepath = @io.path
23
+ read_headers
24
+ @io.close
25
+ else
26
+ @io = file
27
+ @filepath = @io.path
28
+ read_headers
29
+ end
30
+ end
31
+
32
+ # Return the name of the input file.
33
+ def filename
34
+ File.basename(@filepath)
35
+ end
36
+
37
+ # Get the identifier of the audio codec (for example PCM would be 1).
38
+ def audio_format_id
39
+ @audio_format_id
40
+ end
41
+
42
+ # Get the name of the audio codec (for example 'PCM').
43
+ def audio_format
44
+ case @audio_format_id
45
+ when 0x01 then
46
+ "PCM"
47
+ when 0x02 then
48
+ "Microsoft ADPCM"
49
+ when 0x06 then
50
+ "a-law"
51
+ when 0x07 then
52
+ "u-law"
53
+ when 0x11 then
54
+ "IMA ADPCM"
55
+ when 0x14 then
56
+ "G.723"
57
+ when 0x31 then
58
+ "GSM"
59
+ when 0x40 then
60
+ "G.721"
61
+ when 0x50 then
62
+ "MPEG-1 Audio"
63
+ when 0x55 then
64
+ "MPEG Audio Layer 3"
65
+ else
66
+ "Unknown (#{@audio_format_id})"
67
+ end
68
+ end
69
+
70
+ # Get the number of channels.
71
+ def channels
72
+ @channels
73
+ end
74
+
75
+ # Get the sample rate (in Hz).
76
+ def sample_rate
77
+ @sample_rate
78
+ end
79
+
80
+ # Get the average number of bytes per second.
81
+ def byte_rate
82
+ @byte_rate
83
+ end
84
+
85
+ # Get the number of bytes per sample slice.
86
+ def block_align
87
+ @block_align
88
+ end
89
+
90
+ # Get the number of bits per sample.
91
+ def bits_per_sample
92
+ @bits_per_sample
93
+ end
94
+
95
+ # Get the total number of samples.
96
+ def samples
97
+ if @samples
98
+ @samples
99
+ else
100
+ @data_size / @block_align
101
+ end
102
+ end
103
+
104
+ # Get the length of the audio data (in bytes).
105
+ def size
106
+ @data_size
107
+ end
108
+
109
+ # Get the duration of the audio (in seconds).
110
+ def duration
111
+ samples.to_f / sample_rate.to_f
112
+ end
113
+
114
+ private
115
+
116
+ def read_headers
117
+ # Read in the chunk header
118
+ chunk_id = read_fourchar
119
+ raise FileFormatError.new("Chunk id is not 'RIFF'") if chunk_id != 'RIFF'
120
+ chunk_size = read_longint
121
+ chunk_format = read_fourchar
122
+ raise FileFormatError.new("Chunk format is not 'WAVE'") if chunk_format != 'WAVE'
123
+
124
+ # Read in each of the sub-chunks
125
+ position = 0x0C
126
+ while(chunk_size-position) > 0 do
127
+ subchunk_id = read_fourchar
128
+ subchunk_size = read_longint
129
+ case subchunk_id
130
+ when 'fmt '
131
+ read_fmt_chunk(subchunk_size)
132
+ when 'fact'
133
+ read_fact_chunk(subchunk_size)
134
+ when 'data'
135
+ @data_size = subchunk_size
136
+ # Skip over the wave data
137
+ @io.seek(subchunk_size,IO::SEEK_CUR)
138
+ else
139
+ pos = sprintf("0x%x", position)
140
+ $stderr.puts "Warning: unsupported sub-chunk at #{pos}: #{subchunk_id}"
141
+ @io.seek(subchunk_size,IO::SEEK_CUR)
142
+ end
143
+ position += subchunk_size + 8
144
+ end
145
+
146
+ end
147
+
148
+ def read_fmt_chunk(size)
149
+ @audio_format_id = read_shortint
150
+ @channels = read_shortint
151
+ @sample_rate = read_longint
152
+ @byte_rate = read_longint
153
+ @block_align = read_shortint
154
+ @bits_per_sample = read_shortint
155
+
156
+ # Skip any extra parameters
157
+ @io.seek(size-16,IO::SEEK_CUR) if size > 16
158
+ end
159
+
160
+ def read_fact_chunk(size)
161
+ # Read in the number of samples
162
+ @samples = read_longint
163
+
164
+ # Skip any extra data
165
+ @io.seek(size-4,IO::SEEK_CUR) if size > 4
166
+ end
167
+
168
+ def read_fourchar
169
+ @io.read(4)
170
+ end
171
+
172
+ def read_longint
173
+ bytes = @io.read(4)
174
+ bytes ? bytes.unpack('V').first : nil
175
+ end
176
+
177
+ def read_shortint
178
+ bytes = @io.read(2)
179
+ bytes ? bytes.unpack('v').first : nil
180
+ end
181
+
182
+ # Exception raised if there is a problem parsing the Wave file
183
+ class FileFormatError < Exception
184
+ end
185
+
186
+ end
@@ -0,0 +1,13 @@
1
+ begin
2
+ require 'spec'
3
+ rescue LoadError
4
+ require 'rubygems'
5
+ gem 'rspec'
6
+ require 'spec'
7
+ end
8
+
9
+ $:.unshift(File.dirname(__FILE__) + '/../lib')
10
+
11
+ def sample_path(name)
12
+ File.join(File.dirname(__FILE__), '..', 'samples', name + '.wav')
13
+ end
@@ -0,0 +1,433 @@
1
+ $:.unshift(File.dirname(__FILE__))
2
+
3
+ require 'spec_helper'
4
+ require 'waveinfo'
5
+
6
+
7
+ describe WaveInfo do
8
+
9
+ describe "parsing a Mono 11kHz PCM file with no 'fact' chunk" do
10
+ before :each do
11
+ @filepath = sample_path('sine_11k_mono_16bit_pcm')
12
+ @wav = WaveInfo.new( @filepath )
13
+ end
14
+
15
+ it "should get the audio format id right" do
16
+ @wav.audio_format_id.should == 1
17
+ end
18
+
19
+ it "should get the audio format name right" do
20
+ @wav.audio_format.should == 'PCM'
21
+ end
22
+
23
+ it "should get the number of channels right" do
24
+ @wav.channels.should == 1
25
+ end
26
+
27
+ it "should get the sample rate right" do
28
+ @wav.sample_rate.should == 11025
29
+ end
30
+
31
+ it "should get the byte rate right" do
32
+ @wav.byte_rate.should == 22050
33
+ end
34
+
35
+ it "should get the block align value right" do
36
+ @wav.block_align.should == 2
37
+ end
38
+
39
+ it "should get the bits per sample right" do
40
+ @wav.bits_per_sample.should == 16
41
+ end
42
+
43
+ it "should get the audio length in bytes right" do
44
+ @wav.size.should == 8820
45
+ end
46
+
47
+ it "should get the number of samples right" do
48
+ @wav.samples.should == 4410
49
+ end
50
+
51
+ it "should get the audio duration right" do
52
+ @wav.duration.should == 0.4
53
+ end
54
+
55
+ it "should know the name of the file read from" do
56
+ @wav.filename.should == File.basename(@filepath)
57
+ end
58
+ end
59
+
60
+ describe "parsing a Mono 8kHz GSM file with a 'fact' chunk" do
61
+ before :each do
62
+ @filepath = sample_path('sine_8k_mono_gsm')
63
+ @wav = WaveInfo.new( @filepath )
64
+ end
65
+
66
+ it "should get the audio format id right" do
67
+ @wav.audio_format_id.should == 49
68
+ end
69
+
70
+ it "should get the audio format name right" do
71
+ @wav.audio_format.should == 'GSM'
72
+ end
73
+
74
+ it "should get the number of channels right" do
75
+ @wav.channels.should == 1
76
+ end
77
+
78
+ it "should get the sample rate right" do
79
+ @wav.sample_rate.should == 8000
80
+ end
81
+
82
+ it "should get the byte rate right" do
83
+ @wav.byte_rate.should == 1625
84
+ end
85
+
86
+ it "should get the block align value right" do
87
+ @wav.block_align.should == 65
88
+ end
89
+
90
+ it "should get the bits per sample right" do
91
+ @wav.bits_per_sample.should == 0
92
+ end
93
+
94
+ it "should get the audio length in bytes right" do
95
+ @wav.size.should == 650
96
+ end
97
+
98
+ it "should get the number of samples right" do
99
+ @wav.samples.should == 3200
100
+ end
101
+
102
+ it "should get the audio duration right" do
103
+ @wav.duration.should == 0.4
104
+ end
105
+
106
+ it "should know the name of the file read from" do
107
+ @wav.filename.should == File.basename(@filepath)
108
+ end
109
+ end
110
+
111
+ describe "parsing a Stereo 44.1kHz 16-bit PCM file with a 'fact' chunk" do
112
+ before :each do
113
+ @filepath = sample_path('testcase_44k_stereo_16bit_pcm')
114
+ @wav = WaveInfo.new( @filepath )
115
+ end
116
+
117
+ it "should get the audio format id right" do
118
+ @wav.audio_format_id.should == 1
119
+ end
120
+
121
+ it "should get the audio format name right" do
122
+ @wav.audio_format.should == 'PCM'
123
+ end
124
+
125
+ it "should get the number of channels right" do
126
+ @wav.channels.should == 2
127
+ end
128
+
129
+ it "should get the sample rate right" do
130
+ @wav.sample_rate.should == 44100
131
+ end
132
+
133
+ it "should get the byte rate right" do
134
+ @wav.byte_rate.should == 176400
135
+ end
136
+
137
+ it "should get the block align value right" do
138
+ @wav.block_align.should == 4
139
+ end
140
+
141
+ it "should get the bits per sample right" do
142
+ @wav.bits_per_sample.should == 16
143
+ end
144
+
145
+ it "should get the audio length in bytes right" do
146
+ @wav.size.should == 100000
147
+ end
148
+
149
+ it "should get the number of samples right" do
150
+ @wav.samples.should == 25000
151
+ end
152
+
153
+ it "should get the audio duration right" do
154
+ (@wav.duration * 1000).to_i.should == 566
155
+ end
156
+
157
+ it "should know the name of the file read from" do
158
+ @wav.filename.should == File.basename(@filepath)
159
+ end
160
+ end
161
+
162
+ describe "parsing a Mono 11kHz Microsoft ADPCM file with a 'fact' chunk" do
163
+ before :each do
164
+ @filepath = sample_path('sine_11k_mono_ms_adpcm')
165
+ @wav = WaveInfo.new( @filepath )
166
+ end
167
+
168
+ it "should get the audio format id right" do
169
+ @wav.audio_format_id.should == 2
170
+ end
171
+
172
+ it "should get the audio format name right" do
173
+ @wav.audio_format.should == 'Microsoft ADPCM'
174
+ end
175
+
176
+ it "should get the number of channels right" do
177
+ @wav.channels.should == 1
178
+ end
179
+
180
+ it "should get the sample rate right" do
181
+ @wav.sample_rate.should == 11025
182
+ end
183
+
184
+ it "should get the byte rate right" do
185
+ @wav.byte_rate.should == 5784
186
+ end
187
+
188
+ it "should get the block align value right" do
189
+ @wav.block_align.should == 128
190
+ end
191
+
192
+ it "should get the bits per sample right" do
193
+ @wav.bits_per_sample.should == 4
194
+ end
195
+
196
+ it "should get the audio length in bytes right" do
197
+ @wav.size.should == 2432
198
+ end
199
+
200
+ it "should get the number of samples right" do
201
+ @wav.samples.should == 4410
202
+ end
203
+
204
+ it "should get the audio duration right" do
205
+ @wav.duration.should == 0.4
206
+ end
207
+
208
+ it "should know the name of the file read from" do
209
+ @wav.filename.should == File.basename(@filepath)
210
+ end
211
+ end
212
+
213
+ describe "parsing a Mono 11kHz 8-bit PCM file with no 'fact' chunk" do
214
+ before :each do
215
+ @filepath = sample_path('sine_11k_mono_8bit_pcm')
216
+ @wav = WaveInfo.new( @filepath )
217
+ end
218
+
219
+ it "should get the audio format id right" do
220
+ @wav.audio_format_id.should == 1
221
+ end
222
+
223
+ it "should get the audio format name right" do
224
+ @wav.audio_format.should == 'PCM'
225
+ end
226
+
227
+ it "should get the number of channels right" do
228
+ @wav.channels.should == 1
229
+ end
230
+
231
+ it "should get the sample rate right" do
232
+ @wav.sample_rate.should == 11025
233
+ end
234
+
235
+ it "should get the byte rate right" do
236
+ @wav.byte_rate.should == 11025
237
+ end
238
+
239
+ it "should get the block align value right" do
240
+ @wav.block_align.should == 1
241
+ end
242
+
243
+ it "should get the bits per sample right" do
244
+ @wav.bits_per_sample.should == 8
245
+ end
246
+
247
+ it "should get the audio length in bytes right" do
248
+ @wav.size.should == 4410
249
+ end
250
+
251
+ it "should get the number of samples right" do
252
+ @wav.samples.should == 4410
253
+ end
254
+
255
+ it "should get the audio duration right" do
256
+ @wav.duration.should == 0.4
257
+ end
258
+
259
+ it "should know the name of the file read from" do
260
+ @wav.filename.should == File.basename(@filepath)
261
+ end
262
+ end
263
+
264
+ describe "parsing a Mono 11kHz a-law file with a 'fact' chunk" do
265
+ before :each do
266
+ @filepath = sample_path('sine_11k_mono_alaw')
267
+ @wav = WaveInfo.new( @filepath )
268
+ end
269
+
270
+ it "should get the audio format id right" do
271
+ @wav.audio_format_id.should == 6
272
+ end
273
+
274
+ it "should get the audio format name right" do
275
+ @wav.audio_format.should == 'a-law'
276
+ end
277
+
278
+ it "should get the number of channels right" do
279
+ @wav.channels.should == 1
280
+ end
281
+
282
+ it "should get the sample rate right" do
283
+ @wav.sample_rate.should == 11025
284
+ end
285
+
286
+ it "should get the byte rate right" do
287
+ @wav.byte_rate.should == 11025
288
+ end
289
+
290
+ it "should get the block align value right" do
291
+ @wav.block_align.should == 1
292
+ end
293
+
294
+ it "should get the bits per sample right" do
295
+ @wav.bits_per_sample.should == 8
296
+ end
297
+
298
+ it "should get the audio length in bytes right" do
299
+ @wav.size.should == 4410
300
+ end
301
+
302
+ it "should get the number of samples right" do
303
+ @wav.samples.should == 4410
304
+ end
305
+
306
+ it "should get the audio duration right" do
307
+ @wav.duration.should == 0.4
308
+ end
309
+
310
+ it "should know the name of the file read from" do
311
+ @wav.filename.should == File.basename(@filepath)
312
+ end
313
+ end
314
+
315
+ describe "parsing a Mono 11kHz u-law file with a 'fact' chunk" do
316
+ before :each do
317
+ @filepath = sample_path('sine_11k_mono_ulaw')
318
+ @wav = WaveInfo.new( @filepath )
319
+ end
320
+
321
+ it "should get the audio format id right" do
322
+ @wav.audio_format_id.should == 7
323
+ end
324
+
325
+ it "should get the audio format name right" do
326
+ @wav.audio_format.should == 'u-law'
327
+ end
328
+
329
+ it "should get the number of channels right" do
330
+ @wav.channels.should == 1
331
+ end
332
+
333
+ it "should get the sample rate right" do
334
+ @wav.sample_rate.should == 11025
335
+ end
336
+
337
+ it "should get the byte rate right" do
338
+ @wav.byte_rate.should == 11025
339
+ end
340
+
341
+ it "should get the block align value right" do
342
+ @wav.block_align.should == 1
343
+ end
344
+
345
+ it "should get the bits per sample right" do
346
+ @wav.bits_per_sample.should == 8
347
+ end
348
+
349
+ it "should get the audio length in bytes right" do
350
+ @wav.size.should == 4410
351
+ end
352
+
353
+ it "should get the number of samples right" do
354
+ @wav.samples.should == 4410
355
+ end
356
+
357
+ it "should get the audio duration right" do
358
+ @wav.duration.should == 0.4
359
+ end
360
+
361
+ it "should know the name of the file read from" do
362
+ @wav.filename.should == File.basename(@filepath)
363
+ end
364
+ end
365
+
366
+ describe "parsing a Mono 11kHz IMA ADPCM file with a 'fact' chunk" do
367
+ before :each do
368
+ @filepath = sample_path('sine_11k_mono_ima_adpcm')
369
+ @wav = WaveInfo.new( @filepath )
370
+ end
371
+
372
+ it "should get the audio format id right" do
373
+ @wav.audio_format_id.should == 17
374
+ end
375
+
376
+ it "should get the audio format name right" do
377
+ @wav.audio_format.should == 'IMA ADPCM'
378
+ end
379
+
380
+ it "should get the number of channels right" do
381
+ @wav.channels.should == 1
382
+ end
383
+
384
+ it "should get the sample rate right" do
385
+ @wav.sample_rate.should == 11025
386
+ end
387
+
388
+ it "should get the byte rate right" do
389
+ @wav.byte_rate.should == 5589
390
+ end
391
+
392
+ it "should get the block align value right" do
393
+ @wav.block_align.should == 256
394
+ end
395
+
396
+ it "should get the bits per sample right" do
397
+ @wav.bits_per_sample.should == 4
398
+ end
399
+
400
+ it "should get the audio length in bytes right" do
401
+ @wav.size.should == 2304
402
+ end
403
+
404
+ it "should get the number of samples right" do
405
+ @wav.samples.should == 4410
406
+ end
407
+
408
+ it "should get the audio duration right" do
409
+ @wav.duration.should == 0.4
410
+ end
411
+
412
+ it "should know the name of the file read from" do
413
+ @wav.filename.should == File.basename(@filepath)
414
+ end
415
+ end
416
+
417
+ describe "parsing an invalid WAVE file" do
418
+ it "should throw an exception if the first chunk id isn't 'RIFF'" do
419
+ data = StringIO.new("INVALID")
420
+ lambda { WaveInfo.new( data ) }.should raise_error(WaveInfo::FileFormatError)
421
+ end
422
+
423
+ it "should throw an exception if the chunk format isn't 'WAVE'" do
424
+ data = StringIO.new("RIFF\0\0\0\0INVALID")
425
+ lambda { WaveInfo.new( data ) }.should raise_error(WaveInfo::FileFormatError)
426
+ end
427
+
428
+ it "should not throw an exception if WAVE file is valid but has no sub-chunks" do
429
+ data = StringIO.new("RIFF\4\0\0\0WAVE")
430
+ lambda { WaveInfo.new( data ) }.should_not raise_error
431
+ end
432
+ end
433
+ end
metadata ADDED
@@ -0,0 +1,68 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: waveinfo
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Nicholas J Humfrey
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-03-09 00:00:00 +00:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: waveinfo is a pure-ruby gem to get the information from the headers of Wave (.wav) files.
17
+ email: njh@aelius.com
18
+ executables:
19
+ - waveinfo
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README
24
+ - COPYING
25
+ files:
26
+ - Rakefile
27
+ - lib/waveinfo.rb
28
+ - spec/spec_helper.rb
29
+ - spec/waveinfo_spec.rb
30
+ - samples/sine_11k_mono_16bit_pcm.wav
31
+ - samples/sine_11k_mono_8bit_pcm.wav
32
+ - samples/sine_11k_mono_alaw.wav
33
+ - samples/sine_11k_mono_ima_adpcm.wav
34
+ - samples/sine_11k_mono_ms_adpcm.wav
35
+ - samples/sine_11k_mono_ulaw.wav
36
+ - samples/sine_8k_mono_16bit_pcm.wav
37
+ - samples/sine_8k_mono_gsm.wav
38
+ - samples/testcase_44k_stereo_16bit_pcm.wav
39
+ - README
40
+ - COPYING
41
+ has_rdoc: true
42
+ homepage: http://waveinfo.rubyforge.org
43
+ post_install_message:
44
+ rdoc_options: []
45
+
46
+ require_paths:
47
+ - lib
48
+ required_ruby_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: "0"
53
+ version:
54
+ required_rubygems_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: "0"
59
+ version:
60
+ requirements: []
61
+
62
+ rubyforge_project: waveinfo
63
+ rubygems_version: 1.3.1
64
+ signing_key:
65
+ specification_version: 2
66
+ summary: Pure-ruby gem to get the information from the headers of Wave (.wav) files.
67
+ test_files: []
68
+