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

Using the sample code provided in the win32 sound module in a loop demonstrates the problem i am having. i need to generate a bunch of wav files with different pulse widths and repeat periods. i have a more complicated graphical program that allows me to change parameters. the problem is that once i create one wav file, i can never make one with fewer repeats. try the simple code below to see what i mean and please help me figure out how to make wav files with fewer repeats.
use strict; use Win32::Sound; my $data = ""; my $counter = 0; my $increment = 440/44100; my $repeats; my $input = 1; while ($input){ print "\nenter number of reps \"enter\" to quit.\n"; $input=<STDIN>; chomp $input; $repeats = $input; make_wav(); } sub make_wav{ my $WAV = new Win32::Sound::WaveOut(44100, 8, 2); $data = ""; $counter = 0; for ( my $i = 1 ; $i < $repeats + 1 ; $i++ ) { print "\ndoing repeat number $i"; for my $j (1..4410) { my $v = sin($counter/2*3.14) * 128 + 128; $data .= pack("cc", $v, $v); $counter += $increment; } for my $k (1..440) { #silence between pulses my $v = 128; $data .= pack("cc", $v, $v); } } $WAV->Unload(); # drop it $WAV->Load($data); # get it $WAV->Write(); # hear it 1 until $WAV->Status(); # wait for completion $WAV->Save("temp.wav",$data); # write to disk $WAV->Close(); }

Replies are listed 'Best First'.
Re: win32 sound problem
by toolic (Bishop) on Feb 27, 2011 at 19:43 UTC
    try the simple code below to see what i mean
    I did try the code, but I don't understand what you expect to happen. Can you give a more concrete example? What should I expect to happen if I first enter 5, then enter 3, for example?

    Here are some suggestions:

    • Use warnings and eliminate the warning messages you get.
    • Use perltidy to neaten your indentation to make your code easier to follow and debug.
    • Localize the scope of as many variables as possible. For example, pass $repeats as a parameter to your sub: make_wav($repeats);
    • See also: Basic debugging checklist
      the code is supposed to make play and save a wav file each time you enter a repeat value. on win32, if your sound is turned up you should hear the number of clicks that repeats is set to. temp.wav is also created in the working folder. this all works. the only problem is that something is not resetting. if you enter 2 repeats it does 2 repeats. then enter 5 and it does 5 but if you then enter 1, it does 5 again. here is the script with the variables localized. also tried it with warnings and get back warnings that i do not understand about the data packing.
      use strict; #use warnings; use Win32::Sound; my $input = 1; while ($input){ print "\nenter number of repetitions of pulse \"enter\" to quit.\ +n"; $input=<STDIN>; chomp $input; make_wav($input); } sub make_wav{ my $repeats = shift; my $data = ""; my $counter = 0; my $increment = 440/44100; my $WAV = new Win32::Sound::WaveOut(44100, 8, 2); $data = ""; $counter = 0; for ( my $i = 1 ; $i < $repeats + 1 ; $i++ ) { print "\ndoing repeat number $i"; for my $j (1..4410) { my $v = sin($counter/2*3.14) * 128 + 128; $data .= pack("cc", $v, $v); $counter += $increment; } for my $k (1..440) { #silence between pulses my $v = 128; $data .= pack("cc", $v, $v); } } $WAV->Unload(); # drop it $WAV->Load($data); # get it $WAV->Write(); # hear it 1 until $WAV->Status(); # wait for completion $WAV->Save("temp.wav",$data); # write to disk $WAV->Close();
        Did you try calling CloseDevice()?

        Maybe it's a bug in Win32::Sound. Try looking at the module's source code to see why it seems to retain state from a previous call. If it is a bug, maybe you'll be able to submit a patch and report it on CPAN.

        A Super Search finds a similar issue: Win32::Sound buffer problems

Re: win32 sound problem
by kejohm (Hermit) on Feb 28, 2011 at 06:10 UTC

    The warnings you mentioned above about data packing are most likely coming from using an incorrect pack format for the data passed to pack. The 'c' format expects a signed 8 bit value (-128 to 127); since you are passing pack a value between 0 and 255 (an unsigned value) you need to use the 'C' format instead. See perlfunc for more details about pack formats.

    Update: Link fixed.