lame 0.0.1
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.
- data/.gitignore +20 -0
- data/.rspec +3 -0
- data/.rvmrc +1 -0
- data/.travis.yml +13 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +181 -0
- data/Rakefile +6 -0
- data/docs/id3v2.4.0-structure.txt +731 -0
- data/docs/lame-3.99.5.h +1323 -0
- data/lame.gemspec +28 -0
- data/lib/lame.rb +31 -0
- data/lib/lame/buffer.rb +21 -0
- data/lib/lame/configuration.rb +228 -0
- data/lib/lame/decoder.rb +38 -0
- data/lib/lame/decoding/decoded_frame.rb +25 -0
- data/lib/lame/decoding/id3_tag_parser.rb +53 -0
- data/lib/lame/decoding/mp3_data_header_parser.rb +64 -0
- data/lib/lame/decoding/mpeg_audio_frame_finder.rb +46 -0
- data/lib/lame/decoding/mpeg_audio_frame_matcher.rb +98 -0
- data/lib/lame/decoding/single_frame_decoder.rb +51 -0
- data/lib/lame/decoding/stream_decoder.rb +37 -0
- data/lib/lame/delegation.rb +68 -0
- data/lib/lame/encoder.rb +73 -0
- data/lib/lame/encoding/encode_short_buffer.rb +26 -0
- data/lib/lame/encoding/flusher.rb +22 -0
- data/lib/lame/encoding/id3.rb +46 -0
- data/lib/lame/encoding/vbr_info.rb +22 -0
- data/lib/lame/error.rb +13 -0
- data/lib/lame/ffi.rb +20 -0
- data/lib/lame/ffi/decode_flags.rb +19 -0
- data/lib/lame/ffi/enums.rb +75 -0
- data/lib/lame/ffi/functions.rb +272 -0
- data/lib/lame/ffi/global_flags.rb +20 -0
- data/lib/lame/ffi/mp3_data.rb +37 -0
- data/lib/lame/ffi/version.rb +17 -0
- data/lib/lame/version.rb +3 -0
- data/spec/buffer_spec.rb +26 -0
- data/spec/configuration_spec.rb +391 -0
- data/spec/decoder_spec.rb +120 -0
- data/spec/decoding/decoded_frame_spec.rb +44 -0
- data/spec/decoding/id3_tag_parser_spec.rb +54 -0
- data/spec/decoding/mp3_data_header_parser_spec.rb +95 -0
- data/spec/decoding/mpeg_audio_frame_finder_spec.rb +50 -0
- data/spec/decoding/mpeg_audio_frame_matcher_spec.rb +179 -0
- data/spec/decoding/single_frame_decoder_spec.rb +104 -0
- data/spec/decoding/stream_decoder_spec.rb +43 -0
- data/spec/delegation_spec.rb +146 -0
- data/spec/encoder_spec.rb +279 -0
- data/spec/encoding/encode_short_buffer_spec.rb +72 -0
- data/spec/encoding/flusher_spec.rb +47 -0
- data/spec/encoding/id3_spec.rb +106 -0
- data/spec/encoding/vbr_info_spec.rb +47 -0
- data/spec/ffi/decode_flags_spec.rb +16 -0
- data/spec/ffi/encoding_spec.rb +223 -0
- data/spec/ffi/global_flags_spec.rb +542 -0
- data/spec/ffi/id3tag_spec.rb +135 -0
- data/spec/ffi/mp3_data_spec.rb +26 -0
- data/spec/files/dies-irae.wav +0 -0
- data/spec/integration/decoding_spec.rb +179 -0
- data/spec/integration/encoding_spec.rb +126 -0
- data/spec/integration/id3_tags_spec.rb +96 -0
- data/spec/spec_helper.rb +175 -0
- metadata +254 -0
@@ -0,0 +1,120 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module LAME
|
4
|
+
describe Decoder do
|
5
|
+
|
6
|
+
let(:decode_flags) { stub("decode flags") }
|
7
|
+
let(:mp3_file) { stub("mp3 file") }
|
8
|
+
let(:id3_tag_parser) { stub("id3 tag parser", :skip! => nil) }
|
9
|
+
let(:mp3_data_header_parser) { stub("mp3 data header parser", :parse! => nil) }
|
10
|
+
|
11
|
+
# Stub away all collaborators:
|
12
|
+
before do
|
13
|
+
Decoding::Id3TagParser.stub(:new).and_return(id3_tag_parser)
|
14
|
+
Decoding::Mp3DataHeaderParser.stub(:new).and_return(mp3_data_header_parser)
|
15
|
+
FFI::DecodeFlags.stub(:new).and_return(decode_flags)
|
16
|
+
end
|
17
|
+
|
18
|
+
subject(:decoder) { Decoder.new(mp3_file) }
|
19
|
+
|
20
|
+
context "initialization" do
|
21
|
+
|
22
|
+
it "initializes DecodeFlags" do
|
23
|
+
FFI::DecodeFlags.should_receive(:new)
|
24
|
+
Decoder.new(mp3_file)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "has the DecodeFlags" do
|
28
|
+
decode_flags = stub
|
29
|
+
FFI::DecodeFlags.stub(:new).and_return(decode_flags)
|
30
|
+
decoder.decode_flags.should eql decode_flags
|
31
|
+
end
|
32
|
+
|
33
|
+
it "has the mp3 file path" do
|
34
|
+
decoder.mp3_file.should eql mp3_file
|
35
|
+
end
|
36
|
+
|
37
|
+
it "skips the id3 offset" do
|
38
|
+
Decoding::Id3TagParser.should_receive(:new).with(mp3_file)
|
39
|
+
id3_tag_parser.should_receive(:skip!)
|
40
|
+
|
41
|
+
decoder
|
42
|
+
end
|
43
|
+
|
44
|
+
it "parses the mp3 data header" do
|
45
|
+
parser = stub
|
46
|
+
mp3_data = stub
|
47
|
+
Decoding::Mp3DataHeaderParser.should_receive(:new).with(decode_flags, mp3_file).and_return(parser)
|
48
|
+
parser.should_receive(:parse!).and_return(mp3_data)
|
49
|
+
|
50
|
+
decoder.mp3_data.should eql mp3_data
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
context "after initialization" do
|
56
|
+
|
57
|
+
let(:mp3_data) { stub("mp3 data") }
|
58
|
+
|
59
|
+
# stubbing galore!
|
60
|
+
before do
|
61
|
+
FFI::DecodeFlags.stub(:new).and_return(decode_flags)
|
62
|
+
|
63
|
+
parser = stub
|
64
|
+
Decoding::Mp3DataHeaderParser.stub(:new).and_return(parser)
|
65
|
+
parser.stub(:parse!).and_return(mp3_data)
|
66
|
+
end
|
67
|
+
|
68
|
+
describe "#each_decoded_frame" do
|
69
|
+
|
70
|
+
let(:stream_decoder) { stub }
|
71
|
+
before do
|
72
|
+
Decoding::StreamDecoder.stub(:new).and_return(stream_decoder)
|
73
|
+
end
|
74
|
+
|
75
|
+
it "initializes a stream decoder with mp3 file and mp3 data" do
|
76
|
+
stream_decoder.stub(:each_decoded_frame)
|
77
|
+
|
78
|
+
Decoding::StreamDecoder.should_receive(:new).with(decode_flags, mp3_data, mp3_file)
|
79
|
+
|
80
|
+
decoder.each_decoded_frame
|
81
|
+
end
|
82
|
+
|
83
|
+
it "delegates to a stream decoder" do
|
84
|
+
stream_decoder.should_receive(:each_decoded_frame)
|
85
|
+
|
86
|
+
decoder.each_decoded_frame
|
87
|
+
end
|
88
|
+
|
89
|
+
it "re-yields the stream decoder's yield" do
|
90
|
+
stream_decoder.stub(:each_decoded_frame).and_yield(:one).and_yield(:two)
|
91
|
+
|
92
|
+
expect { |block|
|
93
|
+
decoder.each_decoded_frame(&block)
|
94
|
+
}.to yield_successive_args(:one, :two)
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
describe "#channel_mode" do
|
100
|
+
|
101
|
+
it "delegates to mp3_data" do
|
102
|
+
mp3_data.should_receive(:channel_mode).and_return(:stereo)
|
103
|
+
decoder.channel_mode.should eql :stereo
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
107
|
+
|
108
|
+
describe "#sample_rate" do
|
109
|
+
|
110
|
+
it "delegates to mp3_data" do
|
111
|
+
mp3_data.should_receive(:sample_rate).and_return(44100)
|
112
|
+
decoder.sample_rate.should eql 44100
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module LAME
|
4
|
+
module Decoding
|
5
|
+
describe DecodedFrame do
|
6
|
+
|
7
|
+
it "is initialized with left and right samples" do
|
8
|
+
left = stub
|
9
|
+
right = stub
|
10
|
+
|
11
|
+
decoded_frame = DecodedFrame.new(left, right)
|
12
|
+
|
13
|
+
decoded_frame.left.should eql left
|
14
|
+
decoded_frame.right.should eql right
|
15
|
+
end
|
16
|
+
|
17
|
+
it "can be built with FFI Buffers" do
|
18
|
+
left_buffer = ::FFI::MemoryPointer.new(:short, 4)
|
19
|
+
right_buffer = ::FFI::MemoryPointer.new(:short, 4)
|
20
|
+
|
21
|
+
left_buffer.put_array_of_short(0, [1,2,3,4])
|
22
|
+
right_buffer.put_array_of_short(0, [5,6,7,8])
|
23
|
+
|
24
|
+
decoded_frame = DecodedFrame.from_short_buffers(left_buffer, right_buffer)
|
25
|
+
|
26
|
+
decoded_frame.left.should eql [1,2,3,4]
|
27
|
+
decoded_frame.right.should eql [5,6,7,8]
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "#samples" do
|
31
|
+
|
32
|
+
it "returns zipped version of samples" do
|
33
|
+
left = [1,2,3,4]
|
34
|
+
right = [5,6,7,8]
|
35
|
+
|
36
|
+
decoded_frame = DecodedFrame.new(left, right)
|
37
|
+
|
38
|
+
decoded_frame.samples.should eql [[1,5],[2,6],[3,7],[4,8]]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module LAME
|
4
|
+
module Decoding
|
5
|
+
describe Id3TagParser do
|
6
|
+
|
7
|
+
let(:stream) { StringIO.new(stream_string) }
|
8
|
+
let(:parser) { Id3TagParser.new(stream) }
|
9
|
+
|
10
|
+
describe "#skip!" do
|
11
|
+
|
12
|
+
context "valid header" do
|
13
|
+
let(:stream_string) do
|
14
|
+
header = "ID3 "
|
15
|
+
header << 0b00000000
|
16
|
+
header << 0b00000000
|
17
|
+
header << 0b00000010
|
18
|
+
header << 0b01010101
|
19
|
+
header << " "*341 # the above bits are '341'
|
20
|
+
end
|
21
|
+
|
22
|
+
it "seeks the file until after the id3 tag" do
|
23
|
+
parser.skip!
|
24
|
+
stream.pos.should eql 351
|
25
|
+
end
|
26
|
+
|
27
|
+
it "start from the start of the stream" do
|
28
|
+
stream.seek(42)
|
29
|
+
parser.skip!
|
30
|
+
stream.pos.should eql 351
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
context "no id3 tag" do
|
36
|
+
let(:stream_string) { " "*1024 }
|
37
|
+
|
38
|
+
it "does not crash if id3 tag is not present" do
|
39
|
+
expect {
|
40
|
+
parser.skip!
|
41
|
+
}.not_to raise_error
|
42
|
+
end
|
43
|
+
|
44
|
+
it "does not seek the stream if no header is present" do
|
45
|
+
parser.skip!
|
46
|
+
stream.pos.should eql 0
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module LAME
|
4
|
+
module Decoding
|
5
|
+
describe Mp3DataHeaderParser do
|
6
|
+
|
7
|
+
subject(:parser) { Mp3DataHeaderParser.new(decode_flags, stream) }
|
8
|
+
|
9
|
+
let(:decode_flags) { stub("decode flags") }
|
10
|
+
let(:stream) { StringIO.new(stream_string) }
|
11
|
+
let(:mpeg_finder) { stub }
|
12
|
+
|
13
|
+
let(:stream_string) { "a"*100 }
|
14
|
+
|
15
|
+
before do
|
16
|
+
LAME.stub(:hip_decode1_headersB) do |_, _, _, _, _, mp3_data, _, _|
|
17
|
+
# fake that the header was found
|
18
|
+
mp3_data[:header_parsed] = 1
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
it "seeks the input stream until the first mpeg frame" do
|
23
|
+
MPEGAudioFrameFinder.should_receive(:new).with(stream).and_return(mpeg_finder)
|
24
|
+
mpeg_finder.should_receive(:find!)
|
25
|
+
|
26
|
+
parser.parse!
|
27
|
+
end
|
28
|
+
|
29
|
+
context "decoding headers" do
|
30
|
+
|
31
|
+
before do
|
32
|
+
MPEGAudioFrameFinder.stub(:new => stub.as_null_object)
|
33
|
+
end
|
34
|
+
|
35
|
+
it "reads 100 bytes from the stream" do
|
36
|
+
stream.should_receive(:read).with(100).and_return("a"*100)
|
37
|
+
parser.parse!
|
38
|
+
end
|
39
|
+
|
40
|
+
it "parses headers with LAME" do
|
41
|
+
LAME.should_receive(:hip_decode1_headersB) do |decode_flags, in_buffer, size, _, _, mp3_data, _, _|
|
42
|
+
decode_flags.should eql decode_flags
|
43
|
+
in_buffer.get_string(0).should eql "a"*100
|
44
|
+
size.should eql 100
|
45
|
+
mp3_data.should be_a(LAME::FFI::MP3Data)
|
46
|
+
|
47
|
+
# fake that the header was found
|
48
|
+
mp3_data[:header_parsed] = 1
|
49
|
+
end
|
50
|
+
parser.parse!
|
51
|
+
end
|
52
|
+
|
53
|
+
context "larger input" do
|
54
|
+
let(:stream_string) { "a"*1000 }
|
55
|
+
let(:expected_reads) { 5 }
|
56
|
+
|
57
|
+
it "reads 100 bytes until a header was parsed" do
|
58
|
+
decode_count = 0
|
59
|
+
|
60
|
+
LAME.should_receive(:hip_decode1_headersB).exactly(expected_reads).times
|
61
|
+
|
62
|
+
LAME.stub(:hip_decode1_headersB) do |_, _, _, _, _, mp3_data, _, _|
|
63
|
+
decode_count += 1
|
64
|
+
|
65
|
+
# simulate parsed header after 5 reads:
|
66
|
+
mp3_data[:header_parsed] = (decode_count == expected_reads) ? 1 : 0
|
67
|
+
end
|
68
|
+
|
69
|
+
parser.parse!
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
it "returns the parsed mp3 data if a header was parsed" do
|
74
|
+
mp3_data = stub("mp3 data", :header_parsed? => true)
|
75
|
+
LAME::FFI::MP3Data.stub(:new).and_return(mp3_data)
|
76
|
+
LAME.stub(:hip_decode1_headersB)
|
77
|
+
|
78
|
+
parser.parse!.should eql mp3_data
|
79
|
+
end
|
80
|
+
|
81
|
+
it "raises an error if the header could not be parsed" do
|
82
|
+
mp3_data = stub("mp3 data", :header_parsed? => false)
|
83
|
+
LAME::FFI::MP3Data.stub(:new).and_return(mp3_data)
|
84
|
+
LAME.stub(:hip_decode1_headersB)
|
85
|
+
|
86
|
+
expect {
|
87
|
+
parser.parse!
|
88
|
+
}.to raise_error(Mp3DataHeaderNotFoundError)
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module LAME
|
4
|
+
module Decoding
|
5
|
+
describe MPEGAudioFrameFinder do
|
6
|
+
|
7
|
+
subject(:finder) { MPEGAudioFrameFinder.new(stream) }
|
8
|
+
|
9
|
+
let(:stream) { StringIO.new(stream_string) }
|
10
|
+
let(:stream_string) { "1234567890" }
|
11
|
+
|
12
|
+
it "tries to find the mpeg frame 4 bytes at a time until a header is found" do
|
13
|
+
matcher1 = stub("matcher", :match? => false)
|
14
|
+
matcher2 = stub("matcher", :match? => false)
|
15
|
+
matcher3 = stub("matcher", :match? => true)
|
16
|
+
|
17
|
+
MPEGAudioFrameMatcher.should_receive(:new).with("1234").and_return(matcher1)
|
18
|
+
MPEGAudioFrameMatcher.should_receive(:new).with("2345").and_return(matcher2)
|
19
|
+
MPEGAudioFrameMatcher.should_receive(:new).with("3456").and_return(matcher3)
|
20
|
+
|
21
|
+
finder.find!
|
22
|
+
end
|
23
|
+
|
24
|
+
it "seeks the stream at the position of the found frame" do
|
25
|
+
matcher1 = stub("matcher", :match? => false)
|
26
|
+
matcher2 = stub("matcher", :match? => false)
|
27
|
+
matcher3 = stub("matcher", :match? => true)
|
28
|
+
|
29
|
+
MPEGAudioFrameMatcher.stub(:new).with("1234").and_return(matcher1)
|
30
|
+
MPEGAudioFrameMatcher.stub(:new).with("2345").and_return(matcher2)
|
31
|
+
MPEGAudioFrameMatcher.stub(:new).with("3456").and_return(matcher3)
|
32
|
+
|
33
|
+
finder.find!
|
34
|
+
|
35
|
+
stream.pos.should eql 2
|
36
|
+
end
|
37
|
+
|
38
|
+
it "raises an error if no header could be found" do
|
39
|
+
matcher = stub("matcher", :match? => false)
|
40
|
+
|
41
|
+
MPEGAudioFrameMatcher.stub(:new).and_return(matcher)
|
42
|
+
|
43
|
+
expect {
|
44
|
+
finder.find!
|
45
|
+
}.to raise_error(MPEGAudioFrameNotFoundError)
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,179 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module LAME
|
4
|
+
module Decoding
|
5
|
+
describe MPEGAudioFrameMatcher do
|
6
|
+
|
7
|
+
B_EMPTY = 0b00000000
|
8
|
+
|
9
|
+
B1_LEADING = 0b11111111
|
10
|
+
B2_LEADING = 0b11100000
|
11
|
+
B2_MPEG25 = 0b00000000
|
12
|
+
B2_MPEG_RESV = 0b00001000
|
13
|
+
B2_MPEG2 = 0b00010000
|
14
|
+
B2_MPEG1 = 0b00011000
|
15
|
+
B2_LAYER0 = 0b00000000 # reserved
|
16
|
+
B2_LAYER3 = 0b00000010 # Layer III
|
17
|
+
B2_LAYER2 = 0b00000100 # Layer II
|
18
|
+
B2_LAYER1 = 0b00000110 # Layer I
|
19
|
+
|
20
|
+
# Comments below are for MP3
|
21
|
+
B3_BITRATE0 = 0b00000000
|
22
|
+
B3_BITRATE1 = 0b00010000 # lowest (32 in MP3)
|
23
|
+
B3_BITRATE9 = 0b10010000 # 128kbit in MP3
|
24
|
+
B3_BITRATE11 = 0b10110000 # 192kbit in MP3
|
25
|
+
B3_BITRATE14 = 0b11100000 # highest (320 in MP3)
|
26
|
+
B3_BITRATE15 = 0b11110000
|
27
|
+
B3_SMPRATE0 = 0b00000000 # 44100
|
28
|
+
B3_SMPRATE1 = 0b00000100 # 48000
|
29
|
+
B3_SMPRATE2 = 0b00001000 # 32000
|
30
|
+
B3_SMPRATE3 = 0b00001100 # reserved
|
31
|
+
|
32
|
+
B4_STEREO = 0b00000000
|
33
|
+
B4_JOINT = 0b01000000
|
34
|
+
B4_DUAL = 0b10000000
|
35
|
+
B4_MONO = 0b11000000
|
36
|
+
B4_EMPH_NONE = 0b00000000
|
37
|
+
B4_EMPH_5015 = 0b00000001
|
38
|
+
B4_EMPH_RESV = 0b00000010 # reserved
|
39
|
+
B4_EMPH_CCIT = 0b00000011
|
40
|
+
|
41
|
+
shared_examples_for "4 valid bytes" do
|
42
|
+
it "matches" do
|
43
|
+
bytes = [b1, b2, b3, b4].pack("C*")
|
44
|
+
MPEGAudioFrameMatcher.new(bytes).match?.should be_true
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
shared_examples_for "4 invalid bytes" do
|
49
|
+
it "does not match" do
|
50
|
+
bytes = [b1, b2, b3, b4].pack("C*")
|
51
|
+
MPEGAudioFrameMatcher.new(bytes).match?.should be_false
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context "MPEG1, Layer III, 128kbit, 44khz, stereo, no-emph" do
|
56
|
+
let(:b1) { B1_LEADING }
|
57
|
+
let(:b2) { B2_LEADING | B2_MPEG1 | B2_LAYER3 }
|
58
|
+
let(:b3) { B3_BITRATE9 | B3_SMPRATE0 }
|
59
|
+
let(:b4) { B4_STEREO | B4_EMPH_NONE }
|
60
|
+
|
61
|
+
it_behaves_like "4 valid bytes"
|
62
|
+
end
|
63
|
+
|
64
|
+
context "MPEG2, Layer II, 160kbit, 24khz, mono, 50/15ms emph" do
|
65
|
+
let(:b1) { B1_LEADING }
|
66
|
+
let(:b2) { B2_LEADING | B2_MPEG2 | B2_LAYER2 }
|
67
|
+
let(:b3) { B3_BITRATE14 | B3_SMPRATE1 }
|
68
|
+
let(:b4) { B4_MONO | B4_EMPH_5015 }
|
69
|
+
|
70
|
+
it_behaves_like "4 valid bytes"
|
71
|
+
end
|
72
|
+
|
73
|
+
context "all 0 bites" do
|
74
|
+
let(:b1) { B_EMPTY }
|
75
|
+
let(:b2) { B_EMPTY }
|
76
|
+
let(:b3) { B_EMPTY }
|
77
|
+
let(:b4) { B_EMPTY }
|
78
|
+
|
79
|
+
it_behaves_like "4 invalid bytes"
|
80
|
+
end
|
81
|
+
|
82
|
+
context "reserved MPEG" do
|
83
|
+
let(:b1) { B1_LEADING }
|
84
|
+
let(:b2) { B2_LEADING | B2_MPEG_RESV | B2_LAYER3 } # <-- B2_MPEG_RESV
|
85
|
+
let(:b3) { B3_BITRATE9 | B3_SMPRATE0 }
|
86
|
+
let(:b4) { B4_STEREO | B4_EMPH_NONE }
|
87
|
+
|
88
|
+
it_behaves_like "4 invalid bytes"
|
89
|
+
end
|
90
|
+
|
91
|
+
context "reserved Layer" do
|
92
|
+
let(:b1) { B1_LEADING }
|
93
|
+
let(:b2) { B2_LEADING | B2_MPEG1 | B2_LAYER0 } # <-- B2_LAYER0
|
94
|
+
let(:b3) { B3_BITRATE9 | B3_SMPRATE0 }
|
95
|
+
let(:b4) { B4_STEREO | B4_EMPH_NONE }
|
96
|
+
|
97
|
+
it_behaves_like "4 invalid bytes"
|
98
|
+
end
|
99
|
+
|
100
|
+
context "reserved bitrate" do
|
101
|
+
let(:b1) { B1_LEADING }
|
102
|
+
let(:b2) { B2_LEADING | B2_MPEG1 | B2_LAYER3 }
|
103
|
+
let(:b3) { B3_BITRATE15 | B3_SMPRATE0 } # <-- B3_BITRATE15
|
104
|
+
let(:b4) { B4_STEREO | B4_EMPH_NONE }
|
105
|
+
|
106
|
+
it_behaves_like "4 invalid bytes"
|
107
|
+
end
|
108
|
+
|
109
|
+
context "reserved sampling rate" do
|
110
|
+
let(:b1) { B1_LEADING }
|
111
|
+
let(:b2) { B2_LEADING | B2_MPEG1 | B2_LAYER3 }
|
112
|
+
let(:b3) { B3_BITRATE9 | B3_SMPRATE3 } # <-- B3_SMPRATE3
|
113
|
+
let(:b4) { B4_STEREO | B4_EMPH_NONE }
|
114
|
+
|
115
|
+
it_behaves_like "4 invalid bytes"
|
116
|
+
end
|
117
|
+
|
118
|
+
context "valid MPEG1 Layer II bitrate/channel mode combination" do
|
119
|
+
let(:b1) { B1_LEADING }
|
120
|
+
let(:b2) { B2_LEADING | B2_MPEG1 | B2_LAYER2 }
|
121
|
+
let(:b3) { B3_BITRATE1 | B3_SMPRATE2 }
|
122
|
+
let(:b4) { B4_MONO | B4_EMPH_NONE }
|
123
|
+
|
124
|
+
# bitrate '1' and 'mono' is valid
|
125
|
+
it_behaves_like "4 valid bytes"
|
126
|
+
end
|
127
|
+
|
128
|
+
context "another valid MPEG1 Layer II bitrate/channel mode combination" do
|
129
|
+
let(:b1) { B1_LEADING }
|
130
|
+
let(:b2) { B2_LEADING | B2_MPEG1 | B2_LAYER2 }
|
131
|
+
let(:b3) { B3_BITRATE11 | B3_SMPRATE2 }
|
132
|
+
let(:b4) { B4_JOINT | B4_EMPH_NONE }
|
133
|
+
|
134
|
+
# bitrate '11' and 'joint_stereo' is valid
|
135
|
+
it_behaves_like "4 valid bytes"
|
136
|
+
end
|
137
|
+
|
138
|
+
context "yet another valid MPEG1 Layer II bitrate/channel mode combination" do
|
139
|
+
let(:b1) { B1_LEADING }
|
140
|
+
let(:b2) { B2_LEADING | B2_MPEG1 | B2_LAYER2 }
|
141
|
+
let(:b3) { B3_BITRATE9 | B3_SMPRATE2 }
|
142
|
+
let(:b4) { B4_JOINT | B4_EMPH_NONE }
|
143
|
+
|
144
|
+
# bitrate '9' and 'joint_stereo' is valid
|
145
|
+
it_behaves_like "4 valid bytes"
|
146
|
+
end
|
147
|
+
|
148
|
+
context "invalid MPEG1 Layer II bitrate/channel mode combination" do
|
149
|
+
let(:b1) { B1_LEADING }
|
150
|
+
let(:b2) { B2_LEADING | B2_MPEG1 | B2_LAYER2 }
|
151
|
+
let(:b3) { B3_BITRATE1 | B3_SMPRATE2 }
|
152
|
+
let(:b4) { B4_STEREO | B4_EMPH_NONE }
|
153
|
+
|
154
|
+
# bitrate '1' and 'stereo' is invalid
|
155
|
+
it_behaves_like "4 invalid bytes"
|
156
|
+
end
|
157
|
+
|
158
|
+
context "another invalid MPEG1 Layer II bitrate/channel mode combination" do
|
159
|
+
let(:b1) { B1_LEADING }
|
160
|
+
let(:b2) { B2_LEADING | B2_MPEG1 | B2_LAYER2 }
|
161
|
+
let(:b3) { B3_BITRATE11 | B3_SMPRATE2 }
|
162
|
+
let(:b4) { B4_MONO | B4_EMPH_NONE }
|
163
|
+
|
164
|
+
# bitrate '11' and 'mono' is invalid
|
165
|
+
it_behaves_like "4 invalid bytes"
|
166
|
+
end
|
167
|
+
|
168
|
+
context "invalid emphasis" do
|
169
|
+
let(:b1) { B1_LEADING }
|
170
|
+
let(:b2) { B2_LEADING | B2_MPEG1 | B2_LAYER3 }
|
171
|
+
let(:b3) { B3_BITRATE9 | B3_SMPRATE0 }
|
172
|
+
let(:b4) { B4_STEREO | B4_EMPH_RESV }
|
173
|
+
|
174
|
+
it_behaves_like "4 invalid bytes"
|
175
|
+
end
|
176
|
+
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|