wavefile 0.7.0 → 0.8.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 (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)