waveinfo 0.0.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.
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
+