65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 C++ 播放 XM - 从文件和内存

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.90/5 (10投票s)

2010 年 10 月 21 日

CPOL

3分钟阅读

viewsIcon

32426

downloadIcon

902

使用未打包的 BASSMOD.dll 从文件和内存纯 C++ 播放 XM 音乐文件

引言

有些人喜欢在他们的应用程序中播放音乐。通常,可能是因为大小的原因,人们更喜欢 .xm 文件并播放它们。大多数情况是 MFC 和 Win32。un4seen.com 编写了 BASSMOD.dll,它可以播放它们。该项目使用此 DLL **而不链接到 bassmod.lib**。

背景

网上有一些代码示例可以做到这一点,但该项目有三个优点是其他项目所没有的

  1. 他们的代码使用 bassmod.lib 将应用程序链接到 bassmod.dll。因此,程序员无法从其资源中提取 bassmod.dll 并使用它。
  2. 他们的代码很混乱,人们无法轻松使用。
  3. bassmod.dll 使用 **PEtite 2.2** 打包。这可能会导致一些杀毒软件将其检测为病毒或可疑文件。或者用户可能会对此感到怀疑。我已经成功解除了 bassmod.dll 的打包,**您可以在您的项目中**使用解包后的 bassmod.dll。解包后的 bassmod.dll 包含在软件包中。

PEiD_4_bassmod.dll.jpg

Using the Code

您只需要 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;

winmm.dll 中需要的函数指针

typedef DWORD (__stdcall *func_timeGetTime)();
func_timeGetTime ptimeGetTime; 

现在,我们应该在运行时获取所需函数的地址(使用 `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); 

我将项目编码为重复播放音乐,但您可以更改 `BASSMOD_MusicSetSync` 的参数以使其只播放一次。

我在我的项目中定义了两个全局变量

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 等播放器播放它。这很酷。

我也在软件包中包含了 bassmod.lib。根据这张图片,我的代码是不需要它的:

no_additional_dependency.JPG

我包含了 bassmod.lib,因为我认为也许有些人想将 bassmod.dll 链接到他们的项目中。我再次重申,**bassmod.lib 是绝对不必要的。**

© . All rights reserved.