c++ - 如何在 C++ 程序中播放或打开 *.mp3 或 *.wav 声音文件?

标签 c++ audio visual-c++ graphics

<分区>

我是计算机科学专业的学生。我有一个最后学期的项目来开发一个图形和声音的短游戏。

最佳答案

首先,编写如下代码:

#include <Mmsystem.h>
#include <mciapi.h>
//these two headers are already included in the <Windows.h> header
#pragma comment(lib, "Winmm.lib")

打开*.mp3:

mciSendString("open \"*.mp3\" type mpegvideo alias mp3", NULL, 0, NULL);

播放*.mp3:

mciSendString("play mp3", NULL, 0, NULL);

播放并等待 *.mp3 播放完毕:

mciSendString("play mp3 wait", NULL, 0, NULL);

要重播(从头开始再次播放)*.mp3:

mciSendString("play mp3 from 0", NULL, 0, NULL);

重播并等待 *.mp3 播放完毕:

mciSendString("play mp3 from 0 wait", NULL, 0, NULL);

播放 *.mp3 并在每次结束时像循环一样重播:

mciSendString("play mp3 repeat", NULL, 0, NULL);

如果你想在*.mp3播放完毕后做一些事情,那么你需要通过WNDCLASSEX结构RegisterClassExCreateWindowEx并在 while 循环中使用 GetMessageTranslateMessageDispatchMessage 函数处理消息并调用:

mciSendString("play mp3 notify", NULL, 0, hwnd); //hwnd is an handle to the window returned from CreateWindowEx. If this doesn't work, then replace the hwnd with MAKELONG(hwnd, 0).

在窗口过程中,添加case MM_MCINOTIFY:里面的代码会在mp3播放完毕后执行。

但是如果您编写控制台应用程序并且您不处理windows,那么您可以CreateThread 通过在 dwCreationFlags 参数中指定 CREATE_SUSPENDED 标志处于挂起状态,并将返回值保存在 static 变量中并随意调用它。例如,我称之为 mp3。这个static变量的类型当然是HANDLE

这是此线程的 lpStartAddressThreadProc:

DWORD WINAPI MP3Proc(_In_ LPVOID lpParameter) //lpParameter can be a pointer to a structure that store data that you cannot access outside of this function. You can prepare this structure before `CreateThread` and give it's address in the `lpParameter`
{
    Data *data = (Data*)lpParameter; //If you call this structure Data, but you can call it whatever you want.
    while (true)
    {
        mciSendString("play mp3 from 0 wait", NULL, 0, NULL);
        //Do here what you want to do when the mp3 playback is over
        SuspendThread(GetCurrentThread()); //or the handle of this thread that you keep in a static variable instead
    }
}

您现在要做的就是每次要重播您的 mp3 时 ResumeThread(mp3);,每次播放结束时都会发生一些事情。

您可以#define play_my_mp3 ResumeThread(mp3); 使您的代码更具可读性。

当然,如果您想播放 mp3 文件,您可以删除 while (true)SuspendThreadfrom 0 代码仅一次,结束后随心所欲。

如果您删除SuspendThread 调用,那么声音将一遍又一遍地播放,并在结束时执行某些操作。这相当于:

mciSendString("play mp3 repeat notify", NULL, 0, hwnd); //or MAKELONG(hwnd, 0) instead

在 Windows 中。

要在中间暂停 *.mp3:

mciSendString("pause mp3", NULL, 0, NULL);

并恢复它:

mciSendString("resume mp3", NULL, 0, NULL);

中途停止:

mciSendString("stop mp3", NULL, 0, NULL);

请注意,您不能恢复已停止的声音,只能暂停,但您可以通过执行 play 命令重播它。 播放完 *.mp3 后,请不要忘记:

mciSendString("close mp3", NULL, 0, NULL);

所有这些操作也适用于(处理)wave 文件,但是对于 wave 文件,您可以使用“waveaudio”而不是“mpegvideo”。 您也可以直接播放它们而无需打开它们:

PlaySound("*.wav", GetModuleHandle(NULL), SND_FILENAME);

如果您不想指定模块句柄:

sndPlaySound("*.wav", SND_FILENAME);

如果不想等到播放结束:

PlaySound("*.wav", GetModuleHandle(NULL), SND_FILENAME | SND_ASYNC);
//or
sndPlaySound("*.wav", SND_FILENAME | SND_ASYNC);

反复播放波形文件:

PlaySound("*.wav", GetModuleHandle(NULL), SND_FILENAME | SND_ASYNC | SND_LOOP);
//or
sndPlaySound("*.wav", SND_FILENAME | SND_ASYNC | SND_LOOP);

请注意,您必须同时指定 SND_ASYNCSND_LOOP 标志,因为您永远不会等到重复无数次的声音结束!

您还可以使用 fread 函数fopen wave 文件并将其所有字节复制到缓冲区(巨大/巨大(非常大)的字节数组)和然后:

PlaySound(buffer, GetModuleHandle(NULL), SND_MEMORY);
//or
PlaySound(buffer, GetModuleHandle(NULL), SND_MEMORY | SND_ASYNC);
//or
PlaySound(buffer, GetModuleHandle(NULL), SND_MEMORY | SND_ASYNC | SND_LOOP);
//or
sndPlaySound(buffer, SND_MEMORY);
//or
sndPlaySound(buffer, SND_MEMORY | SND_ASYNC);
//or
sndPlaySound(buffer, SND_MEMORY | SND_ASYNC | SND_LOOP);

OpenFileCreateFileCreateFile2 以及 ReadFileReadFileEx 函数可以用来代替 fopenfread 函数。

希望这完全完美地回答了您的问题。

关于c++ - 如何在 C++ 程序中播放或打开 *.mp3 或 *.wav 声音文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22253074/

相关文章:

c++ - ArrayList 无法返回结构

c++ - 从无序数据构建 QVariant 列表

visual-c++ - <msbuild/> 任务失败而 <devenv/> 在 CruiseControl.NET 中的 MFC 应用程序成功?

c++ - Typedef 到 C++ 中的周围类型

java - 如何将 SourceDataLine 的内容写入文件?

C++ new、delete、new[] 和 delete[]

用于处理网格上的分布式矩阵的 C++ 库

c++ - 覆盖私有(private)函数

c# - 从AudioSource数据Unity C#到Text Azure的语音

c# - Java 相当于 C# system.beep?