icanhasaudio 0.1.0 → 0.1.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.
- 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.
|