wavefile 0.5.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +6 -14
- data/README.markdown +8 -17
- data/lib/wavefile.rb +9 -9
- data/lib/wavefile/buffer.rb +61 -15
- data/lib/wavefile/duration.rb +34 -3
- data/lib/wavefile/format.rb +54 -8
- data/lib/wavefile/info.rb +34 -4
- data/lib/wavefile/reader.rb +57 -42
- data/lib/wavefile/writer.rb +39 -18
- data/test/buffer_test.rb +141 -0
- data/test/buffer_test.rbc +19560 -0
- data/test/duration_test.rbc +1536 -0
- data/test/fixtures/unsupported/unsupported_bits_per_sample.wav +0 -0
- data/test/fixtures/valid/valid_mono_pcm_16_44100_junk_chunk_with_padding_byte.wav +0 -0
- data/test/fixtures/valid/valid_mono_pcm_24_44100.wav +0 -0
- data/test/fixtures/valid/valid_stereo_pcm_24_44100.wav +0 -0
- data/test/fixtures/valid/valid_tri_pcm_24_44100.wav +0 -0
- data/test/format_test.rb +16 -0
- data/test/format_test.rbc +5325 -0
- data/test/info_test.rbc +759 -0
- data/test/reader_test.rb +12 -1
- data/test/reader_test.rbc +7927 -0
- data/test/wavefile_io_test_helper.rb +7 -0
- data/test/wavefile_io_test_helper.rbc +2013 -0
- data/test/writer_test.rbc +6105 -0
- metadata +16 -5
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
metadata.gz: !binary |-
|
9
|
-
ZjVlZjg0NTBjOTFhMTI2NjFlZWMzNzVlOTc5NjY4MjFjMDI5OWNmYmY5MmQ2
|
10
|
-
MDE0ZDAxNWUxYWFiYWU5NjRiMWU4MWE5NWQ0ZjBlNTQwNDc4ZDExYmY3NmEz
|
11
|
-
M2IxZmRlYTVkNjliODY3OGY2YmY4YjFhYTUzZTllNGU3M2YwNzI=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
YjRmYWVkZDVkYjJmMGI4OTAwOTgzM2RlYTA1OGYwNmYzMGViMjAyNzk4N2Ey
|
14
|
-
ZTliMDVkNmNlYWMxNDg4ODA3Y2Q3YTQxZjhiNjQ3YTgwZjFiOGIwMGM1YWJk
|
15
|
-
MTg0MGJlMDEwOGRiNGMwY2ZhNjY5NzlhZDQ3ODU1NDlhYzUxNTY=
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 48ad3ca7155a04fd1b674dd9add8f556746db460
|
4
|
+
data.tar.gz: a8f70d7c7ddce88d1bd93a7c2fef2963b80fc2d4
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 3eb29c14f9146190fa8a01bb36e4a1e25259f09bf36d27f390bb99e1229f25abb94dd9438937fcb52f856d088b114717a626b0e78948a0156551cb313a02a2b6
|
7
|
+
data.tar.gz: 91d5abb8d5284a387b267ef951a5974298ceb497bb7b6cb8c7e53c034a32ac5b90c3a2f2e356cfabf788c0f279427fbdf877e5e052f42ebfc20f461de45558d4
|
data/README.markdown
CHANGED
@@ -2,6 +2,7 @@ A pure 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 produce audio, such as [drum machine](http://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: <http://wavefilegem.com/>
|
5
6
|
|
6
7
|
# Example Usage
|
7
8
|
|
@@ -27,7 +28,7 @@ More examples can be [found on the wiki](https://github.com/jstrait/wavefile/wik
|
|
27
28
|
# Features
|
28
29
|
|
29
30
|
* Ability to read and write Wave files with any number of channels in the following formats:
|
30
|
-
* PCM (8, 16, and 32 bits per sample)
|
31
|
+
* PCM (8, 16, 24, and 32 bits per sample)
|
31
32
|
* Floating Point (32 and 64 bits per sample)
|
32
33
|
* Ability to read sample data from a file in any of the supported formats, regardless of the file's actual sample format
|
33
34
|
|
@@ -46,24 +47,14 @@ More examples can be [found on the wiki](https://github.com/jstrait/wavefile/wik
|
|
46
47
|
* Pure Ruby, so no need to compile a separate extension in order to use it.
|
47
48
|
|
48
49
|
|
49
|
-
# Current Release: v0.
|
50
|
+
# Current Release: v0.6.0
|
50
51
|
|
51
52
|
This release includes these improvements:
|
52
53
|
|
53
|
-
* Support for reading and writing Wave files containing
|
54
|
-
*
|
55
|
-
*
|
56
|
-
*
|
57
|
-
* Ability to get these attributes as a `Duration` object as well: `Reader.total_duration`, `Writer.total_duration`.
|
58
|
-
* The 2nd argument to `Format.new` now indicates the sample format, not the bits per sample. For example, `:pcm_16` or `:float_32` instead of `8` or `16`. For backwards compatibility, `8`, `16`, and `32` can still be given and will be interpreted as `:pcm_8`, `:pcm_16`, and `:pcm_32`, but this support might be removed in the future.
|
59
|
-
* Bug fix: Wave files are no longer corrupted when an unhandled exception occurs inside a `Writer` block. (Thanks to [James Tunnell](https://github.com/jamestunnell) for reporting and fixing this).
|
60
|
-
* Bug fix: `Writer.file_name` now returns the file name, instead of always returning nil (Thanks to [James Tunnell](https://github.com/jamestunnell) for reporting this).
|
61
|
-
|
62
|
-
This release also includes changes that are not backwards compatible with v0.4.0. (Until version v1.0, no guarantees to avoid this will be made, but I'll try to have a good reason before doing so).
|
63
|
-
|
64
|
-
* `Info.duration` now returns a `Duration` object, instead of a hash.
|
65
|
-
* `Info.sample_count` has been renamed `sample_frame_count`.
|
66
|
-
* Some constants in the `WaveFile` module have changed. (In general, you should treat these as internal to this gem and not use them in your own program).
|
54
|
+
* Support for reading and writing Wave files containing 24-bit PCM sample data, and the ability to convert buffers containing 24-bit PCM sample data to/from other formats. (Thanks to [Rich Orton](https://github.com/richorton) for suggesting this).
|
55
|
+
* Reading files with 2 or more channels is now faster.
|
56
|
+
* Converting buffers from one format to another is now faster in certain cases.
|
57
|
+
* Bug fix: Files containing certain chunks with an odd size are now read properly. According to the Wave file spec, all chunks should be aligned to an even number of bytes. If the chunk has an odd size, a padding byte should be appended to bring the chunk to an even size. The `Reader` class now properly takes this expected padding byte into account for all chunks when reading files. (Previously it just took this into account for the main `data` chunk). (Thanks to [Andrew Kuklewicz](https://github.com/kookster) for reporting this).
|
67
58
|
|
68
59
|
|
69
60
|
# Compatibility
|
@@ -71,7 +62,7 @@ This release also includes changes that are not backwards compatible with v0.4.0
|
|
71
62
|
WaveFile has been tested with these Ruby versions, and appears to be compatible with them:
|
72
63
|
|
73
64
|
* MRI 2.0.0, 1.9.3, 1.9.2, 1.9.1, 1.8.7
|
74
|
-
* JRuby 1.7.
|
65
|
+
* JRuby 1.7.8
|
75
66
|
* Rubinius 1.2.4
|
76
67
|
* MacRuby 0.12
|
77
68
|
|
data/lib/wavefile.rb
CHANGED
@@ -6,11 +6,11 @@ require 'wavefile/reader'
|
|
6
6
|
require 'wavefile/writer'
|
7
7
|
|
8
8
|
module WaveFile
|
9
|
-
VERSION = "0.
|
9
|
+
VERSION = "0.6.0"
|
10
10
|
|
11
|
-
WAVEFILE_FORMAT_CODE = "WAVE"
|
12
|
-
FORMAT_CHUNK_BYTE_LENGTH = {:pcm => 16, :float => 18}
|
13
|
-
FORMAT_CODES = {:pcm => 1, :float => 3}
|
11
|
+
WAVEFILE_FORMAT_CODE = "WAVE" # :nodoc:
|
12
|
+
FORMAT_CHUNK_BYTE_LENGTH = {:pcm => 16, :float => 18} # :nodoc:
|
13
|
+
FORMAT_CODES = {:pcm => 1, :float => 3} # :nodoc:
|
14
14
|
CHUNK_IDS = {:riff => "RIFF",
|
15
15
|
:format => "fmt ",
|
16
16
|
:data => "data",
|
@@ -23,12 +23,12 @@ module WaveFile
|
|
23
23
|
:labeled_text => "ltxt",
|
24
24
|
:note => "note",
|
25
25
|
:sample => "smpl",
|
26
|
-
:instrument => "inst" }
|
26
|
+
:instrument => "inst" } # :nodoc:
|
27
27
|
|
28
|
-
PACK_CODES = {:pcm => {8 => "C*", 16 => "s*", 32 => "l*"},
|
29
|
-
:float => { 32 => "e*", 64 => "E*"}}
|
28
|
+
PACK_CODES = {:pcm => {8 => "C*", 16 => "s*", 24 => "C*", 32 => "l*"},
|
29
|
+
:float => { 32 => "e*", 64 => "E*"}} # :nodoc:
|
30
30
|
|
31
|
-
UNSIGNED_INT_16 = "v"
|
32
|
-
UNSIGNED_INT_32 = "V"
|
31
|
+
UNSIGNED_INT_16 = "v" # :nodoc:
|
32
|
+
UNSIGNED_INT_32 = "V" # :nodoc:
|
33
33
|
end
|
34
34
|
|
data/lib/wavefile/buffer.rb
CHANGED
@@ -1,32 +1,54 @@
|
|
1
1
|
module WaveFile
|
2
|
-
# Error that is raised when an attempt is made to perform an unsupported or undefined
|
3
|
-
# conversion between two sample data formats.
|
2
|
+
# Error that is raised when an attempt is made to perform an unsupported or undefined
|
3
|
+
# conversion between two sample data formats. For example, converting a Buffer with
|
4
|
+
# 3 channels into a Buffer with 2 channels is undefined.
|
4
5
|
class BufferConversionError < StandardError; end
|
5
6
|
|
6
7
|
|
7
|
-
# Represents a collection of samples in a certain format (e.g. 16-bit mono).
|
8
|
-
# Reader returns sample data contained in Buffers, and Writer expects incoming sample
|
8
|
+
# Represents a collection of samples in a certain format (e.g. 16-bit mono).
|
9
|
+
# Reader returns sample data contained in Buffers, and Writer expects incoming sample
|
9
10
|
# data to be contained in a Buffer as well.
|
10
11
|
#
|
11
12
|
# Contains methods to convert the sample data in the buffer to a different format.
|
12
13
|
class Buffer
|
13
14
|
|
14
|
-
# Creates a new Buffer.
|
15
|
-
#
|
15
|
+
# Creates a new Buffer.
|
16
|
+
#
|
17
|
+
# samples - An array of samples. If the Format has 1 channel (i.e. is mono), this
|
18
|
+
# should be a flat array of samples such as [0.5, 0.4, -0.3, ...]. If the
|
19
|
+
# Format has 2 or more channels the array should include a sub-array for
|
20
|
+
# each sample frame. For example, [[0.5, 0.2], [0.1, 0.6], [-0.2, 0.4], ...]
|
21
|
+
# for a stereo file.
|
22
|
+
#
|
23
|
+
# format - A Format instance which describes the sample format of the sample array.
|
24
|
+
#
|
25
|
+
# Note that the sample array is not compared with the format to make sure
|
26
|
+
# they match - you are on the honor system to make sure they do. If they
|
27
|
+
# don't match, unexpected things will happen.
|
28
|
+
#
|
29
|
+
# Examples
|
30
|
+
#
|
31
|
+
# samples = ([0.5] * 50) + ([-0.5] * 50) # A 440Hz mono square wave
|
32
|
+
# buffer = Buffer.new(samples, Format.new(:mono, :float, 44100)
|
33
|
+
#
|
34
|
+
# samples = ([0.5, 0.5] * 50) + ([-0.5, -0.5] * 50) # A 440Hz stereo square wave
|
35
|
+
# buffer = Buffer.new(samples, Format.new(2, :float, 44100)
|
36
|
+
#
|
37
|
+
# Returns a constructed Buffer.
|
16
38
|
def initialize(samples, format)
|
17
39
|
@samples = samples
|
18
40
|
@format = format
|
19
41
|
end
|
20
42
|
|
21
43
|
|
22
|
-
# Creates a new Buffer containing the sample data of this Buffer, but converted to
|
44
|
+
# Creates a new Buffer containing the sample data of this Buffer, but converted to
|
23
45
|
# a different format.
|
24
46
|
#
|
25
47
|
# new_format - The format that the sample data should be converted to
|
26
48
|
#
|
27
49
|
# Examples
|
28
50
|
#
|
29
|
-
# new_format = Format.new(:mono,
|
51
|
+
# new_format = Format.new(:mono, :pcm_16, 44100)
|
30
52
|
# new_buffer = old_buffer.convert(new_format)
|
31
53
|
#
|
32
54
|
# Returns a new Buffer; the existing Buffer is unmodified.
|
@@ -36,14 +58,14 @@ module WaveFile
|
|
36
58
|
end
|
37
59
|
|
38
60
|
|
39
|
-
# Converts the sample data contained in the Buffer to a new format. The sample data
|
61
|
+
# Converts the sample data contained in the Buffer to a new format. The sample data
|
40
62
|
# is converted in place, so the existing Buffer is modified.
|
41
63
|
#
|
42
64
|
# new_format - The format that the sample data should be converted to
|
43
65
|
#
|
44
66
|
# Examples
|
45
67
|
#
|
46
|
-
# new_format = Format.new(:mono,
|
68
|
+
# new_format = Format.new(:mono, :pcm_16, 44100)
|
47
69
|
# old_buffer.convert!(new_format)
|
48
70
|
#
|
49
71
|
# Returns self.
|
@@ -54,30 +76,50 @@ module WaveFile
|
|
54
76
|
end
|
55
77
|
|
56
78
|
|
57
|
-
#
|
79
|
+
# Returns the number of channels the buffer's sample data has
|
58
80
|
def channels
|
59
81
|
@format.channels
|
60
82
|
end
|
61
83
|
|
62
84
|
|
63
|
-
#
|
85
|
+
# Returns the bits per sample of the buffer's sample data
|
64
86
|
def bits_per_sample
|
65
87
|
@format.bits_per_sample
|
66
88
|
end
|
67
89
|
|
68
90
|
|
69
|
-
#
|
91
|
+
# Returns the sample rate of the buffer's sample data
|
70
92
|
def sample_rate
|
71
93
|
@format.sample_rate
|
72
94
|
end
|
73
95
|
|
96
|
+
# Returns the sample data contained in the Buffer as an Array. If the Format has
|
97
|
+
# 1 channel, the Array will be a flat list of samples. If the Format has 2 or more
|
98
|
+
# channels, the Array will include sub arrays for each sample frame, with a sample
|
99
|
+
# for each channel.
|
100
|
+
#
|
101
|
+
# Examples
|
102
|
+
#
|
103
|
+
# samples = mono_buffer.samples
|
104
|
+
# # => [-0.5, 0.3, 0.2, -0.9, ...]
|
105
|
+
#
|
106
|
+
# samples = stereo_buffer.samples
|
107
|
+
# # => [[-0.2, 0.5], [0.1, 0.2], [-0.4, 0.7], [0.1, 0.2], ...]
|
108
|
+
#
|
109
|
+
# samples = three_channel_buffer.samples
|
110
|
+
# # => [[0.3, 0.5, 0.2], [-0.1, 0.2, -0.9], [0.2, 0.3, -0.4], [0.1, 0.2, -0.8], ...]
|
74
111
|
attr_reader :samples
|
75
112
|
|
76
113
|
private
|
77
114
|
|
78
115
|
def convert_buffer(samples, old_format, new_format)
|
79
|
-
|
80
|
-
|
116
|
+
if old_format.channels > new_format.channels
|
117
|
+
samples = convert_channels(samples, old_format.channels, new_format.channels)
|
118
|
+
samples = convert_sample_format(samples, old_format, new_format)
|
119
|
+
else
|
120
|
+
samples = convert_sample_format(samples, old_format, new_format)
|
121
|
+
samples = convert_channels(samples, old_format.channels, new_format.channels)
|
122
|
+
end
|
81
123
|
|
82
124
|
samples
|
83
125
|
end
|
@@ -141,6 +183,8 @@ module WaveFile
|
|
141
183
|
convert_sample_format_helper(samples) {|sample| (sample - 128).to_f / 128.0 }
|
142
184
|
elsif old_bits_per_sample == 16
|
143
185
|
convert_sample_format_helper(samples) {|sample| sample.to_f / 32768.0 }
|
186
|
+
elsif old_bits_per_sample == 24
|
187
|
+
convert_sample_format_helper(samples) {|sample| sample.to_f / 8388608.0 }
|
144
188
|
elsif old_bits_per_sample == 32
|
145
189
|
convert_sample_format_helper(samples) {|sample| sample.to_f / 2147483648.0 }
|
146
190
|
end
|
@@ -151,6 +195,8 @@ module WaveFile
|
|
151
195
|
convert_sample_format_helper(samples) {|sample| (sample * 127.0).round + 128 }
|
152
196
|
elsif new_bits_per_sample == 16
|
153
197
|
convert_sample_format_helper(samples) {|sample| (sample * 32767.0).round }
|
198
|
+
elsif new_bits_per_sample == 24
|
199
|
+
convert_sample_format_helper(samples) {|sample| (sample * 8388607.0).round }
|
154
200
|
elsif new_bits_per_sample == 32
|
155
201
|
convert_sample_format_helper(samples) {|sample| (sample * 2147483647.0).round }
|
156
202
|
end
|
data/lib/wavefile/duration.rb
CHANGED
@@ -1,6 +1,32 @@
|
|
1
1
|
module WaveFile
|
2
|
-
# Calculates playback time given the number of sample frames and the sample rate.
|
2
|
+
# Calculates playback time given the number of sample frames and the sample rate. For
|
3
|
+
# example, you can use this to calculate how long a given Wave file is.
|
4
|
+
#
|
5
|
+
# The hours, minutes, seconds, and milliseconds fields return values like you would
|
6
|
+
# see on a stopwatch, and not the total amount of time in that unit. For example, a
|
7
|
+
# stopwatch running for exactly 2 hours would show something like "2:00:00.000".
|
8
|
+
# Accordingly, if the given sample frame count and sample rate add up to exactly
|
9
|
+
# 2 hours, then hours will be 2, and minutes, seconds, and milliseconds will all be 0.
|
10
|
+
#
|
11
|
+
# This class is immutable - once a new Duration is constructed, it can't be modified.
|
3
12
|
class Duration
|
13
|
+
# Constructs a new immutable Duration.
|
14
|
+
#
|
15
|
+
# sample_frame_count - The number of sample frames, i.e. the number
|
16
|
+
# samples in each channel.
|
17
|
+
# sample_rate - The number of samples per second, such as 44100
|
18
|
+
#
|
19
|
+
# Examples:
|
20
|
+
#
|
21
|
+
# duration = Duration.new(400_000_000, 44100)
|
22
|
+
# duration.hours # => 2
|
23
|
+
# duration.minutes # => 31
|
24
|
+
# duration.seconds # => 10
|
25
|
+
# duration.milliseconds # => 294
|
26
|
+
#
|
27
|
+
# Note that the hours, minutes, seconds, and milliseconds fields do not return
|
28
|
+
# the total of the respective unit in the entire duration. For example, if a
|
29
|
+
# duration is exactly 2 hours, then minutes will be 0, not 120.
|
4
30
|
def initialize(sample_frame_count, sample_rate)
|
5
31
|
@sample_frame_count = sample_frame_count
|
6
32
|
@sample_rate = sample_rate
|
@@ -28,7 +54,12 @@ module WaveFile
|
|
28
54
|
|
29
55
|
@milliseconds = (sample_frame_count / sample_frames_per_millisecond).floor
|
30
56
|
end
|
31
|
-
|
32
|
-
attr_reader :sample_frame_count
|
57
|
+
|
58
|
+
attr_reader :sample_frame_count
|
59
|
+
attr_reader :sample_rate
|
60
|
+
attr_reader :hours
|
61
|
+
attr_reader :minutes
|
62
|
+
attr_reader :seconds
|
63
|
+
attr_reader :milliseconds
|
33
64
|
end
|
34
65
|
end
|
data/lib/wavefile/format.rb
CHANGED
@@ -1,20 +1,44 @@
|
|
1
1
|
module WaveFile
|
2
2
|
class InvalidFormatError < StandardError; end
|
3
3
|
|
4
|
+
# Represents information about the data format for a Wave file, such as number of
|
5
|
+
# channels, bits per sample, sample rate, and so forth. A Format instance is used
|
6
|
+
# by Reader to indicate what format to read samples out as, and by Writer to
|
7
|
+
# indicate what format to write samples as.
|
8
|
+
#
|
9
|
+
# This class is immutable - once a new Format is constructed, it can't be modified.
|
4
10
|
class Format
|
5
11
|
# Not using ranges because of 1.8.7 performance problems with Range.max
|
6
|
-
MIN_CHANNELS = 1
|
7
|
-
MAX_CHANNELS = 65535
|
12
|
+
MIN_CHANNELS = 1 # :nodoc:
|
13
|
+
MAX_CHANNELS = 65535 # :nodoc:
|
8
14
|
|
9
|
-
MIN_SAMPLE_RATE = 1
|
10
|
-
MAX_SAMPLE_RATE = 4_294_967_296
|
15
|
+
MIN_SAMPLE_RATE = 1 # :nodoc:
|
16
|
+
MAX_SAMPLE_RATE = 4_294_967_296 # :nodoc:
|
11
17
|
|
12
|
-
SUPPORTED_SAMPLE_FORMATS = [:pcm, :float]
|
18
|
+
SUPPORTED_SAMPLE_FORMATS = [:pcm, :float] # :nodoc:
|
13
19
|
SUPPORTED_BITS_PER_SAMPLE = {
|
14
|
-
:pcm => [8, 16, 32],
|
20
|
+
:pcm => [8, 16, 24, 32],
|
15
21
|
:float => [32, 64],
|
16
|
-
}
|
22
|
+
} # :nodoc:
|
17
23
|
|
24
|
+
# Constructs a new immutable Format.
|
25
|
+
#
|
26
|
+
# channels - The number of channels in the format. Can either be a Fixnum
|
27
|
+
# (e.g. 1, 2, 3) or the symbols :mono (equivalent to 1) or
|
28
|
+
# :stereo (equivalent to 2).
|
29
|
+
# format_code - A symbol indicating the format of each sample. Consists of
|
30
|
+
# two parts: a format code, and the bits per sample. The valid
|
31
|
+
# values are :pcm_8, :pcm_16, :pcm_32, :float_32, :float_64,
|
32
|
+
# and :float (equivalent to :float_32)
|
33
|
+
# sample_rate - The number of samples per second, such as 44100
|
34
|
+
#
|
35
|
+
# Examples
|
36
|
+
#
|
37
|
+
# format = Format.new(1, :pcm_16, 44100)
|
38
|
+
# format = Format.new(:mono, :pcm_16, 44100) # Equivalent to above
|
39
|
+
#
|
40
|
+
# format = Format.new(:stereo, :float_32, 44100)
|
41
|
+
# format = Format.new(:stereo, :float, 44100)
|
18
42
|
def initialize(channels, format_code, sample_rate)
|
19
43
|
channels = normalize_channels(channels)
|
20
44
|
sample_format, bits_per_sample = normalize_format_code(format_code)
|
@@ -31,15 +55,37 @@ module WaveFile
|
|
31
55
|
@byte_rate = @block_align * @sample_rate
|
32
56
|
end
|
33
57
|
|
58
|
+
# Returns true if the format has 1 channel, false otherwise.
|
34
59
|
def mono?
|
35
60
|
@channels == 1
|
36
61
|
end
|
37
62
|
|
63
|
+
# Returns true if the format has 2 channels, false otherwise.
|
38
64
|
def stereo?
|
39
65
|
@channels == 2
|
40
66
|
end
|
41
67
|
|
42
|
-
|
68
|
+
# Returns the number of channels, such as 1 or 2. This will always return a
|
69
|
+
# Fixnum, even if the number of channels is specified with a symbol (e.g. :mono)
|
70
|
+
# in the constructor.
|
71
|
+
attr_reader :channels
|
72
|
+
|
73
|
+
# Returns a symbol indicating the sample format, such as :pcm or :float
|
74
|
+
attr_reader :sample_format
|
75
|
+
|
76
|
+
# Returns the number of bits per sample, such as 8, 16, 24, 32, or 64.
|
77
|
+
attr_reader :bits_per_sample
|
78
|
+
|
79
|
+
# Returns the number of samples per second, such as 44100.
|
80
|
+
attr_reader :sample_rate
|
81
|
+
|
82
|
+
# Returns the number of bytes in each sample frame. For example, in a 16-bit stereo file,
|
83
|
+
# this will be 4 (2 bytes for each 16-bit sample, times 2 channels).
|
84
|
+
attr_reader :block_align
|
85
|
+
|
86
|
+
# Returns the number of bytes contained in 1 second of sample data.
|
87
|
+
# Is equivalent to block_align * sample_rate.
|
88
|
+
attr_reader :byte_rate
|
43
89
|
|
44
90
|
private
|
45
91
|
|
data/lib/wavefile/info.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
module WaveFile
|
2
|
+
# Contains metadata about an existing wave file. Returned by Reader.info.
|
3
|
+
#
|
4
|
+
# This class is immutable - once a new Info is constructed, it can't be modified.
|
2
5
|
class Info
|
3
|
-
def initialize(file_name, raw_format_chunk, sample_frame_count)
|
6
|
+
def initialize(file_name, raw_format_chunk, sample_frame_count) # :nodoc:
|
4
7
|
@file_name = file_name
|
5
8
|
@audio_format = raw_format_chunk[:audio_format]
|
6
9
|
@channels = raw_format_chunk[:channels]
|
@@ -13,8 +16,35 @@ module WaveFile
|
|
13
16
|
@duration = Duration.new(@sample_frame_count, @sample_rate)
|
14
17
|
end
|
15
18
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
+
# Returns the name of file this Info contains metadata about.
|
20
|
+
attr_reader :file_name
|
21
|
+
|
22
|
+
# Returns a Fixnum indicating the audio format, such as 1 for PCM or 3 for IEEE float.
|
23
|
+
attr_reader :audio_format
|
24
|
+
|
25
|
+
# Returns the number of channels, such as 1 or 2.
|
26
|
+
attr_reader :channels
|
27
|
+
|
28
|
+
# Returns the number of bits per sample, such as 8, 16, 32, or 64.
|
29
|
+
attr_reader :bits_per_sample
|
30
|
+
|
31
|
+
# Returns the number of samples per second, such as 44100.
|
32
|
+
attr_reader :sample_rate
|
33
|
+
|
34
|
+
# Returns the number of bytes contained in 1 second of sample data.
|
35
|
+
# Is equivalent to block_align * sample_rate.
|
36
|
+
attr_reader :byte_rate
|
37
|
+
|
38
|
+
# Returns the number of bytes in each sample frame. For example, in a 16-bit stereo file,
|
39
|
+
# this will be 4 (2 bytes for each 16-bit sample, times 2 channels).
|
40
|
+
attr_reader :block_align
|
41
|
+
|
42
|
+
# Returns the total number of sample frames in the file. A sample frame contains a single
|
43
|
+
# sample for each channel. So if there are 1,000 sample frames in a stereo file, this means
|
44
|
+
# there are 1,000 left-channel samples and 1,000 right-channel samples.
|
45
|
+
attr_reader :sample_frame_count
|
46
|
+
|
47
|
+
# Returns a Duration instance for the total number of sample frames in the file
|
48
|
+
attr_reader :duration
|
19
49
|
end
|
20
50
|
end
|