icanhasaudio 0.1.1 → 0.1.2

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 (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