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

Joh*_*ott 7 c++ audio graphics visual-c++

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

小智 40

首先,编写以下代码:

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

要打开*.mp3:

mciSendString("open \"*.mp3\" type mpegvideo alias mp3", NULL, 0, NULL);
Run Code Online (Sandbox Code Playgroud)

要播放*.mp3:

mciSendString("play mp3", NULL, 0, NULL);
Run Code Online (Sandbox Code Playgroud)

要播放并等到*.mp3播放完毕:

mciSendString("play mp3 wait", NULL, 0, NULL);
Run Code Online (Sandbox Code Playgroud)

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

mciSendString("play mp3 from 0", NULL, 0, NULL);
Run Code Online (Sandbox Code Playgroud)

要重播并等到*.mp3播放完毕:

mciSendString("play mp3 from 0 wait", NULL, 0, NULL);
Run Code Online (Sandbox Code Playgroud)

播放*.mp3并在每次循环时重播它:

mciSendString("play mp3 repeat", NULL, 0, NULL);
Run Code Online (Sandbox Code Playgroud)

如果你想在*.mp3完成播放时做某事,那么你需要RegisterClassEx通过WNDCLASSEX结构,CreateWindowEx并在循环中使用GetMessage,TranslateMessageDispatchMessage函数处理它的消息while并调用:

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).
Run Code Online (Sandbox Code Playgroud)

在窗口过程中,添加case MM_MCINOTIFY:mp3中的代码将在mp3播放完毕后执行.

但是如果您编写控制台应用程序并且不处理窗口,则可以CreateThread通过CREATE_SUSPENDEDdwCreationFlags参数中指定标志来暂停状态,并将返回值保存在static变量中并随意调用它.例如,我称之为mp3.当然,这个static变量的类型HANDLE.

这里是ThreadProclpStartAddress这个线程:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

你现在要做的就是ResumeThread(mp3);每次你想要重放你的mp3时,每次完成时都会发生一些事情.

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

当然,如果您只想播放一次 mp3文件并在结束时执行任何操作while (true),您可以删除SuspendThread0代码.

如果你只是取消了这个SuspendThread电话,那么声音会一遍又一遍地播放,并在它结束时做一些事情.这相当于:

mciSendString("play mp3 repeat notify", NULL, 0, hwnd); //or MAKELONG(hwnd, 0) instead
Run Code Online (Sandbox Code Playgroud)

在窗户.

暂停中间的*.mp3:

mciSendString("pause mp3", NULL, 0, NULL);
Run Code Online (Sandbox Code Playgroud)

并恢复它:

mciSendString("resume mp3", NULL, 0, NULL);
Run Code Online (Sandbox Code Playgroud)

要在中间阻止它:

mciSendString("stop mp3", NULL, 0, NULL);
Run Code Online (Sandbox Code Playgroud)

请注意,您无法恢复已停止但仅暂停的声音,但您可以通过执行播放命令重播它.当你完成播放*.mp3时,不要忘记:

mciSendString("close mp3", NULL, 0, NULL);
Run Code Online (Sandbox Code Playgroud)

所有这些操作也适用于(使用)波形文件,但对于波形文件,您可以使用"waveaudio"而不是"mpegvideo".您也可以直接播放它们而无需打开它们:

PlaySound("*.wav", GetModuleHandle(NULL), SND_FILENAME);
Run Code Online (Sandbox Code Playgroud)

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

sndPlaySound("*.wav", SND_FILENAME);
Run Code Online (Sandbox Code Playgroud)

如果您不想等到播放结束:

PlaySound("*.wav", GetModuleHandle(NULL), SND_FILENAME | SND_ASYNC);
//or
sndPlaySound("*.wav", SND_FILENAME | SND_ASYNC);
Run Code Online (Sandbox Code Playgroud)

一遍又一遍地播放波形文件:

PlaySound("*.wav", GetModuleHandle(NULL), SND_FILENAME | SND_ASYNC | SND_LOOP);
//or
sndPlaySound("*.wav", SND_FILENAME | SND_ASYNC | SND_LOOP);
Run Code Online (Sandbox Code Playgroud)

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

你也可以使用fopen该函数将波形文件复制到缓冲区(一个巨大的/巨大的(非常大的)字节数组)fread,然后:

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);
Run Code Online (Sandbox Code Playgroud)

可以使用OpenFile或者和/ CreateFileCreateFile2任何一个ReadFileReadFileEx函数代替fopenfread函数.

希望这完全回答你的问题.

  • 哇,我简直不敢相信这个答案到目前为止还没有被注意到!对于像我这样想要在他们的C++代码中实现简单的.mp3声音实现的人来说,这是一个优秀而详细的资源! (7认同)

Xar*_*ska 5

如果你想播放 *.mp3 或 *.wav 文件,我认为最简单的方法是使用SFML

  • 但请记住,由于许可问题,SFML 不支持 MP3 格式。但是,您也可以使用鲜为人知但同样出色的 OGG 格式。 (7认同)

DCu*_*rro 5

http://sfml-dev.org/documentation/2.0/classsf_1_1Music.php

SFML不像另一个建议的那样具有mp3支持。我一直做的就是使用Audacity,将我的所有音乐制作成ogg,然后将所有音效保留为wav。

加载和播放wav很简单(粗略的示例):

http://www.sfml-dev.org/tutorials/2.0/audio-sounds.php

#include <SFML/Audio.hpp>
...
sf::SoundBuffer buffer;
if (!buffer.loadFromFile("sound.wav")){
    return -1;
}
sf::Sound sound;
sound.setBuffer(buffer);
sound.play();
Run Code Online (Sandbox Code Playgroud)

流ogg音乐文件也很简单:

#include <SFML/Audio.hpp>
...
sf::Music music;
if (!music.openFromFile("music.ogg"))
    return -1; // error
music.play();
Run Code Online (Sandbox Code Playgroud)


use*_*484 2

使用库来 (a) 读取声音文件并 (b) 播放它们。(我建议您在业余时间的某个时候自己尝试一下,但是......)

也许(*nix):

Windows:DirectX。