Back when I needed to play back sound asynchronously, I used FMOD and this sample player:
package Sound::Fmod;
use strict;
use Win32::API;
=head1 NAME
Sound::Fmod - interface to the Fmod sound library
=head1 SYNOPSIS
use Sound::Fmod;
my $player = Sound::Fmod->new();
$player->init(32000, 64, 0)
or die $player->get_error;
my $mod = $player->load_song('../../media/invtro94.s3m')
or die "Couldn't load song: " . $player->get_error;
$mod->play_song();
while (1) {
print "...\n";
sleep 10;
};
=cut
sub new {
my ($package) = @_;
my $self = {};
bless $self, $package;
$self;
};
sub load_song {
my ($self,$filename) = @_;
warn "Loading $filename";
my $buffer = " " x 1024;
$buffer = $self->_load_song($filename);
print length $buffer;
Sound::Fmod::Song->new($buffer);
};
sub load_samples {
my $self = shift;
my @result;
for my $filename (@_) {
#$filename =~ s!/!\\!g;
my $handle;
if ($filename =~ /.pcm/i) {
$handle = $self->_load_sample(-1,$filename,0x10051,0,0);
} else {
$handle = $self->_load_sample(-1,$filename,0x02000,0,0);
};
die "Couldn't load $filename :" . $self->get_error unless $handle;
push @result, Sound::Fmod::Sample->new($handle);
};
@result;
};
# My own lame DLL loader, ugly hacked together
# because I'm too stupid to use Inline::C and too
# lazy to learn XS:
my $library = 'fmod';
my %functions = (
init => ['FSOUND_Init','LLL','L'],
DESTROY => ['FSOUND_Close','',''],
_load_song => ['FMUSIC_LoadSong','P','L'],
_load_sample => ['FSOUND_Sample_Load','LPLLL','L'],
get_error => ['FSOUND_GetError','','L'],
__PACKAGE__ . "::Song::_play_song" => ['FMUSIC_PlaySong','L',''],
__PACKAGE__ . "::Song::_DESTROY" => ['FMUSIC_FreeSong','L',''],
__PACKAGE__ . "::Sample::_play" => ['FSOUND_PlaySound','LL','']
+,
__PACKAGE__ . "::Sample::_DESTROY" => ['FSOUND_Sample_Free','L',''
+],
);
# Simplicistic fudging of names
sub mangle {
my ($name,$args) = @_;
die "Unknown argument '$args'" unless $args =~ m!^[LP]*$!;
my $size = (length $args) * 4;
"_$name\@$size"
};
sub load_function {
my ($f) = @_;
die "Unknown function $f"
unless exists $functions{$f};
my @args = ('fmod.dll', @{$functions{$f}});
$args[1] = mangle(@args[1,2]);
my $code = Win32::API->new(@args);
die "Couldn't load $f from fmod: $! / $^E"
unless $code;
no strict 'refs';
*{$f} = sub { my $self = shift; $code->Call(@_) };
};
load_function($_)
for keys %functions;
package Sound::Fmod::Song;
sub new {
my ($package,$handle) = @_;
my $self = \$handle;
bless $self, $package;
$self;
};
sub play_song {
my ($self) = @_;
$self->_play_song($$self);
};
sub DESTROY {
my $self = shift;
$self->_DESTROY($$self);
};
package Sound::Fmod::Sample;
sub new {
my ($package,$handle) = @_;
my $self = \$handle;
bless $self, $package;
$self;
};
sub play {
my ($self) = @_;
$self->_play(-1,$$self);
};
sub DESTROY {
my $self = shift;
$self->_DESTROY($$self);
};
1;
I wrote it against the 3.x API - I haven't looked whether it still works with the 4.x APIs. |