/*
* @(#)$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.h bass.lib bass.dll
glut.h glut.lib glut.dll
程序简介:
1,chan:一个DWORD类型的全局句柄保持内存中的声音数据
2,BASS_ChannelGetLength:获得声音文件的字节长度
每个像素字节数 = 文件的字节长度 / 显示区域的宽度
Bpp = file_length / area_width
将文件的字节数据分为area_width块。每块有bpp个字节。
3,QWORD pos = BASS_ChannelGetPosition(chan,BASS_POS_BYTE); 获得当前播放字节的位置。4,DWORD wpos = pos / g_bypePerPixel; 获得当前像素位置:第pos个字节位于第几个数据块
5,DWORD peaks_level = BASS_ChannelGetLevel(chan); 获得当前波峰的峰值,振幅
DWORD avg_level = ( LOWORD(peaks_level) + HIWORD(peaks_level) )/2; 需要计算出平均峰值。
6,波峰值的区间是0~32768,所以可以将平均峰值转化到区间:[0,1]。在display函数中,每次根据当前声音的波峰值转化到标准0,1区间,以此作为3d场景中的模型缩放因子。
7,scanPeaks函数是预处理声音文件,存储所有的峰值数据显示。
8,可以修改width的数值。Width值越大,显示出来的声音波更加精确。
修改日志:
11/7/2010 增加声音重复播放!
效果图:
http://blog.csdn.net/ryfdizuo/article/details/5987246