Consider pack/unpack in a pure perl implementation. It may be helpful to set the record delimiter $/ to a reference to a constant integer. That triggers magic which will let you read a file in fixed length chunks.
There is a PDL::Audio module, but I had difficulty with it, seemed to be version problems. PDL in general is a good way to improve the performance of numerical array operations. I'm currently using it to do FFT of data.
Update: Have you looked at Mmap for working on these files?
Here's a PDL FFT example with a small enough data set to show results explicitly:
#!/usr/bin/perl -w
use strict;
use PDL;
use PDL::IO::Misc;
use PDL::FFT qw(:Func);
use constant TWOPI=>8*atan2 1,1;
my $data = PDL->new([ map { exp(-$_/10) * cos(TWOPI*3*$_/16) } 0..15 ]
+);
# this is a print routine
print 'Original Data:',$/;
PDL::IO::Misc::wcols($data);
# works in place, modifies $data
realfft($data);
print 'Transformed Data:',$/;
PDL::IO::Misc::wcols($data);
realifft($data);
print 'Restored Data:',$/;
PDL::IO::Misc::wcols($data);
Which produces:
After Compline, Zaxo | [reply] [Watch: Dir/Any] [d/l] |
Oops, guess I should've specified the ability to look backwards / forwards in the data, hence the substr(). I use the pack/unpack when I don't need to know anything other than a current sample value.
For example, without using arrays or hashes, be able to look forward in the data while processing an waveform:
assuming 16bit/mono:
my $cur_smp = 0;
my $len = length($input_data) / 2;
foreach (unpack("s*",$input_data)) {
# take the value and add to it the sample value
# five samples ahead
if($len < $cur_smp + 5) {
# if we don't have enough samples left to look ahead,
# just go with what we've got
$output .= pack("s",$_);
$cur_smp++;
next;
}
my $five_ahead = unpack("s",substr($input_data,($cur_smp + 5) * 2,2)
+);
$output .= pack("s",$_ + $five_ahead);
$cur_smp++;
next;
}
That substr() is a big hit on large amounts of data, but some sort of look-ahead/back is necessary on things like multi-tap delays and variable delays, and a perl array is out of the question. I'm balking at the math knowledge necessary for PDL, since DSP is a pretty new subject for me, on the low-level aspects of the algorithms.
Would you mind sharing an example of doing the FFT with PDL?
Thanks!
!c
| [reply] [Watch: Dir/Any] [d/l] |
By pure-perl, I mean the code written by the developer, not necessarily any modules being used.
There's a whole bunch of audio related modules on CPAN. Even if you don't want to use any modules for some strange reason(?) they are worth taking a look at to see how other's have approached the task.
In particular, the docs for Audio::Wav state that the module is written entirely in Perl. I don't have much experience manipulating audio data though, so I could be completely off the mark here :).
| [reply] [Watch: Dir/Any] |
Please have a look at this node. I started years ago
with a Perl Virtual Sound Generator, but stopped that
project "years ago". Presumably the URL won't work anymore. If you want the sources, I could mail them to you.
Bye
PetaMem
| [reply] [Watch: Dir/Any] |
There is an example at
Analyzing WAV Files with Perl. In this example,
I needed to track the frequency of a tone versus time.
I used Audio::Wav, PDL, and
PDL::FFT.
This code includes various algorithms to track the frequency
of a tone. The example graphs are for the algorithm
that worked best for my application.
I have written some other audio analysis modules, also,
so please let me know if you would like more examples.
It should work perfectly the first time! - toma | [reply] [Watch: Dir/Any] |