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.
Files changed (64) hide show
  1. data/.gitignore +20 -0
  2. data/.rspec +3 -0
  3. data/.rvmrc +1 -0
  4. data/.travis.yml +13 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +181 -0
  8. data/Rakefile +6 -0
  9. data/docs/id3v2.4.0-structure.txt +731 -0
  10. data/docs/lame-3.99.5.h +1323 -0
  11. data/lame.gemspec +28 -0
  12. data/lib/lame.rb +31 -0
  13. data/lib/lame/buffer.rb +21 -0
  14. data/lib/lame/configuration.rb +228 -0
  15. data/lib/lame/decoder.rb +38 -0
  16. data/lib/lame/decoding/decoded_frame.rb +25 -0
  17. data/lib/lame/decoding/id3_tag_parser.rb +53 -0
  18. data/lib/lame/decoding/mp3_data_header_parser.rb +64 -0
  19. data/lib/lame/decoding/mpeg_audio_frame_finder.rb +46 -0
  20. data/lib/lame/decoding/mpeg_audio_frame_matcher.rb +98 -0
  21. data/lib/lame/decoding/single_frame_decoder.rb +51 -0
  22. data/lib/lame/decoding/stream_decoder.rb +37 -0
  23. data/lib/lame/delegation.rb +68 -0
  24. data/lib/lame/encoder.rb +73 -0
  25. data/lib/lame/encoding/encode_short_buffer.rb +26 -0
  26. data/lib/lame/encoding/flusher.rb +22 -0
  27. data/lib/lame/encoding/id3.rb +46 -0
  28. data/lib/lame/encoding/vbr_info.rb +22 -0
  29. data/lib/lame/error.rb +13 -0
  30. data/lib/lame/ffi.rb +20 -0
  31. data/lib/lame/ffi/decode_flags.rb +19 -0
  32. data/lib/lame/ffi/enums.rb +75 -0
  33. data/lib/lame/ffi/functions.rb +272 -0
  34. data/lib/lame/ffi/global_flags.rb +20 -0
  35. data/lib/lame/ffi/mp3_data.rb +37 -0
  36. data/lib/lame/ffi/version.rb +17 -0
  37. data/lib/lame/version.rb +3 -0
  38. data/spec/buffer_spec.rb +26 -0
  39. data/spec/configuration_spec.rb +391 -0
  40. data/spec/decoder_spec.rb +120 -0
  41. data/spec/decoding/decoded_frame_spec.rb +44 -0
  42. data/spec/decoding/id3_tag_parser_spec.rb +54 -0
  43. data/spec/decoding/mp3_data_header_parser_spec.rb +95 -0
  44. data/spec/decoding/mpeg_audio_frame_finder_spec.rb +50 -0
  45. data/spec/decoding/mpeg_audio_frame_matcher_spec.rb +179 -0
  46. data/spec/decoding/single_frame_decoder_spec.rb +104 -0
  47. data/spec/decoding/stream_decoder_spec.rb +43 -0
  48. data/spec/delegation_spec.rb +146 -0
  49. data/spec/encoder_spec.rb +279 -0
  50. data/spec/encoding/encode_short_buffer_spec.rb +72 -0
  51. data/spec/encoding/flusher_spec.rb +47 -0
  52. data/spec/encoding/id3_spec.rb +106 -0
  53. data/spec/encoding/vbr_info_spec.rb +47 -0
  54. data/spec/ffi/decode_flags_spec.rb +16 -0
  55. data/spec/ffi/encoding_spec.rb +223 -0
  56. data/spec/ffi/global_flags_spec.rb +542 -0
  57. data/spec/ffi/id3tag_spec.rb +135 -0
  58. data/spec/ffi/mp3_data_spec.rb +26 -0
  59. data/spec/files/dies-irae.wav +0 -0
  60. data/spec/integration/decoding_spec.rb +179 -0
  61. data/spec/integration/encoding_spec.rb +126 -0
  62. data/spec/integration/id3_tags_spec.rb +96 -0
  63. data/spec/spec_helper.rb +175 -0
  64. 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