|
lofichurch has asked for the
wisdom of the Perl Monks concerning the following question:
I'm wondering whether or not anyone out there is currently working to utilize Perl for audio manipulation, in a (mostly) pure-perl implementation? By pure-perl, I mean the code written by the developer, not necessarily any modules being used.
What I'm really wondering is what is the best approach to working with the actual waveform data? Just using perl arrays seems easy enough, where each sample is expressed as an array element, but really bogs down in memory and CPU time when the number of samples exceeds a second's worth at 44,100Hz. I've been using a substr()-based solution, but this has a tendancy to be a big hassle when working with bitrates higher than 8 (and if you don't use pack/unpack, you can end up with garbled data). I've heard of using PDL for this, but can't find a reference to clear examples.
Some examples of using susbtr() to manipulate wave data can be found at http://www.digitalkoma.com/church/projects/perl-dsp.html.
Is anyone out there also wrestling with wave data, and have some suggestions?
Thanks!
Re: Manipulating Audio Data in Perl by Zaxo (Archbishop) on Jun 13, 2002 at 20:52 UTC |
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] [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] [d/l] |
Re: Manipulating Audio Data in Perl by cjf (Vicar) on Jun 14, 2002 at 08:55 UTC |
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] |
Re: Manipulating Audio Data in Perl by PetaMem (Priest) on Jun 14, 2002 at 09:49 UTC |
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] |
Re: Manipulating Audio Data in Perl by toma (Vicar) on Jun 16, 2002 at 16:30 UTC |
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] |
Back to
Seekers of Perl Wisdom
|
|