基于bass& glut的声音可视化

 /* * @(#)$Id: bass_app.cpp [7/11/2010 RenYaFei] [email protected] $ * @(#)基于OpenGL的声音可视化 * Author: Dizuo.Hangzhou. * All Rights Reserved. * bass download URL: http://www.un4seen.com/ */ #include #include #include #include #include #include "bass.h" #pragma comment( lib, "bass.lib") using namespace std; ////////////////////////////////////////////////////////////////////////// std::vector wave_ampli; int g_max_ampli(0); int g_min_ampli(1000); float g_camera_z = 0; bool g_stop(false); std::string file_name("jazz_drum.mp3"); //std::string file_name("only for you.mp3"); DWORD chan; //the file handle DWORD g_bypePerPixel; // const int MAX_PEAK = 32768; // peak max amplitude const int WIDTH = 600; // display width const int HEIGHT = 201; // height (odd number for centre line) ////////////////////////////////////////////////////////////////////////// // scan the peaks void ScanPeaks(DWORD decoder) { DWORD length = BASS_ChannelGetLength(decoder, BASS_POS_BYTE); g_bypePerPixel=BASS_ChannelGetLength(decoder,BASS_POS_BYTE)/WIDTH; // bytes per pixel if (g_bypePerPixelcpos) { DWORD a(0); int max_ampli = peak[0]*(HEIGHT/2)/MAX_PEAK; int min_ampli = peak[1]*(HEIGHT/2)/MAX_PEAK; int avg_ampli = (max_ampli + min_ampli)/2; if (avg_ampli>g_max_ampli) g_max_ampli = avg_ampli; if (avg_ampli=WIDTH) break; // gone off end of display cpos=pos; peak[0]=peak[1]=0; } } BASS_StreamFree(decoder); // free the decoder } ////////////////////////////////////////////////////////////////////////// void CALLBACK LoopSyncProc(HSYNC handle, DWORD channel, DWORD data, void *user) { BASS_ChannelSetPosition(channel,0,BASS_POS_BYTE); // failed, go to start of file instead } ////////////////////////////////////////////////////////////////////////// bool PlayFile() { const char* file=file_name.c_str(); if (!(chan=BASS_StreamCreateFile(FALSE,file,0,0,0)) && !(chan=BASS_MusicLoad(FALSE,file,0,0,BASS_MUSIC_RAMPS|BASS_MUSIC_POSRESET|BASS_MUSIC_PRESCAN,0))) { return FALSE; // Can't load the file } // repeat playing BASS_ChannelSetSync(chan,BASS_SYNC_END|BASS_SYNC_MIXTIME,0,LoopSyncProc,0); // set sync to loop at end BASS_ChannelPlay(chan,false); return true; } void init() { ////////////////////////////////////////////////////////////////////////// // Init bass if(!BASS_Init(-1,44100,0,0,NULL)) { std::cout << ("Can't initialize device"); return ; } if(!PlayFile()) { // start a file playing BASS_Free(); std::cout << "Cannot play the file" << std::endl; return; } DWORD chan2=BASS_StreamCreateFile(FALSE, file_name.c_str(),0,0,BASS_STREAM_DECODE); if (!chan2) chan2=BASS_MusicLoad(FALSE, file_name.c_str(),0,0,BASS_MUSIC_DECODE,0); ScanPeaks(chan2); for (size_t i(0); i

 

如下图:

矩形框中是声音文件: jazz_drum.mp3的振幅显示。一条运动的黄线是当然播放位置。

空间中的五个torus会根据声音的振幅缩放,与声音同步~

 基于bass& glut的声音可视化_第1张图片

 

程序依赖库:

bass.h  bass.lib  bass.dll

glut.h  glut.lib  glut.dll

 

程序简介:

1chan:一个DWORD类型的全局句柄保持内存中的声音数据

2BASS_ChannelGetLength:获得声音文件的字节长度

每个像素字节数 = 文件的字节长度 / 显示区域的宽度

Bpp = file_length / area_width

将文件的字节数据分为area_width块。每块有bpp个字节。

3QWORD pos = BASS_ChannelGetPosition(chan,BASS_POS_BYTE); 获得当前播放字节的位置。4DWORD wpos = pos / g_bypePerPixel; 获得当前像素位置:第pos个字节位于第几个数据块

5DWORD peaks_level = BASS_ChannelGetLevel(chan);     获得当前波峰的峰值,振幅

DWORD avg_level = ( LOWORD(peaks_level) + HIWORD(peaks_level) )/2;  需要计算出平均峰值。

6,波峰值的区间是0~32768,所以可以将平均峰值转化到区间:[0,1]。在display函数中,每次根据当前声音的波峰值转化到标准01区间,以此作为3d场景中的模型缩放因子。

7scanPeaks函数是预处理声音文件,存储所有的峰值数据显示。

8,可以修改width的数值。Width值越大,显示出来的声音波更加精确。

 

 

修改日志:
11/7/2010 增加声音重复播放!

效果图:

基于bass& glut的声音可视化_第2张图片

 

你可能感兴趣的:(OpenGL,C++,随想&&感想,Visual,Programming,OpenGL技术专栏)