wavefile 0.8.1 → 1.0.0
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.
- checksums.yaml +5 -5
- data/LICENSE +1 -1
- data/README.markdown +33 -28
- data/Rakefile +2 -2
- data/lib/wavefile.rb +5 -5
- data/lib/wavefile/chunk_readers/format_chunk_reader.rb +1 -1
- data/lib/wavefile/duration.rb +1 -1
- data/lib/wavefile/format.rb +120 -29
- data/lib/wavefile/reader.rb +18 -16
- data/lib/wavefile/unvalidated_format.rb +51 -3
- data/lib/wavefile/writer.rb +74 -21
- data/test/buffer_test.rb +13 -10
- data/test/chunk_readers/format_chunk_reader_test.rb +40 -40
- data/test/fixtures/{invalid → wave/invalid}/bad_riff_header.wav +0 -0
- data/test/fixtures/{invalid → wave/invalid}/bad_wavefile_format.wav +0 -0
- data/test/fixtures/{invalid → wave/invalid}/empty.wav +0 -0
- data/test/fixtures/{invalid → wave/invalid}/empty_format_chunk.wav +0 -0
- data/test/fixtures/{invalid → wave/invalid}/incomplete_riff_header.wav +0 -0
- data/test/fixtures/{invalid → wave/invalid}/insufficient_format_chunk.wav +0 -0
- data/test/fixtures/{invalid → wave/invalid}/no_data_chunk.wav +0 -0
- data/test/fixtures/{invalid → wave/invalid}/no_format_chunk.wav +0 -0
- data/test/fixtures/{unsupported → wave/unsupported}/bad_audio_format.wav +0 -0
- data/test/fixtures/{unsupported → wave/unsupported}/bad_channel_count.wav +0 -0
- data/test/fixtures/{unsupported → wave/unsupported}/bad_sample_rate.wav +0 -0
- data/test/fixtures/{unsupported → wave/unsupported}/extensible_container_size_bigger_than_sample_size.wav +0 -0
- data/test/fixtures/wave/unsupported/extensible_unsupported_subformat_guid.wav +0 -0
- data/test/fixtures/{unsupported → wave/unsupported}/unsupported_audio_format.wav +0 -0
- data/test/fixtures/{unsupported → wave/unsupported}/unsupported_bits_per_sample.wav +0 -0
- data/test/fixtures/{valid → wave/valid}/no_samples.wav +0 -0
- data/test/fixtures/wave/valid/valid_extensible_20_pcm_16_44100_speaker_mapping_overflow.wav +0 -0
- data/test/fixtures/{valid → wave/valid}/valid_extensible_mono_float_32_44100.wav +0 -0
- data/test/fixtures/{valid → wave/valid}/valid_extensible_mono_float_64_44100.wav +0 -0
- data/test/fixtures/wave/valid/valid_extensible_mono_pcm_16_44100.wav +0 -0
- data/test/fixtures/wave/valid/valid_extensible_mono_pcm_16_44100_non_default_speaker_mapping.wav +0 -0
- data/test/fixtures/wave/valid/valid_extensible_mono_pcm_24_44100.wav +0 -0
- data/test/fixtures/wave/valid/valid_extensible_mono_pcm_32_44100.wav +0 -0
- data/test/fixtures/wave/valid/valid_extensible_mono_pcm_8_44100.wav +0 -0
- data/test/fixtures/{valid → wave/valid}/valid_extensible_stereo_float_32_44100.wav +0 -0
- data/test/fixtures/{valid → wave/valid}/valid_extensible_stereo_float_64_44100.wav +0 -0
- data/test/fixtures/wave/valid/valid_extensible_stereo_pcm_16_44100.wav +0 -0
- data/test/fixtures/wave/valid/valid_extensible_stereo_pcm_16_44100_center_right_speakers.wav +0 -0
- data/test/fixtures/wave/valid/valid_extensible_stereo_pcm_16_44100_more_speakers_than_channels.wav +0 -0
- data/test/fixtures/wave/valid/valid_extensible_stereo_pcm_16_44100_more_speakers_than_defined_by_spec.wav +0 -0
- data/test/fixtures/wave/valid/valid_extensible_stereo_pcm_16_44100_only_undefined_high_bit_speakers.wav +0 -0
- data/test/fixtures/wave/valid/valid_extensible_stereo_pcm_24_44100.wav +0 -0
- data/test/fixtures/wave/valid/valid_extensible_stereo_pcm_24_44100_incomplete_speaker_mapping.wav +0 -0
- data/test/fixtures/wave/valid/valid_extensible_stereo_pcm_24_44100_no_speaker_mapping.wav +0 -0
- data/test/fixtures/wave/valid/valid_extensible_stereo_pcm_32_44100.wav +0 -0
- data/test/fixtures/wave/valid/valid_extensible_stereo_pcm_8_44100.wav +0 -0
- data/test/fixtures/{valid → wave/valid}/valid_extensible_tri_float_32_44100.wav +0 -0
- data/test/fixtures/{valid → wave/valid}/valid_extensible_tri_float_64_44100.wav +0 -0
- data/test/fixtures/wave/valid/valid_extensible_tri_pcm_16_44100.wav +0 -0
- data/test/fixtures/wave/valid/valid_extensible_tri_pcm_16_44100_custom_speaker_mapping.wav +0 -0
- data/test/fixtures/wave/valid/valid_extensible_tri_pcm_24_44100.wav +0 -0
- data/test/fixtures/wave/valid/valid_extensible_tri_pcm_32_44100.wav +0 -0
- data/test/fixtures/wave/valid/valid_extensible_tri_pcm_8_44100.wav +0 -0
- data/test/fixtures/{valid → wave/valid}/valid_mono_float_32_44100.wav +0 -0
- data/test/fixtures/{valid → wave/valid}/valid_mono_float_64_44100.wav +0 -0
- data/test/fixtures/{valid → wave/valid}/valid_mono_pcm_16_44100.wav +0 -0
- data/test/fixtures/{valid → wave/valid}/valid_mono_pcm_16_44100_junk_chunk_with_padding_byte.wav +0 -0
- data/test/fixtures/wave/valid/valid_mono_pcm_16_44100_with_extension.wav +0 -0
- data/test/fixtures/{valid → wave/valid}/valid_mono_pcm_24_44100.wav +0 -0
- data/test/fixtures/{valid → wave/valid}/valid_mono_pcm_32_44100.wav +0 -0
- data/test/fixtures/{valid → wave/valid}/valid_mono_pcm_8_44100.wav +0 -0
- data/test/fixtures/{valid → wave/valid}/valid_mono_pcm_8_44100_with_padding_byte.wav +0 -0
- data/test/fixtures/{valid → wave/valid}/valid_stereo_float_32_44100.wav +0 -0
- data/test/fixtures/{valid → wave/valid}/valid_stereo_float_64_44100.wav +0 -0
- data/test/fixtures/{valid → wave/valid}/valid_stereo_pcm_16_44100.wav +0 -0
- data/test/fixtures/{valid → wave/valid}/valid_stereo_pcm_24_44100.wav +0 -0
- data/test/fixtures/{valid → wave/valid}/valid_stereo_pcm_32_44100.wav +0 -0
- data/test/fixtures/{valid → wave/valid}/valid_stereo_pcm_8_44100.wav +0 -0
- data/test/fixtures/{valid → wave/valid}/valid_tri_float_32_44100.wav +0 -0
- data/test/fixtures/{valid → wave/valid}/valid_tri_float_64_44100.wav +0 -0
- data/test/fixtures/{valid → wave/valid}/valid_tri_pcm_16_44100.wav +0 -0
- data/test/fixtures/{valid → wave/valid}/valid_tri_pcm_24_44100.wav +0 -0
- data/test/fixtures/{valid → wave/valid}/valid_tri_pcm_32_44100.wav +0 -0
- data/test/fixtures/{valid → wave/valid}/valid_tri_pcm_8_44100.wav +0 -0
- data/test/format_test.rb +189 -3
- data/test/reader_test.rb +179 -4
- data/test/unvalidated_format_test.rb +181 -6
- data/test/wavefile_io_test_helper.rb +11 -1
- data/test/writer_test.rb +246 -25
- metadata +70 -80
- data/test/fixtures/actual_output/total_duration_mono_float_32_44100.wav +0 -0
- data/test/fixtures/actual_output/total_duration_mono_float_64_44100.wav +0 -0
- data/test/fixtures/actual_output/total_duration_mono_pcm_16_44100.wav +0 -0
- data/test/fixtures/actual_output/total_duration_mono_pcm_24_44100.wav +0 -0
- data/test/fixtures/actual_output/total_duration_mono_pcm_32_44100.wav +0 -0
- data/test/fixtures/actual_output/total_duration_mono_pcm_8_44100.wav +0 -0
- data/test/fixtures/actual_output/total_duration_stereo_float_32_44100.wav +0 -0
- data/test/fixtures/actual_output/total_duration_stereo_float_64_44100.wav +0 -0
- data/test/fixtures/actual_output/total_duration_stereo_pcm_16_44100.wav +0 -0
- data/test/fixtures/actual_output/total_duration_stereo_pcm_24_44100.wav +0 -0
- data/test/fixtures/actual_output/total_duration_stereo_pcm_32_44100.wav +0 -0
- data/test/fixtures/actual_output/total_duration_stereo_pcm_8_44100.wav +0 -0
- data/test/fixtures/actual_output/total_duration_tri_float_32_44100.wav +0 -0
- data/test/fixtures/actual_output/total_duration_tri_float_64_44100.wav +0 -0
- data/test/fixtures/actual_output/total_duration_tri_pcm_16_44100.wav +0 -0
- data/test/fixtures/actual_output/total_duration_tri_pcm_24_44100.wav +0 -0
- data/test/fixtures/actual_output/total_duration_tri_pcm_32_44100.wav +0 -0
- data/test/fixtures/actual_output/total_duration_tri_pcm_8_44100.wav +0 -0
- data/test/fixtures/invalid/README.markdown +0 -10
- data/test/fixtures/unsupported/README.markdown +0 -6
- data/test/fixtures/unsupported/extensible_unsupported_subformat_guid.wav +0 -0
- data/test/fixtures/valid/README.markdown +0 -3
- data/test/fixtures/valid/valid_extensible_mono_pcm_16_44100.wav +0 -0
- data/test/fixtures/valid/valid_extensible_mono_pcm_24_44100.wav +0 -0
- data/test/fixtures/valid/valid_extensible_mono_pcm_32_44100.wav +0 -0
- data/test/fixtures/valid/valid_extensible_mono_pcm_8_44100.wav +0 -0
- data/test/fixtures/valid/valid_extensible_stereo_pcm_16_44100.wav +0 -0
- data/test/fixtures/valid/valid_extensible_stereo_pcm_24_44100.wav +0 -0
- data/test/fixtures/valid/valid_extensible_stereo_pcm_32_44100.wav +0 -0
- data/test/fixtures/valid/valid_extensible_stereo_pcm_8_44100.wav +0 -0
- data/test/fixtures/valid/valid_extensible_tri_pcm_16_44100.wav +0 -0
- data/test/fixtures/valid/valid_extensible_tri_pcm_24_44100.wav +0 -0
- data/test/fixtures/valid/valid_extensible_tri_pcm_32_44100.wav +0 -0
- data/test/fixtures/valid/valid_extensible_tri_pcm_8_44100.wav +0 -0
@@ -15,6 +15,7 @@ module WaveFile
|
|
15
15
|
@byte_rate = fields[:byte_rate]
|
16
16
|
@block_align = fields[:block_align]
|
17
17
|
@bits_per_sample = fields[:bits_per_sample]
|
18
|
+
@speaker_mapping = parse_speaker_mapping(fields[:speaker_mapping])
|
18
19
|
@valid_bits_per_sample = fields[:valid_bits_per_sample]
|
19
20
|
end
|
20
21
|
|
@@ -36,8 +37,7 @@ module WaveFile
|
|
36
37
|
if @valid_bits_per_sample
|
37
38
|
if @valid_bits_per_sample != @bits_per_sample
|
38
39
|
raise UnsupportedFormatError,
|
39
|
-
"Sample container size (#{@bits_per_sample}) and valid bits per sample (#{@valid_bits_per_sample}) "
|
40
|
-
"differ."
|
40
|
+
"Sample container size (#{@bits_per_sample}) and valid bits per sample (#{@valid_bits_per_sample}) differ."
|
41
41
|
end
|
42
42
|
|
43
43
|
bits_per_sample = @valid_bits_per_sample
|
@@ -47,7 +47,55 @@ module WaveFile
|
|
47
47
|
|
48
48
|
sample_format = "#{FORMAT_CODES.invert[audio_format_code]}_#{bits_per_sample}".to_sym
|
49
49
|
|
50
|
-
|
50
|
+
speaker_mapping = @speaker_mapping
|
51
|
+
if !speaker_mapping.nil?
|
52
|
+
speaker_mapping = speaker_mapping[0...channels]
|
53
|
+
end
|
54
|
+
|
55
|
+
Format.new(@channels, sample_format, @sample_rate, speaker_mapping: speaker_mapping)
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
# Internal
|
61
|
+
def parse_speaker_mapping(bit_field)
|
62
|
+
return nil if bit_field.nil?
|
63
|
+
|
64
|
+
mapping = []
|
65
|
+
speaker_index = 0
|
66
|
+
|
67
|
+
while speaker_index < SPEAKER_POSITIONS.length
|
68
|
+
if bit_field & (2 ** speaker_index) != 0
|
69
|
+
mapping << SPEAKER_POSITIONS[speaker_index]
|
70
|
+
end
|
71
|
+
|
72
|
+
speaker_index += 1
|
73
|
+
end
|
74
|
+
|
75
|
+
mapping.fill(:undefined, mapping.length, @channels - mapping.length)
|
76
|
+
mapping.freeze
|
51
77
|
end
|
78
|
+
|
79
|
+
# Internal
|
80
|
+
SPEAKER_POSITIONS = [
|
81
|
+
:front_left,
|
82
|
+
:front_right,
|
83
|
+
:front_center,
|
84
|
+
:low_frequency,
|
85
|
+
:back_left,
|
86
|
+
:back_right,
|
87
|
+
:front_left_of_center,
|
88
|
+
:front_right_of_center,
|
89
|
+
:back_center,
|
90
|
+
:side_left,
|
91
|
+
:side_right,
|
92
|
+
:top_center,
|
93
|
+
:top_front_left,
|
94
|
+
:top_front_center,
|
95
|
+
:top_front_right,
|
96
|
+
:top_back_left,
|
97
|
+
:top_back_center,
|
98
|
+
:top_back_right,
|
99
|
+
].freeze
|
52
100
|
end
|
53
101
|
end
|
data/lib/wavefile/writer.rb
CHANGED
@@ -12,7 +12,7 @@ module WaveFile
|
|
12
12
|
# end
|
13
13
|
#
|
14
14
|
# If no block is given, you'll need to manually close the Writer when done. The underlaying
|
15
|
-
# file will not be valid or playable until close is called.
|
15
|
+
# file will not be valid or playable until #close is called.
|
16
16
|
#
|
17
17
|
# writer = Writer.new("my_file.wav", Format.new(:mono, :pcm_16, 44100))
|
18
18
|
# # Write sample data here
|
@@ -82,9 +82,9 @@ module WaveFile
|
|
82
82
|
# writer.write(buffer)
|
83
83
|
# end
|
84
84
|
#
|
85
|
-
# Writer.new("my_file.wav", Format.new(:stereo, :pcm_16, 44100))
|
86
|
-
#
|
87
|
-
#
|
85
|
+
# writer = Writer.new("my_file.wav", Format.new(:stereo, :pcm_16, 44100))
|
86
|
+
# writer.write(buffer)
|
87
|
+
# writer.close
|
88
88
|
# # This will raise WriterClosedError because the Writer has already been closed.
|
89
89
|
# writer.write(buffer)
|
90
90
|
#
|
@@ -140,6 +140,7 @@ module WaveFile
|
|
140
140
|
# writer = Writer.new("my_file.wav", Format.new(:mono, :pcm_16, 44100))
|
141
141
|
# writer.write(buffer)
|
142
142
|
# writer.close
|
143
|
+
# writer.close # Does nothing, since Writer is already closed
|
143
144
|
#
|
144
145
|
# # Closing a Writer writing to an externally opened IO
|
145
146
|
# file = File.open("my_file.wav", "wb")
|
@@ -168,12 +169,10 @@ module WaveFile
|
|
168
169
|
# end
|
169
170
|
# # Writer is automatically closed here, because block has exited
|
170
171
|
#
|
171
|
-
# Returns nothing. Has side effect of closing the Writer.
|
172
|
-
#
|
172
|
+
# Returns nothing. Has side effect of closing the Writer. If the Writer is already
|
173
|
+
# closed, does nothing.
|
173
174
|
def close
|
174
|
-
if @closed
|
175
|
-
raise WriterClosedError
|
176
|
-
end
|
175
|
+
return if @closed
|
177
176
|
|
178
177
|
# The RIFF specification requires that each chunk be aligned to an even number of bytes,
|
179
178
|
# even if the byte count is an odd number. Therefore if an odd number of bytes has been
|
@@ -219,52 +218,106 @@ module WaveFile
|
|
219
218
|
|
220
219
|
private
|
221
220
|
|
222
|
-
# Internal
|
221
|
+
# Internal
|
222
|
+
# Padding value written to the end of chunks whose payload is an odd number of bytes. The RIFF
|
223
223
|
# specification requires that each chunk be aligned to an even number of bytes, even if the byte
|
224
224
|
# count is an odd number.
|
225
225
|
#
|
226
226
|
# See http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/Docs/riffmci.pdf, page 11.
|
227
227
|
EMPTY_BYTE = "\000" # :nodoc:
|
228
228
|
|
229
|
-
# Internal
|
229
|
+
# Internal
|
230
|
+
# The number of bytes at the beginning of a wave file before the sample data in the data chunk
|
230
231
|
# starts, assuming this canonical format:
|
231
232
|
#
|
232
233
|
# RIFF Chunk Header (12 bytes)
|
233
|
-
# Format Chunk (16 bytes for PCM, 18 bytes for floating point)
|
234
|
-
# FACT Chunk (0 bytes for PCM, 12 bytes for
|
234
|
+
# Format Chunk (16 bytes for PCM, 18 bytes for floating point, 40 bytes for WAVE_FORMAT_EXTENSIBLE)
|
235
|
+
# FACT Chunk (0 bytes for PCM, 12 bytes for any other format)
|
235
236
|
# Data Chunk Header (8 bytes)
|
236
237
|
#
|
237
238
|
# All wave files written by Writer use this canonical format.
|
238
|
-
CANONICAL_HEADER_BYTE_LENGTH = {:pcm => 36, :float => 50} # :nodoc:
|
239
|
+
CANONICAL_HEADER_BYTE_LENGTH = {:pcm => 36, :float => 50, :extensible => 72}.freeze # :nodoc:
|
240
|
+
|
241
|
+
# Internal
|
242
|
+
FORMAT_CHUNK_BYTE_LENGTH = {:pcm => 16, :float => 18, :extensible => 40}.freeze # :nodoc:
|
239
243
|
|
240
244
|
# Internal
|
241
|
-
|
245
|
+
SPEAKER_MAPPING_BIT_VALUES = {
|
246
|
+
undefined: 0,
|
247
|
+
front_left: 1,
|
248
|
+
front_right: 2,
|
249
|
+
front_center: 4,
|
250
|
+
low_frequency: 8,
|
251
|
+
back_left: 16,
|
252
|
+
back_right: 32,
|
253
|
+
front_left_of_center: 64,
|
254
|
+
front_right_of_center: 128,
|
255
|
+
back_center: 256,
|
256
|
+
side_left: 512,
|
257
|
+
side_right: 1024,
|
258
|
+
top_center: 2048,
|
259
|
+
top_front_left: 4096,
|
260
|
+
top_front_center: 8192,
|
261
|
+
top_front_right: 16384,
|
262
|
+
top_back_left: 32768,
|
263
|
+
top_back_center: 65536,
|
264
|
+
top_back_right: 131072,
|
265
|
+
}.freeze # :nodoc:
|
242
266
|
|
243
|
-
# Internal
|
267
|
+
# Internal
|
268
|
+
def pack_speaker_mapping(speaker_mapping)
|
269
|
+
speaker_mapping.inject(0) do |result, speaker|
|
270
|
+
result |= SPEAKER_MAPPING_BIT_VALUES[speaker]
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
# Internal
|
275
|
+
# Writes the RIFF chunk header, format chunk, and the header for the data chunk. After this
|
244
276
|
# method is called the file will be "queued up" and ready for writing actual sample data.
|
245
277
|
def write_header(sample_frame_count)
|
278
|
+
extensible = @format.channels > 2 ||
|
279
|
+
(@format.sample_format == :pcm && @format.bits_per_sample != 8 && @format.bits_per_sample != 16) ||
|
280
|
+
(@format.channels == 1 && @format.speaker_mapping != [:front_center]) ||
|
281
|
+
(@format.channels == 2 && @format.speaker_mapping != [:front_left, :front_right])
|
282
|
+
format_code = extensible ? :extensible : @format.sample_format
|
283
|
+
requires_fact_chunk = (format_code != :pcm)
|
284
|
+
|
246
285
|
sample_data_byte_count = sample_frame_count * @format.block_align
|
247
286
|
|
248
287
|
# Write the header for the RIFF chunk
|
249
288
|
header = CHUNK_IDS[:riff]
|
250
|
-
header += [CANONICAL_HEADER_BYTE_LENGTH[
|
289
|
+
header += [CANONICAL_HEADER_BYTE_LENGTH[format_code] + sample_data_byte_count].pack(UNSIGNED_INT_32)
|
251
290
|
header += WAVEFILE_FORMAT_CODE
|
252
291
|
|
253
292
|
# Write the format chunk
|
254
293
|
header += CHUNK_IDS[:format]
|
255
|
-
header += [FORMAT_CHUNK_BYTE_LENGTH[
|
256
|
-
header += [FORMAT_CODES[
|
294
|
+
header += [FORMAT_CHUNK_BYTE_LENGTH[format_code]].pack(UNSIGNED_INT_32)
|
295
|
+
header += [FORMAT_CODES[format_code]].pack(UNSIGNED_INT_16)
|
257
296
|
header += [@format.channels].pack(UNSIGNED_INT_16)
|
258
297
|
header += [@format.sample_rate].pack(UNSIGNED_INT_32)
|
259
298
|
header += [@format.byte_rate].pack(UNSIGNED_INT_32)
|
260
299
|
header += [@format.block_align].pack(UNSIGNED_INT_16)
|
261
300
|
header += [@format.bits_per_sample].pack(UNSIGNED_INT_16)
|
262
|
-
if
|
301
|
+
if format_code == :float
|
263
302
|
header += [0].pack(UNSIGNED_INT_16)
|
264
303
|
end
|
265
304
|
|
305
|
+
if extensible
|
306
|
+
header += [22].pack(UNSIGNED_INT_16)
|
307
|
+
header += [@format.bits_per_sample].pack(UNSIGNED_INT_16)
|
308
|
+
header += [pack_speaker_mapping(@format.speaker_mapping)].pack(UNSIGNED_INT_32)
|
309
|
+
|
310
|
+
if @format.sample_format == :pcm
|
311
|
+
format_guid = WaveFile::SUB_FORMAT_GUID_PCM
|
312
|
+
elsif @format.sample_format == :float
|
313
|
+
format_guid = WaveFile::SUB_FORMAT_GUID_FLOAT
|
314
|
+
end
|
315
|
+
|
316
|
+
header += format_guid
|
317
|
+
end
|
318
|
+
|
266
319
|
# Write the FACT chunk, if necessary
|
267
|
-
|
320
|
+
if requires_fact_chunk
|
268
321
|
header += CHUNK_IDS[:fact]
|
269
322
|
header += [4].pack(UNSIGNED_INT_32)
|
270
323
|
header += [sample_frame_count].pack(UNSIGNED_INT_32)
|
data/test/buffer_test.rb
CHANGED
@@ -1,9 +1,12 @@
|
|
1
1
|
require 'minitest/autorun'
|
2
2
|
require 'wavefile.rb'
|
3
|
+
require 'wavefile_io_test_helper.rb'
|
3
4
|
|
4
5
|
include WaveFile
|
5
6
|
|
6
7
|
class BufferTest < Minitest::Test
|
8
|
+
include WaveFileIOTestHelper
|
9
|
+
|
7
10
|
def test_convert
|
8
11
|
old_format = Format.new(:mono, :pcm_16, 44100)
|
9
12
|
new_format = Format.new(:stereo, :pcm_16, 22050)
|
@@ -38,7 +41,7 @@ class BufferTest < Minitest::Test
|
|
38
41
|
|
39
42
|
|
40
43
|
def test_convert_buffer_channels
|
41
|
-
|
44
|
+
SUPPORTED_BITS_PER_SAMPLE[:pcm].each do |bits_per_sample|
|
42
45
|
format_code = "pcm_#{bits_per_sample}".to_sym
|
43
46
|
|
44
47
|
[44100, 22050].each do |sample_rate|
|
@@ -83,7 +86,7 @@ class BufferTest < Minitest::Test
|
|
83
86
|
end
|
84
87
|
|
85
88
|
def test_convert_buffer_bits_per_sample_no_op
|
86
|
-
|
89
|
+
SUPPORTED_BITS_PER_SAMPLE[:pcm].each do |bits_per_sample|
|
87
90
|
format_code = "pcm_#{bits_per_sample}".to_sym
|
88
91
|
|
89
92
|
b = Buffer.new([0, 128, 255], Format.new(:mono, format_code, 44100))
|
@@ -143,7 +146,7 @@ class BufferTest < Minitest::Test
|
|
143
146
|
end
|
144
147
|
|
145
148
|
def test_convert_buffer_bits_per_sample_8_to_float
|
146
|
-
|
149
|
+
SUPPORTED_BITS_PER_SAMPLE[:float].each do |bits_per_sample|
|
147
150
|
float_format = "float_#{bits_per_sample}".to_sym
|
148
151
|
|
149
152
|
# Mono
|
@@ -211,7 +214,7 @@ class BufferTest < Minitest::Test
|
|
211
214
|
end
|
212
215
|
|
213
216
|
def test_convert_buffer_bits_per_sample_16_to_float
|
214
|
-
|
217
|
+
SUPPORTED_BITS_PER_SAMPLE[:float].each do |bits_per_sample|
|
215
218
|
float_format = "float_#{bits_per_sample}".to_sym
|
216
219
|
|
217
220
|
# Mono
|
@@ -282,7 +285,7 @@ class BufferTest < Minitest::Test
|
|
282
285
|
end
|
283
286
|
|
284
287
|
def test_convert_buffer_bits_per_sample_24_to_float
|
285
|
-
|
288
|
+
SUPPORTED_BITS_PER_SAMPLE[:float].each do |bits_per_sample|
|
286
289
|
float_format = "float_#{bits_per_sample}".to_sym
|
287
290
|
|
288
291
|
# Mono
|
@@ -354,7 +357,7 @@ class BufferTest < Minitest::Test
|
|
354
357
|
end
|
355
358
|
|
356
359
|
def test_convert_buffer_bits_per_sample_32_to_float
|
357
|
-
|
360
|
+
SUPPORTED_BITS_PER_SAMPLE[:float].each do |bits_per_sample|
|
358
361
|
float_format = "float_#{bits_per_sample}".to_sym
|
359
362
|
|
360
363
|
# Mono
|
@@ -375,7 +378,7 @@ class BufferTest < Minitest::Test
|
|
375
378
|
end
|
376
379
|
|
377
380
|
def test_convert_buffer_bits_per_sample_float_to_8
|
378
|
-
|
381
|
+
SUPPORTED_BITS_PER_SAMPLE[:float].each do |bits_per_sample|
|
379
382
|
float_format = "float_#{bits_per_sample}".to_sym
|
380
383
|
|
381
384
|
# Mono
|
@@ -395,7 +398,7 @@ class BufferTest < Minitest::Test
|
|
395
398
|
end
|
396
399
|
|
397
400
|
def test_convert_buffer_bits_per_sample_float_to_16
|
398
|
-
|
401
|
+
SUPPORTED_BITS_PER_SAMPLE[:float].each do |bits_per_sample|
|
399
402
|
float_format = "float_#{bits_per_sample}".to_sym
|
400
403
|
|
401
404
|
# Mono
|
@@ -415,7 +418,7 @@ class BufferTest < Minitest::Test
|
|
415
418
|
end
|
416
419
|
|
417
420
|
def test_convert_buffer_bits_per_sample_float_to_24
|
418
|
-
|
421
|
+
SUPPORTED_BITS_PER_SAMPLE[:float].each do |bits_per_sample|
|
419
422
|
float_format = "float_#{bits_per_sample}".to_sym
|
420
423
|
|
421
424
|
# Mono
|
@@ -435,7 +438,7 @@ class BufferTest < Minitest::Test
|
|
435
438
|
end
|
436
439
|
|
437
440
|
def test_convert_buffer_bits_per_sample_float_to_32
|
438
|
-
|
441
|
+
SUPPORTED_BITS_PER_SAMPLE[:float].each do |bits_per_sample|
|
439
442
|
float_format = "float_#{bits_per_sample}".to_sym
|
440
443
|
|
441
444
|
# Mono
|
@@ -7,13 +7,13 @@ include WaveFile::ChunkReaders
|
|
7
7
|
class FormatChunkReaderTest < Minitest::Test
|
8
8
|
def test_basic_pcm_no_extension
|
9
9
|
io = StringIO.new
|
10
|
-
io.
|
11
|
-
io.
|
12
|
-
io.
|
13
|
-
io.
|
14
|
-
io.
|
15
|
-
io.
|
16
|
-
io.
|
10
|
+
io.write([1].pack(UNSIGNED_INT_16)) # Audio format
|
11
|
+
io.write([2].pack(UNSIGNED_INT_16)) # Channels
|
12
|
+
io.write([44100].pack(UNSIGNED_INT_32)) # Sample rate
|
13
|
+
io.write([176400].pack(UNSIGNED_INT_32)) # Byte rate
|
14
|
+
io.write([4].pack(UNSIGNED_INT_16)) # Block align
|
15
|
+
io.write([16].pack(UNSIGNED_INT_16)) # Bits per sample
|
16
|
+
io.write("data") # Start of the next chunk
|
17
17
|
io.rewind
|
18
18
|
|
19
19
|
format_chunk_reader = FormatChunkReader.new(io, 16)
|
@@ -33,13 +33,13 @@ class FormatChunkReaderTest < Minitest::Test
|
|
33
33
|
# is still read properly.
|
34
34
|
def test_gibberish_no_extension
|
35
35
|
io = StringIO.new
|
36
|
-
io.
|
37
|
-
io.
|
38
|
-
io.
|
39
|
-
io.
|
40
|
-
io.
|
41
|
-
io.
|
42
|
-
io.
|
36
|
+
io.write([555].pack(UNSIGNED_INT_16)) # Audio format
|
37
|
+
io.write([111].pack(UNSIGNED_INT_16)) # Channels
|
38
|
+
io.write([12345].pack(UNSIGNED_INT_32)) # Sample rate
|
39
|
+
io.write([9].pack(UNSIGNED_INT_32)) # Byte rate
|
40
|
+
io.write([8000].pack(UNSIGNED_INT_16)) # Block align
|
41
|
+
io.write([23433].pack(UNSIGNED_INT_16)) # Bits per sample
|
42
|
+
io.write("data") # Start of the next chunk
|
43
43
|
io.rewind
|
44
44
|
|
45
45
|
format_chunk_reader = FormatChunkReader.new(io, 16)
|
@@ -57,14 +57,14 @@ class FormatChunkReaderTest < Minitest::Test
|
|
57
57
|
|
58
58
|
def test_basic_float_with_empty_extension
|
59
59
|
io = StringIO.new
|
60
|
-
io.
|
61
|
-
io.
|
62
|
-
io.
|
63
|
-
io.
|
64
|
-
io.
|
65
|
-
io.
|
66
|
-
io.
|
67
|
-
io.
|
60
|
+
io.write([3].pack(UNSIGNED_INT_16)) # Audio format
|
61
|
+
io.write([2].pack(UNSIGNED_INT_16)) # Channels
|
62
|
+
io.write([44100].pack(UNSIGNED_INT_32)) # Sample rate
|
63
|
+
io.write([352800].pack(UNSIGNED_INT_32)) # Byte rate
|
64
|
+
io.write([8].pack(UNSIGNED_INT_16)) # Block align
|
65
|
+
io.write([32].pack(UNSIGNED_INT_16)) # Bits per sample
|
66
|
+
io.write([0].pack(UNSIGNED_INT_16)) # Extension size
|
67
|
+
io.write("data") # Start of the next chunk
|
68
68
|
io.rewind
|
69
69
|
|
70
70
|
format_chunk_reader = FormatChunkReader.new(io, 18)
|
@@ -82,17 +82,17 @@ class FormatChunkReaderTest < Minitest::Test
|
|
82
82
|
|
83
83
|
def test_wave_format_extensible
|
84
84
|
io = StringIO.new
|
85
|
-
io.
|
86
|
-
io.
|
87
|
-
io.
|
88
|
-
io.
|
89
|
-
io.
|
90
|
-
io.
|
91
|
-
io.
|
92
|
-
io.
|
93
|
-
io.
|
94
|
-
io.
|
95
|
-
io.
|
85
|
+
io.write([65534].pack(UNSIGNED_INT_16)) # Audio format
|
86
|
+
io.write([2].pack(UNSIGNED_INT_16)) # Channels
|
87
|
+
io.write([44100].pack(UNSIGNED_INT_32)) # Sample rate
|
88
|
+
io.write([264600].pack(UNSIGNED_INT_32)) # Byte rate
|
89
|
+
io.write([6].pack(UNSIGNED_INT_16)) # Block align
|
90
|
+
io.write([24].pack(UNSIGNED_INT_16)) # Bits per sample
|
91
|
+
io.write([22].pack(UNSIGNED_INT_16)) # Extension size
|
92
|
+
io.write([20].pack(UNSIGNED_INT_16)) # Valid bits per sample
|
93
|
+
io.write([0].pack(UNSIGNED_INT_32)) # Channel mask
|
94
|
+
io.write(SUB_FORMAT_GUID_PCM)
|
95
|
+
io.write("data") # Start of the next chunk
|
96
96
|
io.rewind
|
97
97
|
|
98
98
|
format_chunk_reader = FormatChunkReader.new(io, 40)
|
@@ -113,13 +113,13 @@ class FormatChunkReaderTest < Minitest::Test
|
|
113
113
|
|
114
114
|
def test_chunk_size_too_small
|
115
115
|
io = StringIO.new
|
116
|
-
io.
|
117
|
-
io.
|
118
|
-
io.
|
119
|
-
io.
|
120
|
-
io.
|
121
|
-
io.
|
122
|
-
io.
|
116
|
+
io.write([1].pack(UNSIGNED_INT_16)) # Audio format
|
117
|
+
io.write([2].pack(UNSIGNED_INT_16)) # Channels
|
118
|
+
io.write([44100].pack(UNSIGNED_INT_32)) # Sample rate
|
119
|
+
io.write([176400].pack(UNSIGNED_INT_32)) # Byte rate
|
120
|
+
io.write([4].pack(UNSIGNED_INT_16)) # Block align
|
121
|
+
io.write([16].pack(UNSIGNED_INT_16)) # Bits per sample
|
122
|
+
io.write("data") # Start of the next chunk
|
123
123
|
io.rewind
|
124
124
|
|
125
125
|
format_chunk_reader = FormatChunkReader.new(io, 15)
|
File without changes
|