Как воспроизвести или открыть звуковой файл *.mp3 или *.wav в программе C++?
Я студент информатики. У меня есть последний семестр Project для разработки короткой игры в графике вместе со звуком.
6 ответов
Прежде всего, напишите следующий код:
#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 закончил играть, вам нужно 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).
В процедуре окна добавьте case MM_MCINOTIFY:
Код там будет выполнен, когда закончится воспроизведение mp3.
Но если вы программируете консольное приложение и не имеете дело с окнами, тогда вы можете CreateThread
в состоянии ожидания, указав CREATE_SUSPENDED
флаг в dwCreationFlags
параметр и сохранить возвращаемое значение в static
переменная и называйте это как хотите. Например, я называю это mp3. Тип этого static
переменная HANDLE
конечно.
Здесь 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
}
}
Все, что вам нужно сделать сейчас, это ResumeThread(mp3);
каждый раз, когда вы хотите воспроизвести свой mp3, и что-то будет происходить каждый раз, когда он заканчивается.
Вы можете #define play_my_mp3 ResumeThread(mp3);
чтобы сделать ваш код более читабельным.
Конечно, вы можете удалить while (true)
, SuspendThread
и коды от 0, если вы хотите воспроизвести свой mp3-файл только один раз и делать все, что захотите, когда он закончится.
Если вы только удалите SuspendThread
звоните, тогда звук будет играть снова и снова и делать что-нибудь, когда он закончится. Это эквивалентно:
mciSendString("play mp3 repeat notify", NULL, 0, hwnd); //or MAKELONG(hwnd, 0) instead
в окнах.
Чтобы приостановить *.mp3 посередине:
mciSendString("pause mp3", NULL, 0, NULL);
и возобновить это:
mciSendString("resume mp3", NULL, 0, NULL);
Чтобы остановить это в середине:
mciSendString("stop mp3", NULL, 0, NULL);
Обратите внимание, что вы не можете возобновить звук, который был остановлен, но только приостановлен, но вы можете воспроизвести его, выполнив команду воспроизведения. Когда вы закончите играть в этот *.mp3, не забудьте:
mciSendString("close mp3", NULL, 0, NULL);
Все эти действия также применимы и к (работе с) волновым файлам, но с волновыми файлами вы можете использовать "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_ASYNC
а также SND_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);
Или OpenFile
или же CreateFile
или же CreateFile2
и либо ReadFile
или же ReadFileEx
функции могут быть использованы вместо fopen
а также fread
функции.
Надеюсь, что это полностью отвечает на ваш вопрос.
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();
Потоковая передача музыки в формате ogg также проста:
#include <SFML/Audio.hpp>
...
sf::Music music;
if (!music.openFromFile("music.ogg"))
return -1; // error
music.play();
Если вы хотите воспроизвести файл *.mp3 или *.wav, я думаю, что самый простой способ - использовать SFML.
Попробуйте с простым кодом C++ в VC++.
#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;
}
Я бы использовал FMOD, чтобы сделать это для вашей игры. Он имеет возможность воспроизводить любой файл, в основном, для звуков, и его довольно просто реализовать на C++. совместное использование FMOD и Dir3ect X может быть мощным и не таким сложным. Если вы знакомы с классами Singleton, я бы создал класс звукового менеджера Singleton в вашем win main cpp, а затем имел бы доступ к нему всякий раз, когда загружается или воспроизводится новая музыка или звуковые эффекты. вот пример аудио-менеджера
#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
Используйте библиотеку, чтобы (а) прочитать звуковые файлы и (б) воспроизвести их. (Я бы порекомендовал попробовать оба в свое свободное время, но...)
Возможно (* nix):
Windows: DirectX.