icanhasaudio 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. data/History.txt +6 -0
  2. data/Manifest.txt +24 -14
  3. data/README.txt +2 -0
  4. data/Rakefile +15 -8
  5. data/ext/icanhasaudio/audio_mpeg_decoder.c +220 -0
  6. data/ext/icanhasaudio/audio_mpeg_decoder.h +8 -0
  7. data/ext/icanhasaudio/audio_mpeg_decoder_mp3data.c +96 -0
  8. data/ext/icanhasaudio/audio_mpeg_decoder_mp3data.h +8 -0
  9. data/ext/{mpeg_encoder.c → icanhasaudio/audio_mpeg_encoder.c} +94 -102
  10. data/ext/icanhasaudio/audio_mpeg_encoder.h +8 -0
  11. data/ext/{rb_ogg.c → icanhasaudio/audio_ogg_decoder.c} +18 -9
  12. data/ext/icanhasaudio/audio_ogg_decoder.h +8 -0
  13. data/ext/{extconf.rb → icanhasaudio/extconf.rb} +2 -2
  14. data/ext/{get_audio.c → icanhasaudio/get_audio.c} +1 -6
  15. data/ext/{get_audio.h → icanhasaudio/get_audio.h} +2 -0
  16. data/ext/icanhasaudio/native.c +9 -0
  17. data/ext/icanhasaudio/native.h +21 -0
  18. data/ext/{rb_wav.c → icanhasaudio/rb_wav.c} +1 -2
  19. data/ext/{rb_wav.h → icanhasaudio/rb_wav.h} +1 -2
  20. data/lib/icanhasaudio.rb +4 -0
  21. data/lib/icanhasaudio/mpeg.rb +1 -24
  22. data/lib/icanhasaudio/mpeg/decoder.rb +95 -0
  23. data/lib/icanhasaudio/ogg.rb +1 -21
  24. data/lib/icanhasaudio/ogg/decoder.rb +31 -0
  25. data/lib/icanhasaudio/version.rb +8 -0
  26. data/lib/icanhasaudio/wav.rb +1 -0
  27. data/lib/icanhasaudio/wav/file.rb +62 -0
  28. data/test/assets/icha.mp3 +0 -0
  29. data/test/helper.rb +15 -0
  30. data/test/mpeg/test_decoder.rb +20 -0
  31. data/test/test_mpeg_encoder.rb +2 -4
  32. metadata +31 -18
  33. data/ext/decoder.c +0 -95
  34. data/ext/decoder.h +0 -3
  35. data/ext/icanhasaudio.c +0 -183
  36. data/ext/icanhasaudio.h +0 -8
  37. data/ext/mpeg_encoder.h +0 -10
  38. data/ext/syncword.c +0 -45
  39. data/ext/syncword.h +0 -3
data/History.txt CHANGED
@@ -1,3 +1,9 @@
1
+ === 0.1.2
2
+
3
+ * Bugfix
4
+ * Determining bitrate by filesize if not determined yet.
5
+ * Moving lots of C code to Ruby!
6
+
1
7
  === 0.1.1
2
8
 
3
9
  * 1 Bugfix
data/Manifest.txt CHANGED
@@ -6,22 +6,32 @@ Rakefile
6
6
  examples/decoder.rb
7
7
  examples/encoder.rb
8
8
  examples/kexp.rb
9
- ext/decoder.c
10
- ext/decoder.h
11
- ext/extconf.rb
12
- ext/get_audio.c
13
- ext/get_audio.h
14
- ext/icanhasaudio.c
15
- ext/icanhasaudio.h
16
- ext/mpeg_encoder.c
17
- ext/mpeg_encoder.h
18
- ext/rb_ogg.c
19
- ext/rb_wav.c
20
- ext/rb_wav.h
21
- ext/syncword.c
22
- ext/syncword.h
9
+ ext/icanhasaudio/audio_mpeg_decoder.c
10
+ ext/icanhasaudio/audio_mpeg_decoder.h
11
+ ext/icanhasaudio/audio_mpeg_decoder_mp3data.c
12
+ ext/icanhasaudio/audio_mpeg_decoder_mp3data.h
13
+ ext/icanhasaudio/audio_mpeg_encoder.c
14
+ ext/icanhasaudio/audio_mpeg_encoder.h
15
+ ext/icanhasaudio/audio_ogg_decoder.c
16
+ ext/icanhasaudio/audio_ogg_decoder.h
17
+ ext/icanhasaudio/extconf.rb
18
+ ext/icanhasaudio/get_audio.c
19
+ ext/icanhasaudio/get_audio.h
20
+ ext/icanhasaudio/native.c
21
+ ext/icanhasaudio/native.h
22
+ ext/icanhasaudio/rb_wav.c
23
+ ext/icanhasaudio/rb_wav.h
24
+ lib/icanhasaudio.rb
23
25
  lib/icanhasaudio/mpeg.rb
26
+ lib/icanhasaudio/mpeg/decoder.rb
24
27
  lib/icanhasaudio/mpeg/encoder.rb
25
28
  lib/icanhasaudio/ogg.rb
29
+ lib/icanhasaudio/ogg/decoder.rb
30
+ lib/icanhasaudio/version.rb
31
+ lib/icanhasaudio/wav.rb
32
+ lib/icanhasaudio/wav/file.rb
33
+ test/assets/icha.mp3
26
34
  test/assets/testcase.wav
35
+ test/helper.rb
36
+ test/mpeg/test_decoder.rb
27
37
  test/test_mpeg_encoder.rb
data/README.txt CHANGED
@@ -1,5 +1,7 @@
1
1
  = Audio::MPEG
2
2
 
3
+ http://icanhasaudio.com/
4
+ http://github.com/tenderlove/icanhasaudio/tree/master
3
5
  http://seattlerb.rubyforge.org/
4
6
 
5
7
  == DESCRIPTION. LULZ
data/Rakefile CHANGED
@@ -4,26 +4,33 @@ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), "lib")
4
4
 
5
5
  kind = Config::CONFIG["DLEXT"]
6
6
 
7
- Hoe.new('icanhasaudio', '0.1.1') do |p|
7
+ require 'icanhasaudio/version'
8
+
9
+ Hoe.new('icanhasaudio', Audio::MPEG::Decoder::VERSION) do |p|
8
10
  p.rubyforge_name = 'seattlerb'
9
11
  p.author = 'Aaron Patterson'
10
12
  p.email = 'aaronp@rubyforge.org'
11
13
  p.summary = "icanhasaudio is a lame/vorbis wrapper for decoding ur mp3s and ur oggs."
12
14
  p.description = p.paragraphs_of('README.txt', 3..6).join("\n\n")
13
15
  p.url = p.paragraphs_of('README.txt', 1).first.strip
14
- p.spec_extras = { :extensions => ['ext/extconf.rb'] }
15
- p.clean_globs = ["ext/Makefile", "ext/*.{o,so,bundle,log}"]
16
+ p.spec_extras = {
17
+ :extensions => ['ext/icanhasaudio/extconf.rb']
18
+ }
19
+ p.clean_globs = [
20
+ "ext/icanhasaudio/Makefile",
21
+ "ext/icanhasaudio/*.{o,so,bundle,log}"
22
+ ]
16
23
  end
17
24
 
18
25
  Rake::Task[:test].prerequisites << :extension
19
26
 
20
27
  desc "I can haz binary"
21
- task :extension => ["ext/icanhasaudio.#{kind}"]
28
+ task :extension => ["ext/icanhasaudio/native.#{kind}"]
22
29
 
23
- file "ext/Makefile" => "ext/extconf.rb" do
24
- Dir.chdir("ext") { ruby "extconf.rb" }
30
+ file "ext/icanhasaudio/Makefile" => "ext/icanhasaudio/extconf.rb" do
31
+ Dir.chdir("ext/icanhasaudio") { ruby "extconf.rb" }
25
32
  end
26
33
 
27
- file "ext/icanhasaudio.#{kind}" => FileList["ext/Makefile", "ext/*.{c,h}"] do
28
- Dir.chdir("ext") { sh "make" }
34
+ file "ext/icanhasaudio/native.#{kind}" => FileList["ext/icanhasaudio/Makefile", "ext/icanhasaudio/*.{c,h}"] do
35
+ Dir.chdir("ext/icanhasaudio") { sh "make" }
29
36
  end
@@ -0,0 +1,220 @@
1
+ /*
2
+ * Most of this code was take from the lame front end. So thank you to the
3
+ * lame team! The good parts are theirs, the bad parts are mine.
4
+ *
5
+ * The rest of it is (c) 2007 Aaron Patterson <aaronp@tenderlovemaking.com>
6
+ *
7
+ * Released under the GPL
8
+ */
9
+ #include <audio_mpeg_decoder.h>
10
+
11
+ static void reader_mark(lame_global_flags * lgf) {}
12
+ static void reader_free(lame_global_flags * gfp) {
13
+ lame_close(gfp);
14
+ }
15
+
16
+ /*
17
+ * call-seq:
18
+ * Audio::MPEG::Decoder.new
19
+ *
20
+ * Returns a new MPEG Decoder object.
21
+ */
22
+ static VALUE
23
+ reader_allocate(VALUE klass) {
24
+ int i = 0;
25
+ lame_global_flags * gfp = lame_init();
26
+ lame_set_decode_only(gfp, 1);
27
+ i = lame_init_params(gfp);
28
+
29
+ if(i < 0) {
30
+ rb_raise(rb_eRuntimeError, "Fatal error during initialization.\n");
31
+ }
32
+ lame_decode_init();
33
+ return Data_Wrap_Struct(klass, reader_mark, reader_free, gfp);
34
+ }
35
+
36
+ /*
37
+ * call-seq:
38
+ * Audio::MPEG::Decoder.lame_version
39
+ *
40
+ * Returns the version of lame you are using.
41
+ */
42
+ static VALUE method_lame_version(VALUE klass) {
43
+ const char * version = get_lame_version();
44
+ return rb_str_new(version, strlen(version));
45
+ }
46
+
47
+ /*
48
+ * call-seq:
49
+ * decode_headers_for(buffer)
50
+ *
51
+ * Decode the mp3 headers for +buffer+.
52
+ */
53
+ static VALUE decode_headers_for(VALUE self, VALUE rb_buffer)
54
+ {
55
+ int enc_delay;
56
+ int enc_padding;
57
+ mp3data_struct * mp3data;
58
+
59
+ unsigned char * buf = (unsigned char *)StringValuePtr(rb_buffer);
60
+ int len = NUM2INT(rb_funcall(rb_buffer, rb_intern("length"), 0));
61
+ short int pcm_l[1152], pcm_r[1152];
62
+
63
+ VALUE rb_mp3data = rb_funcall(self, rb_intern("mp3data"), 0);
64
+ Data_Get_Struct(rb_mp3data, mp3data_struct, mp3data);
65
+
66
+ int ret = lame_decode1_headersB(buf,
67
+ len,
68
+ pcm_l,
69
+ pcm_r,
70
+ mp3data,
71
+ &enc_delay,
72
+ &enc_padding
73
+ );
74
+
75
+ if(ret == -1)
76
+ rb_raise(rb_eRuntimeError, "Decode headers failed.\n");
77
+
78
+ return rb_mp3data;
79
+ }
80
+
81
+ /*
82
+ * call-seq:
83
+ * native_decode(input_io, output_io)
84
+ *
85
+ * Decode the input IO and write it to the output IO.
86
+ */
87
+ static VALUE native_decode(VALUE self, VALUE infile, VALUE outf) {
88
+ lame_global_flags * gfp;
89
+ short int Buffer[2][1152];
90
+ int iread;
91
+ double wavsize;
92
+ int i;
93
+ int tmp_num_channels;
94
+ int skip;
95
+ VALUE raw;
96
+ mp3data_struct * mp3data;
97
+
98
+ VALUE rb_mp3data = rb_funcall(self, rb_intern("mp3data"), 0);
99
+ Data_Get_Struct(rb_mp3data, mp3data_struct, mp3data);
100
+
101
+ raw = rb_iv_get(self, "@raw");
102
+
103
+ Data_Get_Struct(self, lame_global_flags, gfp);
104
+ tmp_num_channels = lame_get_num_channels( gfp );
105
+ lame_set_num_samples(gfp, MAX_U_32_NUM);
106
+
107
+ skip = lame_get_encoder_delay(gfp)+528+1;
108
+
109
+ rb_iv_set(self, "@bits", INT2NUM(16));
110
+
111
+ wavsize = -skip;
112
+ if(lame_get_num_samples(gfp) == MAX_U_32_NUM) {
113
+ rb_funcall(self, rb_intern("determine_samples_for"), 1, infile);
114
+ }
115
+ mp3data->totalframes = mp3data->nsamp / mp3data->framesize;
116
+
117
+ assert(tmp_num_channels >= 1 && tmp_num_channels <= 2);
118
+
119
+ do {
120
+ char BitBuffer16[1152 * 4];
121
+ int bit_16_i = 0;
122
+ iread = get_audio16(self, infile, Buffer, mp3data);
123
+ mp3data->framenum += iread / mp3data->framesize;
124
+ wavsize += iread;
125
+
126
+ memset(&BitBuffer16, 0, 1152 * 4);
127
+
128
+ skip -= (i = skip < iread ? skip : iread); /* 'i' samples are to skip in this frame */
129
+
130
+ for (; i < iread; i++) {
131
+ /* Write the 0 channel */
132
+ BitBuffer16[bit_16_i] = Buffer[0][i] & 0xFF;
133
+ BitBuffer16[bit_16_i + 1] = ((Buffer[0][i] >> 8) & 0xFF);
134
+
135
+ if (tmp_num_channels == 2) {
136
+ BitBuffer16[bit_16_i + 2] = Buffer[1][i] & 0xFF;
137
+ BitBuffer16[bit_16_i + 3] = ((Buffer[1][i] >> 8) & 0xFF);
138
+ bit_16_i += 4;
139
+ } else {
140
+ bit_16_i += 2;
141
+ }
142
+ }
143
+ rb_funcall(outf, rb_intern("write"), 1, rb_str_new(BitBuffer16, bit_16_i));
144
+ } while (iread);
145
+
146
+ i = (16 / 8) * tmp_num_channels;
147
+ assert(i > 0);
148
+ if (wavsize <= 0) {
149
+ wavsize = 0;
150
+ }
151
+ else if (wavsize > 0xFFFFFFD0 / i) {
152
+ wavsize = 0xFFFFFFD0;
153
+ }
154
+ else {
155
+ wavsize *= i;
156
+ }
157
+
158
+ rb_iv_set(self, "@wavsize", INT2NUM(wavsize));
159
+ return Qnil;
160
+ }
161
+
162
+ /*
163
+ * call-seq:
164
+ * num_channels
165
+ *
166
+ * Get the number of channels
167
+ */
168
+ static VALUE get_num_channels(VALUE self)
169
+ {
170
+ lame_global_flags * gfp;
171
+ Data_Get_Struct(self, lame_global_flags, gfp);
172
+ return INT2NUM(lame_get_num_channels(gfp));
173
+ }
174
+
175
+ /*
176
+ * call-seq:
177
+ * num_samples=(number)
178
+ *
179
+ * Set the number of samples
180
+ */
181
+ static VALUE set_num_samples(VALUE self, VALUE sample_count)
182
+ {
183
+ lame_global_flags * gfp;
184
+ Data_Get_Struct(self, lame_global_flags, gfp);
185
+ lame_set_num_samples(gfp, NUM2INT(sample_count));
186
+ return sample_count;
187
+ }
188
+
189
+ /*
190
+ * call-seq:
191
+ * in_samplerate
192
+ *
193
+ * Get the input samplerate
194
+ */
195
+ static VALUE get_in_samplerate(VALUE self)
196
+ {
197
+ lame_global_flags * gfp;
198
+ Data_Get_Struct(self, lame_global_flags, gfp);
199
+ return INT2NUM(lame_get_in_samplerate(gfp));
200
+ }
201
+
202
+ void init_audio_mpeg_decoder() {
203
+ VALUE rb_mAudio = rb_define_module("Audio");
204
+ VALUE rb_mMpeg = rb_define_module_under(rb_mAudio, "MPEG");
205
+ VALUE rb_cDecoder = rb_define_class_under(rb_mMpeg, "Decoder", rb_cObject);
206
+
207
+ rb_define_singleton_method(
208
+ rb_cDecoder,
209
+ "lame_version",
210
+ method_lame_version,
211
+ 0
212
+ );
213
+
214
+ rb_define_alloc_func(rb_cDecoder, reader_allocate);
215
+ rb_define_method(rb_cDecoder, "num_samples=", set_num_samples, 1);
216
+ rb_define_method(rb_cDecoder, "in_samplerate", get_in_samplerate, 0);
217
+ rb_define_private_method(rb_cDecoder, "native_decode", native_decode, 2);
218
+ rb_define_private_method(rb_cDecoder, "decode_headers_for", decode_headers_for, 1);
219
+ rb_define_private_method(rb_cDecoder, "num_channels", get_num_channels, 0);
220
+ }
@@ -0,0 +1,8 @@
1
+ #ifndef AUDIO_MPEG_DECODER_H
2
+ #define AUDIO_MPEG_DECODER_H
3
+
4
+ #include <native.h>
5
+
6
+ void init_audio_mpeg_decoder();
7
+
8
+ #endif
@@ -0,0 +1,96 @@
1
+ #include <audio_mpeg_decoder_mp3data.h>
2
+
3
+ /*
4
+ * call-seq:
5
+ * header_parsed?
6
+ *
7
+ * Has the mp3 header been parsed yet?
8
+ */
9
+ static VALUE header_parsed_eh(VALUE self)
10
+ {
11
+ mp3data_struct * mp3data;
12
+ Data_Get_Struct(self, mp3data_struct, mp3data);
13
+
14
+ if(mp3data->header_parsed == 1) return Qtrue;
15
+ return Qfalse;
16
+ }
17
+
18
+ /*
19
+ * call-seq:
20
+ * bitrate
21
+ *
22
+ * Get the bitrate
23
+ */
24
+ static VALUE bitrate(VALUE self)
25
+ {
26
+ mp3data_struct * mp3data;
27
+ Data_Get_Struct(self, mp3data_struct, mp3data);
28
+ return INT2NUM(mp3data->bitrate);
29
+ }
30
+
31
+ /*
32
+ * call-seq:
33
+ * total_frames
34
+ *
35
+ * Get the total frames for this mp3
36
+ */
37
+ static VALUE total_frames(VALUE self)
38
+ {
39
+ mp3data_struct * mp3data;
40
+ Data_Get_Struct(self, mp3data_struct, mp3data);
41
+ return INT2NUM(mp3data->totalframes);
42
+ }
43
+
44
+ /*
45
+ * call-seq:
46
+ * nsamp
47
+ *
48
+ * Get the number of samples
49
+ */
50
+ static VALUE get_nsamp(VALUE self)
51
+ {
52
+ mp3data_struct * mp3data;
53
+ Data_Get_Struct(self, mp3data_struct, mp3data);
54
+ return LONG2NUM(mp3data->nsamp);
55
+ }
56
+
57
+ /*
58
+ * call-seq:
59
+ * nsamp=(num)
60
+ *
61
+ * Set the number of samples to +num+
62
+ */
63
+ static VALUE set_nsamp(VALUE self, VALUE num)
64
+ {
65
+ mp3data_struct * mp3data;
66
+ Data_Get_Struct(self, mp3data_struct, mp3data);
67
+ mp3data->nsamp = NUM2LONG(num);
68
+ return num;
69
+ }
70
+
71
+ static VALUE deallocate(mp3data_struct * mp3data)
72
+ {
73
+ free(mp3data);
74
+ }
75
+
76
+ static VALUE allocate(VALUE klass)
77
+ {
78
+ mp3data_struct * mp3data = calloc(1, sizeof(mp3data_struct));
79
+ return Data_Wrap_Struct(klass, 0, deallocate, mp3data);
80
+ }
81
+
82
+ void init_audio_mpeg_decoder_mp3data()
83
+ {
84
+ VALUE rb_mAudio = rb_define_module("Audio");
85
+ VALUE rb_mMpeg = rb_define_module_under(rb_mAudio, "MPEG");
86
+ VALUE rb_cDecoder = rb_define_class_under(rb_mMpeg, "Decoder", rb_cObject);
87
+ VALUE klass = rb_define_class_under(rb_cDecoder, "MP3Data", rb_cObject);
88
+
89
+ rb_const_set(klass, rb_intern("MAX_U_32_NUM"), INT2NUM(MAX_U_32_NUM));
90
+ rb_define_method(klass, "header_parsed?", header_parsed_eh, 0);
91
+ rb_define_method(klass, "bitrate", bitrate, 0);
92
+ rb_define_method(klass, "total_frames", total_frames, 0);
93
+ rb_define_method(klass, "nsamp", get_nsamp, 0);
94
+ rb_define_method(klass, "nsamp=", set_nsamp, 1);
95
+ rb_define_alloc_func(klass, allocate);
96
+ }
@@ -0,0 +1,8 @@
1
+ #ifndef AUDIO_MPEG_DECODER_MP3DATA
2
+ #define AUDIO_MPEG_DECODER_MP3DATA
3
+
4
+ #include <native.h>
5
+
6
+ void init_audio_mpeg_decoder_mp3data();
7
+
8
+ #endif