#!C:/Perl/bin/perl
#use strict;
use Win32;
use Win32::Sound;
use Win32::GUI;
my %DEC;
$DEC{'WAV'} = "temple.wav";
$DEC{'GUI_WIDTH'} = 640;
$DEC{'GUI_HEIGHT'} = 480;
$DEC{'GUI_HEIGHT_MIN'} = 300;
$DEC{'GUI_WIDTH_MIN'} = 400;
$DEC{'WAVGRAPH_X'} = 1;
$DEC{'WAVGRAPH_Y'} = 150;
$DEC{'WAVGRAPH_W'} = 540;
$DEC{'WAVGRAPH_H'} = 165;
$DEC{'PEN_GRAY'} = new Win32::GUI::Pen(-color => [ 125,125,125 ], -wid
+th => 1);
$DEC{'PEN_BLK'} = new Win32::GUI::Pen(-color => [ 0,0,0 ], -width => 1
+);
$DEC{'BRUSH_GRAY'} = new Win32::GUI::Brush([ 125,125,125 ]);
$DEC{'BRUSH_BLK'} = new Win32::GUI::Brush([ 0,0,0 ]);
my $desk = Win32::GUI::GetDesktopWindow();
my $dw = Win32::GUI::Width($desk);
my $dh = Win32::GUI::Height($desk);
my $x = ($dw - $DEC{'GUI_WIDTH'}) / 2;
my $y = ($dh - $DEC{'GUI_HEIGHT'}) / 2;
my $MW = new Win32::GUI::Window(-left => $x, -top=> $y, -helpbutton =>
+ 0, -menu => 0, -maximizebox => 0, -minimizebox => 0, -resizable => 1
+, -topmost => 0, -width => $DEC{'GUI_WIDTH'}, -height => $DEC{'GUI_HE
+IGHT'}, -name => "Window", -text => "$ENV{'PROGRAM_NAME'}");# -intera
+ctive => 0, -onMouseMove => \&MouseMove, -onMouseUp => \&MouseUp, -on
+MouseDown => \&MouseDown);
my $SoundFileGroup = $MW->AddGroupbox(-left => 7, -top => (30), -text
+=> "Sound File ", -name => "SoundFileGroup",-height => 100, -width =
+> 385);
my $GraphGroup = $MW->AddGroupbox(-left => 7, -top => (140), -text =>
+"Sound Graph ", -name => "GraphGroup",-height => 265, -width => 385)
+;
my $PlotButton = $MW->AddButton(-left => 325, -top => 50, -name => 'Pl
+otButton', -text => 'Graph');
my $ListenButton = $MW->AddButton(-left => 325, -top => 80, -name => '
+ListenButton', -text => 'Listen');
my $WavFile = $MW->AddTextfield(-name => "WavFile", -tabstop => 6, -au
+tovscroll => 0, -text => "$DEC{'WAV'}", -sunken => 1, -left => 20, -t
+op => 50, -width => 300, -height => 22, -multiline => 0);
##################EDIT
#######################
my $DC = $MW->GetDC;
$MW->Show();
Win32::GUI::DoEvents();
Win32::GUI::DoEvents();
Win32::GUI::Dialog();
sub ListenButton_Click{
&PlotButton_Click;
my $left = $MW->GraphGroup->Left+4;
my $top = $MW->GraphGroup->Top+15;
my $width = $MW->GraphGroup->Width-10;
my $height = ($MW->GraphGroup->Height-21);
$DC->SelectObject($DEC{'PEN_BLK'});
my %WV = &DescribeWav($DEC{'WAV'});
my $LPS = int(($width/$WV{'Duration'}));
$width = $LPS;
$WAV = new Win32::Sound::WaveOut($DEC{'WAV'});
$WAV-> Play() or die "Play: $!";
for(my $cnt = 0; $cnt <= ($WV{'TotalSamples'});$cnt++){
my $at = $WAV->Position();
if ($WV{'nChannels'} > 1){$at = $at*2;}
if ($WV{'nBitsPerSample'} > 8){$at = $at*2;}
$WV{'at'} = $at;
my $gper = int(($at*($MW->GraphGroup->Width-10))/($WV{'TotalSa
+mples'}*$WV{'nBlockAlign'}));
$DC->BeginPath();
$DC->MoveTo($left+$gper,$top);
$DC->LineTo($left+$gper,$top+5);
$DC->MoveTo($left+$gper,$top+$height-5);
$DC->LineTo($left+$gper,$top+$height);
$DC->EndPath();
$DC->StrokePath();
if ($WAV->Status() == 1){$cnt = $WV{'TotalSamples'}+1;}
}
$WAV->Reset();
Win32::GUI::DoEvents();
}######################################## end ListenButton_Click
sub PlotWav{
my $wav = $_[0];
my $left = $_[1];
my $top = $_[2];
my $width = $_[3];
my $height = $_[4];
my $secbarheight = ($height*20)/200;
my $subsecbarheight = ($height*10)/200;
my %WAV = &DescribeWav($wav);
$MW->GraphGroup->Text("$WAV{'FileName'} : $WAV{'FileDescription'}
+: Samples=$WAV{'TotalSamples'} Dur=$WAV{'Duration'}");
$MW->InvalidateRect(1);
Win32::GUI::DoEvents();
$DC->SelectObject($DEC{'PEN_GRAY'});
$DC->BeginPath();
$DC->MoveTo($left,$top);
$DC->LineTo(($left+$width),$top);
$DC->LineTo(($left+$width),($top+$height));
$DC->LineTo($left,($top+$height));
$DC->LineTo($left,$top);
$DC->EndPath();
$DC->StrokePath();
####### PLOT SECONDS BAR
my $LPS = int(($width/$WAV{'Duration'}));
for(my $sec = 0;$sec <= $WAV{'Duration'};$sec++){
$DC->BeginPath();
$DC->MoveTo(($left+($sec*$LPS)),$top);
$DC->LineTo(($left+($sec*$LPS)),$top+$secbarheight);
$DC->MoveTo(($left+($sec*$LPS)),$top+$height-$secbarheight);
$DC->LineTo(($left+($sec*$LPS)),$top+$height);
$DC->EndPath();
$DC->StrokePath();
}
####### PLOT SUBSECONDS BAR
$DEC{'PEN_SUB'} = new Win32::GUI::Pen(-color => [ 200,200,200 ], -
+width => 1);
$DC->SelectObject($DEC{'PEN_SUB'});
for(my $sec = 0;$sec <= $WAV{'Duration'};$sec++){
for(my $subsec = 1;$subsec < 10;$subsec++){
my $asec = $sec+($subsec/10);
if ($asec <= $WAV{'Duration'}){
$DC->BeginPath();
$DC->MoveTo(($left+($asec*$LPS)),$top+1);
if ($asec =~ /\.5/){
$DC->LineTo(($left+($asec*$LPS)),$top+($subsecbarh
+eight+($subsecbarheight/2)));
$DC->MoveTo(($left+($asec*$LPS)),$top+$height-($su
+bsecbarheight+($subsecbarheight/2)));
$DC->LineTo(($left+($asec*$LPS)),$top+$height);
}else{
$DC->LineTo(($left+($asec*$LPS)),$top+$subsecb
+arheight+1);
$DC->MoveTo(($left+($asec*$LPS)),$top+$height-
+$subsecbarheight);
$DC->LineTo(($left+($asec*$LPS)),$top+$height)
+;
}
$DC->EndPath();
$DC->StrokePath();
}
}
}
####### END SECONDS BAR
$DEC{'PEN_LEFT'} = new Win32::GUI::Pen(-color => [ 250,50,50 ]
+, -width => 1);
$DC->SelectObject($DEC{'PEN_LEFT'});
$DC->BeginPath();
$DC->MoveTo($left,$top+($height/2));
my $volume = 1;#0-1
my $SPS = ($LPS*$WAV{'Duration'});
my %INF;
$INF{'file'} = $WAV{'FilePath'};
$INF{'start'} = &GetDataStart($WAV{'FilePath'});
$INF{'nBlockAlign'} = $WAV{'nBlockAlign'};
$INF{'nBitsPerSample'} = $WAV{'nBitsPerSample'};
for(my $x = 1;$x<=$width;$x=$x+1){
$INF{'sample'} = int(($WAV{'TotalSamples'}*$x)/$SPS);
my ($alc,$arc) = &GetSample(%INF);
my $lx = $alc;
if ($INF{'nBitsPerSample'} == 8){$lx = int(($lx-128)*(($he
+ight/4))/255);}
if ($INF{'nBitsPerSample'} == 16){$lx = int($lx*(($height/
+2))/65335);}
$DC->LineTo(($left+$x),$top+($height/4)+$lx);
}
$DC->EndPath();
$DC->StrokePath();
Win32::GUI::DoEvents();
################ RIGHT CHANNEL
$DEC{'PEN_RIGHT'} = new Win32::GUI::Pen(-color => [ 50,250,50
+], -width => 1);
$DC->SelectObject($DEC{'PEN_RIGHT'});
$DC->BeginPath();
$DC->MoveTo($left,$top+($height/2));
my $volume = 1;#0-1
my $SPS = ($LPS*$WAV{'Duration'});
my %INFR;
$INFR{'file'} = $WAV{'FilePath'};
$INFR{'start'} = &GetDataStart($WAV{'FilePath'});
$INFR{'nBlockAlign'} = $WAV{'nBlockAlign'};
$INFR{'BPS'} = $WAV{'nBitsPerSample'};
for(my $x = 1;$x<=$width;$x=$x+1){
$INFR{'sample'} = int(($WAV{'TotalSamples'}*$x)/$SPS);
my ($alc,$arc) = &GetSample(%INFR);
my $rx = $arc;
if ($INF{'nBitsPerSample'} == 16){$rx = int($rx*(($height/
+2))/65335);}
$DC->LineTo(($left+$x),$top+(($height/4)*3)+$rx);
}
$DC->EndPath();
$DC->StrokePath();
Win32::GUI::DoEvents();
}######################################## end PlotWav
sub PlotButton_Click {
$DEC{'PEN_L'} = new Win32::GUI::Pen(-color => [ 33,123,33 ], -widt
+h => 1);
$DEC{'PEN_R'} = new Win32::GUI::Pen(-color => [ 123,33,33 ], -widt
+h => 1);
$DEC{'WAV'} = $MW->WavFile->Text();
my %PLOT = @_;
$MW->InvalidateRect(1);
Win32::GUI::DoEvents();
undef $WAV;
my $left = $MW->GraphGroup->Left+4;
my $top = $MW->GraphGroup->Top+15;
my $width = $MW->GraphGroup->Width-10;
my $height = ($MW->GraphGroup->Height-21);
my $secbarheight = ($height*20)/200;
my $subsecbarheight = ($height*10)/200;
&PlotWav($DEC{'WAV'},$left,$top,$width,$height);
}######################################## end PlotButton_Click
sub Window_Terminate {
$DEC{'TERMINATING'} = 1;
return -1;
}######################################## end Window_Terminate
sub Window_Resize {
if ($MW->Width < $DEC{'GUI_WIDTH_MIN'}){$MW->Width($DEC{'GUI_WIDTH
+_MIN'});}
if ($MW->Height < $DEC{'GUI_HEIGHT_MIN'}){$MW->Height($DEC{'GUI_HE
+IGHT_MIN'});}
$DEC{'GUI_WIDTH'} = $MW->Width;
$DEC{'GUI_HEIGHT'} = $MW->Height;
$MW->SoundFileGroup->Width($DEC{'GUI_WIDTH'}-20);
$MW->GraphGroup->Width($DEC{'GUI_WIDTH'}-20);
$MW->GraphGroup->Height($DEC{'GUI_HEIGHT'}-180);
}######################################## end Window_Resize
sub DescribeWav{
my $file = $_[0];
my %WAV;
my $file_size = int(-s "$file");
local $/ = \1;
my $sp;
my $rcnt;
my $str;
my $firChunkCnt = 0;
my $headChunk = "";
my $dataChunk = "";
my $isDataChunk;
my %chunks;
$WAV{'FilePath'} = $file;
$WAV{'FileName'} = $file;
$WAV{'FileSize'} = $file_size;
$WAV{'FileName'} =~ s/.*[\\|\/]+//;
while ($sp <= $file_size){
open (FILE,$file);
seek(FILE,$sp,0);
while (my $li = <FILE>){
$rcnt++;
$str .= $li;
if ($rcnt == 12){
if (!$str =~ /RIFF.{4}WAVE/){print "Not a WAVE Chunk H
+eader\n";return;}
$str =~ s/RIFF(.{4})WAVE/$1/i;
$str = "";
}
if (($rcnt > 12)&&($li eq "f")&&(!$firChunkCnt)){$firChunk
+Cnt = $rcnt;}
if ($firChunkCnt){
$headChunk .= $li;
if (length $headChunk == 23){
if ($headChunk =~ /fmt\W/){
$headChunk =~ s/^(....)(....)(..)(..)(....)(..
+.)(..)(..)/$1\|$2\|$3\|$4\|$5\|$6\|$7\|$8/;
my($ckID,$nChunkSize,$wFormatTag,$nChannels,$n
+SamplePerSec,$nAvgBytesPerSec,$nBlockAlign,$nBitsPerSample) = split(/
+\|/,$headChunk);
$WAV{'nChunkSize'} = unpack("s",$nChunkSize);
$WAV{'wFormatTag'} = unpack("v*",$wFormatTag);
$WAV{'nChannels'} = unpack("v*",$nChannels);
$WAV{'nSamplePerSec'} = unpack("v*",$nSamplePe
+rSec);
$WAV{'nAvgBytesPerSec'} = unpack("v*",$nAvgByt
+esPerSec);
$WAV{'nBlockAlign'} = int(unpack("H*",$nBlockA
+lign));
$WAV{'nBitsPerSample'} = int(hex(unpack("H*",$
+nBitsPerSample)));
if ($WAV{'wFormatTag'} == 1){my @mss = ("mono"
+,"stereo");$WAV{'FileDescription'} = $WAV{'nBitsPerSample'}."bit ".$m
+ss[$WAV{'nChannels'}-1]." ".($WAV{'nSamplePerSec'}/1000)."hz";}
$headChunk = "";
$WAV{'VALID'} = 1;
if ($WAV{'wFormatTag'} != 1){$WAV{'VALID'} = 0
+;}
$sp = $file_size+1;
$WAV{'DataChunkStart'} = ($WAV{'nChunkSize'}+$
+firChunkCnt+7)+8;
last;
}
}
}
}
close FILE;
}
$sp = int($WAV{'DataChunkStart'}-8);
$rcnt = 0;
$str = "";
open (FILE,$file);
while ($sp < $file_size){
seek(FILE,$sp,0);
while (my $li = <FILE>){
$rcnt++;
$str .= $li;
if ($rcnt > 8){
$str =~ s/(....)/$1\|/;
my($name,$lg) = split(/\|/,$str,2);
$lg = unpack("V",$lg);
if (($name eq "data")&&(!$WAV{'SoundChunkStart'})){
$WAV{'SoundChunkStart'} = $sp+8;
$WAV{'SoundChunkLength'} = $lg;
$WAV{'TotalSamples'} = int($WAV{'SoundChunkLength'
+}/$WAV{'nBlockAlign'});
$WAV{'Duration'} = $WAV{'TotalSamples'}/$WAV{'nSam
+plePerSec'};
}
$chunks{$name} = $lg.":".($rcnt+$sp);
$rcnt = 0;$str = "";$sp = $sp+$lg+8;last;
}
}
}close FILE;
foreach my $li(keys %chunks){
$WAV{"Chunk$li"} = $chunks{$li};
$WAV{'TotalChunks'}++;
}
return %WAV;
}############################################# end DescribeWav
sub GetSample{
my %INF = @_;
my $asp = $INF{'start'}+(($INF{'sample'}-1)*$INF{'nBlockAlign'});
local $/ = \1;
open(FILE,$INF{'file'});
binmode FILE;
seek(FILE,$asp,0);
my $cnt;
my $lis;
while (my $li = <FILE>){
$lis .= $li;
if (length $lis >= $INF{'nBlockAlign'}){
my ($lc,$rc);
#1=8 bit mono,2=8bitstereo or 16bitmono,4=16bitstereo
if ($INF{'nBlockAlign'} == 1){
$lc = hex(unpack("H*",$lis));}
if ($INF{'nBlockAlign'} == 2){
if ($INF{'nBitsPerSample'} == 16){
$lc = unpack("s",$lc);
}else{
($lc,$rc) = unpack('a1a1', $lis);
$lc = hex(unpack("H*",$lc));
$rc = hex(unpack("H*",$rc));
}
}###############################
if ($INF{'nBlockAlign'} == 4){
($lc,$rc) = unpack('a2a2', $lis);
$lc = unpack("s",$lc);$rc = unpack("s",$rc);
}###############################
close FILE;
local $/ = \n;
if (!$lc){$lc = 0;}
if (!$rc){$rc = 0;}
return $lc,$rc;
}
}
}################################ end GetSample
sub GetDataStart{
my $file = $_[0];
my $str;
local $/ = \1;
open(FILE,$file);
binmode FILE;
seek(FILE,0,0);
while (my $li = <FILE>){
$str .= $li;
if ($str =~ /data$/){
close FILE;
local $/ = \n;
return length($str)+4;
}
}
close FILE;
}################################ end GetDataStart
-
Are you posting in the right place? Check out Where do I post X? to know for sure.
-
Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
<code> <a> <b> <big>
<blockquote> <br /> <dd>
<dl> <dt> <em> <font>
<h1> <h2> <h3> <h4>
<h5> <h6> <hr /> <i>
<li> <nbsp> <ol> <p>
<small> <strike> <strong>
<sub> <sup> <table>
<td> <th> <tr> <tt>
<u> <ul>
-
Snippets of code should be wrapped in
<code> tags not
<pre> tags. In fact, <pre>
tags should generally be avoided. If they must
be used, extreme care should be
taken to ensure that their contents do not
have long lines (<70 chars), in order to prevent
horizontal scrolling (and possible janitor
intervention).
-
Want more info? How to link
or How to display code and escape characters
are good places to start.