如何在 C++ 程序中播放或打开 *.mp3 或 *.wav 声音文件?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22253074/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to play or open *.mp3 or *.wav sound file in c++ program?
提问by John Talbott
I'm a student of Computer Science. I have a final semester Project to develop a short game in graphics along with the sound.
我是计算机科学专业的学生。我有一个最后学期的项目来开发一个带有声音的图形短游戏。
回答by
First of all, write the following code:
首先,编写如下代码:
#include <Mmsystem.h>
#include <mciapi.h>
//these two headers are already included in the <Windows.h> header
#pragma comment(lib, "Winmm.lib")
To open *.mp3:
打开 *.mp3:
mciSendString("open \"*.mp3\" type mpegvideo alias mp3", NULL, 0, NULL);
To play *.mp3:
播放 *.mp3:
mciSendString("play mp3", NULL, 0, NULL);
To play and wait until the *.mp3 has finished playing:
播放并等待 *.mp3 播放完毕:
mciSendString("play mp3 wait", NULL, 0, NULL);
To replay (play again from start) the *.mp3:
要重播(从头开始再次播放)*.mp3:
mciSendString("play mp3 from 0", NULL, 0, NULL);
To replay and wait until the *.mp3 has finished playing:
要重播并等待 *.mp3 播放完毕:
mciSendString("play mp3 from 0 wait", NULL, 0, NULL);
To play the *.mp3 and replay it every time it ends like a loop:
播放 *.mp3 并在每次循环结束时重播:
mciSendString("play mp3 repeat", NULL, 0, NULL);
If you want to do something when the *.mp3 has finished playing, then you need to RegisterClassEx
by the WNDCLASSEX
structure, CreateWindowEx
and process it's messages with the GetMessage, TranslateMessageand DispatchMessagefunctions in a while
loop and call:
如果你想在 *.mp3 播放完后做一些事情,那么你需要RegisterClassEx
通过WNDCLASSEX
结构,CreateWindowEx
并在循环中使用GetMessage,TranslateMessage和DispatchMessage函数处理它的消息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).
In the window procedure, add the case MM_MCINOTIFY:
The code in there will be executed when the mp3 has finished playing.
在窗口程序中,添加case MM_MCINOTIFY:
mp3 播放完毕后执行的代码。
Butif you program a ConsoleApplication and you don't deal with windows, then you can CreateThread
in suspend state by specifying the CREATE_SUSPENDED
flag in the dwCreationFlags
parameter and keep the return value in a static
variable and call it whatever you want. For instance, I call it mp3. The type of this static
variable is HANDLE
of course.
但是,如果您编写控制台应用程序并且不处理windows,那么您可以CreateThread
通过CREATE_SUSPENDED
在dwCreationFlags
参数中指定标志并将返回值保留在static
变量中并随意调用它来处于挂起状态。例如,我称之为 mp3。这个static
变量的类型HANDLE
当然是。
Here is the ThreadProc
for the lpStartAddress
of this thread:
这里是ThreadProc
为lpStartAddress
这个线程:
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
}
}
All what you have to do now is to ResumeThread(mp3);
every time you want to replay your mp3 and something will happen every time it finishes.
你现在要做的就是ResumeThread(mp3);
每次你想重播你的 mp3 时,每次完成时都会发生一些事情。
You can #define play_my_mp3 ResumeThread(mp3);
to make your code more readable.
您可以#define play_my_mp3 ResumeThread(mp3);
使您的代码更具可读性。
Of course you can remove the while (true)
, SuspendThread
and the from 0codes, if you want to play your mp3 file only onceand do whatever you want when it is over.
当然,如果您只想播放 mp3 文件一次并在播放结束后做任何您想做的事情while (true)
,您可以删除,SuspendThread
和from 0代码。
If you onlyremove the SuspendThread
call, then the sound will play over and over again and do something whenever it is over. This is equivalent to:
如果您只删除SuspendThread
呼叫,那么声音将一遍又一遍地播放,并在结束时执行某些操作。这相当于:
mciSendString("play mp3 repeat notify", NULL, 0, hwnd); //or MAKELONG(hwnd, 0) instead
in windows.
在窗户里。
To pause the *.mp3 in middle:
在中间暂停 *.mp3:
mciSendString("pause mp3", NULL, 0, NULL);
and to resume it:
并恢复它:
mciSendString("resume mp3", NULL, 0, NULL);
To stop it in middle:
要在中间停止它:
mciSendString("stop mp3", NULL, 0, NULL);
Note that you cannot resume a sound that has been stopped, but only paused, but you can replay it by carrying out the playcommand. When you're done playing this *.mp3, don't forget to:
请注意,您不能继续播放已停止的声音,而只能继续播放,但您可以通过执行播放命令重新播放它。播放完 *.mp3 后,请不要忘记:
mciSendString("close mp3", NULL, 0, NULL);
All these actions also apply to (work with) wave files too, but with wave files, you can use "waveaudio" instead of "mpegvideo". Also you can just play them directly without opening them:
所有这些操作也适用于(使用)波形文件,但对于波形文件,您可以使用“waveaudio”而不是“mpegvideo”。您也可以直接播放它们而无需打开它们:
PlaySound("*.wav", GetModuleHandle(NULL), SND_FILENAME);
If you don't want to specify an handle to a module:
如果您不想指定模块的句柄:
sndPlaySound("*.wav", SND_FILENAME);
If you don't want to wait until the playback is over:
如果不想等到播放结束:
PlaySound("*.wav", GetModuleHandle(NULL), SND_FILENAME | SND_ASYNC);
//or
sndPlaySound("*.wav", SND_FILENAME | SND_ASYNC);
To play the wave file over and over again:
一遍又一遍地播放波形文件:
PlaySound("*.wav", GetModuleHandle(NULL), SND_FILENAME | SND_ASYNC | SND_LOOP);
//or
sndPlaySound("*.wav", SND_FILENAME | SND_ASYNC | SND_LOOP);
Note that you must specify both the SND_ASYNC
and SND_LOOP
flags, because you never going to wait until a sound, that repeats itself countless times, is over!
请注意,您必须同时指定 theSND_ASYNC
和SND_LOOP
flags,因为您永远不会等到重复无数次的声音结束!
Also you can fopen
the wave file and copy all it's bytes to a buffer (an enormous/huge (very big) array of bytes) with the fread
function and then:
您也可以使用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);
Either OpenFile
or CreateFile
or CreateFile2
and either ReadFile
or ReadFileEx
functions can be used instead of fopen
and fread
functions.
可以使用OpenFile
orCreateFile
或CreateFile2
and 或者ReadFile
orReadFileEx
函数来代替fopen
andfread
函数。
Hope this fully answers perfectly your question.
希望这完全可以完美回答您的问题。
回答by DCurro
http://sfml-dev.org/documentation/2.0/classsf_1_1Music.php
http://sfml-dev.org/documentation/2.0/classsf_1_1Music.php
SFML does not have mp3 support as another has suggested. What I always do is use Audacity and make all my music into ogg, and leave all my sound effects as wav.
SFML 不像另一个人建议的那样支持 mp3。我总是用 Audacity 把我所有的音乐都做成 ogg,把我所有的音效都保留为 wav。
Loading and playing a wav is simple (crude example):
加载和播放 wav 很简单(粗略的例子):
http://www.sfml-dev.org/tutorials/2.0/audio-sounds.php
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();
Streaming an ogg music file is also simple:
流式传输 ogg 音乐文件也很简单:
#include <SFML/Audio.hpp>
...
sf::Music music;
if (!music.openFromFile("music.ogg"))
return -1; // error
music.play();
回答by Xardaska
回答by Kulamani
Try with simple c++ code in VC++.
尝试在 VC++ 中使用简单的 C++ 代码。
#include <windows.h>
#include <iostream>
#pragma comment(lib, "winmm.lib")
int main(int argc, char* argv[])
{
std::cout<<"Sound playing... enjoy....!!!";
PlaySound("C:\temp\sound_test.wav", NULL, SND_FILENAME); //SND_FILENAME or SND_LOOP
return 0;
}
回答by Josh
I would use FMOD to do this for your game. It has the ability to play any file mostly for sounds and is pretty simple to implement in C++. using FMOD and Dir3ect X together can be powerful and not that difficult. If you are familiar with Singleton classes I would create a Singleton class of a sound manager in your win main cpp and then have access to it whenever to load or play new music or sound effects. here's an audio manager example
我会使用 FMOD 为您的游戏执行此操作。它能够播放任何文件,主要是为了声音,并且在 C++ 中实现起来非常简单。一起使用 FMOD 和 Dir3ect X 可以很强大,而且并不难。如果您熟悉 Singleton 类,我将在您的 win main cpp 中创建一个声音管理器的 Singleton 类,然后在加载或播放新音乐或声音效果时都可以访问它。这是一个音频管理器示例
#pragma once
#ifndef H_AUDIOMANAGER
#define H_AUDIOMANAGER
#include <string>
#include <Windows.h>
#include "fmod.h"
#include "fmod.hpp"
#include "fmod_codec.h"
#include "fmod_dsp.h"
#include "fmod_errors.h"
#include "fmod_memoryinfo.h"
#include "fmod_output.h"
class AudioManager
{
public:
// Destructor
~AudioManager(void);
void Initialize(void); // Initialize sound components
void Shutdown(void); // Shutdown sound components
// Singleton instance manip methods
static AudioManager* GetInstance(void);
static void DestroyInstance(void);
// Accessors
FMOD::System* GetSystem(void)
{return soundSystem;}
// Sound playing
void Play(FMOD::Sound* sound); // Play a sound/music with default channel
void PlaySFX(FMOD::Sound* sound); // Play a sound effect with custom channel
void PlayBGM(FMOD::Sound* sound); // Play background music with custom channel
// Volume adjustment methods
void SetBGMVolume(float volume);
void SetSFXVolume(float volume);
private:
static AudioManager* instance; // Singleton instance
AudioManager(void); // Constructor
FMOD::System* soundSystem; // Sound system object
FMOD_RESULT result;
FMOD::Channel* bgmChannel; // Channel for background music
static const int numSfxChannels = 4;
FMOD::Channel* sfxChannels[numSfxChannels]; // Channel for sound effects
};
#endif
回答by user3392484
Use a library to (a) read the sound file(s) and (b) play them back. (I'd recommend trying both yourself at some point in your spare time, but...)
使用库来 (a) 读取声音文件和 (b) 播放它们。(我建议您在空闲时间的某个时候自己尝试一下,但是......)
Perhaps (*nix):
也许(* nix):
Windows: DirectX.
视窗:DirectX。