wavefile 1.1.1 → 1.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE +1 -1
- data/README.markdown +39 -18
- data/lib/wavefile/buffer.rb +9 -7
- data/lib/wavefile/chunk_readers/format_chunk_reader.rb +11 -7
- data/lib/wavefile/duration.rb +3 -3
- data/lib/wavefile/reader.rb +13 -4
- data/lib/wavefile/sampler_info.rb +1 -1
- data/lib/wavefile/sampler_loop.rb +1 -1
- data/lib/wavefile/smpte_timecode.rb +1 -1
- data/lib/wavefile/writer.rb +3 -3
- data/lib/wavefile.rb +17 -17
- data/test/fixtures/wave/invalid/bad_wavefile_format.wav +0 -0
- data/test/fixtures/wave/invalid/empty_format_chunk.wav +0 -0
- data/test/fixtures/wave/invalid/extensible_format_chunk_extension_incomplete.wav +0 -0
- data/test/fixtures/wave/invalid/extensible_format_chunk_extension_incomplete_in_incorrectly_sized_chunk.wav +0 -0
- data/test/fixtures/wave/invalid/extensible_format_chunk_extension_incomplete_in_large_enough_chunk.wav +0 -0
- data/test/fixtures/wave/invalid/extensible_format_chunk_extension_missing.wav +0 -0
- data/test/fixtures/wave/invalid/extensible_format_chunk_extension_size_incomplete.wav +0 -0
- data/test/fixtures/wave/invalid/extensible_format_chunk_extension_size_incomplete_with_padding_byte.wav +0 -0
- data/test/fixtures/wave/invalid/extensible_format_chunk_extension_truncated.wav +0 -0
- data/test/fixtures/wave/invalid/extensible_format_chunk_oversized_extension_too_large.wav +0 -0
- data/test/fixtures/wave/invalid/float_format_chunk_extension_size_incomplete.wav +0 -0
- data/test/fixtures/wave/invalid/float_format_chunk_extension_size_incomplete_with_padding_byte.wav +0 -0
- data/test/fixtures/wave/invalid/float_format_chunk_oversized_extension_too_large.wav +0 -0
- data/test/fixtures/wave/invalid/format_chunk_extra_bytes_with_odd_size_and_missing_padding_byte.wav +0 -0
- data/test/fixtures/wave/invalid/format_chunk_with_extra_byte_and_missing_padding_byte.wav +0 -0
- data/test/fixtures/wave/invalid/insufficient_format_chunk.wav +0 -0
- data/test/fixtures/wave/invalid/no_data_chunk.wav +0 -0
- data/test/fixtures/wave/invalid/no_format_chunk.wav +0 -0
- data/test/fixtures/wave/invalid/no_format_chunk_size.wav +0 -0
- data/test/fixtures/wave/invalid/no_riff_format.wav +0 -0
- data/test/fixtures/wave/invalid/unsupported_format_extension_size_incomplete.wav +0 -0
- data/test/fixtures/wave/invalid/unsupported_format_extension_size_incomplete_with_padding_byte.wav +0 -0
- data/test/fixtures/wave/invalid/unsupported_format_extension_truncated.wav +0 -0
- data/test/fixtures/wave/invalid/unsupported_format_oversized_extension_too_large.wav +0 -0
- data/test/fixtures/wave/unsupported/bad_sample_rate.wav +0 -0
- data/test/fixtures/wave/unsupported/extensible_container_size_bigger_than_sample_size.wav +0 -0
- data/test/fixtures/wave/unsupported/extensible_unsupported_subformat_guid.wav +0 -0
- data/test/fixtures/wave/unsupported/unsupported_audio_format.wav +0 -0
- data/test/fixtures/wave/unsupported/unsupported_format_code_missing_extension_size.wav +0 -0
- data/test/fixtures/wave/unsupported/unsupported_format_code_with_extension.wav +0 -0
- data/test/fixtures/wave/unsupported/unsupported_format_code_with_extension_and_extra_bytes.wav +0 -0
- data/test/fixtures/wave/unsupported/unsupported_format_code_with_incomplete_extension.wav +0 -0
- data/test/fixtures/wave/unsupported/unsupported_format_code_with_oversized_extension.wav +0 -0
- data/test/fixtures/wave/unsupported/unsupported_format_code_with_oversized_extension_and_extra_bytes.wav +0 -0
- data/test/fixtures/wave/valid/valid_extensible_format_chunk_oversized_extension.wav +0 -0
- data/test/fixtures/wave/valid/valid_extensible_format_chunk_oversized_extension_and_extra_bytes.wav +0 -0
- data/test/fixtures/wave/valid/valid_extensible_format_chunk_with_extra_bytes.wav +0 -0
- data/test/fixtures/wave/valid/valid_float_format_chunk_missing_extension_size.wav +0 -0
- data/test/fixtures/wave/valid/valid_float_format_chunk_oversized_extension.wav +0 -0
- data/test/fixtures/wave/valid/valid_float_format_chunk_oversized_extension_and_extra_bytes.wav +0 -0
- data/test/fixtures/wave/valid/valid_float_format_chunk_with_extra_bytes.wav +0 -0
- data/test/fixtures/wave/valid/valid_format_chunk_extra_bytes_with_odd_size_and_padding_byte.wav +0 -0
- data/test/fixtures/wave/valid/valid_format_chunk_with_extra_byte_and_padding_byte.wav +0 -0
- data/test/fixtures/wave/valid/valid_format_chunk_with_extra_bytes.wav +0 -0
- data/test/reader_test.rb +442 -6
- data/test/wavefile_io_test_helper.rb +3 -3
- data/test/writer_test.rb +1 -1
- metadata +40 -8
- data/test/fixtures/wave/unsupported/bad_audio_format.wav +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 00fb7f8e8dc794a4cb669d3709cc05a1776f752a27d501668760bf14bae70746
|
4
|
+
data.tar.gz: 0a86b94b3c8891b365be3c9ffc17f824b5a97b31d22a9d9a884caf66657a935e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7c0978db16d2ea9baca96c9880b8816bd9829bbb7e2c34404d815e58219eb7dc715b0e9e30d6b4b75f6fb2dc1b22b517ececd0fcfd3ac43d76ff148761ed2bf7
|
7
|
+
data.tar.gz: a57b221b66a60962d3ad7e3c90ff66b0bee00e848f7aafd2eebc282ef0fefed7998f5a4c2b6297ade454566ff0fbeacf0e7887d892c6e22939e4490edaec80cc
|
data/LICENSE
CHANGED
data/README.markdown
CHANGED
@@ -2,14 +2,14 @@ A Ruby gem for reading and writing sound files in Wave format (*.wav).
|
|
2
2
|
|
3
3
|
You can use this gem to create Ruby programs that work with audio, such as a [command-line drum machine](https://beatsdrummachine.com). Since it is written in pure Ruby (as opposed to wrapping an existing C library), you can use it without having to compile a separate extension.
|
4
4
|
|
5
|
-
For more info, check out the website: <
|
5
|
+
For more info, check out the website: <https://wavefilegem.com/>
|
6
6
|
|
7
7
|
# Example Usage
|
8
8
|
|
9
|
-
This
|
9
|
+
This example shows how to append three separate Wave files into a single file:
|
10
10
|
|
11
11
|
```ruby
|
12
|
-
require
|
12
|
+
require "wavefile"
|
13
13
|
include WaveFile
|
14
14
|
|
15
15
|
FILES_TO_APPEND = ["file1.wav", "file2.wav", "file3.wav"]
|
@@ -23,7 +23,7 @@ Writer.new("append.wav", Format.new(:stereo, :pcm_16, 44100)) do |writer|
|
|
23
23
|
end
|
24
24
|
```
|
25
25
|
|
26
|
-
More examples can be found at <
|
26
|
+
More examples can be found at <https://wavefilegem.com/examples>.
|
27
27
|
|
28
28
|
|
29
29
|
# Installation
|
@@ -34,16 +34,16 @@ First, install the WaveFile gem from rubygems.org:
|
|
34
34
|
|
35
35
|
...and include it in your Ruby program:
|
36
36
|
|
37
|
-
require
|
37
|
+
require "wavefile"
|
38
38
|
|
39
|
-
Note that if you're installing the gem into the default Ruby that comes pre-installed on MacOS (as opposed to a Ruby installed via [RVM](
|
39
|
+
Note that if you're installing the gem into the default Ruby that comes pre-installed on MacOS (as opposed to a Ruby installed via [RVM](https://rvm.io/) or [rbenv](https://github.com/sstephenson/rbenv/)), you should used `sudo gem install wavefile`. Otherwise you might run into a file permission error.
|
40
40
|
|
41
41
|
|
42
42
|
# Compatibility
|
43
43
|
|
44
44
|
WaveFile has been tested with these Ruby versions, and appears to be compatible with them:
|
45
45
|
|
46
|
-
* MRI 2.
|
46
|
+
* MRI 3.2.0, 3.1.3, 3.0.5, 2.7.7, 2.6.10, 2.5.9, 2.4.10, 2.3.8, 2.2.10, 2.1.10, 2.0.0-p648
|
47
47
|
|
48
48
|
2.0 is the minimum supported Ruby version.
|
49
49
|
|
@@ -65,25 +65,46 @@ This gem lets you read and write audio data! You can use it to create Ruby progr
|
|
65
65
|
* Seamlessly convert between sample formats. Read sample data from a file into any format supported by this gem, regardless of how the sample data is stored in the actual file. Or, create sample data in one format (such as floats between -1.0 and 1.0), but write it to a file in a different format (such as 16-bit PCM).
|
66
66
|
* Automatic file management, similar to how `IO.open` works. That is, you can open a file for reading or writing, and if a block is given, the file will automatically be closed when the block exits.
|
67
67
|
* Query metadata about Wave files (sample rate, number of channels, number of sample frames, etc.), including files that are in a format this gem can't read or write.
|
68
|
-
*
|
68
|
+
* Easy to install, since it's written in pure Ruby. There's no need to compile a separate extension in order to use it.
|
69
69
|
|
70
70
|
|
71
|
-
# Current Release: v1.1.
|
71
|
+
# Current Release: v1.1.2
|
72
72
|
|
73
|
-
Released on December
|
73
|
+
Released on December 30, 2022, this version fixes several edge case bugs related to reading a *.wav file's `"fmt "` chunk. In particular, reading a `"fmt "` chunk that has extra trailing bytes; reading a `"fmt "` chunk in WAVE_FORMAT_EXTENSIBLE format whose chunk extension is missing, incomplete, or has extra trailing bytes; and reading a `"fmt "` chunk whose chunk extension is too large to fit in the chunk. In short, some valid files that were previously rejected can now be read, and some invalid files are handled more properly.
|
74
74
|
|
75
|
-
|
75
|
+
The full details:
|
76
|
+
|
77
|
+
* **Bug Fix:** Files that have extra bytes at the end of the `"fmt "` chunk can now be read.
|
78
|
+
|
79
|
+
If the format code is `1`, the `"fmt "` chunk has extra bytes if the chunk body size is greater than 16 bytes. Otherwise, "extra bytes" means the chunk contains bytes after the chunk extension (not including the required padding byte for an odd-sized chunk).
|
80
|
+
|
81
|
+
Previously, attempting to open certain files like this via `Reader.new` would result in `InvalidFormatError` being raised with a misleading `"Not a supported wave file. The format chunk extension is shorter than expected."` message. This was misleading because if the format code is `1`, the `"fmt "` chunk won't actually have a chunk extension, and for other format codes the chunk extension might actually be the expected size or larger. When reading a file like this, any extra data in the `"fmt "` chunk beyond what is expected based on the relevant format code will now be ignored.
|
82
|
+
|
83
|
+
* There was a special case where a file like this _could_ be opened correctly. If the format code was `1`, and the value of bytes 16 and 17 (0-based), when interpreted as a 16-bit unsigned little-endian integer, happened to be the same as the number of subsequent bytes in the chunk, the file could be opened without issue. For example, if the `"fmt "` chunk size was `22`, the format code was `1`, and the value of bytes 16 and 17 was `4` (when interpreted as a 16-bit unsigned little-endian integer), the file could be opened correctly.
|
84
|
+
* There was another special case where `InvalidFormatError` would be incorrectly raised, but the error message would be different (and also misleading). If the format code was `1`, and there was exactly 1 extra byte in the `"fmt "` chunk (i.e. the chunk size was 17 bytes), the error message would be `"Not a supported wave file. The format chunk is missing an expected extension."` This was misleading because when the format code is `1`, the `"fmt "` chunk doesn't have a chunk extension.
|
85
|
+
* Thanks to [@CromonMS](https://github.com/CromonMS) for reporting this as an issue.
|
86
|
+
|
87
|
+
* **Bug Fix:** Files in WAVE_FORMAT_EXTENSIBLE format with a missing or incomplete `"fmt "` chunk extension can no longer be opened using `Reader.new`.
|
88
|
+
|
89
|
+
Previously, a `Reader` instance could be constructed for a file like this, but the relevant fields on the object returned by `Reader#native_format` would contain `nil` or `""` values for these fields, and no sample data could be read from the file. Since files like this are missing required fields that don't necessarily have sensible default values, it seems like it shouldn't be possible to create a `Reader` instance from them. After this fix, attempting to do so will cause `InvalidFormatError` to be raised.
|
76
90
|
|
91
|
+
* **Bug Fix:** Files in WAVE_FORMAT_EXTENSIBLE format that have extra bytes at the end of the `"fmt "` chunk extension can now be read.
|
77
92
|
|
78
|
-
|
93
|
+
This is similar but different from the first bug above; that bug refers to extra bytes _after_ the chunk extension, while this bug refers to extra bytes _inside_ the chunk extension. A WAVE_FORMAT_EXTENSIBLE `"fmt "` chunk extension has extra bytes if it is larger than 22 bytes.
|
79
94
|
|
80
|
-
|
95
|
+
Previously, a `Reader` instance could be constructed for a file like this, but `Reader#native_format#sub_audio_format_guid` would have an incorrect value, and sample data could not be read from the file. After this fix, this field will have the correct value, and if it is one of the supported values then sample data can be read. Any extra data at the end of the chunk extension will be ignored.
|
81
96
|
|
82
|
-
|
83
|
-
|
84
|
-
* **Bug Fix
|
85
|
-
|
86
|
-
|
97
|
+
Implicit in this scenario is that the `"fmt "` chunk has a stated size large enough to fit the oversized chunk extension. For cases where it doesn't, see the next bug fix below.
|
98
|
+
|
99
|
+
* **Bug Fix:** More accurate message on the `InvalidFormatError` raised when reading a file whose `"fmt "` chunk extension is too large to fit in the chunk.
|
100
|
+
|
101
|
+
The message will now correctly state that the chunk extension is too large, rather than `"Not a supported wave file. The format chunk extension is shorter than expected."`. As an example of what "too large" means, if a `"fmt "` chunk has a size of 50 bytes, then any chunk extension larger than 32 bytes will be too large and overflow out of the chunk, since a chunk extension's content always starts at byte 18 (0-based).
|
102
|
+
|
103
|
+
# Previous Release: v1.1.1
|
104
|
+
|
105
|
+
Released on December 29, 2019, this version contains this change:
|
106
|
+
|
107
|
+
* Removes `warning: Using the last argument as keyword parameters is deprecated; maybe ** should be added to the call` output when reading a file with a `smpl` chunk using Ruby 2.7.0. (And presumably, higher Ruby versions as well, but Ruby 2.7.0 is the most recent Ruby version at the time of this release).
|
87
108
|
|
88
109
|
For changes in previous versions, visit <https://github.com/jstrait/wavefile/releases>.
|
89
110
|
|
data/lib/wavefile/buffer.rb
CHANGED
@@ -37,15 +37,17 @@ module WaveFile
|
|
37
37
|
# don't match, unexpected things will happen.
|
38
38
|
#
|
39
39
|
# Examples
|
40
|
+
# # One cycle of a floating point 441Hz mono square wave
|
41
|
+
# samples = ([0.5] * 50) + ([-0.5] * 50)
|
42
|
+
# buffer = Buffer.new(samples, Format.new(:mono, :float, 44100))
|
40
43
|
#
|
41
|
-
#
|
42
|
-
#
|
44
|
+
# # One cycle of a floating point 441Hz stereo square wave
|
45
|
+
# samples = ([0.5, 0.5] * 50) + ([-0.5, -0.5] * 50)
|
46
|
+
# buffer = Buffer.new(samples, Format.new(2, :float, 44100))
|
43
47
|
#
|
44
|
-
#
|
45
|
-
#
|
46
|
-
#
|
47
|
-
# samples = ([16000] * 50) + ([-16000] * 50) # A 16-bit PCM 440Hz mono square wave
|
48
|
-
# buffer = Buffer.new(samples, Format.new(1, :pcm_16, 44100)
|
48
|
+
# # One cycle of a 16-bit PCM 441Hz mono square wave
|
49
|
+
# samples = ([16000] * 50) + ([-16000] * 50)
|
50
|
+
# buffer = Buffer.new(samples, Format.new(1, :pcm_16, 44100))
|
49
51
|
#
|
50
52
|
# Returns a constructed Buffer.
|
51
53
|
def initialize(samples, format)
|
@@ -22,21 +22,25 @@ module WaveFile
|
|
22
22
|
format_chunk[:block_align],
|
23
23
|
format_chunk[:bits_per_sample] = raw_bytes.slice!(0...MINIMUM_CHUNK_SIZE).unpack("vvVVvv")
|
24
24
|
|
25
|
-
if @chunk_size > MINIMUM_CHUNK_SIZE
|
26
|
-
|
27
|
-
|
28
|
-
if format_chunk[:extension_size] == nil
|
25
|
+
if format_chunk[:audio_format] == FORMAT_CODES[:extensible] || (format_chunk[:audio_format] != FORMAT_CODES[:pcm] && @chunk_size > MINIMUM_CHUNK_SIZE)
|
26
|
+
if raw_bytes.length < 2
|
29
27
|
raise_error InvalidFormatError, "The format chunk is missing an expected extension."
|
30
28
|
end
|
31
29
|
|
32
|
-
|
33
|
-
|
30
|
+
format_chunk[:extension_size] = raw_bytes.slice!(0...2).unpack(UNSIGNED_INT_16).first
|
31
|
+
|
32
|
+
if format_chunk[:extension_size] > raw_bytes.length
|
33
|
+
raise_error InvalidFormatError, "The format chunk extension size of #{format_chunk[:extension_size]} bytes is too large to fit in the format chunk. The format chunk has a stated size of #{@chunk_size} bytes, with #{raw_bytes.length} bytes available for the extension."
|
34
34
|
end
|
35
35
|
|
36
36
|
if format_chunk[:audio_format] == FORMAT_CODES[:extensible]
|
37
|
+
if format_chunk[:extension_size] < 22
|
38
|
+
raise_error InvalidFormatError, "The format chunk extension size of #{format_chunk[:extension_size]} bytes is too small. Since the format chunk has a format code of #{FORMAT_CODES[:extensible]} (i.e. WAVE_FORMAT_EXTENSIBLE), the extension size must be at least 22 bytes."
|
39
|
+
end
|
40
|
+
|
37
41
|
format_chunk[:valid_bits_per_sample] = raw_bytes.slice!(0...2).unpack(UNSIGNED_INT_16).first
|
38
42
|
format_chunk[:speaker_mapping] = raw_bytes.slice!(0...4).unpack(UNSIGNED_INT_32).first
|
39
|
-
format_chunk[:sub_audio_format_guid] = raw_bytes
|
43
|
+
format_chunk[:sub_audio_format_guid] = raw_bytes.slice!(0...16)
|
40
44
|
end
|
41
45
|
end
|
42
46
|
|
data/lib/wavefile/duration.rb
CHANGED
@@ -37,17 +37,17 @@ module WaveFile
|
|
37
37
|
sample_frames_per_hour = sample_frames_per_minute * 60
|
38
38
|
@hours, @minutes, @seconds, @milliseconds = 0, 0, 0, 0
|
39
39
|
|
40
|
-
if
|
40
|
+
if sample_frame_count >= sample_frames_per_hour
|
41
41
|
@hours = sample_frame_count / sample_frames_per_hour
|
42
42
|
sample_frame_count -= sample_frames_per_hour * @hours
|
43
43
|
end
|
44
44
|
|
45
|
-
if
|
45
|
+
if sample_frame_count >= sample_frames_per_minute
|
46
46
|
@minutes = sample_frame_count / sample_frames_per_minute
|
47
47
|
sample_frame_count -= sample_frames_per_minute * @minutes
|
48
48
|
end
|
49
49
|
|
50
|
-
if
|
50
|
+
if sample_frame_count >= sample_frames_per_second
|
51
51
|
@seconds = sample_frame_count / sample_frames_per_second
|
52
52
|
sample_frame_count -= sample_frames_per_second * @seconds
|
53
53
|
end
|
data/lib/wavefile/reader.rb
CHANGED
@@ -56,9 +56,9 @@ module WaveFile
|
|
56
56
|
end
|
57
57
|
|
58
58
|
|
59
|
-
# Public:
|
60
|
-
# no more sample
|
61
|
-
# closed. Each Buffer is passed to the given block.
|
59
|
+
# Public: Starting from the current reading position, reads sample frames into successive Buffers
|
60
|
+
# of the specified size, until there are no more sample frames to be read. When the final sample
|
61
|
+
# frame has been read the Reader is automatically closed. Each Buffer is passed to the given block.
|
62
62
|
#
|
63
63
|
# If the Reader is constructed from an open IO, the IO is NOT closed after all sample data is
|
64
64
|
# read. However, the Reader will be closed and any attempt to continue to read from it will
|
@@ -93,6 +93,15 @@ module WaveFile
|
|
93
93
|
# # Although Reader is closed, file still needs to be manually closed
|
94
94
|
# file.close
|
95
95
|
#
|
96
|
+
# reader = Reader.new("my_file.wav")
|
97
|
+
# reader.read(100)
|
98
|
+
# # Reading using `each_buffer` will start at the 101st sample frame:
|
99
|
+
# reader.each_buffer do |buffer|
|
100
|
+
# puts "#{buffer.samples.length} sample frames read"
|
101
|
+
# end
|
102
|
+
# # At this point, the Reader is now closed (even without
|
103
|
+
# # a call to `close()`)
|
104
|
+
#
|
96
105
|
# Returns nothing. Has side effect of closing the Reader.
|
97
106
|
def each_buffer(sample_frame_count=4096)
|
98
107
|
begin
|
@@ -116,7 +125,7 @@ module WaveFile
|
|
116
125
|
#
|
117
126
|
# Raises UnsupportedFormatError if file is in a format that can't be read by this gem.
|
118
127
|
#
|
119
|
-
# Raises ReaderClosedError if the
|
128
|
+
# Raises ReaderClosedError if the Reader has been closed.
|
120
129
|
#
|
121
130
|
# Raises EOFError if no samples could be read due to reaching the end of the file.
|
122
131
|
def read(sample_frame_count)
|
@@ -11,7 +11,7 @@ module WaveFile
|
|
11
11
|
# Public: Provides a way to indicate the data contained in a "smpl" chunk.
|
12
12
|
# That is, information about how the *.wav file could be used by a
|
13
13
|
# sampler, such as the file's MIDI note or loop points. If a *.wav
|
14
|
-
# file contains a "smpl" chunk, then Reader
|
14
|
+
# file contains a "smpl" chunk, then Reader#sampler_info will
|
15
15
|
# return an instance of this object with the relevant info.
|
16
16
|
class SamplerInfo
|
17
17
|
VALID_32_BIT_INTEGER_RANGE = 0..4_294_967_295 # :nodoc:
|
@@ -12,7 +12,7 @@ module WaveFile
|
|
12
12
|
# Public: Provides a way to indicate the data about sampler loop points
|
13
13
|
# in a file's "smpl" chunk. That is, information about how a sampler
|
14
14
|
# could loop between a sample range while playing this *.wav as a note.
|
15
|
-
# If a *.wav file contains a "smpl" chunk, then Reader
|
15
|
+
# If a *.wav file contains a "smpl" chunk, then Reader#sampler_info#loops
|
16
16
|
# will return an array of SamplerLoop objects with the relevant info.
|
17
17
|
class SamplerLoop
|
18
18
|
VALID_32_BIT_INTEGER_RANGE = 0..4_294_967_295 # :nodoc:
|
@@ -6,7 +6,7 @@ module WaveFile
|
|
6
6
|
class InvalidSMPTETimecodeError < StandardError; end
|
7
7
|
|
8
8
|
# Public: Represents an SMPTE timecode: https://en.wikipedia.org/wiki/SMPTE_timecode
|
9
|
-
# If a *.wav file has a "smpl" chunk, then Reader
|
9
|
+
# If a *.wav file has a "smpl" chunk, then Reader#sampler_info#smpte_offset
|
10
10
|
# will return an instance of this class.
|
11
11
|
class SMPTETimecode
|
12
12
|
VALID_8_BIT_UNSIGNED_INTEGER_RANGE = 0..255 # :nodoc:
|
data/lib/wavefile/writer.rb
CHANGED
@@ -242,10 +242,10 @@ module WaveFile
|
|
242
242
|
# Data Chunk Header (8 bytes)
|
243
243
|
#
|
244
244
|
# All wave files written by Writer use this canonical format.
|
245
|
-
CANONICAL_HEADER_BYTE_LENGTH = {:
|
245
|
+
CANONICAL_HEADER_BYTE_LENGTH = {pcm: 36, float: 50, extensible: 72}.freeze # :nodoc:
|
246
246
|
|
247
247
|
# Internal
|
248
|
-
FORMAT_CHUNK_BYTE_LENGTH = {:
|
248
|
+
FORMAT_CHUNK_BYTE_LENGTH = {pcm: 16, float: 18, extensible: 40}.freeze # :nodoc:
|
249
249
|
|
250
250
|
# Internal
|
251
251
|
SPEAKER_MAPPING_BIT_VALUES = {
|
@@ -273,7 +273,7 @@ module WaveFile
|
|
273
273
|
# Internal
|
274
274
|
def pack_speaker_mapping(speaker_mapping)
|
275
275
|
speaker_mapping.inject(0) do |result, speaker|
|
276
|
-
result
|
276
|
+
result | SPEAKER_MAPPING_BIT_VALUES[speaker]
|
277
277
|
end
|
278
278
|
end
|
279
279
|
|
data/lib/wavefile.rb
CHANGED
@@ -10,28 +10,28 @@ require 'wavefile/unvalidated_format'
|
|
10
10
|
require 'wavefile/writer'
|
11
11
|
|
12
12
|
module WaveFile
|
13
|
-
VERSION = "1.1.
|
13
|
+
VERSION = "1.1.2"
|
14
14
|
|
15
15
|
WAVEFILE_FORMAT_CODE = "WAVE" # :nodoc:
|
16
|
-
FORMAT_CODES = {:
|
16
|
+
FORMAT_CODES = {pcm: 1, float: 3, extensible: 65534}.freeze # :nodoc:
|
17
17
|
SUB_FORMAT_GUID_PCM = String.new("\x01\x00\x00\x00\x00\x00\x10\x00\x80\x00\x00\xAA\x00\x38\x9B\x71").force_encoding("ASCII-8BIT").freeze # :nodoc:
|
18
18
|
SUB_FORMAT_GUID_FLOAT = String.new("\x03\x00\x00\x00\x00\x00\x10\x00\x80\x00\x00\xAA\x00\x38\x9B\x71").force_encoding("ASCII-8BIT").freeze # :nodoc:
|
19
|
-
CHUNK_IDS = {:
|
20
|
-
:
|
21
|
-
:
|
22
|
-
:
|
23
|
-
:
|
24
|
-
:
|
25
|
-
:
|
26
|
-
:
|
27
|
-
:
|
28
|
-
:
|
29
|
-
:
|
30
|
-
:
|
31
|
-
:
|
19
|
+
CHUNK_IDS = {riff: "RIFF",
|
20
|
+
format: "fmt ",
|
21
|
+
data: "data",
|
22
|
+
fact: "fact",
|
23
|
+
silence: "slnt",
|
24
|
+
cue: "cue ",
|
25
|
+
playlist: "plst",
|
26
|
+
list: "list",
|
27
|
+
label: "labl",
|
28
|
+
labeled_text: "ltxt",
|
29
|
+
note: "note",
|
30
|
+
sample: "smpl",
|
31
|
+
instrument: "inst" }.freeze # :nodoc:
|
32
32
|
|
33
|
-
PACK_CODES = {:
|
34
|
-
:
|
33
|
+
PACK_CODES = {pcm: { 8 => "C*", 16 => "s<*", 24 => "C*", 32 => "l<*"}.freeze,
|
34
|
+
float: { 32 => "e*", 64 => "E*"}.freeze}.freeze # :nodoc:
|
35
35
|
|
36
36
|
UNSIGNED_INT_16 = "v" # :nodoc:
|
37
37
|
UNSIGNED_INT_32 = "V" # :nodoc:
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
data/test/fixtures/wave/invalid/float_format_chunk_extension_size_incomplete_with_padding_byte.wav
ADDED
Binary file
|
Binary file
|
data/test/fixtures/wave/invalid/format_chunk_extra_bytes_with_odd_size_and_missing_padding_byte.wav
ADDED
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
data/test/fixtures/wave/invalid/unsupported_format_extension_size_incomplete_with_padding_byte.wav
ADDED
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
data/test/fixtures/wave/unsupported/unsupported_format_code_with_extension_and_extra_bytes.wav
ADDED
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
data/test/fixtures/wave/valid/valid_extensible_format_chunk_oversized_extension_and_extra_bytes.wav
ADDED
Binary file
|
data/test/fixtures/wave/valid/valid_float_format_chunk_oversized_extension_and_extra_bytes.wav
ADDED
Binary file
|
data/test/fixtures/wave/valid/valid_format_chunk_extra_bytes_with_odd_size_and_padding_byte.wav
ADDED
Binary file
|
Binary file
|
Binary file
|
data/test/reader_test.rb
CHANGED
@@ -49,6 +49,73 @@ class ReaderTest < Minitest::Test
|
|
49
49
|
# The format chunk has some data, but not all of the minimum required.
|
50
50
|
"invalid/insufficient_format_chunk.wav",
|
51
51
|
|
52
|
+
# The format chunk has a size of 17, but is missing the required padding byte
|
53
|
+
# The extra byte is part of what would be the chunk extension size if the format
|
54
|
+
# code weren't 1.
|
55
|
+
"invalid/format_chunk_with_extra_byte_and_missing_padding_byte.wav",
|
56
|
+
|
57
|
+
# The format chunk has an odd size with extra bytes at the end, but is
|
58
|
+
# missing the required padding byte
|
59
|
+
"invalid/format_chunk_extra_bytes_with_odd_size_and_missing_padding_byte.wav",
|
60
|
+
|
61
|
+
# The format chunk is floating point but the extension size field is incomplete
|
62
|
+
"invalid/float_format_chunk_extension_size_incomplete.wav",
|
63
|
+
|
64
|
+
# The format chunk is floating point but the extension size field is incomplete.
|
65
|
+
# The padding byte which is present should not be interpreted as part of the size field.
|
66
|
+
"invalid/float_format_chunk_extension_size_incomplete_with_padding_byte.wav",
|
67
|
+
|
68
|
+
# The format chunk is floating point and has an oversized extension,
|
69
|
+
# and the extension is too large to fit in the stated size of the chunk
|
70
|
+
"invalid/float_format_chunk_oversized_extension_too_large.wav",
|
71
|
+
|
72
|
+
# The format chunk is extensible, but the required extension is not present
|
73
|
+
"invalid/extensible_format_chunk_extension_missing.wav",
|
74
|
+
|
75
|
+
# The format chunk is extensible, but the extension size field is incomplete.
|
76
|
+
# The required padding byte is present.
|
77
|
+
"invalid/extensible_format_chunk_extension_size_incomplete_with_padding_byte.wav",
|
78
|
+
|
79
|
+
# The format chunk is extensible, but the extension size field is incomplete.
|
80
|
+
# The required padding byte is not present.
|
81
|
+
"invalid/extensible_format_chunk_extension_size_incomplete.wav",
|
82
|
+
|
83
|
+
# The format chunk is extensible, but the extension is shorter than required
|
84
|
+
"invalid/extensible_format_chunk_extension_incomplete.wav",
|
85
|
+
|
86
|
+
# The format chunk is extensible, but the extension is shorter than required
|
87
|
+
# (even though the chunk is large enough to contain a full extension).
|
88
|
+
"invalid/extensible_format_chunk_extension_incomplete_in_large_enough_chunk.wav",
|
89
|
+
|
90
|
+
# The format chunk is extensible, but the extension is shorter than required
|
91
|
+
# (the chunk has a stated size that is large enough, although it is larger than the actual amount of data).
|
92
|
+
"invalid/extensible_format_chunk_extension_incomplete_in_incorrectly_sized_chunk.wav",
|
93
|
+
|
94
|
+
# The format chunk is extensible, but the chunk doesn't have enough room for the extension
|
95
|
+
"invalid/extensible_format_chunk_extension_truncated.wav",
|
96
|
+
|
97
|
+
# The format chunk is extensible and has an oversized extension,
|
98
|
+
# and the extension is too large to fit in the stated size of the chunk
|
99
|
+
"invalid/extensible_format_chunk_oversized_extension_too_large.wav",
|
100
|
+
|
101
|
+
# The format chunk has an unsupported format code (not an error),
|
102
|
+
# but the extension size field is incomplete.
|
103
|
+
"invalid/unsupported_format_extension_size_incomplete.wav",
|
104
|
+
|
105
|
+
# The format chunk has an unsupported format code (not an error),
|
106
|
+
# but the extension size field is incomplete.
|
107
|
+
# The padding byte which is present should not be interpreted as part of the size field.
|
108
|
+
"invalid/unsupported_format_extension_size_incomplete_with_padding_byte.wav",
|
109
|
+
|
110
|
+
# The format chunk has an unsupported format code (not an error),
|
111
|
+
# but the chunk doesn't have enough room for the extension.
|
112
|
+
"invalid/unsupported_format_extension_truncated.wav",
|
113
|
+
|
114
|
+
# The format chunk has an unsupported format code (not an error),
|
115
|
+
# and an oversized extension. The extension is too large to fit in
|
116
|
+
# the stated size of the chunk.
|
117
|
+
"invalid/unsupported_format_oversized_extension_too_large.wav",
|
118
|
+
|
52
119
|
# The RIFF header and format chunk are OK, but there is no data chunk
|
53
120
|
"invalid/no_data_chunk.wav",
|
54
121
|
|
@@ -127,9 +194,36 @@ class ReaderTest < Minitest::Test
|
|
127
194
|
|
128
195
|
def test_read_from_unsupported_format
|
129
196
|
unsupported_fixtures = [
|
130
|
-
#
|
197
|
+
# Format code has an unsupported value
|
131
198
|
"unsupported/unsupported_audio_format.wav",
|
132
199
|
|
200
|
+
# Format code has an unsupported value, and the format
|
201
|
+
# chunk has an extension.
|
202
|
+
"unsupported/unsupported_format_code_with_extension.wav",
|
203
|
+
|
204
|
+
# Format code has an unsupported value, and the format chunk does not
|
205
|
+
# have the expected "extension size" field. This field is not required
|
206
|
+
# by the gem so this should not cause `InvalidFormatError` to be raised.
|
207
|
+
"unsupported/unsupported_format_code_missing_extension_size.wav",
|
208
|
+
|
209
|
+
# Format code has an unsupported value, the format chunk has an extension,
|
210
|
+
# and extra bytes follow the extension.
|
211
|
+
"unsupported/unsupported_format_code_with_extension_and_extra_bytes.wav",
|
212
|
+
|
213
|
+
# Format code has an unsupported value, and a chunk extension that
|
214
|
+
# is smaller than is should be for the given format code. However,
|
215
|
+
# this should not cause an error because chunk extensions for unsupported
|
216
|
+
# formats are not parsed.
|
217
|
+
"unsupported/unsupported_format_code_with_incomplete_extension.wav",
|
218
|
+
|
219
|
+
# Format code has an unsupported value, and the format chunk has an oversized
|
220
|
+
# extension with extra bytes at the end.
|
221
|
+
"unsupported/unsupported_format_code_with_oversized_extension.wav",
|
222
|
+
|
223
|
+
# Format code has an unsupported value, the format chunk has an oversized extension
|
224
|
+
# with extra bytes at the end, and extra bytes follow the extension.
|
225
|
+
"unsupported/unsupported_format_code_with_oversized_extension_and_extra_bytes.wav",
|
226
|
+
|
133
227
|
# Bits per sample is 20, which is not supported
|
134
228
|
"unsupported/unsupported_bits_per_sample.wav",
|
135
229
|
|
@@ -240,7 +334,9 @@ class ReaderTest < Minitest::Test
|
|
240
334
|
assert_equal(2, reader.native_format.channels)
|
241
335
|
assert_equal(16, reader.native_format.bits_per_sample)
|
242
336
|
assert_equal(44100, reader.native_format.sample_rate)
|
337
|
+
assert_equal(16, reader.native_format.valid_bits_per_sample)
|
243
338
|
assert_equal([:front_left, :front_right], reader.native_format.speaker_mapping)
|
339
|
+
assert_equal(WaveFile::SUB_FORMAT_GUID_PCM, reader.native_format.sub_audio_format_guid)
|
244
340
|
assert_equal(2, reader.format.channels)
|
245
341
|
assert_equal(16, reader.format.bits_per_sample)
|
246
342
|
assert_equal(44100, reader.format.sample_rate)
|
@@ -267,7 +363,9 @@ class ReaderTest < Minitest::Test
|
|
267
363
|
assert_equal(2, reader.native_format.channels)
|
268
364
|
assert_equal(24, reader.native_format.bits_per_sample)
|
269
365
|
assert_equal(44100, reader.native_format.sample_rate)
|
366
|
+
assert_equal(24, reader.native_format.valid_bits_per_sample)
|
270
367
|
assert_equal([:undefined, :undefined], reader.native_format.speaker_mapping)
|
368
|
+
assert_equal(WaveFile::SUB_FORMAT_GUID_PCM, reader.native_format.sub_audio_format_guid)
|
271
369
|
assert_equal(2, reader.format.channels)
|
272
370
|
assert_equal(24, reader.format.bits_per_sample)
|
273
371
|
assert_equal(44100, reader.format.sample_rate)
|
@@ -294,7 +392,9 @@ class ReaderTest < Minitest::Test
|
|
294
392
|
assert_equal(2, reader.native_format.channels)
|
295
393
|
assert_equal(16, reader.native_format.bits_per_sample)
|
296
394
|
assert_equal(44100, reader.native_format.sample_rate)
|
395
|
+
assert_equal(16, reader.native_format.valid_bits_per_sample)
|
297
396
|
assert_equal([:front_left, :front_right, :front_center, :low_frequency], reader.native_format.speaker_mapping)
|
397
|
+
assert_equal(WaveFile::SUB_FORMAT_GUID_PCM, reader.native_format.sub_audio_format_guid)
|
298
398
|
assert_equal(2, reader.format.channels)
|
299
399
|
assert_equal(16, reader.format.bits_per_sample)
|
300
400
|
assert_equal(44100, reader.format.sample_rate)
|
@@ -321,6 +421,7 @@ class ReaderTest < Minitest::Test
|
|
321
421
|
assert_equal(2, reader.native_format.channels)
|
322
422
|
assert_equal(16, reader.native_format.bits_per_sample)
|
323
423
|
assert_equal(44100, reader.native_format.sample_rate)
|
424
|
+
assert_equal(16, reader.native_format.valid_bits_per_sample)
|
324
425
|
# Extra bits for speakers beyond the first 18 are set in the file, but these bits should be ignored
|
325
426
|
assert_equal([:front_left,
|
326
427
|
:front_right,
|
@@ -340,6 +441,7 @@ class ReaderTest < Minitest::Test
|
|
340
441
|
:top_back_left,
|
341
442
|
:top_back_center,
|
342
443
|
:top_back_right], reader.native_format.speaker_mapping)
|
444
|
+
assert_equal(WaveFile::SUB_FORMAT_GUID_PCM, reader.native_format.sub_audio_format_guid)
|
343
445
|
assert_equal(2, reader.format.channels)
|
344
446
|
assert_equal(16, reader.format.bits_per_sample)
|
345
447
|
assert_equal(44100, reader.format.sample_rate)
|
@@ -366,7 +468,9 @@ class ReaderTest < Minitest::Test
|
|
366
468
|
assert_equal(2, reader.native_format.channels)
|
367
469
|
assert_equal(16, reader.native_format.bits_per_sample)
|
368
470
|
assert_equal(44100, reader.native_format.sample_rate)
|
471
|
+
assert_equal(16, reader.native_format.valid_bits_per_sample)
|
369
472
|
assert_equal([:undefined, :undefined], reader.native_format.speaker_mapping)
|
473
|
+
assert_equal(WaveFile::SUB_FORMAT_GUID_PCM, reader.native_format.sub_audio_format_guid)
|
370
474
|
assert_equal(2, reader.format.channels)
|
371
475
|
assert_equal(16, reader.format.bits_per_sample)
|
372
476
|
assert_equal(44100, reader.format.sample_rate)
|
@@ -417,6 +521,308 @@ class ReaderTest < Minitest::Test
|
|
417
521
|
assert_equal(SQUARE_WAVE_CYCLE[:mono][:pcm_16] * 24, buffers[2].samples)
|
418
522
|
end
|
419
523
|
|
524
|
+
def test_read_float_format_chunk_missing_extension_size
|
525
|
+
reader = Reader.new(fixture("valid/valid_float_format_chunk_missing_extension_size.wav"))
|
526
|
+
|
527
|
+
assert_equal(3, reader.native_format.audio_format)
|
528
|
+
assert_equal(1, reader.native_format.channels)
|
529
|
+
assert_equal(32, reader.native_format.bits_per_sample)
|
530
|
+
assert_equal(44100, reader.native_format.sample_rate)
|
531
|
+
assert_nil(reader.native_format.speaker_mapping)
|
532
|
+
assert_nil(reader.native_format.sub_audio_format_guid)
|
533
|
+
assert_nil(reader.native_format.valid_bits_per_sample)
|
534
|
+
assert_equal(1, reader.format.channels)
|
535
|
+
assert_equal(32, reader.format.bits_per_sample)
|
536
|
+
assert_equal(44100, reader.format.sample_rate)
|
537
|
+
assert_equal([:front_center], reader.format.speaker_mapping)
|
538
|
+
assert_equal(false, reader.closed?)
|
539
|
+
assert_equal(0, reader.current_sample_frame)
|
540
|
+
assert_equal(2240, reader.total_sample_frames)
|
541
|
+
assert_equal(true, reader.readable_format?)
|
542
|
+
assert_nil(reader.sampler_info)
|
543
|
+
reader.close
|
544
|
+
|
545
|
+
buffers = read_file("valid/valid_float_format_chunk_missing_extension_size.wav", 1024)
|
546
|
+
|
547
|
+
assert_equal(3, buffers.length)
|
548
|
+
assert_equal([1024, 1024, 192], buffers.map {|buffer| buffer.samples.length })
|
549
|
+
assert_equal(SQUARE_WAVE_CYCLE[:mono][:float] * 128, buffers[0].samples)
|
550
|
+
assert_equal(SQUARE_WAVE_CYCLE[:mono][:float] * 128, buffers[1].samples)
|
551
|
+
assert_equal(SQUARE_WAVE_CYCLE[:mono][:float] * 24, buffers[2].samples)
|
552
|
+
end
|
553
|
+
|
554
|
+
def test_read_format_chunk_with_extra_bytes
|
555
|
+
reader = Reader.new(fixture("valid/valid_format_chunk_with_extra_bytes.wav"))
|
556
|
+
|
557
|
+
assert_equal(1, reader.native_format.audio_format)
|
558
|
+
assert_equal(1, reader.native_format.channels)
|
559
|
+
assert_equal(8, reader.native_format.bits_per_sample)
|
560
|
+
assert_equal(44100, reader.native_format.sample_rate)
|
561
|
+
assert_nil(reader.native_format.speaker_mapping)
|
562
|
+
assert_nil(reader.native_format.sub_audio_format_guid)
|
563
|
+
assert_nil(reader.native_format.valid_bits_per_sample)
|
564
|
+
assert_equal(1, reader.format.channels)
|
565
|
+
assert_equal(8, reader.format.bits_per_sample)
|
566
|
+
assert_equal(44100, reader.format.sample_rate)
|
567
|
+
assert_equal([:front_center], reader.format.speaker_mapping)
|
568
|
+
assert_equal(false, reader.closed?)
|
569
|
+
assert_equal(0, reader.current_sample_frame)
|
570
|
+
assert_equal(2240, reader.total_sample_frames)
|
571
|
+
assert_equal(true, reader.readable_format?)
|
572
|
+
assert_nil(reader.sampler_info)
|
573
|
+
reader.close
|
574
|
+
|
575
|
+
buffers = read_file("valid/valid_format_chunk_with_extra_bytes.wav", 1024)
|
576
|
+
|
577
|
+
assert_equal(3, buffers.length)
|
578
|
+
assert_equal([1024, 1024, 192], buffers.map {|buffer| buffer.samples.length })
|
579
|
+
assert_equal(SQUARE_WAVE_CYCLE[:mono][:pcm_8] * 128, buffers[0].samples)
|
580
|
+
assert_equal(SQUARE_WAVE_CYCLE[:mono][:pcm_8] * 128, buffers[1].samples)
|
581
|
+
assert_equal(SQUARE_WAVE_CYCLE[:mono][:pcm_8] * 24, buffers[2].samples)
|
582
|
+
end
|
583
|
+
|
584
|
+
def test_read_format_chunk_with_extra_byte_and_padding_byte
|
585
|
+
reader = Reader.new(fixture("valid/valid_format_chunk_with_extra_byte_and_padding_byte.wav"))
|
586
|
+
|
587
|
+
assert_equal(1, reader.native_format.audio_format)
|
588
|
+
assert_equal(1, reader.native_format.channels)
|
589
|
+
assert_equal(8, reader.native_format.bits_per_sample)
|
590
|
+
assert_equal(44100, reader.native_format.sample_rate)
|
591
|
+
assert_nil(reader.native_format.speaker_mapping)
|
592
|
+
assert_nil(reader.native_format.sub_audio_format_guid)
|
593
|
+
assert_nil(reader.native_format.valid_bits_per_sample)
|
594
|
+
assert_equal(1, reader.format.channels)
|
595
|
+
assert_equal(8, reader.format.bits_per_sample)
|
596
|
+
assert_equal(44100, reader.format.sample_rate)
|
597
|
+
assert_equal([:front_center], reader.format.speaker_mapping)
|
598
|
+
assert_equal(false, reader.closed?)
|
599
|
+
assert_equal(0, reader.current_sample_frame)
|
600
|
+
assert_equal(2240, reader.total_sample_frames)
|
601
|
+
assert_equal(true, reader.readable_format?)
|
602
|
+
assert_nil(reader.sampler_info)
|
603
|
+
reader.close
|
604
|
+
|
605
|
+
buffers = read_file("valid/valid_format_chunk_with_extra_byte_and_padding_byte.wav", 1024)
|
606
|
+
|
607
|
+
assert_equal(3, buffers.length)
|
608
|
+
assert_equal([1024, 1024, 192], buffers.map {|buffer| buffer.samples.length })
|
609
|
+
assert_equal(SQUARE_WAVE_CYCLE[:mono][:pcm_8] * 128, buffers[0].samples)
|
610
|
+
assert_equal(SQUARE_WAVE_CYCLE[:mono][:pcm_8] * 128, buffers[1].samples)
|
611
|
+
assert_equal(SQUARE_WAVE_CYCLE[:mono][:pcm_8] * 24, buffers[2].samples)
|
612
|
+
end
|
613
|
+
|
614
|
+
def test_read_format_chunk_with_extra_bytes_with_odd_size_and_padding_byte
|
615
|
+
reader = Reader.new(fixture("valid/valid_format_chunk_extra_bytes_with_odd_size_and_padding_byte.wav"))
|
616
|
+
|
617
|
+
assert_equal(1, reader.native_format.audio_format)
|
618
|
+
assert_equal(1, reader.native_format.channels)
|
619
|
+
assert_equal(8, reader.native_format.bits_per_sample)
|
620
|
+
assert_equal(44100, reader.native_format.sample_rate)
|
621
|
+
assert_nil(reader.native_format.speaker_mapping)
|
622
|
+
assert_nil(reader.native_format.sub_audio_format_guid)
|
623
|
+
assert_nil(reader.native_format.valid_bits_per_sample)
|
624
|
+
assert_equal(1, reader.format.channels)
|
625
|
+
assert_equal(8, reader.format.bits_per_sample)
|
626
|
+
assert_equal(44100, reader.format.sample_rate)
|
627
|
+
assert_equal([:front_center], reader.format.speaker_mapping)
|
628
|
+
assert_equal(false, reader.closed?)
|
629
|
+
assert_equal(0, reader.current_sample_frame)
|
630
|
+
assert_equal(2240, reader.total_sample_frames)
|
631
|
+
assert_equal(true, reader.readable_format?)
|
632
|
+
assert_nil(reader.sampler_info)
|
633
|
+
reader.close
|
634
|
+
|
635
|
+
buffers = read_file("valid/valid_format_chunk_extra_bytes_with_odd_size_and_padding_byte.wav", 1024)
|
636
|
+
|
637
|
+
assert_equal(3, buffers.length)
|
638
|
+
assert_equal([1024, 1024, 192], buffers.map {|buffer| buffer.samples.length })
|
639
|
+
assert_equal(SQUARE_WAVE_CYCLE[:mono][:pcm_8] * 128, buffers[0].samples)
|
640
|
+
assert_equal(SQUARE_WAVE_CYCLE[:mono][:pcm_8] * 128, buffers[1].samples)
|
641
|
+
assert_equal(SQUARE_WAVE_CYCLE[:mono][:pcm_8] * 24, buffers[2].samples)
|
642
|
+
end
|
643
|
+
|
644
|
+
def test_read_float_format_chunk_with_oversized_extension
|
645
|
+
reader = Reader.new(fixture("valid/valid_float_format_chunk_oversized_extension.wav"))
|
646
|
+
|
647
|
+
assert_equal(3, reader.native_format.audio_format)
|
648
|
+
assert_equal(1, reader.native_format.channels)
|
649
|
+
assert_equal(32, reader.native_format.bits_per_sample)
|
650
|
+
assert_equal(44100, reader.native_format.sample_rate)
|
651
|
+
assert_nil(reader.native_format.speaker_mapping)
|
652
|
+
assert_nil(reader.native_format.sub_audio_format_guid)
|
653
|
+
assert_nil(reader.native_format.valid_bits_per_sample)
|
654
|
+
assert_equal(1, reader.format.channels)
|
655
|
+
assert_equal(32, reader.format.bits_per_sample)
|
656
|
+
assert_equal(44100, reader.format.sample_rate)
|
657
|
+
assert_equal([:front_center], reader.format.speaker_mapping)
|
658
|
+
assert_equal(false, reader.closed?)
|
659
|
+
assert_equal(0, reader.current_sample_frame)
|
660
|
+
assert_equal(2240, reader.total_sample_frames)
|
661
|
+
assert_equal(true, reader.readable_format?)
|
662
|
+
assert_nil(reader.sampler_info)
|
663
|
+
reader.close
|
664
|
+
|
665
|
+
buffers = read_file("valid/valid_float_format_chunk_oversized_extension.wav", 1024)
|
666
|
+
|
667
|
+
assert_equal(3, buffers.length)
|
668
|
+
assert_equal([1024, 1024, 192], buffers.map {|buffer| buffer.samples.length })
|
669
|
+
assert_equal(SQUARE_WAVE_CYCLE[:mono][:float] * 128, buffers[0].samples)
|
670
|
+
assert_equal(SQUARE_WAVE_CYCLE[:mono][:float] * 128, buffers[1].samples)
|
671
|
+
assert_equal(SQUARE_WAVE_CYCLE[:mono][:float] * 24, buffers[2].samples)
|
672
|
+
end
|
673
|
+
|
674
|
+
def test_read_float_format_chunk_with_extra_bytes
|
675
|
+
reader = Reader.new(fixture("valid/valid_float_format_chunk_with_extra_bytes.wav"))
|
676
|
+
|
677
|
+
assert_equal(3, reader.native_format.audio_format)
|
678
|
+
assert_equal(1, reader.native_format.channels)
|
679
|
+
assert_equal(32, reader.native_format.bits_per_sample)
|
680
|
+
assert_equal(44100, reader.native_format.sample_rate)
|
681
|
+
assert_nil(reader.native_format.speaker_mapping)
|
682
|
+
assert_nil(reader.native_format.sub_audio_format_guid)
|
683
|
+
assert_nil(reader.native_format.valid_bits_per_sample)
|
684
|
+
assert_equal(1, reader.format.channels)
|
685
|
+
assert_equal(32, reader.format.bits_per_sample)
|
686
|
+
assert_equal(44100, reader.format.sample_rate)
|
687
|
+
assert_equal([:front_center], reader.format.speaker_mapping)
|
688
|
+
assert_equal(false, reader.closed?)
|
689
|
+
assert_equal(0, reader.current_sample_frame)
|
690
|
+
assert_equal(2240, reader.total_sample_frames)
|
691
|
+
assert_equal(true, reader.readable_format?)
|
692
|
+
assert_nil(reader.sampler_info)
|
693
|
+
reader.close
|
694
|
+
|
695
|
+
buffers = read_file("valid/valid_float_format_chunk_with_extra_bytes.wav", 1024)
|
696
|
+
|
697
|
+
assert_equal(3, buffers.length)
|
698
|
+
assert_equal([1024, 1024, 192], buffers.map {|buffer| buffer.samples.length })
|
699
|
+
assert_equal(SQUARE_WAVE_CYCLE[:mono][:float] * 128, buffers[0].samples)
|
700
|
+
assert_equal(SQUARE_WAVE_CYCLE[:mono][:float] * 128, buffers[1].samples)
|
701
|
+
assert_equal(SQUARE_WAVE_CYCLE[:mono][:float] * 24, buffers[2].samples)
|
702
|
+
end
|
703
|
+
|
704
|
+
def test_read_float_format_chunk_with_oversized_extension_and_extra_bytes
|
705
|
+
reader = Reader.new(fixture("valid/valid_float_format_chunk_oversized_extension_and_extra_bytes.wav"))
|
706
|
+
|
707
|
+
assert_equal(3, reader.native_format.audio_format)
|
708
|
+
assert_equal(1, reader.native_format.channels)
|
709
|
+
assert_equal(32, reader.native_format.bits_per_sample)
|
710
|
+
assert_equal(44100, reader.native_format.sample_rate)
|
711
|
+
assert_nil(reader.native_format.speaker_mapping)
|
712
|
+
assert_nil(reader.native_format.sub_audio_format_guid)
|
713
|
+
assert_nil(reader.native_format.valid_bits_per_sample)
|
714
|
+
assert_equal(1, reader.format.channels)
|
715
|
+
assert_equal(32, reader.format.bits_per_sample)
|
716
|
+
assert_equal(44100, reader.format.sample_rate)
|
717
|
+
assert_equal([:front_center], reader.format.speaker_mapping)
|
718
|
+
assert_equal(false, reader.closed?)
|
719
|
+
assert_equal(0, reader.current_sample_frame)
|
720
|
+
assert_equal(2240, reader.total_sample_frames)
|
721
|
+
assert_equal(true, reader.readable_format?)
|
722
|
+
assert_nil(reader.sampler_info)
|
723
|
+
reader.close
|
724
|
+
|
725
|
+
buffers = read_file("valid/valid_float_format_chunk_with_extra_bytes.wav", 1024)
|
726
|
+
|
727
|
+
assert_equal(3, buffers.length)
|
728
|
+
assert_equal([1024, 1024, 192], buffers.map {|buffer| buffer.samples.length })
|
729
|
+
assert_equal(SQUARE_WAVE_CYCLE[:mono][:float] * 128, buffers[0].samples)
|
730
|
+
assert_equal(SQUARE_WAVE_CYCLE[:mono][:float] * 128, buffers[1].samples)
|
731
|
+
assert_equal(SQUARE_WAVE_CYCLE[:mono][:float] * 24, buffers[2].samples)
|
732
|
+
end
|
733
|
+
|
734
|
+
def test_read_extensible_format_chunk_with_oversized_extension
|
735
|
+
reader = Reader.new(fixture("valid/valid_extensible_format_chunk_oversized_extension.wav"))
|
736
|
+
|
737
|
+
assert_equal(65534, reader.native_format.audio_format)
|
738
|
+
assert_equal(1, reader.native_format.channels)
|
739
|
+
assert_equal(8, reader.native_format.bits_per_sample)
|
740
|
+
assert_equal(44100, reader.native_format.sample_rate)
|
741
|
+
assert_equal(8, reader.native_format.valid_bits_per_sample)
|
742
|
+
assert_equal([:front_center], reader.native_format.speaker_mapping)
|
743
|
+
assert_equal(WaveFile::SUB_FORMAT_GUID_PCM, reader.native_format.sub_audio_format_guid)
|
744
|
+
assert_equal(1, reader.format.channels)
|
745
|
+
assert_equal(8, reader.format.bits_per_sample)
|
746
|
+
assert_equal(44100, reader.format.sample_rate)
|
747
|
+
assert_equal([:front_center], reader.format.speaker_mapping)
|
748
|
+
assert_equal(false, reader.closed?)
|
749
|
+
assert_equal(0, reader.current_sample_frame)
|
750
|
+
assert_equal(2240, reader.total_sample_frames)
|
751
|
+
assert_equal(true, reader.readable_format?)
|
752
|
+
assert_nil(reader.sampler_info)
|
753
|
+
reader.close
|
754
|
+
|
755
|
+
buffers = read_file("valid/valid_extensible_format_chunk_oversized_extension.wav", 1024)
|
756
|
+
|
757
|
+
assert_equal(3, buffers.length)
|
758
|
+
assert_equal([1024, 1024, 192], buffers.map {|buffer| buffer.samples.length })
|
759
|
+
assert_equal(SQUARE_WAVE_CYCLE[:mono][:pcm_8] * 128, buffers[0].samples)
|
760
|
+
assert_equal(SQUARE_WAVE_CYCLE[:mono][:pcm_8] * 128, buffers[1].samples)
|
761
|
+
assert_equal(SQUARE_WAVE_CYCLE[:mono][:pcm_8] * 24, buffers[2].samples)
|
762
|
+
end
|
763
|
+
|
764
|
+
def test_read_extensible_format_chunk_with_extra_bytes
|
765
|
+
reader = Reader.new(fixture("valid/valid_extensible_format_chunk_with_extra_bytes.wav"))
|
766
|
+
|
767
|
+
assert_equal(65534, reader.native_format.audio_format)
|
768
|
+
assert_equal(1, reader.native_format.channels)
|
769
|
+
assert_equal(8, reader.native_format.bits_per_sample)
|
770
|
+
assert_equal(44100, reader.native_format.sample_rate)
|
771
|
+
assert_equal(8, reader.native_format.valid_bits_per_sample)
|
772
|
+
assert_equal([:front_center], reader.native_format.speaker_mapping)
|
773
|
+
assert_equal(WaveFile::SUB_FORMAT_GUID_PCM, reader.native_format.sub_audio_format_guid)
|
774
|
+
assert_equal(8, reader.native_format.valid_bits_per_sample)
|
775
|
+
assert_equal(1, reader.format.channels)
|
776
|
+
assert_equal(8, reader.format.bits_per_sample)
|
777
|
+
assert_equal(44100, reader.format.sample_rate)
|
778
|
+
assert_equal([:front_center], reader.format.speaker_mapping)
|
779
|
+
assert_equal(false, reader.closed?)
|
780
|
+
assert_equal(0, reader.current_sample_frame)
|
781
|
+
assert_equal(2240, reader.total_sample_frames)
|
782
|
+
assert_equal(true, reader.readable_format?)
|
783
|
+
assert_nil(reader.sampler_info)
|
784
|
+
reader.close
|
785
|
+
|
786
|
+
buffers = read_file("valid/valid_extensible_format_chunk_with_extra_bytes.wav", 1024)
|
787
|
+
|
788
|
+
assert_equal(3, buffers.length)
|
789
|
+
assert_equal([1024, 1024, 192], buffers.map {|buffer| buffer.samples.length })
|
790
|
+
assert_equal(SQUARE_WAVE_CYCLE[:mono][:pcm_8] * 128, buffers[0].samples)
|
791
|
+
assert_equal(SQUARE_WAVE_CYCLE[:mono][:pcm_8] * 128, buffers[1].samples)
|
792
|
+
assert_equal(SQUARE_WAVE_CYCLE[:mono][:pcm_8] * 24, buffers[2].samples)
|
793
|
+
end
|
794
|
+
|
795
|
+
def test_read_extensible_format_chunk_with_oversized_extension_and_extra_bytes
|
796
|
+
reader = Reader.new(fixture("valid/valid_extensible_format_chunk_oversized_extension_and_extra_bytes.wav"))
|
797
|
+
|
798
|
+
assert_equal(65534, reader.native_format.audio_format)
|
799
|
+
assert_equal(1, reader.native_format.channels)
|
800
|
+
assert_equal(8, reader.native_format.bits_per_sample)
|
801
|
+
assert_equal(44100, reader.native_format.sample_rate)
|
802
|
+
assert_equal(8, reader.native_format.valid_bits_per_sample)
|
803
|
+
assert_equal([:front_center], reader.native_format.speaker_mapping)
|
804
|
+
assert_equal(WaveFile::SUB_FORMAT_GUID_PCM, reader.native_format.sub_audio_format_guid)
|
805
|
+
assert_equal(8, reader.native_format.valid_bits_per_sample)
|
806
|
+
assert_equal(1, reader.format.channels)
|
807
|
+
assert_equal(8, reader.format.bits_per_sample)
|
808
|
+
assert_equal(44100, reader.format.sample_rate)
|
809
|
+
assert_equal([:front_center], reader.format.speaker_mapping)
|
810
|
+
assert_equal(false, reader.closed?)
|
811
|
+
assert_equal(0, reader.current_sample_frame)
|
812
|
+
assert_equal(2240, reader.total_sample_frames)
|
813
|
+
assert_equal(true, reader.readable_format?)
|
814
|
+
assert_nil(reader.sampler_info)
|
815
|
+
reader.close
|
816
|
+
|
817
|
+
buffers = read_file("valid/valid_extensible_format_chunk_with_extra_bytes.wav", 1024)
|
818
|
+
|
819
|
+
assert_equal(3, buffers.length)
|
820
|
+
assert_equal([1024, 1024, 192], buffers.map {|buffer| buffer.samples.length })
|
821
|
+
assert_equal(SQUARE_WAVE_CYCLE[:mono][:pcm_8] * 128, buffers[0].samples)
|
822
|
+
assert_equal(SQUARE_WAVE_CYCLE[:mono][:pcm_8] * 128, buffers[1].samples)
|
823
|
+
assert_equal(SQUARE_WAVE_CYCLE[:mono][:pcm_8] * 24, buffers[2].samples)
|
824
|
+
end
|
825
|
+
|
420
826
|
def test_read_with_format_conversion
|
421
827
|
buffers = read_file("valid/valid_mono_pcm_16_44100.wav", 1024, Format.new(:stereo, :pcm_8, 22100))
|
422
828
|
|
@@ -531,6 +937,21 @@ class ReaderTest < Minitest::Test
|
|
531
937
|
assert_equal(2241, reader.total_sample_frames)
|
532
938
|
end
|
533
939
|
|
940
|
+
def test_each_buffer_not_at_beginning_of_file
|
941
|
+
reader = Reader.new(fixture("valid/valid_mono_pcm_16_44100.wav"))
|
942
|
+
|
943
|
+
buffers = []
|
944
|
+
reader.read(8)
|
945
|
+
reader.each_buffer {|buffer| buffers << buffer }
|
946
|
+
|
947
|
+
assert(reader.closed?)
|
948
|
+
assert_equal(1, buffers.length)
|
949
|
+
assert_equal([2232], buffers.map {|buffer| buffer.samples.length })
|
950
|
+
assert_equal(SQUARE_WAVE_CYCLE[:mono][:pcm_16] * 279, buffers[0].samples)
|
951
|
+
assert_equal(2240, reader.current_sample_frame)
|
952
|
+
assert_equal(2240, reader.total_sample_frames)
|
953
|
+
end
|
954
|
+
|
534
955
|
def test_each_buffer_inside_reader_block
|
535
956
|
buffers = []
|
536
957
|
|
@@ -546,6 +967,21 @@ class ReaderTest < Minitest::Test
|
|
546
967
|
assert_equal(SQUARE_WAVE_CYCLE[:mono][:pcm_16] * 24, buffers[2].samples)
|
547
968
|
end
|
548
969
|
|
970
|
+
def test_read_after_each_buffer_inside_block_raises_error
|
971
|
+
buffers = []
|
972
|
+
|
973
|
+
Reader.new(fixture("valid/valid_mono_pcm_16_44100.wav")) do |reader|
|
974
|
+
reader.each_buffer(1024) {|buffer| buffers << buffer }
|
975
|
+
assert_raises(ReaderClosedError) { reader.read(100) }
|
976
|
+
end
|
977
|
+
|
978
|
+
assert_equal(3, buffers.length)
|
979
|
+
assert_equal([1024, 1024, 192], buffers.map {|buffer| buffer.samples.length })
|
980
|
+
assert_equal(SQUARE_WAVE_CYCLE[:mono][:pcm_16] * 128, buffers[0].samples)
|
981
|
+
assert_equal(SQUARE_WAVE_CYCLE[:mono][:pcm_16] * 128, buffers[1].samples)
|
982
|
+
assert_equal(SQUARE_WAVE_CYCLE[:mono][:pcm_16] * 24, buffers[2].samples)
|
983
|
+
end
|
984
|
+
|
549
985
|
def test_read_non_data_chunk_with_padding_byte
|
550
986
|
# This fixture file contains a JUNK chunk with an odd size, aligned to an even number of
|
551
987
|
# bytes via an appended padding byte. If the padding byte is not taken into account, this
|
@@ -621,35 +1057,35 @@ class ReaderTest < Minitest::Test
|
|
621
1057
|
|
622
1058
|
assert_equal(0, reader.current_sample_frame)
|
623
1059
|
assert_equal(2240, reader.total_sample_frames)
|
624
|
-
test_duration({:
|
1060
|
+
test_duration({hours: 0, minutes: 0, seconds: 0, milliseconds: 50, sample_count: 2240},
|
625
1061
|
reader.total_duration)
|
626
1062
|
|
627
1063
|
|
628
1064
|
reader.read(1024)
|
629
1065
|
assert_equal(1024, reader.current_sample_frame)
|
630
1066
|
assert_equal(2240, reader.total_sample_frames)
|
631
|
-
test_duration({:
|
1067
|
+
test_duration({hours: 0, minutes: 0, seconds: 0, milliseconds: 50, sample_count: 2240},
|
632
1068
|
reader.total_duration)
|
633
1069
|
|
634
1070
|
|
635
1071
|
reader.read(1024)
|
636
1072
|
assert_equal(2048, reader.current_sample_frame)
|
637
1073
|
assert_equal(2240, reader.total_sample_frames)
|
638
|
-
test_duration({:
|
1074
|
+
test_duration({hours: 0, minutes: 0, seconds: 0, milliseconds: 50, sample_count: 2240},
|
639
1075
|
reader.total_duration)
|
640
1076
|
|
641
1077
|
|
642
1078
|
reader.read(192)
|
643
1079
|
assert_equal(2240, reader.current_sample_frame)
|
644
1080
|
assert_equal(2240, reader.total_sample_frames)
|
645
|
-
test_duration({:
|
1081
|
+
test_duration({hours: 0, minutes: 0, seconds: 0, milliseconds: 50, sample_count: 2240},
|
646
1082
|
reader.total_duration)
|
647
1083
|
|
648
1084
|
|
649
1085
|
reader.close
|
650
1086
|
assert_equal(2240, reader.current_sample_frame)
|
651
1087
|
assert_equal(2240, reader.total_sample_frames)
|
652
|
-
test_duration({:
|
1088
|
+
test_duration({hours: 0, minutes: 0, seconds: 0, milliseconds: 50, sample_count: 2240},
|
653
1089
|
reader.total_duration)
|
654
1090
|
end
|
655
1091
|
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
module WaveFileIOTestHelper
|
2
|
-
CHANNEL_ALIAS = {
|
2
|
+
CHANNEL_ALIAS = {mono: 1, stereo: 2, tri: 3}
|
3
3
|
|
4
4
|
SUPPORTED_BITS_PER_SAMPLE = {
|
5
|
-
:
|
6
|
-
:
|
5
|
+
pcm: [8, 16, 24, 32].freeze,
|
6
|
+
float: [32, 64].freeze,
|
7
7
|
}.freeze
|
8
8
|
|
9
9
|
SQUARE_WAVE_CYCLE = {}
|
data/test/writer_test.rb
CHANGED
@@ -414,7 +414,7 @@ private
|
|
414
414
|
dir = Dir.new(OUTPUT_FOLDER)
|
415
415
|
file_names = dir.entries
|
416
416
|
file_names.each do |file_name|
|
417
|
-
if
|
417
|
+
if file_name != "." && file_name != ".."
|
418
418
|
File.delete("#{OUTPUT_FOLDER}/#{file_name}")
|
419
419
|
end
|
420
420
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: wavefile
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joel Strait
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-12-30 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: You can use this gem to create Ruby programs that work with audio, by
|
14
14
|
reading and writing Wave sound files (*.wav). Since it is written in pure Ruby (as
|
@@ -48,7 +48,20 @@ files:
|
|
48
48
|
- test/fixtures/wave/invalid/data_chunk_truncated.wav
|
49
49
|
- test/fixtures/wave/invalid/empty.wav
|
50
50
|
- test/fixtures/wave/invalid/empty_format_chunk.wav
|
51
|
+
- test/fixtures/wave/invalid/extensible_format_chunk_extension_incomplete.wav
|
52
|
+
- test/fixtures/wave/invalid/extensible_format_chunk_extension_incomplete_in_incorrectly_sized_chunk.wav
|
53
|
+
- test/fixtures/wave/invalid/extensible_format_chunk_extension_incomplete_in_large_enough_chunk.wav
|
54
|
+
- test/fixtures/wave/invalid/extensible_format_chunk_extension_missing.wav
|
55
|
+
- test/fixtures/wave/invalid/extensible_format_chunk_extension_size_incomplete.wav
|
56
|
+
- test/fixtures/wave/invalid/extensible_format_chunk_extension_size_incomplete_with_padding_byte.wav
|
57
|
+
- test/fixtures/wave/invalid/extensible_format_chunk_extension_truncated.wav
|
58
|
+
- test/fixtures/wave/invalid/extensible_format_chunk_oversized_extension_too_large.wav
|
59
|
+
- test/fixtures/wave/invalid/float_format_chunk_extension_size_incomplete.wav
|
60
|
+
- test/fixtures/wave/invalid/float_format_chunk_extension_size_incomplete_with_padding_byte.wav
|
61
|
+
- test/fixtures/wave/invalid/float_format_chunk_oversized_extension_too_large.wav
|
51
62
|
- test/fixtures/wave/invalid/format_chunk_after_data_chunk.wav
|
63
|
+
- test/fixtures/wave/invalid/format_chunk_extra_bytes_with_odd_size_and_missing_padding_byte.wav
|
64
|
+
- test/fixtures/wave/invalid/format_chunk_with_extra_byte_and_missing_padding_byte.wav
|
52
65
|
- test/fixtures/wave/invalid/incomplete_riff_format.wav
|
53
66
|
- test/fixtures/wave/invalid/incomplete_riff_header.wav
|
54
67
|
- test/fixtures/wave/invalid/insufficient_format_chunk.wav
|
@@ -62,15 +75,27 @@ files:
|
|
62
75
|
- test/fixtures/wave/invalid/smpl_chunk_loop_count_too_high.wav
|
63
76
|
- test/fixtures/wave/invalid/smpl_chunk_truncated_sampler_specific_data.wav
|
64
77
|
- test/fixtures/wave/invalid/truncated_smpl_chunk.wav
|
65
|
-
- test/fixtures/wave/
|
78
|
+
- test/fixtures/wave/invalid/unsupported_format_extension_size_incomplete.wav
|
79
|
+
- test/fixtures/wave/invalid/unsupported_format_extension_size_incomplete_with_padding_byte.wav
|
80
|
+
- test/fixtures/wave/invalid/unsupported_format_extension_truncated.wav
|
81
|
+
- test/fixtures/wave/invalid/unsupported_format_oversized_extension_too_large.wav
|
66
82
|
- test/fixtures/wave/unsupported/bad_channel_count.wav
|
67
83
|
- test/fixtures/wave/unsupported/bad_sample_rate.wav
|
68
84
|
- test/fixtures/wave/unsupported/extensible_container_size_bigger_than_sample_size.wav
|
69
85
|
- test/fixtures/wave/unsupported/extensible_unsupported_subformat_guid.wav
|
70
86
|
- test/fixtures/wave/unsupported/unsupported_audio_format.wav
|
71
87
|
- test/fixtures/wave/unsupported/unsupported_bits_per_sample.wav
|
88
|
+
- test/fixtures/wave/unsupported/unsupported_format_code_missing_extension_size.wav
|
89
|
+
- test/fixtures/wave/unsupported/unsupported_format_code_with_extension.wav
|
90
|
+
- test/fixtures/wave/unsupported/unsupported_format_code_with_extension_and_extra_bytes.wav
|
91
|
+
- test/fixtures/wave/unsupported/unsupported_format_code_with_incomplete_extension.wav
|
92
|
+
- test/fixtures/wave/unsupported/unsupported_format_code_with_oversized_extension.wav
|
93
|
+
- test/fixtures/wave/unsupported/unsupported_format_code_with_oversized_extension_and_extra_bytes.wav
|
72
94
|
- test/fixtures/wave/valid/no_samples.wav
|
73
95
|
- test/fixtures/wave/valid/valid_extensible_20_pcm_16_44100_speaker_mapping_overflow.wav
|
96
|
+
- test/fixtures/wave/valid/valid_extensible_format_chunk_oversized_extension.wav
|
97
|
+
- test/fixtures/wave/valid/valid_extensible_format_chunk_oversized_extension_and_extra_bytes.wav
|
98
|
+
- test/fixtures/wave/valid/valid_extensible_format_chunk_with_extra_bytes.wav
|
74
99
|
- test/fixtures/wave/valid/valid_extensible_mono_float_32_44100.wav
|
75
100
|
- test/fixtures/wave/valid/valid_extensible_mono_float_64_44100.wav
|
76
101
|
- test/fixtures/wave/valid/valid_extensible_mono_pcm_16_44100.wav
|
@@ -97,6 +122,13 @@ files:
|
|
97
122
|
- test/fixtures/wave/valid/valid_extensible_tri_pcm_24_44100.wav
|
98
123
|
- test/fixtures/wave/valid/valid_extensible_tri_pcm_32_44100.wav
|
99
124
|
- test/fixtures/wave/valid/valid_extensible_tri_pcm_8_44100.wav
|
125
|
+
- test/fixtures/wave/valid/valid_float_format_chunk_missing_extension_size.wav
|
126
|
+
- test/fixtures/wave/valid/valid_float_format_chunk_oversized_extension.wav
|
127
|
+
- test/fixtures/wave/valid/valid_float_format_chunk_oversized_extension_and_extra_bytes.wav
|
128
|
+
- test/fixtures/wave/valid/valid_float_format_chunk_with_extra_bytes.wav
|
129
|
+
- test/fixtures/wave/valid/valid_format_chunk_extra_bytes_with_odd_size_and_padding_byte.wav
|
130
|
+
- test/fixtures/wave/valid/valid_format_chunk_with_extra_byte_and_padding_byte.wav
|
131
|
+
- test/fixtures/wave/valid/valid_format_chunk_with_extra_bytes.wav
|
100
132
|
- test/fixtures/wave/valid/valid_mono_float_32_44100.wav
|
101
133
|
- test/fixtures/wave/valid/valid_mono_float_64_44100.wav
|
102
134
|
- test/fixtures/wave/valid/valid_mono_pcm_16_44100.wav
|
@@ -133,12 +165,12 @@ files:
|
|
133
165
|
- test/unvalidated_format_test.rb
|
134
166
|
- test/wavefile_io_test_helper.rb
|
135
167
|
- test/writer_test.rb
|
136
|
-
homepage:
|
168
|
+
homepage: https://wavefilegem.com/
|
137
169
|
licenses:
|
138
170
|
- MIT
|
139
171
|
metadata: {}
|
140
172
|
post_install_message: Thanks for installing the WaveFile gem! For documentation and
|
141
|
-
examples, visit
|
173
|
+
examples, visit https://wavefilegem.com
|
142
174
|
rdoc_options: []
|
143
175
|
require_paths:
|
144
176
|
- lib
|
@@ -153,8 +185,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
153
185
|
- !ruby/object:Gem::Version
|
154
186
|
version: '0'
|
155
187
|
requirements: []
|
156
|
-
rubygems_version: 3.1
|
157
|
-
signing_key:
|
188
|
+
rubygems_version: 3.4.1
|
189
|
+
signing_key:
|
158
190
|
specification_version: 4
|
159
191
|
summary: A pure Ruby library for reading and writing Wave sound files (*.wav)
|
160
192
|
test_files: []
|
Binary file
|