wavefile 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +2 -2
  3. data/README.markdown +67 -47
  4. data/Rakefile +23 -0
  5. data/lib/wavefile.rb +4 -2
  6. data/lib/wavefile/buffer.rb +40 -25
  7. data/lib/wavefile/chunk_readers.rb +7 -1
  8. data/lib/wavefile/chunk_readers/base_chunk_reader.rb +10 -0
  9. data/lib/wavefile/chunk_readers/data_chunk_reader.rb +77 -0
  10. data/lib/wavefile/chunk_readers/format_chunk_reader.rb +59 -0
  11. data/lib/wavefile/chunk_readers/generic_chunk_reader.rb +15 -0
  12. data/lib/wavefile/chunk_readers/riff_chunk_reader.rb +19 -0
  13. data/lib/wavefile/chunk_readers/riff_reader.rb +67 -0
  14. data/lib/wavefile/duration.rb +47 -12
  15. data/lib/wavefile/format.rb +44 -23
  16. data/lib/wavefile/reader.rb +101 -111
  17. data/lib/wavefile/unvalidated_format.rb +36 -6
  18. data/lib/wavefile/writer.rb +138 -40
  19. data/test/buffer_test.rb +21 -17
  20. data/test/chunk_readers/format_chunk_reader_test.rb +130 -0
  21. data/test/duration_test.rb +42 -1
  22. data/test/fixtures/actual_output/total_duration_mono_float_32_44100.wav +0 -0
  23. data/test/fixtures/actual_output/total_duration_mono_float_64_44100.wav +0 -0
  24. data/test/fixtures/actual_output/total_duration_mono_pcm_16_44100.wav +0 -0
  25. data/test/fixtures/actual_output/total_duration_mono_pcm_24_44100.wav +0 -0
  26. data/test/fixtures/actual_output/total_duration_mono_pcm_32_44100.wav +0 -0
  27. data/test/fixtures/actual_output/total_duration_mono_pcm_8_44100.wav +0 -0
  28. data/test/fixtures/actual_output/total_duration_stereo_float_32_44100.wav +0 -0
  29. data/test/fixtures/actual_output/total_duration_stereo_float_64_44100.wav +0 -0
  30. data/test/fixtures/actual_output/total_duration_stereo_pcm_16_44100.wav +0 -0
  31. data/test/fixtures/actual_output/total_duration_stereo_pcm_24_44100.wav +0 -0
  32. data/test/fixtures/actual_output/total_duration_stereo_pcm_32_44100.wav +0 -0
  33. data/test/fixtures/actual_output/total_duration_stereo_pcm_8_44100.wav +0 -0
  34. data/test/fixtures/actual_output/total_duration_tri_float_32_44100.wav +0 -0
  35. data/test/fixtures/actual_output/total_duration_tri_float_64_44100.wav +0 -0
  36. data/test/fixtures/actual_output/total_duration_tri_pcm_16_44100.wav +0 -0
  37. data/test/fixtures/actual_output/total_duration_tri_pcm_24_44100.wav +0 -0
  38. data/test/fixtures/actual_output/total_duration_tri_pcm_32_44100.wav +0 -0
  39. data/test/fixtures/actual_output/total_duration_tri_pcm_8_44100.wav +0 -0
  40. data/test/fixtures/unsupported/README.markdown +1 -1
  41. data/test/fixtures/unsupported/bad_channel_count.wav +0 -0
  42. data/test/fixtures/unsupported/extensible_container_size_bigger_than_sample_size.wav +0 -0
  43. data/test/fixtures/unsupported/extensible_unsupported_subformat_guid.wav +0 -0
  44. data/test/fixtures/valid/valid_extensible_mono_float_32_44100.wav +0 -0
  45. data/test/fixtures/valid/valid_extensible_mono_float_64_44100.wav +0 -0
  46. data/test/fixtures/valid/valid_extensible_mono_pcm_16_44100.wav +0 -0
  47. data/test/fixtures/valid/valid_extensible_mono_pcm_24_44100.wav +0 -0
  48. data/test/fixtures/valid/valid_extensible_mono_pcm_32_44100.wav +0 -0
  49. data/test/fixtures/valid/valid_extensible_mono_pcm_8_44100.wav +0 -0
  50. data/test/fixtures/valid/valid_extensible_stereo_float_32_44100.wav +0 -0
  51. data/test/fixtures/valid/valid_extensible_stereo_float_64_44100.wav +0 -0
  52. data/test/fixtures/valid/valid_extensible_stereo_pcm_16_44100.wav +0 -0
  53. data/test/fixtures/valid/valid_extensible_stereo_pcm_24_44100.wav +0 -0
  54. data/test/fixtures/valid/valid_extensible_stereo_pcm_32_44100.wav +0 -0
  55. data/test/fixtures/valid/valid_extensible_stereo_pcm_8_44100.wav +0 -0
  56. data/test/fixtures/valid/valid_extensible_tri_float_32_44100.wav +0 -0
  57. data/test/fixtures/valid/valid_extensible_tri_float_64_44100.wav +0 -0
  58. data/test/fixtures/valid/valid_extensible_tri_pcm_16_44100.wav +0 -0
  59. data/test/fixtures/valid/valid_extensible_tri_pcm_24_44100.wav +0 -0
  60. data/test/fixtures/valid/valid_extensible_tri_pcm_32_44100.wav +0 -0
  61. data/test/fixtures/valid/valid_extensible_tri_pcm_8_44100.wav +0 -0
  62. data/test/format_test.rb +22 -48
  63. data/test/reader_test.rb +188 -93
  64. data/test/unvalidated_format_test.rb +130 -4
  65. data/test/wavefile_io_test_helper.rb +6 -4
  66. data/test/writer_test.rb +118 -95
  67. metadata +47 -4
  68. data/lib/wavefile/chunk_readers/header_reader.rb +0 -163
  69. data/test/fixtures/actual_output/no_samples.wav +0 -0
@@ -3,7 +3,7 @@ require 'wavefile.rb'
3
3
 
4
4
  include WaveFile
5
5
 
6
- class DurationTest < MiniTest::Unit::TestCase
6
+ class DurationTest < Minitest::Test
7
7
  SECONDS_IN_MINUTE = 60
8
8
  SECONDS_IN_HOUR = SECONDS_IN_MINUTE * 60
9
9
 
@@ -70,4 +70,45 @@ class DurationTest < MiniTest::Unit::TestCase
70
70
  assert_equal(samples_per_hour * 25, duration.sample_frame_count)
71
71
  assert_equal(44100, duration.sample_rate)
72
72
  end
73
+
74
+ def test_equality_exact_same_values
75
+ duration_1 = Duration.new(44100, 1234)
76
+ duration_2 = Duration.new(44100, 1234)
77
+
78
+ assert_equal(duration_1, duration_2)
79
+ end
80
+
81
+ def test_equality_different_values_but_same_duration
82
+ # Durations have different numbers of sample frames and sample rates,
83
+ # but both correspond to the same amount of time (1 second)
84
+ duration_1 = Duration.new(22050, 22050)
85
+ duration_2 = Duration.new(44100, 44100)
86
+
87
+ assert_equal(duration_1, duration_2)
88
+ end
89
+
90
+ def test_equality_different_number_of_sample_frames
91
+ duration_1 = Duration.new(100, 44100)
92
+ duration_2 = Duration.new(200, 44100)
93
+
94
+ assert_equal(false, duration_1 == duration_2)
95
+ end
96
+
97
+ def test_equality_different_sample_rates
98
+ duration_1 = Duration.new(500, 22050)
99
+ duration_2 = Duration.new(500, 44100)
100
+
101
+ assert_equal(false, duration_1 == duration_2)
102
+ end
103
+
104
+ def test_equality_less_than_millisecond_difference
105
+ # Although each represents a different amount of time,
106
+ # the difference is less than 1 millisecond, which is
107
+ # the maximum resolution of a Duration. Therefore, they
108
+ # are considered equal.
109
+ duration_1 = Duration.new(500, 44100)
110
+ duration_2 = Duration.new(501, 44100)
111
+
112
+ assert_equal(duration_1, duration_2)
113
+ end
73
114
  end
@@ -1,6 +1,6 @@
1
1
  The files in this folder are wave files that do not violate the wave file spec, but can not be read by the WaveFile gem.
2
2
 
3
3
  * **unsupported_audio_format.wav** - The audio format defined in the format chunk is 2, or ADPCM. While a valid format, this gem only supports 1 (PCM).
4
- * **unsupported_bits_per_sample.wav** - The bits per sample is 24. While this is a valid sample rate, this gem only supports 8, 16, and 32 bits per sample.
4
+ * **unsupported_bits_per_sample.wav** - The bits per sample is 20, which is not supported by this gem.
5
5
  * **bad_channel_count.wav** - The channel count defined in the format chunk is 0.
6
6
  * **bad_sample_rate.wav** - The sample rate defined in the format chunk is 0.
@@ -3,7 +3,7 @@ require 'wavefile.rb'
3
3
 
4
4
  include WaveFile
5
5
 
6
- class FormatTest < MiniTest::Unit::TestCase
6
+ class FormatTest < Minitest::Test
7
7
  def test_valid_channels
8
8
  [1, 2, 3, 4, 65535].each do |valid_channels|
9
9
  assert_equal(valid_channels, Format.new(valid_channels, :pcm_16, 44100).channels)
@@ -20,10 +20,6 @@ class FormatTest < MiniTest::Unit::TestCase
20
20
  end
21
21
 
22
22
  def test_valid_sample_format
23
- assert_equal(:pcm, Format.new(:mono, 8, 44100).sample_format)
24
- assert_equal(:pcm, Format.new(:mono, 16, 44100).sample_format)
25
- assert_equal(:pcm, Format.new(:mono, 24, 44100).sample_format)
26
- assert_equal(:pcm, Format.new(:mono, 32, 44100).sample_format)
27
23
  assert_equal(:pcm, Format.new(:mono, :pcm_8, 44100).sample_format)
28
24
  assert_equal(:pcm, Format.new(:mono, :pcm_16, 44100).sample_format)
29
25
  assert_equal(:pcm, Format.new(:mono, :pcm_24, 44100).sample_format)
@@ -34,16 +30,12 @@ class FormatTest < MiniTest::Unit::TestCase
34
30
  end
35
31
 
36
32
  def test_invalid_sample_format
37
- ["dsfsfsdf", :foo, 12, :pcm_14, :float_20].each do |invalid_sample_format|
33
+ ["dsfsfsdf", :foo, :pcm, 0, 12, :pcm_14, :pcm_abc, :float_40].each do |invalid_sample_format|
38
34
  assert_raises(InvalidFormatError) { Format.new(:mono, invalid_sample_format, 44100) }
39
35
  end
40
36
  end
41
37
 
42
38
  def test_valid_bits_per_sample
43
- assert_equal(8, Format.new(:mono, 8, 44100).bits_per_sample)
44
- assert_equal(16, Format.new(:mono, 16, 44100).bits_per_sample)
45
- assert_equal(24, Format.new(:mono, 24, 44100).bits_per_sample)
46
- assert_equal(32, Format.new(:mono, 32, 44100).bits_per_sample)
47
39
  assert_equal(8, Format.new(:mono, :pcm_8, 44100).bits_per_sample)
48
40
  assert_equal(16, Format.new(:mono, :pcm_16, 44100).bits_per_sample)
49
41
  assert_equal(24, Format.new(:mono, :pcm_24, 44100).bits_per_sample)
@@ -53,12 +45,6 @@ class FormatTest < MiniTest::Unit::TestCase
53
45
  assert_equal(64, Format.new(:mono, :float_64, 44100).bits_per_sample)
54
46
  end
55
47
 
56
- def test_invalid_bits_per_sample
57
- ["dsfsfsdf", :foo, :pcm, 0, 12, :pcm_14, :pcm_abc, :float_40].each do |invalid_sample_format|
58
- assert_raises(InvalidFormatError) { Format.new(:mono, invalid_sample_format, 44100) }
59
- end
60
- end
61
-
62
48
  def test_valid_sample_rate
63
49
  [1, 44100, 4294967296].each do |valid_sample_rate|
64
50
  assert_equal(valid_sample_rate, Format.new(:mono, :pcm_16, valid_sample_rate).sample_rate)
@@ -73,25 +59,19 @@ class FormatTest < MiniTest::Unit::TestCase
73
59
 
74
60
  def test_byte_and_block_align
75
61
  [1, :mono].each do |one_channel|
76
- [:pcm_8, 8].each do |format_code|
77
- format = Format.new(one_channel, format_code, 44100)
78
- assert_equal(44100, format.byte_rate)
79
- assert_equal(1, format.block_align)
80
- end
62
+ format = Format.new(one_channel, :pcm_8, 44100)
63
+ assert_equal(44100, format.byte_rate)
64
+ assert_equal(1, format.block_align)
81
65
 
82
- [:pcm_16, 16].each do |format_code|
83
- format = Format.new(one_channel, format_code, 44100)
84
- assert_equal(88200, format.byte_rate)
85
- assert_equal(2, format.block_align)
86
- end
66
+ format = Format.new(one_channel, :pcm_16, 44100)
67
+ assert_equal(88200, format.byte_rate)
68
+ assert_equal(2, format.block_align)
87
69
 
88
- [:pcm_24, 24].each do |format_code|
89
- format = Format.new(one_channel, format_code, 44100)
90
- assert_equal(132300, format.byte_rate)
91
- assert_equal(3, format.block_align)
92
- end
70
+ format = Format.new(one_channel, :pcm_24, 44100)
71
+ assert_equal(132300, format.byte_rate)
72
+ assert_equal(3, format.block_align)
93
73
 
94
- [:pcm_32, 32, :float, :float_32].each do |format_code|
74
+ [:pcm_32, :float, :float_32].each do |format_code|
95
75
  format = Format.new(one_channel, format_code, 44100)
96
76
  assert_equal(176400, format.byte_rate)
97
77
  assert_equal(4, format.block_align)
@@ -103,25 +83,19 @@ class FormatTest < MiniTest::Unit::TestCase
103
83
  end
104
84
 
105
85
  [2, :stereo].each do |two_channels|
106
- [:pcm_8, 8].each do |format_code|
107
- format = Format.new(two_channels, format_code, 44100)
108
- assert_equal(88200, format.byte_rate)
109
- assert_equal(2, format.block_align)
110
- end
86
+ format = Format.new(two_channels, :pcm_8, 44100)
87
+ assert_equal(88200, format.byte_rate)
88
+ assert_equal(2, format.block_align)
111
89
 
112
- [:pcm_16, 16].each do |format_code|
113
- format = Format.new(two_channels, format_code, 44100)
114
- assert_equal(176400, format.byte_rate)
115
- assert_equal(4, format.block_align)
116
- end
90
+ format = Format.new(two_channels, :pcm_16, 44100)
91
+ assert_equal(176400, format.byte_rate)
92
+ assert_equal(4, format.block_align)
117
93
 
118
- [:pcm_24, 24].each do |format_code|
119
- format = Format.new(two_channels, format_code, 44100)
120
- assert_equal(264600, format.byte_rate)
121
- assert_equal(6, format.block_align)
122
- end
94
+ format = Format.new(two_channels, :pcm_24, 44100)
95
+ assert_equal(264600, format.byte_rate)
96
+ assert_equal(6, format.block_align)
123
97
 
124
- [:pcm_32, 32, :float, :float_32].each do |format_code|
98
+ [:pcm_32, :float, :float_32].each do |format_code|
125
99
  format = Format.new(two_channels, format_code, 44100)
126
100
  assert_equal(352800, format.byte_rate)
127
101
  assert_equal(8, format.block_align)
@@ -4,7 +4,7 @@ require 'wavefile_io_test_helper.rb'
4
4
 
5
5
  include WaveFile
6
6
 
7
- class ReaderTest < MiniTest::Unit::TestCase
7
+ class ReaderTest < Minitest::Test
8
8
  include WaveFileIOTestHelper
9
9
 
10
10
  FIXTURE_ROOT_PATH = "test/fixtures"
@@ -14,7 +14,7 @@ class ReaderTest < MiniTest::Unit::TestCase
14
14
  assert_raises(Errno::ENOENT) { Reader.new(fixture("i_do_not_exist.wav")) }
15
15
  end
16
16
 
17
- def test_invalid_formats
17
+ def test_initialize_invalid_formats
18
18
  invalid_fixtures = [
19
19
  # File contains 0 bytes
20
20
  "invalid/empty.wav",
@@ -41,14 +41,52 @@ class ReaderTest < MiniTest::Unit::TestCase
41
41
  "invalid/no_data_chunk.wav",
42
42
  ]
43
43
 
44
- # Reader.new and Reader.info should raise the same errors for invalid files,
45
- # so run the tests for both methods.
46
44
  invalid_fixtures.each do |fixture_name|
47
- assert_raises(InvalidFormatError) { Reader.new(fixture(fixture_name)) }
45
+ file_name = fixture(fixture_name)
46
+
47
+ [file_name, string_io_from_file(file_name)].each do |io_or_file_name|
48
+ assert_raises(InvalidFormatError) { Reader.new(io_or_file_name) }
49
+ end
48
50
  end
49
51
  end
50
52
 
51
- def test_unsupported_formats
53
+ def test_initialize_unsupported_format
54
+ file_name = fixture("unsupported/unsupported_bits_per_sample.wav")
55
+
56
+ # Unsupported format, no read format given
57
+ [file_name, string_io_from_file(file_name)].each do |io_or_file_name|
58
+ reader = Reader.new(io_or_file_name)
59
+ assert_equal(2, reader.native_format.channels)
60
+ assert_equal(20, reader.native_format.bits_per_sample)
61
+ assert_equal(44100, reader.native_format.sample_rate)
62
+ assert_equal(2, reader.format.channels)
63
+ assert_equal(20, reader.format.bits_per_sample)
64
+ assert_equal(44100, reader.format.sample_rate)
65
+ assert_equal(false, reader.closed?)
66
+ assert_equal(0, reader.current_sample_frame)
67
+ assert_equal(2240, reader.total_sample_frames)
68
+ assert_equal(false, reader.readable_format?)
69
+ reader.close
70
+ end
71
+
72
+ # Unsupported format, different read format given
73
+ [file_name, string_io_from_file(file_name)].each do |io_or_file_name|
74
+ reader = Reader.new(io_or_file_name, Format.new(:mono, :pcm_16, 22050))
75
+ assert_equal(2, reader.native_format.channels)
76
+ assert_equal(20, reader.native_format.bits_per_sample)
77
+ assert_equal(44100, reader.native_format.sample_rate)
78
+ assert_equal(1, reader.format.channels)
79
+ assert_equal(16, reader.format.bits_per_sample)
80
+ assert_equal(22050, reader.format.sample_rate)
81
+ assert_equal(false, reader.closed?)
82
+ assert_equal(0, reader.current_sample_frame)
83
+ assert_equal(2240, reader.total_sample_frames)
84
+ assert_equal(false, reader.readable_format?)
85
+ reader.close
86
+ end
87
+ end
88
+
89
+ def test_read_from_unsupported_format
52
90
  unsupported_fixtures = [
53
91
  # Audio format is 2, which is not supported
54
92
  "unsupported/unsupported_audio_format.wav",
@@ -61,105 +99,88 @@ class ReaderTest < MiniTest::Unit::TestCase
61
99
 
62
100
  # Sample rate is 0
63
101
  "unsupported/bad_sample_rate.wav",
102
+
103
+ # WAVEFORMATEXTENSIBLE, container size doesn't match sample size
104
+ # Although this is valid, this is not currently supported by this gem
105
+ "unsupported/extensible_container_size_bigger_than_sample_size.wav",
106
+
107
+ # WAVEFORMATEXTENSIBLE, the subformat GUID is not a valid format
108
+ # supported by this gem.
109
+ "unsupported/extensible_unsupported_subformat_guid.wav",
64
110
  ]
65
111
 
66
112
  unsupported_fixtures.each do |fixture_name|
67
- reader = Reader.new(fixture(fixture_name))
68
- assert_equal(false, reader.readable_format?)
69
- assert_raises(UnsupportedFormatError) { reader.read(1024) }
70
- assert_raises(UnsupportedFormatError) { reader.each_buffer(1024) {|buffer| buffer } }
71
- end
72
- end
113
+ file_name = fixture(fixture_name)
73
114
 
74
- def test_initialize_unsupported_format
75
- file_name = fixture("unsupported/unsupported_bits_per_sample.wav")
115
+ [file_name, string_io_from_file(file_name)].each do |io_or_file_name|
116
+ reader = Reader.new(io_or_file_name)
117
+ assert_equal(false, reader.readable_format?)
118
+ assert_raises(UnsupportedFormatError) { reader.read(1024) }
119
+ assert_raises(UnsupportedFormatError) { reader.each_buffer(1024) {|buffer| buffer } }
76
120
 
77
- # Unsupported format, no read format given
78
- reader = Reader.new(file_name)
79
- assert_equal(2, reader.native_format.channels)
80
- assert_equal(20, reader.native_format.bits_per_sample)
81
- assert_equal(44100, reader.native_format.sample_rate)
82
- assert_equal(2, reader.format.channels)
83
- assert_equal(20, reader.format.bits_per_sample)
84
- assert_equal(44100, reader.format.sample_rate)
85
- assert_equal(false, reader.closed?)
86
- assert_equal(file_name, reader.file_name)
87
- assert_equal(0, reader.current_sample_frame)
88
- assert_equal(2240, reader.total_sample_frames)
89
- assert_equal(false, reader.readable_format?)
90
- reader.close
91
-
92
- # Unsupported format, different read format given
93
- reader = Reader.new(file_name, Format.new(:mono, :pcm_16, 22050))
94
- assert_equal(2, reader.native_format.channels)
95
- assert_equal(20, reader.native_format.bits_per_sample)
96
- assert_equal(44100, reader.native_format.sample_rate)
97
- assert_equal(1, reader.format.channels)
98
- assert_equal(16, reader.format.bits_per_sample)
99
- assert_equal(22050, reader.format.sample_rate)
100
- assert_equal(false, reader.closed?)
101
- assert_equal(file_name, reader.file_name)
102
- assert_equal(0, reader.current_sample_frame)
103
- assert_equal(2240, reader.total_sample_frames)
104
- assert_equal(false, reader.readable_format?)
105
- reader.close
121
+ reader.close
122
+ end
123
+ end
106
124
  end
107
125
 
108
126
  def test_initialize
109
127
  format = Format.new(:stereo, :pcm_16, 22050)
110
128
 
111
- exhaustively_test do |channels, sample_format|
112
- file_name = fixture("valid/valid_#{channels}_#{sample_format}_44100.wav")
129
+ exhaustively_test do |format_chunk_format, channels, sample_format|
130
+ file_name = fixture("valid/valid_#{format_chunk_format}#{channels}_#{sample_format}_44100.wav")
113
131
 
114
132
  # Native format
115
- reader = Reader.new(file_name)
116
- assert_equal(CHANNEL_ALIAS[channels], reader.native_format.channels)
117
- assert_equal(extract_bits_per_sample(sample_format), reader.native_format.bits_per_sample)
118
- assert_equal(44100, reader.native_format.sample_rate)
119
- assert_equal(CHANNEL_ALIAS[channels], reader.format.channels)
120
- assert_equal(extract_bits_per_sample(sample_format), reader.format.bits_per_sample)
121
- assert_equal(44100, reader.format.sample_rate)
122
- assert_equal(false, reader.closed?)
123
- assert_equal(file_name, reader.file_name)
124
- assert_equal(0, reader.current_sample_frame)
125
- assert_equal(2240, reader.total_sample_frames)
126
- assert_equal(true, reader.readable_format?)
127
- reader.close
133
+ [file_name, string_io_from_file(file_name)].each do |io_or_file_name|
134
+ reader = Reader.new(io_or_file_name)
135
+ assert_equal(CHANNEL_ALIAS[channels], reader.native_format.channels)
136
+ assert_equal(extract_bits_per_sample(sample_format), reader.native_format.bits_per_sample)
137
+ assert_equal(44100, reader.native_format.sample_rate)
138
+ assert_equal(CHANNEL_ALIAS[channels], reader.format.channels)
139
+ assert_equal(extract_bits_per_sample(sample_format), reader.format.bits_per_sample)
140
+ assert_equal(44100, reader.format.sample_rate)
141
+ assert_equal(false, reader.closed?)
142
+ assert_equal(0, reader.current_sample_frame)
143
+ assert_equal(2240, reader.total_sample_frames)
144
+ assert_equal(true, reader.readable_format?)
145
+ reader.close
146
+ end
128
147
 
129
148
  # Non-native format
130
- reader = Reader.new(file_name, format)
131
- assert_equal(CHANNEL_ALIAS[channels], reader.native_format.channels)
132
- assert_equal(extract_bits_per_sample(sample_format), reader.native_format.bits_per_sample)
133
- assert_equal(44100, reader.native_format.sample_rate)
134
- assert_equal(2, reader.format.channels)
135
- assert_equal(16, reader.format.bits_per_sample)
136
- assert_equal(22050, reader.format.sample_rate)
137
- assert_equal(false, reader.closed?)
138
- assert_equal(file_name, reader.file_name)
139
- assert_equal(0, reader.current_sample_frame)
140
- assert_equal(2240, reader.total_sample_frames)
141
- assert_equal(true, reader.readable_format?)
142
- reader.close
149
+ [file_name, string_io_from_file(file_name)].each do |io_or_file_name|
150
+ reader = Reader.new(io_or_file_name, format)
151
+ assert_equal(CHANNEL_ALIAS[channels], reader.native_format.channels)
152
+ assert_equal(extract_bits_per_sample(sample_format), reader.native_format.bits_per_sample)
153
+ assert_equal(44100, reader.native_format.sample_rate)
154
+ assert_equal(2, reader.format.channels)
155
+ assert_equal(16, reader.format.bits_per_sample)
156
+ assert_equal(22050, reader.format.sample_rate)
157
+ assert_equal(false, reader.closed?)
158
+ assert_equal(0, reader.current_sample_frame)
159
+ assert_equal(2240, reader.total_sample_frames)
160
+ assert_equal(true, reader.readable_format?)
161
+ reader.close
162
+ end
143
163
 
144
164
  # Block is given.
145
- reader = Reader.new(file_name) {|reader| reader.read(1024) }
146
- assert_equal(CHANNEL_ALIAS[channels], reader.native_format.channels)
147
- assert_equal(extract_bits_per_sample(sample_format), reader.native_format.bits_per_sample)
148
- assert_equal(44100, reader.native_format.sample_rate)
149
- assert_equal(CHANNEL_ALIAS[channels], reader.format.channels)
150
- assert_equal(extract_bits_per_sample(sample_format), reader.format.bits_per_sample)
151
- assert_equal(44100, reader.format.sample_rate)
152
- assert(reader.closed?)
153
- assert_equal(file_name, reader.file_name)
154
- assert_equal(1024, reader.current_sample_frame)
155
- assert_equal(2240, reader.total_sample_frames)
156
- assert_equal(true, reader.readable_format?)
165
+ [file_name, string_io_from_file(file_name)].each do |io_or_file_name|
166
+ reader = Reader.new(io_or_file_name) {|r| r.read(1024) }
167
+ assert_equal(CHANNEL_ALIAS[channels], reader.native_format.channels)
168
+ assert_equal(extract_bits_per_sample(sample_format), reader.native_format.bits_per_sample)
169
+ assert_equal(44100, reader.native_format.sample_rate)
170
+ assert_equal(CHANNEL_ALIAS[channels], reader.format.channels)
171
+ assert_equal(extract_bits_per_sample(sample_format), reader.format.bits_per_sample)
172
+ assert_equal(44100, reader.format.sample_rate)
173
+ assert(reader.closed?)
174
+ assert_equal(1024, reader.current_sample_frame)
175
+ assert_equal(2240, reader.total_sample_frames)
176
+ assert_equal(true, reader.readable_format?)
177
+ end
157
178
  end
158
179
  end
159
180
 
160
181
  def test_read_native_format
161
- exhaustively_test do |channels, sample_format|
162
- buffers = read_file("valid/valid_#{channels}_#{sample_format}_44100.wav", 1024)
182
+ exhaustively_test do |format_chunk_format, channels, sample_format|
183
+ buffers = read_file("valid/valid_#{format_chunk_format}#{channels}_#{sample_format}_44100.wav", 1024)
163
184
 
164
185
  assert_equal(3, buffers.length)
165
186
  assert_equal([1024, 1024, 192], buffers.map {|buffer| buffer.samples.length })
@@ -169,6 +190,32 @@ class ReaderTest < MiniTest::Unit::TestCase
169
190
  end
170
191
  end
171
192
 
193
+ def test_read_native_extensible_format
194
+ channels = :stereo
195
+ sample_format = :pcm_16
196
+
197
+ reader = Reader.new(fixture("valid/valid_extensible_stereo_pcm_16_44100.wav"))
198
+ assert_equal(2, reader.native_format.channels)
199
+ assert_equal(16, reader.native_format.bits_per_sample)
200
+ assert_equal(44100, reader.native_format.sample_rate)
201
+ assert_equal(2, reader.format.channels)
202
+ assert_equal(16, reader.format.bits_per_sample)
203
+ assert_equal(44100, reader.format.sample_rate)
204
+ assert_equal(false, reader.closed?)
205
+ assert_equal(0, reader.current_sample_frame)
206
+ assert_equal(2240, reader.total_sample_frames)
207
+ assert_equal(true, reader.readable_format?)
208
+ reader.close
209
+
210
+ buffers = read_file("valid/valid_extensible_stereo_pcm_16_44100.wav", 1024)
211
+
212
+ assert_equal(3, buffers.length)
213
+ assert_equal([1024, 1024, 192], buffers.map {|buffer| buffer.samples.length })
214
+ assert_equal(SQUARE_WAVE_CYCLE[channels][sample_format] * 128, buffers[0].samples)
215
+ assert_equal(SQUARE_WAVE_CYCLE[channels][sample_format] * 128, buffers[1].samples)
216
+ assert_equal(SQUARE_WAVE_CYCLE[channels][sample_format] * 24, buffers[2].samples)
217
+ end
218
+
172
219
  def test_read_with_format_conversion
173
220
  buffers = read_file("valid/valid_mono_pcm_16_44100.wav", 1024, Format.new(:stereo, :pcm_8, 22100))
174
221
 
@@ -195,9 +242,25 @@ class ReaderTest < MiniTest::Unit::TestCase
195
242
  assert_raises(LocalJumpError) { reader.each_buffer(1024) }
196
243
  end
197
244
 
245
+ def test_each_buffer_no_buffer_size_given
246
+ exhaustively_test do |format_chunk_format, channels, sample_format|
247
+ reader = Reader.new(fixture("valid/valid_#{format_chunk_format}#{channels}_#{sample_format}_44100.wav"))
248
+
249
+ buffers = []
250
+ reader.each_buffer {|buffer| buffers << buffer }
251
+
252
+ assert(reader.closed?)
253
+ assert_equal(1, buffers.length)
254
+ assert_equal([2240], buffers.map {|buffer| buffer.samples.length })
255
+ assert_equal(SQUARE_WAVE_CYCLE[channels][sample_format] * 280, buffers[0].samples)
256
+ assert_equal(2240, reader.current_sample_frame)
257
+ assert_equal(2240, reader.total_sample_frames)
258
+ end
259
+ end
260
+
198
261
  def test_each_buffer_native_format
199
- exhaustively_test do |channels, sample_format|
200
- reader = Reader.new(fixture("valid/valid_#{channels}_#{sample_format}_44100.wav"))
262
+ exhaustively_test do |format_chunk_format, channels, sample_format|
263
+ reader = Reader.new(fixture("valid/valid_#{format_chunk_format}#{channels}_#{sample_format}_44100.wav"))
201
264
 
202
265
  buffers = []
203
266
  reader.each_buffer(1024) {|buffer| buffers << buffer }
@@ -270,18 +333,40 @@ class ReaderTest < MiniTest::Unit::TestCase
270
333
  # No-op
271
334
  end
272
335
  assert_equal(true, reader.closed?)
336
+
337
+ # Constructed from an File IO instance
338
+ io = File.open(fixture("valid/valid_mono_pcm_16_44100.wav"), "rb")
339
+ reader = Reader.new(io)
340
+ assert_equal(false, reader.closed?)
341
+ reader.close
342
+ assert(reader.closed?)
343
+ assert_equal(false, io.closed?)
344
+
345
+ # Constructed from an StringIO instance
346
+ io = StringIO.new(File.read(fixture("valid/valid_mono_pcm_16_44100.wav")))
347
+ reader = Reader.new(io)
348
+ assert_equal(false, reader.closed?)
349
+ reader.close
350
+ assert(reader.closed?)
351
+ assert_equal(false, io.closed?)
273
352
  end
274
353
 
275
354
  def test_read_after_close
276
355
  reader = Reader.new(fixture("valid/valid_mono_pcm_16_44100.wav"))
277
- buffer = reader.read(1024)
356
+ reader.read(1024)
357
+ reader.close
358
+ assert_raises(ReaderClosedError) { reader.read(1024) }
359
+
360
+ io = File.open(fixture("valid/valid_mono_pcm_16_44100.wav"), "rb")
361
+ reader = Reader.new(io)
362
+ reader.read(1024)
278
363
  reader.close
279
- assert_raises(IOError) { reader.read(1024) }
364
+ assert_raises(ReaderClosedError) { reader.read(1024) }
280
365
  end
281
366
 
282
367
  def test_sample_counts_manual_reads
283
- exhaustively_test do |channels, sample_format|
284
- reader = Reader.new(fixture("valid/valid_#{channels}_#{sample_format}_44100.wav"))
368
+ exhaustively_test do |format_chunk_format, channels, sample_format|
369
+ reader = Reader.new(fixture("valid/valid_#{format_chunk_format}#{channels}_#{sample_format}_44100.wav"))
285
370
 
286
371
  assert_equal(0, reader.current_sample_frame)
287
372
  assert_equal(2240, reader.total_sample_frames)
@@ -319,10 +404,10 @@ class ReaderTest < MiniTest::Unit::TestCase
319
404
  end
320
405
 
321
406
  def test_sample_counts_each_buffer
322
- exhaustively_test do |channels, sample_format|
407
+ exhaustively_test do |format_chunk_format, channels, sample_format|
323
408
  expected_results = [ 1024, 2048, 2240 ]
324
409
 
325
- file_name = fixture("valid/valid_#{channels}_#{sample_format}_44100.wav")
410
+ file_name = fixture("valid/valid_#{format_chunk_format}#{channels}_#{sample_format}_44100.wav")
326
411
  reader = Reader.new(file_name)
327
412
 
328
413
  assert_equal(0, reader.current_sample_frame)
@@ -365,6 +450,16 @@ private
365
450
  sample_format.to_s.split("_").last.to_i
366
451
  end
367
452
 
453
+ def string_io_from_file(file_name)
454
+ file_contents = File.read(file_name)
455
+
456
+ str_io = StringIO.new
457
+ str_io.syswrite(file_contents)
458
+ str_io.rewind
459
+
460
+ str_io
461
+ end
462
+
368
463
  def test_duration(expected_hash, duration)
369
464
  assert_equal(expected_hash[:hours], duration.hours)
370
465
  assert_equal(expected_hash[:minutes], duration.minutes)