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.
Files changed (117) hide show
  1. checksums.yaml +5 -5
  2. data/LICENSE +1 -1
  3. data/README.markdown +33 -28
  4. data/Rakefile +2 -2
  5. data/lib/wavefile.rb +5 -5
  6. data/lib/wavefile/chunk_readers/format_chunk_reader.rb +1 -1
  7. data/lib/wavefile/duration.rb +1 -1
  8. data/lib/wavefile/format.rb +120 -29
  9. data/lib/wavefile/reader.rb +18 -16
  10. data/lib/wavefile/unvalidated_format.rb +51 -3
  11. data/lib/wavefile/writer.rb +74 -21
  12. data/test/buffer_test.rb +13 -10
  13. data/test/chunk_readers/format_chunk_reader_test.rb +40 -40
  14. data/test/fixtures/{invalid → wave/invalid}/bad_riff_header.wav +0 -0
  15. data/test/fixtures/{invalid → wave/invalid}/bad_wavefile_format.wav +0 -0
  16. data/test/fixtures/{invalid → wave/invalid}/empty.wav +0 -0
  17. data/test/fixtures/{invalid → wave/invalid}/empty_format_chunk.wav +0 -0
  18. data/test/fixtures/{invalid → wave/invalid}/incomplete_riff_header.wav +0 -0
  19. data/test/fixtures/{invalid → wave/invalid}/insufficient_format_chunk.wav +0 -0
  20. data/test/fixtures/{invalid → wave/invalid}/no_data_chunk.wav +0 -0
  21. data/test/fixtures/{invalid → wave/invalid}/no_format_chunk.wav +0 -0
  22. data/test/fixtures/{unsupported → wave/unsupported}/bad_audio_format.wav +0 -0
  23. data/test/fixtures/{unsupported → wave/unsupported}/bad_channel_count.wav +0 -0
  24. data/test/fixtures/{unsupported → wave/unsupported}/bad_sample_rate.wav +0 -0
  25. data/test/fixtures/{unsupported → wave/unsupported}/extensible_container_size_bigger_than_sample_size.wav +0 -0
  26. data/test/fixtures/wave/unsupported/extensible_unsupported_subformat_guid.wav +0 -0
  27. data/test/fixtures/{unsupported → wave/unsupported}/unsupported_audio_format.wav +0 -0
  28. data/test/fixtures/{unsupported → wave/unsupported}/unsupported_bits_per_sample.wav +0 -0
  29. data/test/fixtures/{valid → wave/valid}/no_samples.wav +0 -0
  30. data/test/fixtures/wave/valid/valid_extensible_20_pcm_16_44100_speaker_mapping_overflow.wav +0 -0
  31. data/test/fixtures/{valid → wave/valid}/valid_extensible_mono_float_32_44100.wav +0 -0
  32. data/test/fixtures/{valid → wave/valid}/valid_extensible_mono_float_64_44100.wav +0 -0
  33. data/test/fixtures/wave/valid/valid_extensible_mono_pcm_16_44100.wav +0 -0
  34. data/test/fixtures/wave/valid/valid_extensible_mono_pcm_16_44100_non_default_speaker_mapping.wav +0 -0
  35. data/test/fixtures/wave/valid/valid_extensible_mono_pcm_24_44100.wav +0 -0
  36. data/test/fixtures/wave/valid/valid_extensible_mono_pcm_32_44100.wav +0 -0
  37. data/test/fixtures/wave/valid/valid_extensible_mono_pcm_8_44100.wav +0 -0
  38. data/test/fixtures/{valid → wave/valid}/valid_extensible_stereo_float_32_44100.wav +0 -0
  39. data/test/fixtures/{valid → wave/valid}/valid_extensible_stereo_float_64_44100.wav +0 -0
  40. data/test/fixtures/wave/valid/valid_extensible_stereo_pcm_16_44100.wav +0 -0
  41. data/test/fixtures/wave/valid/valid_extensible_stereo_pcm_16_44100_center_right_speakers.wav +0 -0
  42. data/test/fixtures/wave/valid/valid_extensible_stereo_pcm_16_44100_more_speakers_than_channels.wav +0 -0
  43. data/test/fixtures/wave/valid/valid_extensible_stereo_pcm_16_44100_more_speakers_than_defined_by_spec.wav +0 -0
  44. data/test/fixtures/wave/valid/valid_extensible_stereo_pcm_16_44100_only_undefined_high_bit_speakers.wav +0 -0
  45. data/test/fixtures/wave/valid/valid_extensible_stereo_pcm_24_44100.wav +0 -0
  46. data/test/fixtures/wave/valid/valid_extensible_stereo_pcm_24_44100_incomplete_speaker_mapping.wav +0 -0
  47. data/test/fixtures/wave/valid/valid_extensible_stereo_pcm_24_44100_no_speaker_mapping.wav +0 -0
  48. data/test/fixtures/wave/valid/valid_extensible_stereo_pcm_32_44100.wav +0 -0
  49. data/test/fixtures/wave/valid/valid_extensible_stereo_pcm_8_44100.wav +0 -0
  50. data/test/fixtures/{valid → wave/valid}/valid_extensible_tri_float_32_44100.wav +0 -0
  51. data/test/fixtures/{valid → wave/valid}/valid_extensible_tri_float_64_44100.wav +0 -0
  52. data/test/fixtures/wave/valid/valid_extensible_tri_pcm_16_44100.wav +0 -0
  53. data/test/fixtures/wave/valid/valid_extensible_tri_pcm_16_44100_custom_speaker_mapping.wav +0 -0
  54. data/test/fixtures/wave/valid/valid_extensible_tri_pcm_24_44100.wav +0 -0
  55. data/test/fixtures/wave/valid/valid_extensible_tri_pcm_32_44100.wav +0 -0
  56. data/test/fixtures/wave/valid/valid_extensible_tri_pcm_8_44100.wav +0 -0
  57. data/test/fixtures/{valid → wave/valid}/valid_mono_float_32_44100.wav +0 -0
  58. data/test/fixtures/{valid → wave/valid}/valid_mono_float_64_44100.wav +0 -0
  59. data/test/fixtures/{valid → wave/valid}/valid_mono_pcm_16_44100.wav +0 -0
  60. data/test/fixtures/{valid → wave/valid}/valid_mono_pcm_16_44100_junk_chunk_with_padding_byte.wav +0 -0
  61. data/test/fixtures/wave/valid/valid_mono_pcm_16_44100_with_extension.wav +0 -0
  62. data/test/fixtures/{valid → wave/valid}/valid_mono_pcm_24_44100.wav +0 -0
  63. data/test/fixtures/{valid → wave/valid}/valid_mono_pcm_32_44100.wav +0 -0
  64. data/test/fixtures/{valid → wave/valid}/valid_mono_pcm_8_44100.wav +0 -0
  65. data/test/fixtures/{valid → wave/valid}/valid_mono_pcm_8_44100_with_padding_byte.wav +0 -0
  66. data/test/fixtures/{valid → wave/valid}/valid_stereo_float_32_44100.wav +0 -0
  67. data/test/fixtures/{valid → wave/valid}/valid_stereo_float_64_44100.wav +0 -0
  68. data/test/fixtures/{valid → wave/valid}/valid_stereo_pcm_16_44100.wav +0 -0
  69. data/test/fixtures/{valid → wave/valid}/valid_stereo_pcm_24_44100.wav +0 -0
  70. data/test/fixtures/{valid → wave/valid}/valid_stereo_pcm_32_44100.wav +0 -0
  71. data/test/fixtures/{valid → wave/valid}/valid_stereo_pcm_8_44100.wav +0 -0
  72. data/test/fixtures/{valid → wave/valid}/valid_tri_float_32_44100.wav +0 -0
  73. data/test/fixtures/{valid → wave/valid}/valid_tri_float_64_44100.wav +0 -0
  74. data/test/fixtures/{valid → wave/valid}/valid_tri_pcm_16_44100.wav +0 -0
  75. data/test/fixtures/{valid → wave/valid}/valid_tri_pcm_24_44100.wav +0 -0
  76. data/test/fixtures/{valid → wave/valid}/valid_tri_pcm_32_44100.wav +0 -0
  77. data/test/fixtures/{valid → wave/valid}/valid_tri_pcm_8_44100.wav +0 -0
  78. data/test/format_test.rb +189 -3
  79. data/test/reader_test.rb +179 -4
  80. data/test/unvalidated_format_test.rb +181 -6
  81. data/test/wavefile_io_test_helper.rb +11 -1
  82. data/test/writer_test.rb +246 -25
  83. metadata +70 -80
  84. data/test/fixtures/actual_output/total_duration_mono_float_32_44100.wav +0 -0
  85. data/test/fixtures/actual_output/total_duration_mono_float_64_44100.wav +0 -0
  86. data/test/fixtures/actual_output/total_duration_mono_pcm_16_44100.wav +0 -0
  87. data/test/fixtures/actual_output/total_duration_mono_pcm_24_44100.wav +0 -0
  88. data/test/fixtures/actual_output/total_duration_mono_pcm_32_44100.wav +0 -0
  89. data/test/fixtures/actual_output/total_duration_mono_pcm_8_44100.wav +0 -0
  90. data/test/fixtures/actual_output/total_duration_stereo_float_32_44100.wav +0 -0
  91. data/test/fixtures/actual_output/total_duration_stereo_float_64_44100.wav +0 -0
  92. data/test/fixtures/actual_output/total_duration_stereo_pcm_16_44100.wav +0 -0
  93. data/test/fixtures/actual_output/total_duration_stereo_pcm_24_44100.wav +0 -0
  94. data/test/fixtures/actual_output/total_duration_stereo_pcm_32_44100.wav +0 -0
  95. data/test/fixtures/actual_output/total_duration_stereo_pcm_8_44100.wav +0 -0
  96. data/test/fixtures/actual_output/total_duration_tri_float_32_44100.wav +0 -0
  97. data/test/fixtures/actual_output/total_duration_tri_float_64_44100.wav +0 -0
  98. data/test/fixtures/actual_output/total_duration_tri_pcm_16_44100.wav +0 -0
  99. data/test/fixtures/actual_output/total_duration_tri_pcm_24_44100.wav +0 -0
  100. data/test/fixtures/actual_output/total_duration_tri_pcm_32_44100.wav +0 -0
  101. data/test/fixtures/actual_output/total_duration_tri_pcm_8_44100.wav +0 -0
  102. data/test/fixtures/invalid/README.markdown +0 -10
  103. data/test/fixtures/unsupported/README.markdown +0 -6
  104. data/test/fixtures/unsupported/extensible_unsupported_subformat_guid.wav +0 -0
  105. data/test/fixtures/valid/README.markdown +0 -3
  106. data/test/fixtures/valid/valid_extensible_mono_pcm_16_44100.wav +0 -0
  107. data/test/fixtures/valid/valid_extensible_mono_pcm_24_44100.wav +0 -0
  108. data/test/fixtures/valid/valid_extensible_mono_pcm_32_44100.wav +0 -0
  109. data/test/fixtures/valid/valid_extensible_mono_pcm_8_44100.wav +0 -0
  110. data/test/fixtures/valid/valid_extensible_stereo_pcm_16_44100.wav +0 -0
  111. data/test/fixtures/valid/valid_extensible_stereo_pcm_24_44100.wav +0 -0
  112. data/test/fixtures/valid/valid_extensible_stereo_pcm_32_44100.wav +0 -0
  113. data/test/fixtures/valid/valid_extensible_stereo_pcm_8_44100.wav +0 -0
  114. data/test/fixtures/valid/valid_extensible_tri_pcm_16_44100.wav +0 -0
  115. data/test/fixtures/valid/valid_extensible_tri_pcm_24_44100.wav +0 -0
  116. data/test/fixtures/valid/valid_extensible_tri_pcm_32_44100.wav +0 -0
  117. 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
- Format.new(@channels, sample_format, @sample_rate)
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
@@ -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)) do |writer|
86
- # writer.write(buffer)
87
- # end
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
- # Raises WriterClosedError if the Writer is already closed.
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: Padding value written to the end of chunks whose payload is an odd number of bytes. The RIFF
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: The number of bytes at the beginning of a wave file before the sample data in the data chunk
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 floating point)
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
- FORMAT_CHUNK_BYTE_LENGTH = {:pcm => 16, :float => 18} # :nodoc:
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: Writes the RIFF chunk header, format chunk, and the header for the data chunk. After this
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[@format.sample_format] + sample_data_byte_count].pack(UNSIGNED_INT_32)
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[@format.sample_format]].pack(UNSIGNED_INT_32)
256
- header += [FORMAT_CODES[@format.sample_format]].pack(UNSIGNED_INT_16)
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 @format.sample_format == :float
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
- unless @format.sample_format == :pcm
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)
@@ -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
- Format::SUPPORTED_BITS_PER_SAMPLE[:pcm].each do |bits_per_sample|
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
- Format::SUPPORTED_BITS_PER_SAMPLE[:pcm].each do |bits_per_sample|
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
- Format::SUPPORTED_BITS_PER_SAMPLE[:float].each do |bits_per_sample|
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
- Format::SUPPORTED_BITS_PER_SAMPLE[:float].each do |bits_per_sample|
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
- Format::SUPPORTED_BITS_PER_SAMPLE[:float].each do |bits_per_sample|
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
- Format::SUPPORTED_BITS_PER_SAMPLE[:float].each do |bits_per_sample|
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
- Format::SUPPORTED_BITS_PER_SAMPLE[:float].each do |bits_per_sample|
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
- Format::SUPPORTED_BITS_PER_SAMPLE[:float].each do |bits_per_sample|
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
- Format::SUPPORTED_BITS_PER_SAMPLE[:float].each do |bits_per_sample|
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
- Format::SUPPORTED_BITS_PER_SAMPLE[:float].each do |bits_per_sample|
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.syswrite([1].pack(UNSIGNED_INT_16)) # Audio format
11
- io.syswrite([2].pack(UNSIGNED_INT_16)) # Channels
12
- io.syswrite([44100].pack(UNSIGNED_INT_32)) # Sample rate
13
- io.syswrite([176400].pack(UNSIGNED_INT_32)) # Byte rate
14
- io.syswrite([4].pack(UNSIGNED_INT_16)) # Block align
15
- io.syswrite([16].pack(UNSIGNED_INT_16)) # Bits per sample
16
- io.syswrite("data") # Start of the next chunk
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.syswrite([555].pack(UNSIGNED_INT_16)) # Audio format
37
- io.syswrite([111].pack(UNSIGNED_INT_16)) # Channels
38
- io.syswrite([12345].pack(UNSIGNED_INT_32)) # Sample rate
39
- io.syswrite([9].pack(UNSIGNED_INT_32)) # Byte rate
40
- io.syswrite([8000].pack(UNSIGNED_INT_16)) # Block align
41
- io.syswrite([23433].pack(UNSIGNED_INT_16)) # Bits per sample
42
- io.syswrite("data") # Start of the next chunk
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.syswrite([3].pack(UNSIGNED_INT_16)) # Audio format
61
- io.syswrite([2].pack(UNSIGNED_INT_16)) # Channels
62
- io.syswrite([44100].pack(UNSIGNED_INT_32)) # Sample rate
63
- io.syswrite([352800].pack(UNSIGNED_INT_32)) # Byte rate
64
- io.syswrite([8].pack(UNSIGNED_INT_16)) # Block align
65
- io.syswrite([32].pack(UNSIGNED_INT_16)) # Bits per sample
66
- io.syswrite([0].pack(UNSIGNED_INT_16)) # Extension size
67
- io.syswrite("data") # Start of the next chunk
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.syswrite([65534].pack(UNSIGNED_INT_16)) # Audio format
86
- io.syswrite([2].pack(UNSIGNED_INT_16)) # Channels
87
- io.syswrite([44100].pack(UNSIGNED_INT_32)) # Sample rate
88
- io.syswrite([264600].pack(UNSIGNED_INT_32)) # Byte rate
89
- io.syswrite([6].pack(UNSIGNED_INT_16)) # Block align
90
- io.syswrite([24].pack(UNSIGNED_INT_16)) # Bits per sample
91
- io.syswrite([22].pack(UNSIGNED_INT_16)) # Extension size
92
- io.syswrite([20].pack(UNSIGNED_INT_16)) # Valid bits per sample
93
- io.syswrite([0].pack(UNSIGNED_INT_32)) # Channel mask
94
- io.syswrite(SUB_FORMAT_GUID_PCM)
95
- io.syswrite("data") # Start of the next chunk
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.syswrite([1].pack(UNSIGNED_INT_16)) # Audio format
117
- io.syswrite([2].pack(UNSIGNED_INT_16)) # Channels
118
- io.syswrite([44100].pack(UNSIGNED_INT_32)) # Sample rate
119
- io.syswrite([176400].pack(UNSIGNED_INT_32)) # Byte rate
120
- io.syswrite([4].pack(UNSIGNED_INT_16)) # Block align
121
- io.syswrite([16].pack(UNSIGNED_INT_16)) # Bits per sample
122
- io.syswrite("data") # Start of the next chunk
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)