OpenGL: 基于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会根据声音的振幅缩放,与声音同步~

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

 

程序依赖库:

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 增加声音重复播放!

效果图:

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

http://blog.csdn.net/ryfdizuo/article/details/5987246

你可能感兴趣的:(OpenGL)