在许多情况下,人们更倾向于使用体积较小的文件格式,比如模块文件(.xm)。在Windows平台上,MFC和Win32应用程序经常需要播放这些格式的文件。un4seen.com开发的BASSMOD.dll是一个能够播放.xm文件的动态链接库(DLL)。本项目展示了如何不链接到bassmod.lib的情况下使用这个DLL。
尽管互联网上有许多代码示例可以实现这一功能,但本项目具有三个其他项目不具备的优点:
要使用这段代码,只需要bassmod.dll(包含在包中)。为了方便起见,将bassmod.dll复制到Windows目录中。
当音乐播放到末尾时,它会重新播放。因此,播放音乐是一个无限循环的过程,永远不会返回。为此,创建了一个线程来播放音乐。
HANDLE hthread = CreateThread(NULL, NULL, MusicThread, NULL, NULL, NULL);
如果项目有一个窗口(MFC或使用CreateWindow),这段代码将起作用。但如果项目是Win32,应该为工作创建另一个线程并等待它:
WaitForSingleObject(hthread, INFINITE);
CloseHandle(hthread);
由于本项目不将bassmod.dll链接到EXE,应该在运行时定义需要的函数指针。bassmod.dll中需要的函数指针如下:
typedef int (__stdcall *func_BASSMOD_Init)(int device, int frequency, int flags);
func_BASSMOD_Init pBASSMOD_Init;
typedef int (__stdcall *func_BASSMOD_MusicLoad)(int mem, char *XMfile, int offset, int length, int flags);
func_BASSMOD_MusicLoad pBASSMOD_MusicLoad;
typedef int (__stdcall *func_BASSMOD_MusicSetSync)(int ptype, int param, void *function, int user);
func_BASSMOD_MusicSetSync pBASSMOD_MusicSetSync;
typedef int (__stdcall *func_BASSMOD_MusicPlay)();
func_BASSMOD_MusicPlay pBASSMOD_MusicPlay;
typedef int (__stdcall *func_BASSMOD_Free)();
func_BASSMOD_Free pBASSMOD_Free;
现在,使用GetProcAddress API在运行时获取所需函数的地址,并将其设置为定义的指针:
void SetFunctionAddresses() {
// Load bassmod.dll (included in package)
HMODULE bassmod_module = LoadLibrary("bassmod.dll");
// set bassmod.dll's function pointers in run-time
pBASSMOD_Init = (func_BASSMOD_Init)GetProcAddress(bassmod_module, "BASSMOD_Init");
pBASSMOD_MusicLoad = (func_BASSMOD_MusicLoad)GetProcAddress(bassmod_module, "BASSMOD_MusicLoad");
pBASSMOD_MusicSetSync = (func_BASSMOD_MusicSetSync)GetProcAddress(bassmod_module, "BASSMOD_MusicSetSync");
pBASSMOD_MusicPlay = (func_BASSMOD_MusicPlay)GetProcAddress(bassmod_module, "BASSMOD_MusicPlay");
pBASSMOD_Free = (func_BASSMOD_Free)GetProcAddress(bassmod_module, "BASSMOD_Free");
// Load winmm.dll (in system directory)
HMODULE winmm_module = LoadLibrary("winmm.dll");
// set winmm.dll's function pointer (timeGetTime) in run-time
ptimeGetTime = (func_timeGetTime)GetProcAddress(winmm_module, "timeGetTime");
}
初始化bassmod(BASSMOD_Init)并播放音乐是唯一需要做的事情。
可以从文件播放xm文件:
// load music file
pBASSMOD_MusicLoad(FALSE, xmFileName, 0, 0, BASS_MUSIC_LOOP|BASS_MUSIC_RAMPS|BASS_MUSIC_SURROUND|BASS_MUSIC_CALCLEN);
可以从内存播放xm文件。示例读取文件,将所有内容加载到内存中,然后从内存播放,但也可以从项目的资源中加载到内存。应该从资源加载xm文件并播放。从内存播放如下:
// load the file to memory
HANDLE hfile = CreateFile(xmFileName, GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
DWORD filesize = GetFileSize(hfile, 0);
BYTE *data = new BYTE[filesize];
DWORD read;
ReadFile(hfile, data, filesize, &read, NULL);
CloseHandle(hfile);
// load music file
pBASSMOD_MusicLoad(TRUE, data, 0, filesize, BASS_MUSIC_LOOP|BASS_MUSIC_RAMPS|BASS_MUSIC_SURROUND|BASS_MUSIC_CALCLEN);
在项目中定义了两个全局变量:
char xmFileName[MAX_PATH];
bool playFromMemory;
可以通过它们的名字注意到它们的使用。在项目WinMain函数中,会看到这些行:
// change this value to switch play-mode between memory and file
playFromMemory = true;
// set xm file to play
strcpy(xmFileName, "f:\\4EverBlue Morninsky.xm");
如果设置playFromMemory为true,应用程序将从内存播放;如果设置为false,应用程序将从文件播放。
直接使用了xmFileName,但可以根据需要使用它。
包含了bassmod.h在包中,实际上并不需要。包含它是为了特殊用途,因为也许有人想要更改函数参数等。bassmod.h中有许多值定义,可以在自己的项目中使用(项目不需要它)。
在包中包含了一个示例.xm文件:4EverBlue Morninsky.xm。可以使用项目和像KMplayer这样的播放器播放它。这很酷。