wavefile 0.3.0 → 0.4.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 (55) hide show
  1. data/LICENSE +1 -1
  2. data/README.markdown +29 -56
  3. data/Rakefile +6 -0
  4. data/lib/wavefile.rb +28 -452
  5. data/lib/wavefile/buffer.rb +147 -0
  6. data/lib/wavefile/format.rb +69 -0
  7. data/lib/wavefile/info.rb +53 -0
  8. data/lib/wavefile/reader.rb +296 -0
  9. data/lib/wavefile/writer.rb +128 -0
  10. data/test/buffer_test.rb +121 -0
  11. data/test/fixtures/actual_output/valid_mono_8_44100_with_padding_byte.wav +0 -0
  12. data/test/fixtures/expected_output/no_samples.wav +0 -0
  13. data/test/fixtures/expected_output/valid_mono_16_44100.wav +0 -0
  14. data/test/fixtures/expected_output/valid_mono_32_44100.wav +0 -0
  15. data/test/fixtures/expected_output/valid_mono_8_44100.wav +0 -0
  16. data/test/fixtures/expected_output/valid_mono_8_44100_with_padding_byte.wav +0 -0
  17. data/test/fixtures/expected_output/valid_stereo_16_44100.wav +0 -0
  18. data/test/fixtures/expected_output/valid_stereo_32_44100.wav +0 -0
  19. data/test/fixtures/expected_output/valid_stereo_8_44100.wav +0 -0
  20. data/test/fixtures/expected_output/valid_tri_16_44100.wav +0 -0
  21. data/test/fixtures/expected_output/valid_tri_32_44100.wav +0 -0
  22. data/test/fixtures/expected_output/valid_tri_8_44100.wav +0 -0
  23. data/test/fixtures/invalid/README.markdown +10 -0
  24. data/test/fixtures/invalid/bad_riff_header.wav +1 -0
  25. data/test/fixtures/invalid/bad_wavefile_format.wav +0 -0
  26. data/test/fixtures/invalid/empty.wav +0 -0
  27. data/test/fixtures/invalid/empty_format_chunk.wav +0 -0
  28. data/test/fixtures/invalid/incomplete_riff_header.wav +1 -0
  29. data/test/fixtures/invalid/insufficient_format_chunk.wav +0 -0
  30. data/test/fixtures/invalid/no_data_chunk.wav +0 -0
  31. data/test/fixtures/invalid/no_format_chunk.wav +0 -0
  32. data/test/fixtures/unsupported/README.markdown +6 -0
  33. data/test/fixtures/unsupported/bad_audio_format.wav +0 -0
  34. data/test/fixtures/unsupported/bad_channel_count.wav +0 -0
  35. data/test/fixtures/unsupported/bad_sample_rate.wav +0 -0
  36. data/test/fixtures/unsupported/unsupported_audio_format.wav +0 -0
  37. data/test/fixtures/unsupported/unsupported_bits_per_sample.wav +0 -0
  38. data/test/fixtures/valid/README.markdown +3 -0
  39. data/test/fixtures/valid/valid_mono_16_44100.wav +0 -0
  40. data/test/fixtures/valid/valid_mono_32_44100.wav +0 -0
  41. data/test/fixtures/valid/valid_mono_8_44100.wav +0 -0
  42. data/test/fixtures/valid/valid_mono_8_44100_with_padding_byte.wav +0 -0
  43. data/test/fixtures/valid/valid_stereo_16_44100.wav +0 -0
  44. data/test/fixtures/valid/valid_stereo_32_44100.wav +0 -0
  45. data/test/fixtures/valid/valid_stereo_8_44100.wav +0 -0
  46. data/test/fixtures/valid/valid_tri_16_44100.wav +0 -0
  47. data/test/fixtures/valid/valid_tri_32_44100.wav +0 -0
  48. data/test/fixtures/valid/valid_tri_8_44100.wav +0 -0
  49. data/test/format_test.rb +105 -0
  50. data/test/info_test.rb +60 -0
  51. data/test/reader_test.rb +222 -0
  52. data/test/wavefile_io_test_helper.rb +47 -0
  53. data/test/writer_test.rb +118 -0
  54. metadata +72 -33
  55. data/test/wavefile_test.rb +0 -339
data/test/info_test.rb ADDED
@@ -0,0 +1,60 @@
1
+ require 'test/unit'
2
+ require 'wavefile.rb'
3
+
4
+ include WaveFile
5
+
6
+ class InfoTest < Test::Unit::TestCase
7
+ FILE_NAME = "foo.wav"
8
+ SECONDS_IN_MINUTE = 60
9
+ SECONDS_IN_HOUR = SECONDS_IN_MINUTE * 60
10
+
11
+ def test_basic
12
+ format_chunk = { :audio_format => 1, :channels => 2, :sample_rate => 44100,
13
+ :byte_rate => 176400, :block_align => 4, :bits_per_sample => 16 }
14
+ info = Info.new(FILE_NAME, format_chunk, 44100)
15
+
16
+ assert_equal(FILE_NAME, info.file_name)
17
+ assert_equal(1, info.audio_format)
18
+ assert_equal(2, info.channels)
19
+ assert_equal(44100, info.sample_rate)
20
+ assert_equal(176400, info.byte_rate)
21
+ assert_equal(4, info.block_align)
22
+ assert_equal(16, info.bits_per_sample)
23
+ assert_equal(44100, info.sample_count)
24
+ assert_equal({:hours => 0, :minutes => 0, :seconds => 1, :milliseconds => 0}, info.duration)
25
+ end
26
+
27
+ def test_duration
28
+ format_chunk = { :audio_format => 1, :channels => 2, :byte_rate => 176400, :block_align => 4, :bits_per_sample => 16 }
29
+
30
+ # Test common sample rates (22050 and 44100), and some crazy arbitrary sample rate (12346)
31
+ [22050, 44100, 12346].each do |sample_rate|
32
+ format_chunk[:sample_rate] = sample_rate
33
+
34
+ info = Info.new(FILE_NAME, format_chunk, 0)
35
+ assert_equal({:hours => 0, :minutes => 0, :seconds => 0, :milliseconds => 0}, info.duration)
36
+
37
+ info = Info.new(FILE_NAME, format_chunk, sample_rate / 2)
38
+ assert_equal({:hours => 0, :minutes => 0, :seconds => 0, :milliseconds => 500}, info.duration)
39
+
40
+ info = Info.new(FILE_NAME, format_chunk, sample_rate)
41
+ assert_equal({:hours => 0, :minutes => 0, :seconds => 1, :milliseconds => 0}, info.duration)
42
+
43
+ info = Info.new(FILE_NAME, format_chunk, sample_rate * SECONDS_IN_MINUTE)
44
+ assert_equal({:hours => 0, :minutes => 1, :seconds => 0, :milliseconds => 0}, info.duration)
45
+
46
+ info = Info.new(FILE_NAME, format_chunk, sample_rate * SECONDS_IN_HOUR)
47
+ assert_equal({:hours => 1, :minutes => 0, :seconds => 0, :milliseconds => 0}, info.duration)
48
+
49
+ info = Info.new(FILE_NAME, format_chunk, (sample_rate * SECONDS_IN_MINUTE) + sample_rate + (sample_rate / 2))
50
+ assert_equal({:hours => 0, :minutes => 1, :seconds => 1, :milliseconds => 500}, info.duration)
51
+ end
52
+
53
+ # Test for when the number of hours is more than a day.
54
+ format_chunk[:sample_rate] = 44100
55
+ samples_per_hour = 44100 * 60 * 60
56
+ info = Info.new(FILE_NAME, format_chunk, samples_per_hour * 25)
57
+ assert_equal({:hours => 25, :minutes => 0, :seconds => 0, :milliseconds => 0}, info.duration)
58
+ end
59
+ end
60
+
@@ -0,0 +1,222 @@
1
+ require 'test/unit'
2
+ require 'wavefile.rb'
3
+ require 'wavefile_io_test_helper.rb'
4
+
5
+ include WaveFile
6
+
7
+ class ReaderTest < Test::Unit::TestCase
8
+ include WaveFileIOTestHelper
9
+
10
+ FIXTURE_ROOT_PATH = "test/fixtures"
11
+
12
+
13
+ def test_nonexistent_file
14
+ assert_raise(Errno::ENOENT) { Reader.new(fixture("i_do_not_exist.wav")) }
15
+
16
+ assert_raise(Errno::ENOENT) { Reader.info(fixture("i_do_not_exist.wav")) }
17
+ end
18
+
19
+ def test_invalid_formats
20
+ # Reader.new() and Reader.info() should raise the same errors for invalid files,
21
+ # so run the tests for both methods.
22
+ [:new, :info].each do |method_name|
23
+ # File contains 0 bytes
24
+ assert_raise(InvalidFormatError) { Reader.send(method_name, fixture("invalid/empty.wav")) }
25
+
26
+ # File consists of "RIFF" and nothing else
27
+ assert_raise(InvalidFormatError) { Reader.send(method_name, fixture("invalid/incomplete_riff_header.wav")) }
28
+
29
+ # First 4 bytes in the file are not "RIFF"
30
+ assert_raise(InvalidFormatError) { Reader.send(method_name, fixture("invalid/bad_riff_header.wav")) }
31
+
32
+ # The format code in the RIFF header is not "WAVE"
33
+ assert_raise(InvalidFormatError) { Reader.new(fixture("invalid/bad_wavefile_format.wav")) }
34
+
35
+ # The file consists of just a valid RIFF header
36
+ assert_raise(InvalidFormatError) { Reader.new(fixture("invalid/no_format_chunk.wav")) }
37
+
38
+ # The format chunk has 0 bytes in it (despite the chunk size being 16)
39
+ assert_raise(InvalidFormatError) { Reader.new(fixture("invalid/empty_format_chunk.wav")) }
40
+
41
+ # The format chunk has some data, but not all of the minimum required.
42
+ assert_raise(InvalidFormatError) { Reader.new(fixture("invalid/insufficient_format_chunk.wav")) }
43
+
44
+ # The RIFF header and format chunk are OK, but there is no data chunk
45
+ assert_raise(InvalidFormatError) { Reader.new(fixture("invalid/no_data_chunk.wav")) }
46
+ end
47
+ end
48
+
49
+ def test_unsupported_formats
50
+ # Audio format is 2, which is not supported
51
+ assert_raise(UnsupportedFormatError) { Reader.new(fixture("unsupported/unsupported_audio_format.wav")) }
52
+
53
+ # Bits per sample is 24, which is not supported
54
+ assert_raise(UnsupportedFormatError) { Reader.new(fixture("unsupported/unsupported_bits_per_sample.wav")) }
55
+
56
+ # Channel count is 0
57
+ assert_raise(UnsupportedFormatError) { Reader.new(fixture("unsupported/bad_channel_count.wav")) }
58
+
59
+ # Sample rate is 0
60
+ assert_raise(UnsupportedFormatError) { Reader.new(fixture("unsupported/bad_sample_rate.wav")) }
61
+ end
62
+
63
+ def test_initialize
64
+ format = Format.new(:stereo, 16, 22050)
65
+
66
+ exhaustively_test do |channels, bits_per_sample|
67
+ file_name = fixture("valid/valid_#{channels}_#{bits_per_sample}_44100.wav")
68
+
69
+ # Read native format
70
+ reader = Reader.new(file_name)
71
+ assert_equal(CHANNEL_ALIAS[channels], reader.format.channels)
72
+ assert_equal(bits_per_sample, reader.format.bits_per_sample)
73
+ assert_equal(44100, reader.format.sample_rate)
74
+ assert_equal(false, reader.closed?)
75
+ assert_equal(file_name, reader.file_name)
76
+ reader.close()
77
+
78
+ # Read a non-native format
79
+ reader = Reader.new(file_name, format)
80
+ assert_equal(2, reader.format.channels)
81
+ assert_equal(16, reader.format.bits_per_sample)
82
+ assert_equal(22050, reader.format.sample_rate)
83
+ assert_equal(false, reader.closed?)
84
+ assert_equal(file_name, reader.file_name)
85
+ reader.close()
86
+
87
+ # Block is given.
88
+ reader = Reader.new(file_name) {|reader| reader.read(1024) }
89
+ assert_equal(CHANNEL_ALIAS[channels], reader.format.channels)
90
+ assert_equal(bits_per_sample, reader.format.bits_per_sample)
91
+ assert_equal(44100, reader.format.sample_rate)
92
+ assert(reader.closed?)
93
+ assert_equal(file_name, reader.file_name)
94
+ end
95
+ end
96
+
97
+ def test_read_native_format
98
+ exhaustively_test do |channels, bits_per_sample|
99
+ buffers = read_file("valid/valid_#{channels}_#{bits_per_sample}_44100.wav", 1024)
100
+
101
+ assert_equal(3, buffers.length)
102
+ assert_equal([1024, 1024, 192], buffers.map {|buffer| buffer.samples.length })
103
+ assert_equal(SQUARE_WAVE_CYCLE[channels][bits_per_sample] * 128, buffers[0].samples)
104
+ assert_equal(SQUARE_WAVE_CYCLE[channels][bits_per_sample] * 128, buffers[1].samples)
105
+ assert_equal(SQUARE_WAVE_CYCLE[channels][bits_per_sample] * 24, buffers[2].samples)
106
+ end
107
+ end
108
+
109
+ def test_read_with_format_conversion
110
+ buffers = read_file("valid/valid_mono_16_44100.wav", 1024, Format.new(:stereo, 8, 22100))
111
+
112
+ assert_equal(3, buffers.length)
113
+ assert_equal([1024, 1024, 192], buffers.map {|buffer| buffer.samples.length })
114
+ assert_equal(SQUARE_WAVE_CYCLE[:stereo][8] * 128, buffers[0].samples)
115
+ assert_equal(SQUARE_WAVE_CYCLE[:stereo][8] * 128, buffers[1].samples)
116
+ assert_equal(SQUARE_WAVE_CYCLE[:stereo][8] * 24, buffers[2].samples)
117
+ end
118
+
119
+ def test_read_with_padding_byte
120
+ buffers = read_file("valid/valid_mono_8_44100_with_padding_byte.wav", 1024)
121
+
122
+ assert_equal(3, buffers.length)
123
+ assert_equal([1024, 1024, 191], buffers.map {|buffer| buffer.samples.length })
124
+ assert_equal(SQUARE_WAVE_CYCLE[:mono][8] * 128, buffers[0].samples)
125
+ assert_equal(SQUARE_WAVE_CYCLE[:mono][8] * 128, buffers[1].samples)
126
+ assert_equal((SQUARE_WAVE_CYCLE[:mono][8] * 23) + [88, 88, 88, 88, 167, 167, 167],
127
+ buffers[2].samples)
128
+ end
129
+
130
+ def test_each_buffer_no_block_given
131
+ reader = Reader.new(fixture("valid/valid_mono_16_44100.wav"))
132
+ assert_raise(LocalJumpError) { reader.each_buffer(1024) }
133
+ end
134
+
135
+ def test_each_buffer_native_format
136
+ exhaustively_test do |channels, bits_per_sample|
137
+ reader = Reader.new(fixture("valid/valid_#{channels}_#{bits_per_sample}_44100.wav"))
138
+
139
+ buffers = []
140
+ reader.each_buffer(1024) {|buffer| buffers << buffer }
141
+
142
+ assert(reader.closed?)
143
+ assert_equal(3, buffers.length)
144
+ assert_equal([1024, 1024, 192], buffers.map {|buffer| buffer.samples.length })
145
+ assert_equal(SQUARE_WAVE_CYCLE[channels][bits_per_sample] * 128, buffers[0].samples)
146
+ assert_equal(SQUARE_WAVE_CYCLE[channels][bits_per_sample] * 128, buffers[1].samples)
147
+ assert_equal(SQUARE_WAVE_CYCLE[channels][bits_per_sample] * 24, buffers[2].samples)
148
+ end
149
+ end
150
+
151
+ def test_each_buffer_with_format_conversion
152
+ reader = Reader.new(fixture("valid/valid_mono_16_44100.wav"), Format.new(:stereo, 8, 22050))
153
+ assert_equal(2, reader.format.channels)
154
+ assert_equal(8, reader.format.bits_per_sample)
155
+ assert_equal(22050, reader.format.sample_rate)
156
+
157
+ buffers = []
158
+ reader.each_buffer(1024) {|buffer| buffers << buffer }
159
+
160
+ assert_equal(3, buffers.length)
161
+ assert_equal([1024, 1024, 192], buffers.map {|buffer| buffer.samples.length })
162
+ assert_equal(SQUARE_WAVE_CYCLE[:stereo][8] * 128, buffers[0].samples)
163
+ assert_equal(SQUARE_WAVE_CYCLE[:stereo][8] * 128, buffers[1].samples)
164
+ assert_equal(SQUARE_WAVE_CYCLE[:stereo][8] * 24, buffers[2].samples)
165
+ end
166
+
167
+ def test_each_buffer_with_padding_byte
168
+ buffers = []
169
+ reader = Reader.new(fixture("valid/valid_mono_8_44100_with_padding_byte.wav"))
170
+ reader.each_buffer(1024) {|buffer| buffers << buffer }
171
+
172
+ assert_equal(3, buffers.length)
173
+ assert_equal([1024, 1024, 191], buffers.map {|buffer| buffer.samples.length })
174
+ assert_equal(SQUARE_WAVE_CYCLE[:mono][8] * 128, buffers[0].samples)
175
+ assert_equal(SQUARE_WAVE_CYCLE[:mono][8] * 128, buffers[1].samples)
176
+ assert_equal((SQUARE_WAVE_CYCLE[:mono][8] * 23) + [88, 88, 88, 88, 167, 167, 167],
177
+ buffers[2].samples)
178
+ end
179
+
180
+ def test_closed?
181
+ reader = Reader.new(fixture("valid/valid_mono_16_44100.wav"))
182
+ assert_equal(false, reader.closed?)
183
+ reader.close()
184
+ assert(reader.closed?)
185
+
186
+ # For Reader.each_buffer()
187
+ reader = Reader.new(fixture("valid/valid_mono_16_44100.wav"))
188
+ assert_equal(false, reader.closed?)
189
+ reader.each_buffer(1024) do |buffer|
190
+ # No-op
191
+ end
192
+ assert_equal(true, reader.closed?)
193
+ end
194
+
195
+ def test_read_after_close
196
+ reader = Reader.new(fixture("valid/valid_mono_16_44100.wav"))
197
+ buffer = reader.read(1024)
198
+ reader.close()
199
+ assert_raise(IOError) { reader.read(1024) }
200
+ end
201
+
202
+ private
203
+
204
+ def read_file(file_name, buffer_size, format=nil)
205
+ buffers = []
206
+ reader = Reader.new(fixture(file_name), format)
207
+
208
+ begin
209
+ while true do
210
+ buffers << reader.read(buffer_size)
211
+ end
212
+ rescue EOFError
213
+ reader.close()
214
+ end
215
+
216
+ return buffers
217
+ end
218
+
219
+ def fixture(fixture_name)
220
+ return "#{FIXTURE_ROOT_PATH}/#{fixture_name}"
221
+ end
222
+ end
@@ -0,0 +1,47 @@
1
+ module WaveFileIOTestHelper
2
+ CHANNEL_ALIAS = { :mono => 1, :stereo => 2, :tri => 3}
3
+
4
+ SQUARE_WAVE_CYCLE = {}
5
+ SQUARE_WAVE_CYCLE[:mono] = {}
6
+
7
+ SQUARE_WAVE_CYCLE[:mono][8] = [88, 88, 88, 88, 167, 167, 167, 167]
8
+ SQUARE_WAVE_CYCLE[:mono][16] = [-10000, -10000, -10000, -10000, 10000, 10000, 10000, 10000]
9
+ SQUARE_WAVE_CYCLE[:mono][32] = [-1000000000, -1000000000, -1000000000, -1000000000,
10
+ 1000000000, 1000000000, 1000000000, 1000000000]
11
+
12
+ SQUARE_WAVE_CYCLE[:stereo] = {}
13
+ SQUARE_WAVE_CYCLE[:stereo][8] = [[88, 88], [88, 88], [88, 88], [88, 88],
14
+ [167, 167], [167, 167], [167, 167], [167, 167]]
15
+ SQUARE_WAVE_CYCLE[:stereo][16] = [[-10000, -10000], [-10000, -10000], [-10000, -10000], [-10000, -10000],
16
+ [10000, 10000], [10000, 10000], [10000, 10000], [10000, 10000]]
17
+ SQUARE_WAVE_CYCLE[:stereo][32] = [[-1000000000, -1000000000], [-1000000000, -1000000000],
18
+ [-1000000000, -1000000000], [-1000000000, -1000000000],
19
+ [ 1000000000, 1000000000], [ 1000000000, 1000000000],
20
+ [ 1000000000, 1000000000], [ 1000000000, 1000000000]]
21
+
22
+ SQUARE_WAVE_CYCLE[:tri] = {}
23
+ SQUARE_WAVE_CYCLE[:tri][8] = [[88, 88, 88], [88, 88, 88], [88, 88, 88], [88, 88, 88],
24
+ [167, 167, 167], [167, 167, 167], [167, 167, 167], [167, 167, 167]]
25
+ SQUARE_WAVE_CYCLE[:tri][16] = [[-10000, -10000, -10000], [-10000, -10000, -10000],
26
+ [-10000, -10000, -10000], [-10000, -10000, -10000],
27
+ [ 10000, 10000, 10000], [ 10000, 10000, 10000],
28
+ [ 10000, 10000, 10000], [ 10000, 10000, 10000]]
29
+ SQUARE_WAVE_CYCLE[:tri][32] = [[-1000000000, -1000000000, -1000000000],
30
+ [-1000000000, -1000000000, -1000000000],
31
+ [-1000000000, -1000000000, -1000000000],
32
+ [-1000000000, -1000000000, -1000000000],
33
+ [ 1000000000, 1000000000, 1000000000],
34
+ [ 1000000000, 1000000000, 1000000000],
35
+ [ 1000000000, 1000000000, 1000000000],
36
+ [ 1000000000, 1000000000, 1000000000]]
37
+
38
+
39
+ # Executes the given block against different combinations of number of channels and bits per sample.
40
+ def exhaustively_test
41
+ [:mono, :stereo, :tri].each do |channels|
42
+ Format::SUPPORTED_BITS_PER_SAMPLE.each do |bits_per_sample|
43
+ yield(channels, bits_per_sample)
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,118 @@
1
+ require 'test/unit'
2
+ require 'wavefile.rb'
3
+ require 'wavefile_io_test_helper.rb'
4
+
5
+ include WaveFile
6
+
7
+ class WriterTest < Test::Unit::TestCase
8
+ include WaveFileIOTestHelper
9
+
10
+ OUTPUT_FOLDER = "test/fixtures/actual_output"
11
+
12
+ def setup
13
+ clean_output_folder()
14
+ end
15
+
16
+ def test_write_file_with_no_sample_data
17
+ writer = Writer.new("#{OUTPUT_FOLDER}/no_samples.wav", Format.new(1, 8, 44100))
18
+ writer.close()
19
+
20
+ assert_equal(read_file(:expected, "no_samples.wav"), read_file(:actual, "no_samples.wav"))
21
+ end
22
+
23
+ def test_write_basic_file
24
+ exhaustively_test do |channels, bits_per_sample|
25
+ file_name = "valid_#{channels}_#{bits_per_sample}_44100.wav"
26
+ format = Format.new(CHANNEL_ALIAS[channels], bits_per_sample, 44100)
27
+
28
+ writer = Writer.new("#{OUTPUT_FOLDER}/#{file_name}", format)
29
+ writer.write(Buffer.new(SQUARE_WAVE_CYCLE[channels][bits_per_sample] * 128, format))
30
+ writer.write(Buffer.new(SQUARE_WAVE_CYCLE[channels][bits_per_sample] * 128, format))
31
+ writer.write(Buffer.new(SQUARE_WAVE_CYCLE[channels][bits_per_sample] * 24, format))
32
+ writer.close()
33
+
34
+ assert_equal(read_file(:expected, file_name), read_file(:actual, file_name))
35
+ end
36
+ end
37
+
38
+ def test_write_basic_file_with_a_block
39
+ exhaustively_test do |channels, bits_per_sample|
40
+ file_name = "valid_#{channels}_#{bits_per_sample}_44100.wav"
41
+ format = Format.new(CHANNEL_ALIAS[channels], bits_per_sample, 44100)
42
+
43
+ writer = Writer.new("#{OUTPUT_FOLDER}/#{file_name}", format) do |writer|
44
+ 4.times do
45
+ writer.write(Buffer.new(SQUARE_WAVE_CYCLE[channels][bits_per_sample] * 70, format))
46
+ end
47
+ end
48
+
49
+ assert_equal(read_file(:expected, file_name), read_file(:actual, file_name))
50
+ assert(writer.closed?)
51
+ end
52
+ end
53
+
54
+ def test_write_buffers_of_different_formats
55
+ file_name = "valid_mono_8_44100.wav"
56
+ format_8bit_mono = Format.new(:mono, 8, 44100)
57
+ format_16_bit_mono = Format.new(:mono, 16, 22050)
58
+ format_16bit_stereo = Format.new(:stereo, 16, 44100)
59
+
60
+ writer = Writer.new("#{OUTPUT_FOLDER}/#{file_name}", format_8bit_mono)
61
+ writer.write(Buffer.new(SQUARE_WAVE_CYCLE[:stereo][16] * 128, format_16bit_stereo))
62
+ writer.write(Buffer.new(SQUARE_WAVE_CYCLE[:mono][16] * 128, format_16_bit_mono))
63
+ writer.write(Buffer.new(SQUARE_WAVE_CYCLE[:stereo][16] * 24, format_16bit_stereo))
64
+ writer.close()
65
+
66
+ assert_equal(read_file(:expected, file_name), read_file(:actual, file_name))
67
+ end
68
+
69
+ def test_write_file_with_padding_byte
70
+ file_name = "valid_mono_8_44100_with_padding_byte.wav"
71
+ format = Format.new(1, 8, 44100)
72
+
73
+ writer = Writer.new("#{OUTPUT_FOLDER}/#{file_name}", format)
74
+ writer.write(Buffer.new(SQUARE_WAVE_CYCLE[:mono][8] * 128, format))
75
+ writer.write(Buffer.new(SQUARE_WAVE_CYCLE[:mono][8] * 128, format))
76
+ writer.write(Buffer.new(SQUARE_WAVE_CYCLE[:mono][8] * 23 + [88, 88, 88, 88, 167, 167, 167], format))
77
+ writer.close()
78
+
79
+ assert_equal(read_file(:expected, file_name), read_file(:actual, file_name))
80
+ end
81
+
82
+ def test_closed?
83
+ writer = Writer.new("#{OUTPUT_FOLDER}/closed_test.wav", Format.new(1, 16, 44100))
84
+ assert_equal(false, writer.closed?)
85
+ writer.close()
86
+ assert(writer.closed?)
87
+ end
88
+
89
+ def test_attempt_to_write_after_close
90
+ format = Format.new(1, 8, 44100)
91
+
92
+ writer = Writer.new("#{OUTPUT_FOLDER}/write_after_close.wav", format)
93
+ writer.write(Buffer.new([1, 2, 3, 4], format))
94
+ writer.close()
95
+
96
+ assert_raise(IOError) { writer.write(Buffer.new([5, 6, 7, 8], format)) }
97
+ end
98
+
99
+ private
100
+
101
+ def read_file(type, file_name)
102
+ # For Windows compatibility with binary files, File.read() is not directly used
103
+ return File.open("test/fixtures/#{type}_output/#{file_name}", "rb") {|f| f.read() }
104
+ end
105
+
106
+ def clean_output_folder()
107
+ # Make the folder if it doesn't already exist
108
+ Dir.mkdir(OUTPUT_FOLDER) unless File.exists?(OUTPUT_FOLDER)
109
+
110
+ dir = Dir.new(OUTPUT_FOLDER)
111
+ file_names = dir.entries
112
+ file_names.each do |file_name|
113
+ if(file_name != "." && file_name != "..")
114
+ File.delete("#{OUTPUT_FOLDER}/#{file_name}")
115
+ end
116
+ end
117
+ end
118
+ end