cypress has asked for the wisdom of the Perl Monks concerning the following question:

Hi all, use Win32::Sound; Win32::Sound::Play('Smile.wav'); gives me the first five seconds or so of this audio file and then abruptly exits. What's up? (If I add the flag SND_ASYNC, I get nothing!) Does my problem have to do with being able to sample only the first chunk of this file?

Replies are listed 'Best First'.
Re: Win32::Sound problem
by BrowserUk (Patriarch) on May 07, 2011 at 17:12 UTC

    This plays the wav file supplied on the command line in the background whilst the program in continues in the foreground:

    #! perl -slw use strict; use threads; use Win32::Sound; async { Win32::Sound::Play( $ARGV[ 0 ] ); }->detach; sleep 1, print for 1 .. 50;

    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Win32::Sound problem
by Anonymous Monk on May 07, 2011 at 16:57 UTC
    This is what I've done in the past.
    use Time::HiRes 'sleep'; use Win32::MediaPlayer; sub sound_play { my $winmm = Win32::MediaPlayer->new(); $winmm->load($alarm_sound); $winmm->play(); my $pos = 0; (-$pos + ($pos = $winmm->pos)) or return while sleep 0.1; }

    The relative order of load and play and pos are important here, but I've forgotten why. I think it worked fine in a forked process.

Re: Win32::Sound problem
by cypress (Beadle) on May 07, 2011 at 15:35 UTC
    If I use C Church's program at http://www.perlmonks.org/?node_id=176077, my 2 minute 55 second .wav file (play time) takes almost as long (2:50) to load up. There must be a good, asynchronous way of loading and playing an audio file while simultaneously doing other program stuff.

      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.