WAV 音频文件解读以及可视化

头像
523066680
Administrator
Administrator
帖子: 453
注册时间: 2016年07月19日 12:14
拥有现金: 锁定
储蓄: 锁定
Has thanked: 46 times
Been thanked: 77 times
联系:

WAV 音频文件解读以及可视化

帖子 #1 523066680 » 2019年04月01日 21:28

模块
Code: [全选] [展开/折叠] [Download] (LoadPCM.pm)
  1. package LoadPCM;
  2. use Fcntl qw/:seek/;
  3.  
  4. our $file = "chord.wav";  #default
  5. our $fh;
  6. our %fmt;
  7. our %data;
  8.  
  9. sub init
  10. {
  11.     $file = shift if ( @_ > 0 );
  12.     open our $fh, "<:raw", $file;
  13.     seek($fh, 12, SEEK_SET);      # 略过文件头
  14.     load_fmt_chunk();
  15. }
  16.  
  17. sub load_fmt_chunk
  18. {
  19.     our %fmt;
  20.     my $buff;
  21.     my @item = qw/ ID
  22.             ChunkSize
  23.             FormatTag
  24.             Channels
  25.             SamplesPerSec
  26.             AvgBytesPerSec
  27.             BlockAlign
  28.             BitsPerSample /;
  29.     read($fh, $buff, 24);
  30.     @fmt{ @item } = unpack("LLssLLsss", $buff);
  31.  
  32.     for my $k ( @item )
  33.     {
  34.         printf "%-15s: %d\n", $k, $fmt{$k};
  35.     }
  36. }
  37.  
  38. sub load_data_chunk
  39. {
  40.     my ($rframe, $rlength) = @_;
  41.     our $fh;
  42.     our %data;
  43.     my $buff;
  44.     read($fh, $buff, 8);
  45.     @data{"ID", "ChunkSize"} = unpack("LL", $buff);
  46.     $data{"length"} = $data{ChunkSize} / $fmt{"BlockAlign"};
  47.    
  48.     my @frame;
  49.     my $frame_bytes = $fmt{"BlockAlign"};
  50.  
  51.     for my $it ( 1 .. $data{"length"} )
  52.     {
  53.         read($fh, $buff, $frame_bytes);
  54.         if ( $fmt{"BitsPerSample"} == 8 ) {
  55.             push @frame, [ unpack( "C"x $fmt{"Channels"} , $buff) ];
  56.         } else {
  57.             push @frame, [ unpack( "s"x $fmt{"Channels"} , $buff) ];
  58.         }
  59.     }
  60.  
  61.     $data{"frame"} = \@frame;
  62.     @$rframe = @frame;
  63.     $$rlength = $data{"length"};
  64. }
  65.  
  66. 1;


显示波形图
Code: [全选] [展开/折叠] [Download] (Display.pl)
  1. use Modern::Perl;
  2. use OpenGL qw/ :all /;
  3. use OpenGL::Config;
  4. use Time::HiRes 'sleep';
  5. use LoadPCM;
  6.  
  7. STDOUT->autoflush(1);
  8.  
  9. our $SIZE_X = 800;
  10. our $SIZE_Y = 600;
  11.  
  12. our $WinID;
  13. our $PI  = 3.1415926536;
  14. our $PI2 = $PI * 2;
  15. our $MAX_LEVEL = 10;
  16.  
  17. our @frame;
  18. our $flen;
  19. #LoadPCM::init( "RELOADED - Dead Island installer.wav" );
  20. #LoadPCM::init("linkmicinvitePCM.wav");
  21. #LoadPCM::init("cute.wav");
  22. LoadPCM::init("CHIMES.wav");
  23. LoadPCM::load_data_chunk( \@frame, \$flen );
  24. our $bits = $LoadPCM::fmt{"BitsPerSample"};
  25. our $channels = $LoadPCM::fmt{"Channels"};
  26.  
  27. die "frame data error" if not defined $frame[0]->[0];
  28.  
  29. &Main();
  30.  
  31. sub printstr
  32. {
  33.     for my $i ( split("", $_[0]) )
  34.     {
  35.         #glutBitmapCharacter(GLUT_BITMAP_9_BY_15, ord($i));
  36.         glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, ord($i));        
  37.     }
  38. }
  39.  
  40. sub display
  41. {
  42.     state $offset = 0;
  43.     state $repeat = 0;
  44.  
  45.     glClear(GL_COLOR_BUFFER_BIT);
  46.  
  47.     glPushMatrix();
  48.     glTranslatef(-1.0, -1.0, 0.0);
  49.     glScalef(3.0, 3.0, 3.0);
  50.  
  51.     glColor3f(1.0, 1.0, 1.0);
  52.     glBegin(GL_LINES);
  53.         glVertex3f(-200.0, 0.0, 0.0);
  54.         glVertex3f(200.0, 0.0, 0.0);
  55.         glVertex3f(0.0, -200.0, 0.0);
  56.         glVertex3f(0.0, 200.0, 0.0);
  57.     glEnd();
  58.  
  59.     #if ($bits == 8 ) { glTranslatef(0.0, 50.0, 0.0); }
  60.     glColor3f(1.0, 0.0, 0.0);
  61.  
  62.     my $yscale = 0.1;
  63.     my $xscale = 0.05;
  64.     my $ch = 0;
  65.     glBegin(GL_LINE_STRIP);
  66.     #glBegin(GL_POINTS);
  67.     for my $id ( $offset .. $offset+(100/$xscale) )
  68.     {
  69.         glVertex3f( ($id-$offset)*$xscale, $frame[$id]->[$ch]*$yscale, 0.0 );
  70.     }
  71.     glEnd();
  72.     $offset += 1;
  73.     $repeat = 1;
  74.  
  75.     glPopMatrix();
  76.     glutSwapBuffers();
  77. }
  78.  
  79. sub init
  80. {
  81.     glClearColor(0.0, 0.0, 0.0, 1.0);
  82.     glLineWidth(1.0);
  83.     glPointSize(1.0);
  84.     #glDisable(GL_LINE_SMOOTH);
  85. }
  86.  
  87. sub idle
  88. {
  89.     sleep 0.05;
  90.     glutPostRedisplay();
  91. }
  92.  
  93. sub Reshape
  94. {
  95.     my $half = 100.0;
  96.     glViewport(0.0,0.0, $SIZE_X, $SIZE_Y);
  97.     glMatrixMode(GL_PROJECTION);
  98.     glLoadIdentity();
  99.     glOrtho(0.0, $half, -$half, $half,-20.0,200.0);
  100.     glMatrixMode(GL_MODELVIEW);
  101.     glLoadIdentity();
  102.     gluLookAt(0.0,0.0,100.0,0.0,0.0,0.0, 0.0,1.0,100.0);
  103. }
  104.  
  105. sub hitkey
  106. {
  107.     my $key = shift;
  108.     if (lc(chr($key)) eq 'q')
  109.     {
  110.         glutDestroyWindow($WinID);
  111.     }
  112.     elsif ($key == 27)
  113.     {
  114.         glutDestroyWindow($WinID);
  115.     }
  116. }
  117.  
  118. sub Main
  119. {
  120.     glutInit();
  121.     glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE |GLUT_MULTISAMPLE );
  122.     glutInitWindowSize($SIZE_X, $SIZE_Y);
  123.     glutInitWindowPosition(1,1);
  124.     our $WinID = glutCreateWindow("PCM");
  125.     &init();
  126.     glutDisplayFunc(\&display);
  127.     glutReshapeFunc(\&Reshape);
  128.     glutKeyboardFunc(\&hitkey);
  129.     glutIdleFunc(\&idle);
  130.     glutMainLoop();
  131. }



wave.png


cute.wav.7z
您没有权限查看这个主题的附件。

头像
523066680
Administrator
Administrator
帖子: 453
注册时间: 2016年07月19日 12:14
拥有现金: 锁定
储蓄: 锁定
Has thanked: 46 times
Been thanked: 77 times
联系:

Re: WAV 音频文件解读以及可视化

帖子 #2 523066680 » 2019年04月06日 21:18

2019-04-06
已经做成柱状频谱图(spectrum)

spectrum1.png
您没有权限查看这个主题的附件。


回到 “算法和编码”

在线用户

用户浏览此论坛: 没有注册用户 和 1 访客