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
@@ -14,7 +14,7 @@ class FormatTest < Minitest::Test
14
14
  end
15
15
 
16
16
  def test_invalid_channels
17
- ["dsfsfsdf", :foo, 0, -1, 65536].each do |invalid_channels|
17
+ ["dsfsfsdf", :foo, 0, -1, 65536, 2.5, 2.0].each do |invalid_channels|
18
18
  assert_raises(InvalidFormatError) { Format.new(invalid_channels, :pcm_16, 44100) }
19
19
  end
20
20
  end
@@ -52,11 +52,197 @@ class FormatTest < Minitest::Test
52
52
  end
53
53
 
54
54
  def test_invalid_sample_rate
55
- ["dsfsfsdf", :foo, 0, -1, 4294967297].each do |invalid_sample_rate|
55
+ ["dsfsfsdf", :foo, 0, -1, 4294967297, 44100.5, 44100.0].each do |invalid_sample_rate|
56
56
  assert_raises(InvalidFormatError) { Format.new(:mono, :pcm_16, invalid_sample_rate) }
57
57
  end
58
58
  end
59
59
 
60
+ def test_no_speaker_mapping_set_in_constructor_mono
61
+ assert_equal([:front_center], Format.new(:mono, :pcm_8, 44100).speaker_mapping)
62
+ end
63
+
64
+ def test_no_speaker_mapping_set_in_constructor__stereo
65
+ assert_equal([:front_left, :front_right], Format.new(:stereo, :pcm_8, 44100).speaker_mapping)
66
+ end
67
+
68
+ def test_no_speaker_mapping_set_in_constructor_3_channel
69
+ assert_equal([:front_left, :front_right, :front_center], Format.new(3, :pcm_8, 44100).speaker_mapping)
70
+ end
71
+
72
+ def test_no_speaker_mapping_set_in_constructor_4_channel
73
+ assert_equal([:front_left, :front_right, :back_left, :back_right], Format.new(4, :pcm_8, 44100).speaker_mapping)
74
+ end
75
+
76
+ def test_no_speaker_mapping_set_in_constructor_5_channel
77
+ expected_speaker_mapping = [:front_left, :front_right, :front_center, :back_left, :back_right]
78
+
79
+ assert_equal(expected_speaker_mapping, Format.new(5, :pcm_8, 44100).speaker_mapping)
80
+ end
81
+
82
+ def test_no_speaker_mapping_set_in_constructor_6_channel
83
+ expected_speaker_mapping = [:front_left,
84
+ :front_right,
85
+ :front_center,
86
+ :low_frequency,
87
+ :back_left,
88
+ :back_right]
89
+
90
+ assert_equal(expected_speaker_mapping, Format.new(6, :pcm_8, 44100).speaker_mapping)
91
+ end
92
+
93
+ def test_no_speaker_mapping_set_in_constructor_7_channel
94
+ expected_speaker_mapping = [:front_left,
95
+ :front_right,
96
+ :front_center,
97
+ :low_frequency,
98
+ :back_center,
99
+ :side_left,
100
+ :side_right]
101
+
102
+ assert_equal(expected_speaker_mapping, Format.new(7, :pcm_8, 44100).speaker_mapping)
103
+ end
104
+
105
+ def test_no_speaker_mapping_set_in_constructor_8_channel
106
+ expected_speaker_mapping = [:front_left,
107
+ :front_right,
108
+ :front_center,
109
+ :low_frequency,
110
+ :back_left,
111
+ :back_right,
112
+ :front_left_of_center,
113
+ :front_right_of_center]
114
+
115
+ assert_equal(expected_speaker_mapping, Format.new(8, :pcm_8, 44100).speaker_mapping)
116
+ end
117
+
118
+ def test_no_speaker_mapping_set_in_constructor_9_channel
119
+ expected_speaker_mapping = [:front_left,
120
+ :front_right,
121
+ :front_center,
122
+ :low_frequency,
123
+ :back_left,
124
+ :back_right,
125
+ :front_left_of_center,
126
+ :front_right_of_center,
127
+ :back_center]
128
+
129
+ assert_equal(expected_speaker_mapping, Format.new(9, :pcm_8, 44100).speaker_mapping)
130
+ end
131
+
132
+ def test_no_speaker_mapping_set_in_constructor_18_channel
133
+ expected_speaker_mapping = [
134
+ :front_left,
135
+ :front_right,
136
+ :front_center,
137
+ :low_frequency,
138
+ :back_left,
139
+ :back_right,
140
+ :front_left_of_center,
141
+ :front_right_of_center,
142
+ :back_center,
143
+ :side_left,
144
+ :side_right,
145
+ :top_center,
146
+ :top_front_left,
147
+ :top_front_center,
148
+ :top_front_right,
149
+ :top_back_left,
150
+ :top_back_center,
151
+ :top_back_right,
152
+ ]
153
+
154
+ assert_equal(expected_speaker_mapping, Format.new(18, :pcm_8, 44100).speaker_mapping)
155
+ end
156
+
157
+ def test_no_speaker_mapping_set_in_constructor_20_channel
158
+ expected_speaker_mapping = [
159
+ :front_left,
160
+ :front_right,
161
+ :front_center,
162
+ :low_frequency,
163
+ :back_left,
164
+ :back_right,
165
+ :front_left_of_center,
166
+ :front_right_of_center,
167
+ :back_center,
168
+ :side_left,
169
+ :side_right,
170
+ :top_center,
171
+ :top_front_left,
172
+ :top_front_center,
173
+ :top_front_right,
174
+ :top_back_left,
175
+ :top_back_center,
176
+ :top_back_right,
177
+ :undefined,
178
+ :undefined,
179
+ ]
180
+
181
+ assert_equal(expected_speaker_mapping, Format.new(20, :pcm_8, 44100).speaker_mapping)
182
+ end
183
+
184
+ def test_defined_speaker_mapping_in_constructor
185
+ assert_equal([:front_left, :front_right], Format.new(:stereo, :pcm_8, 44100, speaker_mapping: [:front_left, :front_right]).speaker_mapping)
186
+ end
187
+
188
+ def test_defined_speaker_mapping_with_explicitly_undefined_channels_in_constructor
189
+ assert_equal([:front_left, :undefined, :undefined], Format.new(3, :pcm_8, 44100, speaker_mapping: [:front_left, :undefined, :undefined]).speaker_mapping)
190
+ end
191
+
192
+ def test_defined_speaker_mapping_with_implicitly_undefined_channels_in_constructor
193
+ assert_equal([:front_left, :undefined, :undefined], Format.new(3, :pcm_8, 44100, speaker_mapping: [:front_left]).speaker_mapping)
194
+ end
195
+
196
+ def test_extra_valid_speaker_mapping_fields_in_constructor
197
+ assert_raises(InvalidFormatError) do
198
+ Format.new(2, :pcm_8, 44100, speaker_mapping: [:front_left, :front_right, :front_center, :low_frequency])
199
+ end
200
+ end
201
+
202
+ def test_extra_undefined_speaker_mapping_fields_in_constructor
203
+ assert_raises(InvalidFormatError) do
204
+ Format.new(2, :pcm_8, 44100, speaker_mapping: [:front_left, :front_right, :undefined, :undefined])
205
+ end
206
+ end
207
+
208
+ def test_extra_invalid_speaker_mapping_fields_in_constructor
209
+ assert_raises(InvalidFormatError) do
210
+ Format.new(2, :pcm_8, 44100, speaker_mapping: [:front_left, :front_right, :gibberish, :what_is_this])
211
+ end
212
+ end
213
+
214
+ def test_speaker_mapping_is_frozen_copy
215
+ original_speaker_mapping = [:front_left, :front_right]
216
+
217
+ format = Format.new(:stereo, :pcm_16, 44100, speaker_mapping: original_speaker_mapping)
218
+
219
+ # Changing the original input array after constructing the `Format` doesn't change the `Format` speaker mapping
220
+ assert_equal([:front_left, :front_right], format.speaker_mapping)
221
+ original_speaker_mapping.push(:front_center)
222
+ assert_equal([:front_left, :front_right], format.speaker_mapping)
223
+
224
+ # Changing the underlaying Array should raise an error, since the Array should be frozen
225
+ assert_raises(RuntimeError) { format.speaker_mapping.push(:front_center) }
226
+ end
227
+
228
+ def test_invalid_speaker_mapping
229
+ mapping_with_invalid_speaker = [:front_left, :bad_speaker]
230
+ mapping_with_duplicate_speaker = [:front_left, :front_right, :front_left]
231
+ mapping_with_out_of_order_speakers = [:front_center, :front_left, :front_right]
232
+ mapping_with_out_of_order_speakers_2 = [:undefined, :front_left, :front_right]
233
+ mapping_with_out_of_order_speakers_3 = [:front_left, :undefined, :front_right]
234
+
235
+ assert_raises(InvalidFormatError) { Format.new(:stereo, :pcm_16, 44100, speaker_mapping: mapping_with_invalid_speaker) }
236
+ assert_raises(InvalidFormatError) { Format.new(3, :pcm_16, 44100, speaker_mapping: mapping_with_duplicate_speaker) }
237
+ assert_raises(InvalidFormatError) { Format.new(3, :pcm_16, 44100, speaker_mapping: mapping_with_out_of_order_speakers) }
238
+ assert_raises(InvalidFormatError) { Format.new(3, :pcm_16, 44100, speaker_mapping: mapping_with_out_of_order_speakers_2) }
239
+ assert_raises(InvalidFormatError) { Format.new(3, :pcm_16, 44100, speaker_mapping: mapping_with_out_of_order_speakers_3) }
240
+
241
+ ["dsfsfsdf", :foo, 5].each do |invalid_speaker_mapping|
242
+ assert_raises(InvalidFormatError) { Format.new(:mono, :pcm_16, 44100, speaker_mapping: invalid_speaker_mapping) }
243
+ end
244
+ end
245
+
60
246
  def test_byte_and_block_align
61
247
  [1, :mono].each do |one_channel|
62
248
  format = Format.new(one_channel, :pcm_8, 44100)
@@ -79,7 +265,7 @@ class FormatTest < Minitest::Test
79
265
 
80
266
  format = Format.new(one_channel, :float_64, 44100)
81
267
  assert_equal(352800, format.byte_rate)
82
- assert_equal(8, format.block_align)
268
+ assert_equal(8, format.block_align)
83
269
  end
84
270
 
85
271
  [2, :stereo].each do |two_channels|
@@ -7,7 +7,7 @@ include WaveFile
7
7
  class ReaderTest < Minitest::Test
8
8
  include WaveFileIOTestHelper
9
9
 
10
- FIXTURE_ROOT_PATH = "test/fixtures"
10
+ FIXTURE_ROOT_PATH = "test/fixtures/wave"
11
11
 
12
12
 
13
13
  def test_nonexistent_file
@@ -59,9 +59,11 @@ class ReaderTest < Minitest::Test
59
59
  assert_equal(2, reader.native_format.channels)
60
60
  assert_equal(20, reader.native_format.bits_per_sample)
61
61
  assert_equal(44100, reader.native_format.sample_rate)
62
+ assert_nil(reader.format.speaker_mapping)
62
63
  assert_equal(2, reader.format.channels)
63
64
  assert_equal(20, reader.format.bits_per_sample)
64
65
  assert_equal(44100, reader.format.sample_rate)
66
+ assert_nil(reader.format.speaker_mapping)
65
67
  assert_equal(false, reader.closed?)
66
68
  assert_equal(0, reader.current_sample_frame)
67
69
  assert_equal(2240, reader.total_sample_frames)
@@ -75,9 +77,11 @@ class ReaderTest < Minitest::Test
75
77
  assert_equal(2, reader.native_format.channels)
76
78
  assert_equal(20, reader.native_format.bits_per_sample)
77
79
  assert_equal(44100, reader.native_format.sample_rate)
80
+ assert_nil(reader.native_format.speaker_mapping)
78
81
  assert_equal(1, reader.format.channels)
79
82
  assert_equal(16, reader.format.bits_per_sample)
80
83
  assert_equal(22050, reader.format.sample_rate)
84
+ assert_equal([:front_center], reader.format.speaker_mapping)
81
85
  assert_equal(false, reader.closed?)
82
86
  assert_equal(0, reader.current_sample_frame)
83
87
  assert_equal(2240, reader.total_sample_frames)
@@ -198,9 +202,11 @@ class ReaderTest < Minitest::Test
198
202
  assert_equal(2, reader.native_format.channels)
199
203
  assert_equal(16, reader.native_format.bits_per_sample)
200
204
  assert_equal(44100, reader.native_format.sample_rate)
205
+ assert_equal([:front_left, :front_right], reader.native_format.speaker_mapping)
201
206
  assert_equal(2, reader.format.channels)
202
207
  assert_equal(16, reader.format.bits_per_sample)
203
208
  assert_equal(44100, reader.format.sample_rate)
209
+ assert_equal([:front_left, :front_right], reader.format.speaker_mapping)
204
210
  assert_equal(false, reader.closed?)
205
211
  assert_equal(0, reader.current_sample_frame)
206
212
  assert_equal(2240, reader.total_sample_frames)
@@ -216,6 +222,157 @@ class ReaderTest < Minitest::Test
216
222
  assert_equal(SQUARE_WAVE_CYCLE[channels][sample_format] * 24, buffers[2].samples)
217
223
  end
218
224
 
225
+ def test_read_extensible_no_speaker_mapping
226
+ reader = Reader.new(fixture("valid/valid_extensible_stereo_pcm_24_44100_no_speaker_mapping.wav"))
227
+
228
+ assert_equal(2, reader.native_format.channels)
229
+ assert_equal(24, reader.native_format.bits_per_sample)
230
+ assert_equal(44100, reader.native_format.sample_rate)
231
+ assert_equal([:undefined, :undefined], reader.native_format.speaker_mapping)
232
+ assert_equal(2, reader.format.channels)
233
+ assert_equal(24, reader.format.bits_per_sample)
234
+ assert_equal(44100, reader.format.sample_rate)
235
+ assert_equal([:undefined, :undefined], reader.format.speaker_mapping)
236
+ assert_equal(false, reader.closed?)
237
+ assert_equal(0, reader.current_sample_frame)
238
+ assert_equal(2240, reader.total_sample_frames)
239
+ assert_equal(true, reader.readable_format?)
240
+ reader.close
241
+
242
+ buffers = read_file("valid/valid_extensible_stereo_pcm_24_44100_no_speaker_mapping.wav", 1024)
243
+
244
+ assert_equal(3, buffers.length)
245
+ assert_equal([1024, 1024, 192], buffers.map {|buffer| buffer.samples.length })
246
+ assert_equal(SQUARE_WAVE_CYCLE[:stereo][:pcm_24] * 128, buffers[0].samples)
247
+ assert_equal(SQUARE_WAVE_CYCLE[:stereo][:pcm_24] * 128, buffers[1].samples)
248
+ assert_equal(SQUARE_WAVE_CYCLE[:stereo][:pcm_24] * 24, buffers[2].samples)
249
+ end
250
+
251
+ def test_read_extensible_more_speakers_than_channels
252
+ reader = Reader.new(fixture("valid/valid_extensible_stereo_pcm_16_44100_more_speakers_than_channels.wav"))
253
+
254
+ assert_equal(2, reader.native_format.channels)
255
+ assert_equal(16, reader.native_format.bits_per_sample)
256
+ assert_equal(44100, reader.native_format.sample_rate)
257
+ assert_equal([:front_left, :front_right, :front_center, :low_frequency], reader.native_format.speaker_mapping)
258
+ assert_equal(2, reader.format.channels)
259
+ assert_equal(16, reader.format.bits_per_sample)
260
+ assert_equal(44100, reader.format.sample_rate)
261
+ assert_equal([:front_left, :front_right], reader.format.speaker_mapping)
262
+ assert_equal(false, reader.closed?)
263
+ assert_equal(0, reader.current_sample_frame)
264
+ assert_equal(2240, reader.total_sample_frames)
265
+ assert_equal(true, reader.readable_format?)
266
+ reader.close
267
+
268
+ buffers = read_file("valid/valid_extensible_stereo_pcm_16_44100_more_speakers_than_channels.wav", 1024)
269
+
270
+ assert_equal(3, buffers.length)
271
+ assert_equal([1024, 1024, 192], buffers.map {|buffer| buffer.samples.length })
272
+ assert_equal(SQUARE_WAVE_CYCLE[:stereo][:pcm_16] * 128, buffers[0].samples)
273
+ assert_equal(SQUARE_WAVE_CYCLE[:stereo][:pcm_16] * 128, buffers[1].samples)
274
+ assert_equal(SQUARE_WAVE_CYCLE[:stereo][:pcm_16] * 24, buffers[2].samples)
275
+ end
276
+
277
+ def test_read_extensible_more_speakers_than_defined_by_spec
278
+ reader = Reader.new(fixture("valid/valid_extensible_stereo_pcm_16_44100_more_speakers_than_defined_by_spec.wav"))
279
+
280
+ assert_equal(2, reader.native_format.channels)
281
+ assert_equal(16, reader.native_format.bits_per_sample)
282
+ assert_equal(44100, reader.native_format.sample_rate)
283
+ # Extra bits for speakers beyond the first 18 are set in the file, but these bits should be ignored
284
+ assert_equal([:front_left,
285
+ :front_right,
286
+ :front_center,
287
+ :low_frequency,
288
+ :back_left,
289
+ :back_right,
290
+ :front_left_of_center,
291
+ :front_right_of_center,
292
+ :back_center,
293
+ :side_left,
294
+ :side_right,
295
+ :top_center,
296
+ :top_front_left,
297
+ :top_front_center,
298
+ :top_front_right,
299
+ :top_back_left,
300
+ :top_back_center,
301
+ :top_back_right], reader.native_format.speaker_mapping)
302
+ assert_equal(2, reader.format.channels)
303
+ assert_equal(16, reader.format.bits_per_sample)
304
+ assert_equal(44100, reader.format.sample_rate)
305
+ assert_equal([:front_left, :front_right], reader.format.speaker_mapping)
306
+ assert_equal(false, reader.closed?)
307
+ assert_equal(0, reader.current_sample_frame)
308
+ assert_equal(2240, reader.total_sample_frames)
309
+ assert_equal(true, reader.readable_format?)
310
+ reader.close
311
+
312
+ buffers = read_file("valid/valid_extensible_stereo_pcm_16_44100_more_speakers_than_defined_by_spec.wav", 1024)
313
+
314
+ assert_equal(3, buffers.length)
315
+ assert_equal([1024, 1024, 192], buffers.map {|buffer| buffer.samples.length })
316
+ assert_equal(SQUARE_WAVE_CYCLE[:stereo][:pcm_16] * 128, buffers[0].samples)
317
+ assert_equal(SQUARE_WAVE_CYCLE[:stereo][:pcm_16] * 128, buffers[1].samples)
318
+ assert_equal(SQUARE_WAVE_CYCLE[:stereo][:pcm_16] * 24, buffers[2].samples)
319
+ end
320
+
321
+ def test_read_extensible_only_undefined_high_bit_speakers
322
+ reader = Reader.new(fixture("valid/valid_extensible_stereo_pcm_16_44100_only_undefined_high_bit_speakers.wav"))
323
+
324
+ assert_equal(2, reader.native_format.channels)
325
+ assert_equal(16, reader.native_format.bits_per_sample)
326
+ assert_equal(44100, reader.native_format.sample_rate)
327
+ assert_equal([:undefined, :undefined], reader.native_format.speaker_mapping)
328
+ assert_equal(2, reader.format.channels)
329
+ assert_equal(16, reader.format.bits_per_sample)
330
+ assert_equal(44100, reader.format.sample_rate)
331
+ assert_equal([:undefined, :undefined], reader.format.speaker_mapping)
332
+ assert_equal(false, reader.closed?)
333
+ assert_equal(0, reader.current_sample_frame)
334
+ assert_equal(2240, reader.total_sample_frames)
335
+ assert_equal(true, reader.readable_format?)
336
+ reader.close
337
+
338
+ buffers = read_file("valid/valid_extensible_stereo_pcm_16_44100_only_undefined_high_bit_speakers.wav", 1024)
339
+
340
+ assert_equal(3, buffers.length)
341
+ assert_equal([1024, 1024, 192], buffers.map {|buffer| buffer.samples.length })
342
+ assert_equal(SQUARE_WAVE_CYCLE[:stereo][:pcm_16] * 128, buffers[0].samples)
343
+ assert_equal(SQUARE_WAVE_CYCLE[:stereo][:pcm_16] * 128, buffers[1].samples)
344
+ assert_equal(SQUARE_WAVE_CYCLE[:stereo][:pcm_16] * 24, buffers[2].samples)
345
+ end
346
+
347
+ def test_read_non_extensible_that_has_extension
348
+ reader = Reader.new(fixture("valid/valid_mono_pcm_16_44100_with_extension.wav"))
349
+
350
+ assert_equal(1, reader.native_format.audio_format)
351
+ assert_equal(1, reader.native_format.channels)
352
+ assert_equal(16, reader.native_format.bits_per_sample)
353
+ assert_equal(44100, reader.native_format.sample_rate)
354
+ assert_nil(reader.native_format.speaker_mapping)
355
+ assert_nil(reader.native_format.sub_audio_format_guid)
356
+ assert_nil(reader.native_format.valid_bits_per_sample)
357
+ assert_equal(1, reader.format.channels)
358
+ assert_equal(16, reader.format.bits_per_sample)
359
+ assert_equal(44100, reader.format.sample_rate)
360
+ assert_equal([:front_center], reader.format.speaker_mapping)
361
+ assert_equal(false, reader.closed?)
362
+ assert_equal(0, reader.current_sample_frame)
363
+ assert_equal(2240, reader.total_sample_frames)
364
+ assert_equal(true, reader.readable_format?)
365
+ reader.close
366
+
367
+ buffers = read_file("valid/valid_mono_pcm_16_44100_with_extension.wav", 1024)
368
+
369
+ assert_equal(3, buffers.length)
370
+ assert_equal([1024, 1024, 192], buffers.map {|buffer| buffer.samples.length })
371
+ assert_equal(SQUARE_WAVE_CYCLE[:mono][:pcm_16] * 128, buffers[0].samples)
372
+ assert_equal(SQUARE_WAVE_CYCLE[:mono][:pcm_16] * 128, buffers[1].samples)
373
+ assert_equal(SQUARE_WAVE_CYCLE[:mono][:pcm_16] * 24, buffers[2].samples)
374
+ end
375
+
219
376
  def test_read_with_format_conversion
220
377
  buffers = read_file("valid/valid_mono_pcm_16_44100.wav", 1024, Format.new(:stereo, :pcm_8, 22100))
221
378
 
@@ -309,6 +466,21 @@ class ReaderTest < Minitest::Test
309
466
  assert_equal(2239, reader.total_sample_frames)
310
467
  end
311
468
 
469
+ def test_each_buffer_inside_reader_block
470
+ buffers = []
471
+
472
+ # This should not raise a ReaderClosedError
473
+ Reader.new(fixture("valid/valid_mono_pcm_16_44100.wav")) do |reader|
474
+ reader.each_buffer(1024) {|buffer| buffers << buffer }
475
+ end
476
+
477
+ assert_equal(3, buffers.length)
478
+ assert_equal([1024, 1024, 192], buffers.map {|buffer| buffer.samples.length })
479
+ assert_equal(SQUARE_WAVE_CYCLE[:mono][:pcm_16] * 128, buffers[0].samples)
480
+ assert_equal(SQUARE_WAVE_CYCLE[:mono][:pcm_16] * 128, buffers[1].samples)
481
+ assert_equal(SQUARE_WAVE_CYCLE[:mono][:pcm_16] * 24, buffers[2].samples)
482
+ end
483
+
312
484
  def test_read_non_data_chunk_with_padding_byte
313
485
  # This fixture file contains a JUNK chunk with an odd size, aligned to an even number of
314
486
  # bytes via an appended padding byte. If the padding byte is not taken into account, this
@@ -325,6 +497,9 @@ class ReaderTest < Minitest::Test
325
497
  assert_equal(false, reader.closed?)
326
498
  reader.close
327
499
  assert(reader.closed?)
500
+ # Closing an already closed Reader should be a no-op
501
+ reader.close
502
+ assert(reader.closed?)
328
503
 
329
504
  # For Reader.each_buffer
330
505
  reader = Reader.new(fixture("valid/valid_mono_pcm_16_44100.wav"))
@@ -367,7 +542,7 @@ class ReaderTest < Minitest::Test
367
542
  def test_sample_counts_manual_reads
368
543
  exhaustively_test do |format_chunk_format, channels, sample_format|
369
544
  reader = Reader.new(fixture("valid/valid_#{format_chunk_format}#{channels}_#{sample_format}_44100.wav"))
370
-
545
+
371
546
  assert_equal(0, reader.current_sample_frame)
372
547
  assert_equal(2240, reader.total_sample_frames)
373
548
  test_duration({:hours => 0, :minutes => 0, :seconds => 0, :milliseconds => 50, :sample_count => 2240},
@@ -393,7 +568,7 @@ class ReaderTest < Minitest::Test
393
568
  assert_equal(2240, reader.total_sample_frames)
394
569
  test_duration({:hours => 0, :minutes => 0, :seconds => 0, :milliseconds => 50, :sample_count => 2240},
395
570
  reader.total_duration)
396
-
571
+
397
572
 
398
573
  reader.close
399
574
  assert_equal(2240, reader.current_sample_frame)
@@ -419,7 +594,7 @@ class ReaderTest < Minitest::Test
419
594
  assert_equal(expected_result, reader.current_sample_frame)
420
595
  assert_equal(2240, reader.total_sample_frames)
421
596
  end
422
-
597
+
423
598
  assert_equal(2240, reader.current_sample_frame)
424
599
  assert_equal(2240, reader.total_sample_frames)
425
600
  end