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,72 @@
1
+ require 'spec_helper'
2
+
3
+ module LAME
4
+ module Encoding
5
+ describe EncodeShortBuffer do
6
+
7
+ # stubbing galore!
8
+
9
+ let(:framesize) { 1152 }
10
+ let(:left) { stub(:size => framesize) }
11
+ let(:right) { stub }
12
+ let(:global_flags) { stub }
13
+ let(:configuration) { stub(Configuration, :global_flags => global_flags, :framesize => framesize, :output_buffer_size => 8640) }
14
+
15
+ subject(:encoder) { EncodeShortBuffer.new(configuration) }
16
+
17
+ it "creates input buffers" do
18
+ LAME.stub(:lame_encode_buffer).and_return(0)
19
+
20
+ Buffer.should_receive(:create).with(:short, left)
21
+ Buffer.should_receive(:create).with(:short, right)
22
+
23
+ encoder.encode_frame(left, right)
24
+ end
25
+
26
+ it "creates output buffer" do
27
+ LAME.stub(:lame_encode_buffer).and_return(0)
28
+
29
+ Buffer.stub(:create)
30
+ Buffer.should_receive(:create_empty).with(:uchar, 8640).and_return(stub.as_null_object)
31
+
32
+ encoder.encode_frame(left, right)
33
+ end
34
+
35
+ it "encodes the input" do
36
+ left_stub = stub("left")
37
+ right_stub = stub("right")
38
+ output_stub = stub("output", :get_bytes => [])
39
+
40
+ Buffer.stub(:create).with(:short, left).and_return(left_stub)
41
+ Buffer.stub(:create).with(:short, right).and_return(right_stub)
42
+ Buffer.stub(:create_empty).with(:uchar, 8640).and_return(output_stub)
43
+
44
+ LAME.should_receive(:lame_encode_buffer) do |flags, left_buffer, right_buffer, framesize, output, output_size|
45
+ flags.should eql global_flags
46
+ left_buffer.should eql left_stub
47
+ right_buffer.should eql right_stub
48
+ framesize.should eql 1152
49
+ output.should eql output_stub
50
+ output_size.should eql 8640
51
+
52
+ 0 # return value
53
+ end
54
+
55
+ encoder.encode_frame(left, right)
56
+ end
57
+
58
+ it "returns the encoded data" do
59
+ LAME.stub(:lame_encode_buffer).and_return(512)
60
+
61
+ mp3_data = stub
62
+ output = stub
63
+ output.stub(:get_bytes).with(0, 512).and_return(mp3_data)
64
+
65
+ Buffer.stub(:create)
66
+ Buffer.stub(:create_empty).with(:uchar, 8640).and_return(output)
67
+
68
+ encoder.encode_frame(left, right).should eql mp3_data
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+
3
+ module LAME
4
+ module Encoding
5
+ describe Flusher do
6
+
7
+ let(:global_flags) { stub }
8
+ let(:configuration) { stub(Configuration, :global_flags => global_flags, :framesize => 1152, :output_buffer_size => 8640) }
9
+
10
+ subject(:flusher) { Flusher.new(configuration) }
11
+
12
+ it "creates output buffer" do
13
+ LAME.stub(:lame_encode_flush).and_return(0)
14
+
15
+ Buffer.should_receive(:create_empty).with(:uchar, 8640).and_return(stub.as_null_object)
16
+
17
+ flusher.flush
18
+ end
19
+
20
+ it "flushes" do
21
+ output_stub = stub("output", :get_bytes => [])
22
+ Buffer.stub(:create_empty).with(:uchar, 8640).and_return(output_stub)
23
+
24
+ LAME.should_receive(:lame_encode_flush) do |flags, buffer, buffer_size|
25
+ flags.should eql global_flags
26
+ buffer.should eql output_stub
27
+ buffer_size.should eql 8640
28
+ end
29
+
30
+ flusher.flush
31
+ end
32
+
33
+ it "returns the flushed data" do
34
+ LAME.stub(:lame_encode_flush).and_return(512)
35
+
36
+ mp3_data = stub
37
+ output = stub
38
+ output.stub(:get_bytes).with(0, 512).and_return(mp3_data)
39
+
40
+ Buffer.stub(:create_empty).with(:uchar, 8640).and_return(output)
41
+
42
+ flusher.flush.should eql mp3_data
43
+ end
44
+
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,106 @@
1
+ require 'spec_helper'
2
+
3
+ module LAME
4
+ module Encoding
5
+ describe Id3 do
6
+
7
+ let(:global_flags) { stub }
8
+ let(:configuration) { stub(Configuration, :global_flags => global_flags, :framesize => 1152, :output_buffer_size => 8640) }
9
+
10
+ subject(:id3) { Id3.new(configuration) }
11
+
12
+ describe "#v1" do
13
+ it "creates empty and filled output buffer" do
14
+ LAME.stub(:lame_get_id3v1_tag).and_return(1024, 1024)
15
+
16
+ # Determine size
17
+ Buffer.should_receive(:create_empty).with(:uchar, 0).and_return(stub.as_null_object)
18
+
19
+ # Actual tag
20
+ Buffer.should_receive(:create_empty).with(:uchar, 1024).and_return(stub.as_null_object)
21
+
22
+ id3.v1
23
+ end
24
+
25
+ it "creates tag" do
26
+ # Determine size
27
+ LAME.should_receive(:lame_get_id3v1_tag) do |flags, buffer, buffer_size|
28
+ flags.should eql global_flags
29
+ buffer.size.should eql 0
30
+ buffer_size.should eql 0
31
+ 1024
32
+ end
33
+
34
+ # Get actual tag
35
+ LAME.should_receive(:lame_get_id3v1_tag) do |flags, buffer, buffer_size|
36
+ flags.should eql global_flags
37
+ buffer.size.should eql 1024
38
+ buffer_size.should eql 1024
39
+ end
40
+
41
+ id3.v1
42
+ end
43
+
44
+ it "returns the id3 tag" do
45
+ LAME.stub(:lame_get_id3v1_tag).and_return(512, 512)
46
+
47
+ mp3_data = stub
48
+ output = stub
49
+ output.stub(:get_bytes).with(0, 512).and_return(mp3_data)
50
+
51
+ Buffer.stub(:create_empty).with(:uchar, 0)
52
+ Buffer.stub(:create_empty).with(:uchar, 512).and_return(output)
53
+
54
+ id3.v1.should eql mp3_data
55
+ end
56
+ end
57
+
58
+ describe "#v2" do
59
+ it "creates empty and filled output buffer" do
60
+ LAME.stub(:lame_get_id3v2_tag).and_return(1024, 1024)
61
+
62
+ # Determine size
63
+ Buffer.should_receive(:create_empty).with(:uchar, 0).and_return(stub.as_null_object)
64
+
65
+ # Actual tag
66
+ Buffer.should_receive(:create_empty).with(:uchar, 1024).and_return(stub.as_null_object)
67
+
68
+ id3.v2
69
+ end
70
+
71
+ it "creates tag" do
72
+ # Determine size
73
+ LAME.should_receive(:lame_get_id3v2_tag) do |flags, buffer, buffer_size|
74
+ flags.should eql global_flags
75
+ buffer.size.should eql 0
76
+ buffer_size.should eql 0
77
+ 1024
78
+ end
79
+
80
+ # Get actual tag
81
+ LAME.should_receive(:lame_get_id3v2_tag) do |flags, buffer, buffer_size|
82
+ flags.should eql global_flags
83
+ buffer.size.should eql 1024
84
+ buffer_size.should eql 1024
85
+ end
86
+
87
+ id3.v2
88
+ end
89
+
90
+ it "returns the id3 tag" do
91
+ LAME.stub(:lame_get_id3v2_tag).and_return(512, 512)
92
+
93
+ mp3_data = stub
94
+ output = stub
95
+ output.stub(:get_bytes).with(0, 512).and_return(mp3_data)
96
+
97
+ Buffer.stub(:create_empty).with(:uchar, 0)
98
+ Buffer.stub(:create_empty).with(:uchar, 512).and_return(output)
99
+
100
+ id3.v2.should eql mp3_data
101
+ end
102
+ end
103
+
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+
3
+ module LAME
4
+ module Encoding
5
+ describe VBRInfo do
6
+
7
+ let(:global_flags) { stub }
8
+ let(:configuration) { stub(Configuration, :global_flags => global_flags, :framesize => 1152, :output_buffer_size => 8640 ) }
9
+
10
+ subject(:vbr_info) { VBRInfo.new(configuration) }
11
+
12
+ it "creates output buffer" do
13
+ LAME.stub(:lame_get_lametag_frame).and_return(0)
14
+
15
+ Buffer.should_receive(:create_empty).with(:uchar, 8640).and_return(stub.as_null_object)
16
+
17
+ vbr_info.frame
18
+ end
19
+
20
+ it "cretes the vbr frame" do
21
+ output_stub = stub("output", :get_bytes => [])
22
+ Buffer.stub(:create_empty).with(:uchar, 8640).and_return(output_stub)
23
+
24
+ LAME.should_receive(:lame_get_lametag_frame) do |flags, buffer, buffer_size|
25
+ flags.should eql global_flags
26
+ buffer.should eql output_stub
27
+ buffer_size.should eql 8640
28
+ end
29
+
30
+ vbr_info.frame
31
+ end
32
+
33
+ it "returns the vbr frame" do
34
+ LAME.stub(:lame_get_lametag_frame).and_return(512)
35
+
36
+ mp3_data = stub
37
+ output = stub
38
+ output.stub(:get_bytes).with(0, 512).and_return(mp3_data)
39
+
40
+ Buffer.stub(:create_empty).with(:uchar, 8640).and_return(output)
41
+
42
+ vbr_info.frame.should eql mp3_data
43
+ end
44
+
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,16 @@
1
+ module LAME
2
+ describe DecodeFlags do
3
+ it "initializes LAME" do
4
+ pointer = ::FFI::Pointer.new(0)
5
+ LAME.should_receive(:hip_decode_init).and_return(pointer)
6
+ DecodeFlags.new
7
+ end
8
+
9
+ it "closes the LAME struct pointer" do
10
+ pointer = ::FFI::Pointer.new(0)
11
+ LAME.should_receive(:hip_decode_exit).with(pointer)
12
+ DecodeFlags.release(pointer)
13
+ end
14
+ end
15
+
16
+ end
@@ -0,0 +1,223 @@
1
+ require 'spec_helper'
2
+
3
+ module LAME
4
+ describe "FFI calls" do
5
+
6
+ before do
7
+ @flags_pointer = LAME.lame_init
8
+ end
9
+
10
+ after do
11
+ LAME.lame_close(@flags_pointer)
12
+ end
13
+
14
+ context "initialization" do
15
+
16
+ it "initializes the parameters" do
17
+ LAME.lame_init_params(@flags_pointer).should eql 0
18
+ end
19
+
20
+ it "inits the bitstream" do
21
+ LAME.lame_init_bitstream(@flags_pointer).should eql 0
22
+ end
23
+
24
+ end
25
+
26
+ context "encoding" do
27
+
28
+ before do
29
+ LAME.lame_init_params(@flags_pointer)
30
+ end
31
+
32
+ let(:input_buffer_size) { LAME.lame_get_framesize(@flags_pointer) * 2 }
33
+
34
+ let(:input_buffer_left) { ::FFI::MemoryPointer.new(input_type, input_buffer_size) }
35
+ let(:input_buffer_right) { ::FFI::MemoryPointer.new(input_type, input_buffer_size) }
36
+ let(:input_buffer_interleaved) { ::FFI::MemoryPointer.new(input_type, input_buffer_size*2) }
37
+
38
+ let(:output_buffer_size) { (128*1024)+16384 } # see LAME_MAXMP3BUFFER in lame.h
39
+ let(:output_buffer) { ::FFI::MemoryPointer.new(:uchar, output_buffer_size) }
40
+
41
+ context "encoding" do
42
+
43
+ context "short-buffer" do
44
+ let(:input_type) { :short }
45
+
46
+ it "encodes" do
47
+ return_code = LAME.lame_encode_buffer(@flags_pointer, input_buffer_left, input_buffer_right, input_buffer_size, output_buffer, output_buffer_size)
48
+ return_code.should >= 0
49
+ end
50
+ end
51
+
52
+ context "float-buffer" do
53
+ let(:input_type) { :float }
54
+
55
+ it "encodes" do
56
+ return_code = LAME.lame_encode_buffer_float(@flags_pointer, input_buffer_left, input_buffer_right, input_buffer_size, output_buffer, output_buffer_size)
57
+ return_code.should >= 0
58
+ end
59
+ end
60
+
61
+ context "ieee float-buffer" do
62
+ let(:input_type) { :float }
63
+
64
+ it "encodes" do
65
+ return_code = LAME.lame_encode_buffer_ieee_float(@flags_pointer, input_buffer_left, input_buffer_right, input_buffer_size, output_buffer, output_buffer_size)
66
+ return_code.should >= 0
67
+ end
68
+ end
69
+
70
+ context "ieee double-buffer" do
71
+ let(:input_type) { :double }
72
+
73
+ it "encodes" do
74
+ return_code = LAME.lame_encode_buffer_ieee_double(@flags_pointer, input_buffer_left, input_buffer_right, input_buffer_size, output_buffer, output_buffer_size)
75
+ return_code.should >= 0
76
+ end
77
+ end
78
+
79
+ context "long-buffer" do
80
+ let(:input_type) { :long }
81
+
82
+ it "encodes" do
83
+ return_code = LAME.lame_encode_buffer_long(@flags_pointer, input_buffer_left, input_buffer_right, input_buffer_size, output_buffer, output_buffer_size)
84
+ return_code.should >= 0
85
+ end
86
+ end
87
+
88
+ context "long-buffer" do
89
+ let(:input_type) { :long }
90
+
91
+ it "encodes" do
92
+ return_code = LAME.lame_encode_buffer_long2(@flags_pointer, input_buffer_left, input_buffer_right, input_buffer_size, output_buffer, output_buffer_size)
93
+ return_code.should >= 0
94
+ end
95
+ end
96
+
97
+ context "int-buffer" do
98
+ let(:input_type) { :int }
99
+
100
+ it "encodes" do
101
+ return_code = LAME.lame_encode_buffer_int(@flags_pointer, input_buffer_left, input_buffer_right, input_buffer_size, output_buffer, output_buffer_size)
102
+ return_code.should >= 0
103
+ end
104
+ end
105
+
106
+ context "interleaved" do
107
+
108
+ context "ieee float-buffer" do
109
+ let(:input_type) { :float }
110
+
111
+ it "encodes" do
112
+ return_code = LAME.lame_encode_buffer_interleaved_ieee_float(@flags_pointer, input_buffer_interleaved, input_buffer_size, output_buffer, output_buffer_size)
113
+ return_code.should >= 0
114
+ end
115
+ end
116
+
117
+ context "ieee double-buffer" do
118
+ let(:input_type) { :double }
119
+
120
+ it "encodes" do
121
+ return_code = LAME.lame_encode_buffer_interleaved_ieee_double(@flags_pointer, input_buffer_interleaved, input_buffer_size, output_buffer, output_buffer_size)
122
+ return_code.should >= 0
123
+ end
124
+ end
125
+
126
+ end
127
+
128
+ end
129
+
130
+ context "flushing" do
131
+ let(:input_type) { :short }
132
+
133
+ it "flushes" do
134
+ LAME.lame_encode_flush(@flags_pointer, output_buffer, output_buffer_size).should be >= 0
135
+ end
136
+
137
+ it "flushes nogap" do
138
+ # encode something so the flush doesn't give an error
139
+ LAME.lame_encode_buffer(@flags_pointer, input_buffer_left, input_buffer_right, input_buffer_size, output_buffer, output_buffer_size)
140
+
141
+ LAME.lame_encode_flush_nogap(@flags_pointer, output_buffer, output_buffer_size).should >= 0
142
+ end
143
+ end
144
+
145
+ context "lametag frame" do
146
+ let(:input_type) { :short }
147
+
148
+ it "creates a lametag frame" do
149
+ # encode something so there is a lametag frame with VBR info
150
+ # (0..input_buffer_size).each do |index|
151
+ # input_buffer_left.put_short(index, rand(2**15)-2**14)
152
+ # input_buffer_right.put_short(index, rand(2**15)-2**14)
153
+ # end
154
+
155
+ LAME.lame_encode_buffer(@flags_pointer, input_buffer_left, input_buffer_right, input_buffer_size, output_buffer, output_buffer_size)
156
+
157
+ frame_size = LAME.lame_get_lametag_frame(@flags_pointer, output_buffer, output_buffer_size)
158
+ #p output_buffer.get_bytes(0, frame_size)
159
+ frame_size.should eql 417
160
+ end
161
+ end
162
+
163
+ context "history statistics" do
164
+ let(:input_type) { :short }
165
+
166
+ before do
167
+ LAME.lame_encode_buffer(@flags_pointer, input_buffer_left, input_buffer_right, input_buffer_size, output_buffer, output_buffer_size)
168
+ end
169
+
170
+ it "has bitrate history" do
171
+ bitrate_count_ptr = ::FFI::MemoryPointer.new(:int, 14)
172
+ LAME.lame_bitrate_hist(@flags_pointer, bitrate_count_ptr)
173
+
174
+ bitrate_count = bitrate_count_ptr.read_array_of_int(14)
175
+ # 9th = 128 (see below)
176
+ bitrate_count.should eql [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0]
177
+ end
178
+
179
+ it "has bitrate kbps" do
180
+ bitrate_kbps_ptr = ::FFI::MemoryPointer.new(:int, 14)
181
+ LAME.lame_bitrate_kbps(@flags_pointer, bitrate_kbps_ptr)
182
+
183
+ bitrate_kbps = bitrate_kbps_ptr.read_array_of_int(14)
184
+ # 9th = 128 (see bitrate table, without 0)
185
+ bitrate_kbps.should eql [32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320]
186
+ end
187
+
188
+ it "has stereo mode hist" do
189
+ stereo_mode_hist_ptr = ::FFI::MemoryPointer.new(:int, 4)
190
+ LAME.lame_stereo_mode_hist(@flags_pointer, stereo_mode_hist_ptr)
191
+
192
+ stereo_mode_hist = stereo_mode_hist_ptr.read_array_of_int(4)
193
+ # see lame.h for meaning
194
+ stereo_mode_hist.should eql [0, 0, 1, 0]
195
+ end
196
+
197
+ it "has bitrate stereo mode hist" do
198
+ pending "multi-dimensional array"
199
+ end
200
+
201
+ it "has block type hist" do
202
+ block_type_hist_ptr = ::FFI::MemoryPointer.new(:int, 6)
203
+ LAME.lame_block_type_hist(@flags_pointer, block_type_hist_ptr)
204
+
205
+ block_type_hist = block_type_hist_ptr.read_array_of_int(6)
206
+ # see lame.h for meaning
207
+ block_type_hist.should eql [4, 0, 0, 0, 0, 4]
208
+ end
209
+
210
+ it "has bitrate block type hist" do
211
+ pending "multi-dimensional array"
212
+ end
213
+ end
214
+
215
+ context "closing" do
216
+ it "closes" do
217
+ LAME.lame_close(@flags_pointer).should eql 0
218
+ end
219
+ end
220
+ end
221
+
222
+ end
223
+ end