Code: [show] | [select all]
package LoadPCM;
use Fcntl qw/:seek/;
our $file = "chord.wav"; #default
our $fh;
our %fmt;
our %data;
sub init
{
$file = shift if ( @_ > 0 );
open our $fh, "<:raw", $file;
seek($fh, 12, SEEK_SET); # 略过文件头
load_fmt_chunk();
}
sub load_fmt_chunk
{
our %fmt;
my $buff;
my @item = qw/ ID
ChunkSize
FormatTag
Channels
SamplesPerSec
AvgBytesPerSec
BlockAlign
BitsPerSample /;
read($fh, $buff, 24);
@fmt{ @item } = unpack("LLssLLsss", $buff);
for my $k ( @item )
{
printf "%-15s: %d\n", $k, $fmt{$k};
}
}
sub load_data_chunk
{
my ($rframe, $rlength) = @_;
our $fh;
our %data;
my $buff;
read($fh, $buff, 8);
@data{"ID", "ChunkSize"} = unpack("LL", $buff);
$data{"length"} = $data{ChunkSize} / $fmt{"BlockAlign"};
my @frame;
my $frame_bytes = $fmt{"BlockAlign"};
for my $it ( 1 .. $data{"length"} )
{
read($fh, $buff, $frame_bytes);
if ( $fmt{"BitsPerSample"} == 8 ) {
push @frame, [ unpack( "C"x $fmt{"Channels"} , $buff) ];
} else {
push @frame, [ unpack( "s"x $fmt{"Channels"} , $buff) ];
}
}
$data{"frame"} = \@frame;
@$rframe = @frame;
$$rlength = $data{"length"};
}
1;
Code: [show] | [select all]
use Modern::Perl;
use OpenGL qw/ :all /;
use OpenGL::Config;
use Time::HiRes 'sleep';
use LoadPCM;
STDOUT->autoflush(1);
our $SIZE_X = 800;
our $SIZE_Y = 600;
our $WinID;
our $PI = 3.1415926536;
our $PI2 = $PI * 2;
our $MAX_LEVEL = 10;
our @frame;
our $flen;
#LoadPCM::init( "RELOADED - Dead Island installer.wav" );
#LoadPCM::init("linkmicinvitePCM.wav");
#LoadPCM::init("cute.wav");
LoadPCM::init("CHIMES.wav");
LoadPCM::load_data_chunk( \@frame, \$flen );
our $bits = $LoadPCM::fmt{"BitsPerSample"};
our $channels = $LoadPCM::fmt{"Channels"};
die "frame data error" if not defined $frame[0]->[0];
&Main();
sub printstr
{
for my $i ( split("", $_[0]) )
{
#glutBitmapCharacter(GLUT_BITMAP_9_BY_15, ord($i));
glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, ord($i));
}
}
sub display
{
state $offset = 0;
state $repeat = 0;
glClear(GL_COLOR_BUFFER_BIT);
glPushMatrix();
glTranslatef(-1.0, -1.0, 0.0);
glScalef(3.0, 3.0, 3.0);
glColor3f(1.0, 1.0, 1.0);
glBegin(GL_LINES);
glVertex3f(-200.0, 0.0, 0.0);
glVertex3f(200.0, 0.0, 0.0);
glVertex3f(0.0, -200.0, 0.0);
glVertex3f(0.0, 200.0, 0.0);
glEnd();
#if ($bits == 8 ) { glTranslatef(0.0, 50.0, 0.0); }
glColor3f(1.0, 0.0, 0.0);
my $yscale = 0.1;
my $xscale = 0.05;
my $ch = 0;
glBegin(GL_LINE_STRIP);
#glBegin(GL_POINTS);
for my $id ( $offset .. $offset+(100/$xscale) )
{
glVertex3f( ($id-$offset)*$xscale, $frame[$id]->[$ch]*$yscale, 0.0 );
}
glEnd();
$offset += 1;
$repeat = 1;
glPopMatrix();
glutSwapBuffers();
}
sub init
{
glClearColor(0.0, 0.0, 0.0, 1.0);
glLineWidth(1.0);
glPointSize(1.0);
#glDisable(GL_LINE_SMOOTH);
}
sub idle
{
sleep 0.05;
glutPostRedisplay();
}
sub Reshape
{
my $half = 100.0;
glViewport(0.0,0.0, $SIZE_X, $SIZE_Y);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, $half, -$half, $half,-20.0,200.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0.0,0.0,100.0,0.0,0.0,0.0, 0.0,1.0,100.0);
}
sub hitkey
{
my $key = shift;
if (lc(chr($key)) eq 'q')
{
glutDestroyWindow($WinID);
}
elsif ($key == 27)
{
glutDestroyWindow($WinID);
}
}
sub Main
{
glutInit();
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE |GLUT_MULTISAMPLE );
glutInitWindowSize($SIZE_X, $SIZE_Y);
glutInitWindowPosition(1,1);
our $WinID = glutCreateWindow("PCM");
&init();
glutDisplayFunc(\&display);
glutReshapeFunc(\&Reshape);
glutKeyboardFunc(\&hitkey);
glutIdleFunc(\&idle);
glutMainLoop();
}
- wave.png
- (22.81 KiB) 已下载 28 次
- cute.wav.7z
- (45.16 KiB) 已下载 93 次