2014-03-07 10 views
6

Ich bin ein Student der Informatik. Ich habe ein letztes Semester Projekt, um ein kurzes Spiel in der Grafik zusammen mit dem Ton zu entwickeln.Wie zu spielen oder offen * .mp3 oder * .wav Sound-Datei in C++ Programm?

+1

[WAV info] (https://ccrma.stanford.edu/courses/422/projects/WaveFormat/) – Michael

+3

Um eine sinnvolle und hilfreiche Antwort zu bekommen, anstatt Kommentar auf die Suche im Internet, müssen Sie zeigen Sie an, was Sie versucht haben. Zeigen Sie Beispielcode, der versucht, Ihre MP3-Datei zu laden. Haben Sie gebunden, vorhandene Bibliotheken zu verwenden (aber fehlgeschlagen). Diese sind hilfreicher. – wmorrison365

+3

p.s. Sie können überprüfen, wie diese Bibliotheken es tun: http://en.cppreference.com/w/cpp/links/libs – wmorrison365

Antwort

5

Wenn Sie die * .mp3 oder * .wav-Datei wiedergeben möchten, denke ich, der einfachste Weg wäre, SFML zu verwenden.

+4

Bitte beachten Sie jedoch, dass SFML aufgrund von Lizenzproblemen das MP3-Format nicht unterstützt. Sie können aber auch das weniger bekannte, aber ebenso gute OGG-Format verwenden. – Lukas

2

Ich würde FMOD verwendet diese für Ihr Spiel zu tun. Es hat die Fähigkeit, jede Datei hauptsächlich für Sounds abzuspielen und ist in C++ ziemlich einfach zu implementieren. Die Verwendung von FMOD und Dir3ect X zusammen kann leistungsfähig und nicht so schwierig sein. Wenn Sie mit Singleton-Klassen vertraut sind, würde ich eine Singleton-Klasse eines soliden Manager in Ihrem Gewinn Haupt cpp erstellen und dann den Zugriff darauf haben, wann immer laden oder neue Musik oder Sound-Effekte zu spielen. Hier ist ein Audio-Manager Beispiel

#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 
+1

Das hängt nicht wirklich mit der Frage von op zusammen, aber könnten Sie erklären, warum Sie eine separate Methode zum Herunterfahren haben, anstatt sich auf den Destruktor zu verlassen? – jaho

+1

Da Sie mit so vielen Komponenten wie ein Soundsystem arbeiten sollten, können Sie alle Objekte des Soundsystems dort und nicht im Destruktor behandeln, da der Destruktor den Soundmanager zerstört, aber keines der erzeugten Objekte die Soundklasse eigene Klasse. – Josh

+1

Nun, Sie können den gleichen Code setzen Sie in 'shutdown()' Methode in Destruktor setzen. Das ist eigentlich der Zweck des Destruktors, alle von einem Objekt gehaltenen Ressourcen freizugeben. Ich sehe diese zweistufige Destruktion oft als eine Art Design, kann aber niemals die dahinter stehenden Gründe verstehen. Warum nicht die Standardfunktionen verwenden, die C++ bietet?Außerdem können Sie immer Smartpointer verwenden und müssen sich nicht darum kümmern, die Ressourcen explizit freizugeben. Ich sehe nur nicht die Vorteile einer separaten 'shutdown()' Funktion. – jaho

4

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

SFML nicht MP3-Unterstützung hat als andere vorgeschlagen hat. Was ich immer mache, ist Audacity und mache alle meine Musik zu ogg, und lasse alle meine Soundeffekte als wav.

Laden und eine WAV-Wiedergabe ist einfach (Roh-Beispiel):

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(); 

eine ogg Musikdatei Streaming ist auch einfach:

#include <SFML/Audio.hpp> 
... 
sf::Music music; 
if (!music.openFromFile("music.ogg")) 
    return -1; // error 
music.play(); 
+0

funktioniert für mich mit den vorkompilierten Binärdateien –

22

Zunächst einmal schreiben die folgenden Code:

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

zu * .mp3 zu öffnen:

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

* .mp3 zu spielen: Um

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

:

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

zu spielen, und zu warten, bis das * .mp3 wiedergegeben wird Replay (spielt wieder von Anfang), um die * .mp3:

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

Zum Abspielen und warten, bis das * .mp3 fertig spielen hat:

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

die * zu spielen.mp3 und Wiedergabe es jedes Mal, es wie eine Schleife endet:

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

Wenn Sie etwas tun wollen, wenn das * .mp3 Spiel beendet hat, dann müssen Sie RegisterClassEx durch die WNDCLASSEX Struktur, CreateWindowEx und es ist Prozess-Nachrichten mit die GetMessage, Translate und Dispatch Funktionen in einer while Schleife und rufen:

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). 

Fügen Sie in der Fensterprozedur die case MM_MCINOTIFY: hinzu. Der dort enthaltene Code wird ausgeführt, wenn die MP3-Wiedergabe beendet ist.

Aber wenn Sie programmieren eine Console Anwendung und Sie befassen sich nicht mit Fenster, dann können Sie CreateThread in Suspend-Zustand durch die CREATE_SUSPENDED Flag im dwCreationFlags Parameter angeben und den Rückgabewert halten in ein static Variable und nennen Sie es, was Sie wollen. Zum Beispiel nenne ich es mp3. Der Typ dieser static Variable ist natürlich HANDLE.

Hier ist die ThreadProc für die lpStartAddress dieses Threads:

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 
    } 
} 

Alles was Sie jetzt tun müssen, ist zu ResumeThread(mp3); jedes Mal, wenn Sie Ihren MP3 und etwas wiederholen wollen, werden jedes Mal passieren sie beendet.

Sie können #define play_my_mp3 ResumeThread(mp3);, um Ihren Code lesbarer zu machen.

Natürlich können Sie die while (true), SuspendThread und die von 0 Codes entfernen, wenn Sie möchten, dass Ihre MP3-Datei nur einmal spielen und tun, was Sie wollen, wenn es vorbei ist.

Wenn Sie nur entfernen Sie den SuspendThread Anruf, dann wird der Ton wieder und wieder spielen und etwas tun, wann immer es vorbei ist. Dies entspricht:

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

in Windows.

das * .mp3 in Mitte zu pausieren:

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

und es wieder aufnehmen:

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

es in der Mitte zu stoppen:

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

Beachten Sie, dass Sie nicht wieder aufnehmen kann ein Ton, der gestoppt wurde, aber nur pausiert, aber Sie können ihn abspielen, indem Sie abspielen Befehl. Wenn Sie fertig sind *.mp3, nicht vergessen:

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

All diese Aktionen (Arbeit mit) auch anwenden Welle zu Dateien, aber mit Wave-Dateien, können Sie „Waveaudio“ anstelle von „MPEGVideo“ verwenden. Sie können auch nur sie direkt spielen, ohne sie zu öffnen:

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

Wenn Sie nicht über einen Handle auf ein Modul angeben mögen:

sndPlaySound("*.wav", SND_FILENAME); 

Wenn Sie nicht wollen, bis die warten Wiedergabe ist über:

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

die wave-Datei über spielen und immer wieder:

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

Beachten Sie, dass Sie sowohl die SND_ASYNC als auch die SND_LOOP Flags angeben müssen, da Sie nie warten werden, bis ein Sound, der sich unzählige Male wiederholt, vorbei ist!

Auch können Sie die Wave-Datei fopen und kopieren all seinen Bytes in einen Puffer (eine enorme/riesig (sehr groß) Byte-Array) mit der fread Funktion und dann:

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); 

Entweder OpenFile oder CreateFile oder CreateFile2 und entweder ReadFile oder ReadFileEx Funktionen können anstelle von fopen und fread Funktionen verwendet werden.

Hoffe das vollständig beantwortet perfekt Ihre Frage.

+6

Wow, ich kann nicht glauben, dass diese Antwort bisher nicht wirklich bemerkt wurde! Solch eine gute und detaillierte Ressource für Leute wie mich, die eine einfache .mp3 Sound-Implementierung in ihrem C++ Code wollen! – Sossenbinder

2

Versuchen Sie mit einfachem C++ - Code in 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; 
} 
Verwandte Themen