Audio-Wav
view release on metacpan or search on metacpan
Wav/Read.pm view on Meta::CPAN
my $length = shift;
my $data = $self -> _read_raw( $length );
my $types = $self -> {tools} -> get_wav_pack();
my $pack_str = '';
my $fields = $types -> {order};
foreach my $type ( @{$fields} ) {
$pack_str .= $types -> {types} -> {$type};
}
my @data = unpack $pack_str, $data;
my %record;
for my $id ( 0 .. $#{$fields} ) {
$record{ $fields -> [$id] } = $data[$id];
}
return { %record };
}
sub _read_long {
my $self = shift;
my $data = $self -> _read_raw( 4 );
return unpack 'V', $data;
}
sub _error {
my ($self, @args) = @_;
return $self -> {tools} -> error( $self -> {file}, @args );
}
=head1 AUTHORS
Nick Peskett (see http://www.peskett.co.uk/ for contact details).
Brian Szymanski <ski-cpan@allafrica.com> (0.07-0.14)
Wolfram humann (pureperl 24 and 32 bit read support in 0.09)
Kurt George Gjerde <kurt.gjerde@media.uib.no>. (0.02-0.03)
=cut
1;
__DATA__
#ifdef WIN32
// Note: if it becomes a problem that Visual Studio 6 and
// Embedded Visual C++ 4 dont realize that char has the same
// size as int8_t, check for #if (_MSC_VER < 1300) and use
// signed __int8, unsigned __int16, etc. as in:
// http://msinttypes.googlecode.com/svn/trunk/stdint.h
typedef signed char int8_t;
typedef signed short int16_t;
typedef signed int int32_t;
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
#endif
//NOTE: 16, 32 bit audio do *NOT* work on big-endian platforms yet!
//verified formats (output is identical output to pureperl):
// 1 channel signed 16 little endian
// 2 channel signed 16 little endian
// 1 channel unsigned 8 little endian
// 2 channel unsigned 8 little endian
//verified "looks right" on these formats:
// 1 channel signed 32 little endian
// 2 channel signed 32 little endian
// 1 channel signed 24 little endian
// 2 channel signed 24 little endian
//maximum number of channels per audio stream
#define MAX_CHANNELS 10
//maximum number of bytes per sample (in one channel)
#define MAX_SAMPLE 4
FILE *handle;
int sample_size;
int channels;
int big_end;
int is_signed;
char buf[MAX_SAMPLE];
SV* retvals[MAX_CHANNELS];
void init(FILE *fh, int ss, int ch, int be) {
int i;
handle = fh;
sample_size = ss;
channels = ch;
big_end = be;
is_signed = (ss != 1); //TODO: is this really right?
for(i=0; i<MAX_CHANNELS; i++) {
retvals[i] = newSV(0);
}
}
void read_c(void *self) {
int samples[MAX_CHANNELS];
int nread;
int i, s;
Inline_Stack_Vars;
Inline_Stack_Reset;
for(i=0; i<channels; i++) {
// having fread in the loop is probably slightly less efficient,
// but it avoids byte alignment problems and fread is buffered,
// so it "shouldn't be a problem" (tm). more info:
// http://www.eventhelix.com/RealtimeMantra/ByteAlignmentAndOrdering.htm
nread = fread( buf, sample_size, 1, handle );
if( !nread ) {
if( feof( handle ) && i ) {
perror("got EOF mid-sample!");
} else if( ferror( handle ) ) {
perror("io error");
}
break;
}
switch(sample_size) {
case 4:
if(big_end) {
s = buf[0]; buf[0] = buf[3]; buf[3] = s;
s = buf[1]; buf[1] = buf[2]; buf[2] = s;
}
s = is_signed ?
*((int32_t *)buf) :
( run in 2.346 seconds using v1.01-cache-2.11-cpan-d8267643d1d )