无需链接库的BASSMOD.dll音乐播放

在许多情况下,人们更倾向于使用体积较小的文件格式,比如模块文件(.xm)。在Windows平台上,MFCWin32应用程序经常需要播放这些格式的文件。un4seen.com开发的BASSMOD.dll是一个能够播放.xm文件的动态链接库(DLL)。本项目展示了如何不链接到bassmod.lib的情况下使用这个DLL。

尽管互联网上有许多代码示例可以实现这一功能,但本项目具有三个其他项目不具备的优点:

  • 其他代码需要链接bassmod.lib,这意味着开发者无法从应用程序资源中提取bassmod.dll并使用它。
  • 其他代码结构混乱,难以使用。
  • bassmod.dll使用PEtite 2.2打包,这可能导致一些杀毒软件将其误报为病毒或可疑文件,或者用户对其产生怀疑。本项目成功解包了bassmod.dll,可以在项目中使用未打包的bassmod.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这样的播放器播放它。这很酷。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485