Assuming you're using ActiveState (since you mention PPM), you can download Audio::Wav for ActiveState 5.8.x here or for 5.6.1 here. Remember, you can always manually download the modules from ActiveState's site instead of having ppm download them, then have ppm use a "local repository" to install them.
- - arden. | [reply] |
You're looking for the unpack function, and more specificly, the 's' template character. (Which actualy operates on native-endian values, not specificly little-endian ones. I just noticed that there is no way to specifiy the byteorder using (un)pack for signed values.)
unpack 's*', $data; will convert all of $data into it's meaning, assuming $data contains a bunch of signed 16-bit values.
Warning: Unless otherwise stated, code is untested. Do not use without understanding. Code is posted in the hopes it is useful, but without warranty. All copyrights are relinquished into the public domain unless otherwise stated. I am not an angel. I am capable of error, and err on a fairly regular basis. If I made a mistake, please let me know (such as by replying to this node).
| [reply] [d/l] |
The part that theorbtwo left out of his reply was the matter of reading binary data into a scalar variable (though maybe you've handled this already, since you say you solved getting past the header).
You can read a fixed number of bytes at a time by setting $/ to a numeric value, like this:
$/ = \8; # read 8 bytes at a time;
binmode INPUTFH; # don't forget this on MS-Windows!
# (you can use binmode on STDIN, as well, if needed)
while (<INPUTFH>) { # $_ now holds 8 bytes of data
...
}
Of course, you can use a larger or smaller number of bytes per read, depending on what you want to do. You could also use the "read" or "sysread" functions, where one of the args given to the function is the number of bytes to read. Or if your wav files aren't that big, just seek past the header and slurp the rest all at once into a scalar by setting $/ to undef. | [reply] [d/l] |
| [reply] [d/l] |
You probably want to read the header, then unpack the data based on that, it might be 8 bit or 16 bit, mono or stereo, etc. Here is a way to read the header and determine it's playlength based on byte size, number of channels, etc.
#!/usr/bin/perl -w
use strict;
use Fcntl;
my $fnm = shift;
sysopen WAV,$fnm,O_RDONLY;
my $riff;
sysread WAV,$riff,12;
my $fmt;
sysread WAV,$fmt,24;
my $data;
sysread WAV,$data,8;
close WAV;
# RIFF header: 'RIFF', long length, type='WAVE'
my ($r1,$r2,$r3) = unpack "A4VA4", $riff;
# WAV header, 'fmt ', long length, short unused, short channels,
# long samples/second, long bytes per second, short bytes per sample,
# short bits per sample
my ($f1,$f2,$f3,$f4,$f5,$f6,$f7,$f8) = unpack "A4VvvVVvv",$fmt;
# DATA header, 'DATA', long length
my ($d1,$d2) = unpack "A4V", $data;
my $playlength = $d2/$f6;
print << "EOF";
RIFF header: $r1, length $r2, type $r3
Format: $f1, length $f2, always $f3, channels $f4,
sample rate $f5, bytes per second $f6,
bytes per sample $f7, bits per sample $f8
Data: $d1, length $d2
Playlength: $playlength seconds
EOF
I'm not really a human, but I play one on earth.
flash japh
| [reply] [d/l] |
Thanks for all the suggestions. I was able to get it working with unpack. The header occupies bytes 0-46 of the file and from there
read IN,$buffer,2;
$value = unpack('s',$buffer);
enclosed in a suitable loop yields the data values (for a 16-bit file). I never was able to find Audio-Wav on Activestate. When I search using keyword "Audio" on Komodo/VPM, it doesn't show up. I tried the same thing with command line PPM and got same result. There is Audio-(Daemon, FLAC, Play-MPG123, PSID, Radio-V4L, SID, Tools, WMA) but no Wav.
Anyway, reading it as above is pretty straighforward so mission accomplished. | [reply] [d/l] |