Как воспроизвести или открыть звуковой файл *.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.

Другие вопросы по тегам