icanhasaudio 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +9 -4
- data/Rakefile +1 -2
- data/examples/kexp.rb +1 -1
- data/ext/decoder.c +1 -7
- data/ext/icanhasaudio.c +2 -2
- data/ext/mpeg_encoder.c +108 -0
- data/lib/icanhasaudio/mpeg.rb +11 -0
- data/lib/icanhasaudio/mpeg/encoder.rb +146 -131
- metadata +5 -4
data/History.txt
CHANGED
@@ -1,17 +1,22 @@
|
|
1
|
-
|
1
|
+
=== 0.1.1
|
2
|
+
|
3
|
+
* 1 Bugfix
|
4
|
+
* Only rewinding output files if its possible.
|
5
|
+
|
6
|
+
=== 0.1.0
|
2
7
|
|
3
8
|
* 1 major enhancement
|
4
9
|
* Added MPEG Encoder
|
5
10
|
|
6
|
-
|
11
|
+
=== 0.0.3
|
7
12
|
* 1 minor enhancement
|
8
13
|
* Fixed extconf to be a little more smart.
|
9
14
|
|
10
|
-
|
15
|
+
=== 0.0.2
|
11
16
|
* 1 major enhancement
|
12
17
|
* I can has ogg decoder!
|
13
18
|
|
14
|
-
|
19
|
+
=== 0.0.1 / 2007-07-10
|
15
20
|
|
16
21
|
* 1 major enhancement
|
17
22
|
* I can has birfday!
|
data/Rakefile
CHANGED
@@ -4,14 +4,13 @@ $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.
|
7
|
+
Hoe.new('icanhasaudio', '0.1.1') do |p|
|
8
8
|
p.rubyforge_name = 'seattlerb'
|
9
9
|
p.author = 'Aaron Patterson'
|
10
10
|
p.email = 'aaronp@rubyforge.org'
|
11
11
|
p.summary = "icanhasaudio is a lame/vorbis wrapper for decoding ur mp3s and ur oggs."
|
12
12
|
p.description = p.paragraphs_of('README.txt', 3..6).join("\n\n")
|
13
13
|
p.url = p.paragraphs_of('README.txt', 1).first.strip
|
14
|
-
p.changes = p.paragraphs_of('History.txt', 0..2).join("\n\n")
|
15
14
|
p.spec_extras = { :extensions => ['ext/extconf.rb'] }
|
16
15
|
p.clean_globs = ["ext/Makefile", "ext/*.{o,so,bundle,log}"]
|
17
16
|
end
|
data/examples/kexp.rb
CHANGED
data/ext/decoder.c
CHANGED
@@ -86,13 +86,7 @@ lame_decoder(VALUE self, VALUE infile, VALUE outf, mp3data_struct * mp3data)
|
|
86
86
|
wavsize *= i;
|
87
87
|
}
|
88
88
|
|
89
|
-
if(!raw &&
|
90
|
-
rb_funcall( outf,
|
91
|
-
rb_intern("seek"),
|
92
|
-
2,
|
93
|
-
INT2NUM(0),
|
94
|
-
rb_const_get(rb_cIO, rb_intern("SEEK_SET")) );
|
95
|
-
|
89
|
+
if(!raw && rb_funcall(self, rb_intern("attempt_rewind"), 1, outf)) {
|
96
90
|
rewrite_header(headbuf, (int)wavsize);
|
97
91
|
rb_funcall(outf, rb_intern("write"), 1, rb_str_new(headbuf, 44));
|
98
92
|
}
|
data/ext/icanhasaudio.c
CHANGED
@@ -163,8 +163,8 @@ void Init_icanhasaudio() {
|
|
163
163
|
rb_mOgg = rb_define_module_under(rb_mAudio, "OGG");
|
164
164
|
rb_cOggDecoder = rb_define_class_under(rb_mOgg, "Decoder", rb_cObject);
|
165
165
|
|
166
|
-
/* VERSION = '0.1.
|
167
|
-
rb_define_const(rb_cDecoder, "VERSION", rb_str_new2("0.1.
|
166
|
+
/* VERSION = '0.1.1' */
|
167
|
+
rb_define_const(rb_cDecoder, "VERSION", rb_str_new2("0.1.1"));
|
168
168
|
rb_define_singleton_method(
|
169
169
|
rb_cDecoder,
|
170
170
|
"lame_version",
|
data/ext/mpeg_encoder.c
CHANGED
@@ -296,6 +296,12 @@ static VALUE MpegEncoder_set_genre(VALUE self, VALUE genre) {
|
|
296
296
|
|
297
297
|
/* Private methods. */
|
298
298
|
|
299
|
+
/*
|
300
|
+
* call-seq:
|
301
|
+
* encoder.write_vbr_tag
|
302
|
+
*
|
303
|
+
* Write the vbr tag
|
304
|
+
*/
|
299
305
|
static VALUE MpegEncoder_write_vbr_tag(VALUE self) {
|
300
306
|
lame_global_flags * gfp;
|
301
307
|
|
@@ -305,6 +311,12 @@ static VALUE MpegEncoder_write_vbr_tag(VALUE self) {
|
|
305
311
|
return Qfalse;
|
306
312
|
}
|
307
313
|
|
314
|
+
/*
|
315
|
+
* call-seq:
|
316
|
+
* encoder.print_internals
|
317
|
+
*
|
318
|
+
* Print the lame internals. For debugging
|
319
|
+
*/
|
308
320
|
static VALUE MpegEncoder_print_internals(VALUE self) {
|
309
321
|
lame_global_flags * gfp;
|
310
322
|
|
@@ -313,6 +325,12 @@ static VALUE MpegEncoder_print_internals(VALUE self) {
|
|
313
325
|
return Qnil;
|
314
326
|
}
|
315
327
|
|
328
|
+
/*
|
329
|
+
* call-seq:
|
330
|
+
* encoder.mpeg_quality
|
331
|
+
*
|
332
|
+
* Get the mpeg quality
|
333
|
+
*/
|
316
334
|
static VALUE MpegEncoder_get_mpeg_quality(VALUE self) {
|
317
335
|
lame_global_flags * gfp;
|
318
336
|
|
@@ -320,6 +338,12 @@ static VALUE MpegEncoder_get_mpeg_quality(VALUE self) {
|
|
320
338
|
return INT2NUM(lame_get_quality(gfp));
|
321
339
|
}
|
322
340
|
|
341
|
+
/*
|
342
|
+
* call-seq:
|
343
|
+
* encoder.compression_ratio
|
344
|
+
*
|
345
|
+
* Get the mpeg compression ratio
|
346
|
+
*/
|
323
347
|
static VALUE MpegEncoder_get_compression_ratio(VALUE self) {
|
324
348
|
lame_global_flags * gfp;
|
325
349
|
|
@@ -327,6 +351,12 @@ static VALUE MpegEncoder_get_compression_ratio(VALUE self) {
|
|
327
351
|
return rb_float_new(lame_get_compression_ratio(gfp));
|
328
352
|
}
|
329
353
|
|
354
|
+
/*
|
355
|
+
* call-seq:
|
356
|
+
* encoder.mpeg_verison
|
357
|
+
*
|
358
|
+
* Get the mpeg version
|
359
|
+
*/
|
330
360
|
static VALUE MpegEncoder_get_mpeg_version(VALUE self) {
|
331
361
|
lame_global_flags * gfp;
|
332
362
|
|
@@ -334,6 +364,12 @@ static VALUE MpegEncoder_get_mpeg_version(VALUE self) {
|
|
334
364
|
return INT2NUM(lame_get_version(gfp));
|
335
365
|
}
|
336
366
|
|
367
|
+
/*
|
368
|
+
* call-seq:
|
369
|
+
* encoder.mpeg_mode
|
370
|
+
*
|
371
|
+
* Get the mpeg mode
|
372
|
+
*/
|
337
373
|
static VALUE MpegEncoder_get_mpeg_mode(VALUE self) {
|
338
374
|
lame_global_flags * gfp;
|
339
375
|
|
@@ -341,6 +377,12 @@ static VALUE MpegEncoder_get_mpeg_mode(VALUE self) {
|
|
341
377
|
return INT2NUM(lame_get_mode(gfp));
|
342
378
|
}
|
343
379
|
|
380
|
+
/*
|
381
|
+
* call-seq:
|
382
|
+
* encoder.force_ms
|
383
|
+
*
|
384
|
+
* Get the force ms flag
|
385
|
+
*/
|
344
386
|
static VALUE MpegEncoder_get_force_ms(VALUE self) {
|
345
387
|
lame_global_flags * gfp;
|
346
388
|
|
@@ -348,6 +390,12 @@ static VALUE MpegEncoder_get_force_ms(VALUE self) {
|
|
348
390
|
return INT2NUM(lame_get_force_ms(gfp));
|
349
391
|
}
|
350
392
|
|
393
|
+
/*
|
394
|
+
* call-seq:
|
395
|
+
* encoder.out_samplerate
|
396
|
+
*
|
397
|
+
* Get the out samplerate
|
398
|
+
*/
|
351
399
|
static VALUE MpegEncoder_get_out_samplerate(VALUE self) {
|
352
400
|
lame_global_flags * gfp;
|
353
401
|
|
@@ -355,6 +403,12 @@ static VALUE MpegEncoder_get_out_samplerate(VALUE self) {
|
|
355
403
|
return INT2NUM(lame_get_out_samplerate(gfp));
|
356
404
|
}
|
357
405
|
|
406
|
+
/*
|
407
|
+
* call-seq:
|
408
|
+
* encoder.in_samplerate=
|
409
|
+
*
|
410
|
+
* Set the input samplerate
|
411
|
+
*/
|
358
412
|
static VALUE MpegEncoder_set_in_samplerate(VALUE self, VALUE samplerate) {
|
359
413
|
lame_global_flags * gfp;
|
360
414
|
|
@@ -363,6 +417,12 @@ static VALUE MpegEncoder_set_in_samplerate(VALUE self, VALUE samplerate) {
|
|
363
417
|
return samplerate;
|
364
418
|
}
|
365
419
|
|
420
|
+
/*
|
421
|
+
* call-seq:
|
422
|
+
* encoder.num_samples=
|
423
|
+
*
|
424
|
+
* Set the number of samples
|
425
|
+
*/
|
366
426
|
static VALUE MpegEncoder_set_num_samples(VALUE self, VALUE num_samples) {
|
367
427
|
lame_global_flags * gfp;
|
368
428
|
|
@@ -371,6 +431,12 @@ static VALUE MpegEncoder_set_num_samples(VALUE self, VALUE num_samples) {
|
|
371
431
|
return num_samples;
|
372
432
|
}
|
373
433
|
|
434
|
+
/*
|
435
|
+
* call-seq:
|
436
|
+
* encoder.num_samples
|
437
|
+
*
|
438
|
+
* Get the number of samples
|
439
|
+
*/
|
374
440
|
static VALUE MpegEncoder_get_num_samples(VALUE self) {
|
375
441
|
lame_global_flags * gfp;
|
376
442
|
|
@@ -378,6 +444,12 @@ static VALUE MpegEncoder_get_num_samples(VALUE self) {
|
|
378
444
|
return ULONG2NUM(lame_get_num_samples(gfp));
|
379
445
|
}
|
380
446
|
|
447
|
+
/*
|
448
|
+
* call-seq:
|
449
|
+
* encoder.num_channels=
|
450
|
+
*
|
451
|
+
* Set the number of channels
|
452
|
+
*/
|
381
453
|
static VALUE MpegEncoder_set_num_channels(VALUE self, VALUE num_channels) {
|
382
454
|
lame_global_flags * gfp;
|
383
455
|
|
@@ -386,6 +458,12 @@ static VALUE MpegEncoder_set_num_channels(VALUE self, VALUE num_channels) {
|
|
386
458
|
return num_channels;
|
387
459
|
}
|
388
460
|
|
461
|
+
/*
|
462
|
+
* call-seq:
|
463
|
+
* encoder.num_channels
|
464
|
+
*
|
465
|
+
* Get the number of channels
|
466
|
+
*/
|
389
467
|
static VALUE MpegEncoder_get_num_channels(VALUE self) {
|
390
468
|
lame_global_flags * gfp;
|
391
469
|
|
@@ -393,6 +471,12 @@ static VALUE MpegEncoder_get_num_channels(VALUE self) {
|
|
393
471
|
return INT2NUM(lame_get_num_channels(gfp));
|
394
472
|
}
|
395
473
|
|
474
|
+
/*
|
475
|
+
* call-seq:
|
476
|
+
* encoder.framesize
|
477
|
+
*
|
478
|
+
* Get the framesize
|
479
|
+
*/
|
396
480
|
static VALUE MpegEncoder_get_framesize(VALUE self) {
|
397
481
|
lame_global_flags * gfp;
|
398
482
|
|
@@ -400,6 +484,12 @@ static VALUE MpegEncoder_get_framesize(VALUE self) {
|
|
400
484
|
return INT2NUM(lame_get_framesize(gfp));
|
401
485
|
}
|
402
486
|
|
487
|
+
/*
|
488
|
+
* call-seq:
|
489
|
+
* encoder.encoder_buffer(left, right)
|
490
|
+
*
|
491
|
+
* Get the encoder buffer
|
492
|
+
*/
|
403
493
|
static VALUE MpegEncoder_encoder_buffer(VALUE self, VALUE left, VALUE right) {
|
404
494
|
unsigned char mp3buffer[LAME_MAXMP3BUFFER];
|
405
495
|
int * buffer_left;
|
@@ -434,6 +524,12 @@ static VALUE MpegEncoder_encoder_buffer(VALUE self, VALUE left, VALUE right) {
|
|
434
524
|
return rb_str_new(mp3buffer, imp3);
|
435
525
|
}
|
436
526
|
|
527
|
+
/*
|
528
|
+
* call-seq:
|
529
|
+
* encoder.flush
|
530
|
+
*
|
531
|
+
* Flush the encoder
|
532
|
+
*/
|
437
533
|
static VALUE MpegEncoder_flush(VALUE self) {
|
438
534
|
unsigned char mp3buffer[LAME_MAXMP3BUFFER];
|
439
535
|
int imp3;
|
@@ -450,6 +546,12 @@ static VALUE MpegEncoder_flush(VALUE self) {
|
|
450
546
|
return rb_str_new(mp3buffer, imp3);
|
451
547
|
}
|
452
548
|
|
549
|
+
/*
|
550
|
+
* call-seq:
|
551
|
+
* encoder.write_vbr_tags(outfile)
|
552
|
+
*
|
553
|
+
* Write the VBR tags to +outfile+
|
554
|
+
*/
|
453
555
|
static VALUE MpegEncoder_write_vbr_tags(VALUE self, VALUE outfile) {
|
454
556
|
OpenFile *fp;
|
455
557
|
lame_global_flags * gfp;
|
@@ -461,6 +563,12 @@ static VALUE MpegEncoder_write_vbr_tags(VALUE self, VALUE outfile) {
|
|
461
563
|
return Qnil;
|
462
564
|
}
|
463
565
|
|
566
|
+
/*
|
567
|
+
* call-seq:
|
568
|
+
* encoder.init_params
|
569
|
+
*
|
570
|
+
* Initialize lame parameters.
|
571
|
+
*/
|
464
572
|
static VALUE MpegEncoder_init_params(VALUE self) {
|
465
573
|
lame_global_flags * gfp;
|
466
574
|
|
data/lib/icanhasaudio/mpeg.rb
CHANGED
@@ -8,7 +8,18 @@ class Audio::MPEG::Decoder
|
|
8
8
|
|
9
9
|
def initialize
|
10
10
|
@bits = 16
|
11
|
+
@raw = nil
|
11
12
|
yield self if block_given?
|
12
13
|
end
|
14
|
+
|
15
|
+
private
|
16
|
+
def attempt_rewind(outf)
|
17
|
+
begin
|
18
|
+
outf.seek(0, IO::SEEK_SET)
|
19
|
+
true
|
20
|
+
rescue
|
21
|
+
false
|
22
|
+
end
|
23
|
+
end
|
13
24
|
end
|
14
25
|
|
@@ -92,149 +92,164 @@ module Audio
|
|
92
92
|
|
93
93
|
def parse_header(file)
|
94
94
|
header = file.read(4).unpack('N').first
|
95
|
-
case header
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
95
|
+
info = case header
|
96
|
+
when WAV_ID_RIFF # Wave file
|
97
|
+
info = self.class.parse_wave_header(file)
|
98
|
+
when IFF_ID_FORM # AIFF file
|
99
|
+
info = self.class.parse_aiff_header(file)
|
100
|
+
else
|
101
|
+
$stderr.puts "Assuming RAW PCM"
|
102
|
+
file.rewind
|
103
|
+
nil
|
104
|
+
end
|
105
|
+
if info
|
106
|
+
self.num_channels = info[:num_channels]
|
107
|
+
self.in_samplerate = info[:in_samplerate]
|
108
|
+
self.num_samples = info[:num_samples]
|
109
|
+
self.pcmbitwidth = info[:bit_width]
|
103
110
|
end
|
104
111
|
end
|
105
112
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
chunk_size
|
122
|
-
|
123
|
-
case type
|
124
|
-
when IFF_ID_COMM
|
125
|
-
sub_size = file.read(4).unpack('N').first
|
113
|
+
public
|
114
|
+
class << self
|
115
|
+
def parse_aiff_header(file)
|
116
|
+
chunk_size = file.read(4).unpack('N').first
|
117
|
+
type_id = file.read(4).unpack('N').first
|
118
|
+
|
119
|
+
raise unless [IFF_ID_AIFF, IFF_ID_AIFC].any? { |x| type_id == x }
|
120
|
+
|
121
|
+
sub_size = 0
|
122
|
+
sample_type = nil
|
123
|
+
sample_size = nil
|
124
|
+
num_channels = nil
|
125
|
+
block_size = nil
|
126
|
+
sample_rate = nil
|
127
|
+
is_aiff = false
|
128
|
+
while chunk_size > 0
|
129
|
+
type = file.read(4).unpack('N').first
|
126
130
|
chunk_size -= 4
|
127
131
|
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
132
|
+
case type
|
133
|
+
when IFF_ID_COMM
|
134
|
+
sub_size = file.read(4).unpack('N').first
|
135
|
+
chunk_size -= 4
|
136
|
+
|
137
|
+
num_channels = file.read(2).unpack('n').first
|
138
|
+
sub_size -= 2
|
139
|
+
num_sample_frames = file.read(4).unpack('N').first
|
140
|
+
sub_size -= 4
|
141
|
+
sample_size = file.read(2).unpack('n').first
|
142
|
+
sub_size -= 2
|
143
|
+
sample_rate = unpack_ieee(file.read(10))
|
144
|
+
sub_size -= 10
|
145
|
+
|
146
|
+
if type_id == IFF_ID_AIFC
|
147
|
+
data_type = file.read(4).unpack('N').first
|
148
|
+
sub_size -=4
|
149
|
+
|
150
|
+
raise unless [ IFF_ID_2CLE,
|
151
|
+
IFF_ID_2CBE,
|
152
|
+
IFF_ID_NONE,
|
153
|
+
].any? { |x| data_type == x }
|
154
|
+
|
155
|
+
#if sample_size == 16
|
156
|
+
# swap bytes....
|
157
|
+
end
|
158
|
+
|
159
|
+
file.read(sub_size)
|
160
|
+
when IFF_ID_SSND
|
161
|
+
sub_size = file.read(4).unpack('N').first
|
162
|
+
chunk_size -= sub_size
|
163
|
+
|
164
|
+
block_offset = file.read(4).unpack('N').first
|
165
|
+
sub_size -= 4
|
166
|
+
block_size = file.read(4).unpack('N').first
|
167
|
+
sub_size -= 4
|
168
|
+
|
169
|
+
sample_type = IFF_ID_SSND
|
170
|
+
file.read(block_offset)
|
171
|
+
is_aiff = true
|
172
|
+
break
|
173
|
+
else
|
174
|
+
sub_size = file.read(4).unpack('N').first
|
175
|
+
chunk_size -= sub_size
|
176
|
+
file.read(sub_size)
|
148
177
|
end
|
149
|
-
|
150
|
-
file.read(sub_size)
|
151
|
-
when IFF_ID_SSND
|
152
|
-
sub_size = file.read(4).unpack('N').first
|
153
|
-
chunk_size -= sub_size
|
154
|
-
|
155
|
-
block_offset = file.read(4).unpack('N').first
|
156
|
-
sub_size -= 4
|
157
|
-
block_size = file.read(4).unpack('N').first
|
158
|
-
sub_size -= 4
|
159
|
-
|
160
|
-
sample_type = IFF_ID_SSND
|
161
|
-
file.read(block_offset)
|
162
|
-
is_aiff = true
|
163
|
-
break
|
164
|
-
else
|
165
|
-
sub_size = file.read(4).unpack('N').first
|
166
|
-
chunk_size -= sub_size
|
167
|
-
file.read(sub_size)
|
168
178
|
end
|
169
|
-
end
|
170
179
|
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
180
|
+
# Validate the header
|
181
|
+
if is_aiff
|
182
|
+
raise "Sound data is not PCM" unless sample_type == IFF_ID_SSND
|
183
|
+
raise "Sound data is not 16 bits" unless sample_size == 16
|
184
|
+
unless num_channels == 1 || num_channels == 2
|
185
|
+
raise "Sound data is not mono or stereo"
|
186
|
+
end
|
187
|
+
raise "Block size is not 0 bytes" unless block_size == 0
|
177
188
|
end
|
178
|
-
raise "Block size is not 0 bytes" unless block_size == 0
|
179
|
-
end
|
180
189
|
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
190
|
+
{
|
191
|
+
:num_channels => num_channels,
|
192
|
+
:in_samplerate => simple_rate.to_i,
|
193
|
+
:num_samples => num_sample_frames,
|
194
|
+
:bit_width => sample_size,
|
195
|
+
}
|
196
|
+
end
|
186
197
|
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
198
|
+
def unpack_ieee(data)
|
199
|
+
(expon, hi_mant, lo_mant) = data.unpack('nNN')
|
200
|
+
expon -= 16383
|
201
|
+
hi_mant * (2 ** (expon -= 31)) + lo_mant * (2 ** (expon -= 32))
|
202
|
+
end
|
192
203
|
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
204
|
+
def parse_wave_header(file)
|
205
|
+
format_tag = nil
|
206
|
+
channels = nil
|
207
|
+
samples_per_sec = nil
|
208
|
+
avg_bytes_per_sec = nil
|
209
|
+
block_align = nil
|
210
|
+
bits_per_sample = nil
|
211
|
+
is_wav = false
|
212
|
+
data_length = 0
|
213
|
+
|
214
|
+
file_length = file.read(4).unpack('N').first
|
215
|
+
raise "Corrupt wave" if file.read(4).unpack('N').first != WAV_ID_WAVE
|
216
|
+
20.times {
|
217
|
+
type = file.read(4).unpack('N').first
|
218
|
+
case type
|
219
|
+
when WAV_ID_FMT
|
220
|
+
sub_size = file.read(4).unpack('V').first
|
221
|
+
raise "Corrupt wave" if sub_size < 16
|
222
|
+
|
223
|
+
( format_tag,
|
224
|
+
channels,
|
225
|
+
samples_per_sec,
|
226
|
+
avg_bytes_per_sec,
|
227
|
+
block_align, bits_per_sample) = *(file.read(16).unpack('vvVVvv'))
|
228
|
+
sub_size -= 16
|
229
|
+
|
230
|
+
file.read(sub_size) if sub_size > 0
|
231
|
+
when WAV_ID_DATA
|
232
|
+
sub_size = file.read(4).unpack('V').first
|
233
|
+
data_length = sub_size
|
234
|
+
is_wav = true
|
235
|
+
break;
|
236
|
+
else
|
237
|
+
sub_size = file.read(4).unpack('V').first
|
238
|
+
file.read(sub_size)
|
239
|
+
end
|
240
|
+
}
|
241
|
+
raise "Unsupported format" unless format_tag == 1
|
242
|
+
raise unless is_wav
|
243
|
+
|
244
|
+
{
|
245
|
+
:num_channels => channels,
|
246
|
+
:in_samplerate => samples_per_sec,
|
247
|
+
:bytes_in_seconds => data_length,
|
248
|
+
:milliseconds => (data_length/2)/(samples_per_sec/1000)/2,
|
249
|
+
:num_samples => data_length / (channels*((bits_per_sample+7)/8)),
|
250
|
+
:bit_width => bits_per_sample,
|
251
|
+
}
|
252
|
+
end
|
238
253
|
end
|
239
254
|
end
|
240
255
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: icanhasaudio
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aaron Patterson
|
@@ -9,17 +9,18 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-
|
12
|
+
date: 2008-08-04 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: hoe
|
17
|
+
type: :development
|
17
18
|
version_requirement:
|
18
19
|
version_requirements: !ruby/object:Gem::Requirement
|
19
20
|
requirements:
|
20
21
|
- - ">="
|
21
22
|
- !ruby/object:Gem::Version
|
22
|
-
version: 1.
|
23
|
+
version: 1.7.0
|
23
24
|
version:
|
24
25
|
description: Hai! icanhasaudio? is an interface to lame for decoding ur MP3s. I iz in ur computer. Decodin ur mp3s. Whatevs! I also decodin ur OGGz! I kin also encodin' ur WAV and AIFF to mp3z! == SYNOPSYS ROFLOL require 'icanhasaudio' reader = Audio::MPEG::Decoder.new File.open(ARGV[0], 'rb') { |input_lol| File.open(ARGV[1], 'wb') { |output_lol| reader.decode(input_lol, output_lol) } }
|
25
26
|
email: aaronp@rubyforge.org
|
@@ -84,7 +85,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
84
85
|
requirements: []
|
85
86
|
|
86
87
|
rubyforge_project: seattlerb
|
87
|
-
rubygems_version: 1.0
|
88
|
+
rubygems_version: 1.2.0
|
88
89
|
signing_key:
|
89
90
|
specification_version: 2
|
90
91
|
summary: icanhasaudio is a lame/vorbis wrapper for decoding ur mp3s and ur oggs.
|