web-dev-qa-db-fra.com

Comment lire ou ouvrir un fichier son * .mp3 ou * .wav dans un programme c ++?

Je suis étudiant en informatique. J'ai un projet de semestre final pour développer un petit jeu graphique avec le son.

7
John Talbott

Tout d'abord, écrivez le code suivant:

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

Pour ouvrir * .mp3:

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

Pour jouer au * .mp3:

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

Pour jouer et attendre la fin de la lecture du * .mp3:

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

Pour rejouer (relire depuis le début) le * .mp3:

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

Pour rejouer et attendre la fin de la lecture du * .mp3:

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

Pour jouer au * .mp3 et le rejouer chaque fois qu'il se termine comme une boucle:

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

Si vous voulez faire quelque chose quand le * .mp3 a fini de jouer, alors vous devez RegisterClassEx par la structure WNDCLASSEX, CreateWindowEx et traiter ses messages avec le GetMessage, TranslateMessage et DispatchMessage fonctions dans une boucle while et appelez:

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

Dans la procédure de la fenêtre, ajoutez le case MM_MCINOTIFY: Le code qu'il contient sera exécuté lorsque la lecture du mp3 sera terminée.

Mais si vous programmez une Console Application et que vous ne traitez pas avec windows, alors vous pouvez CreateThread en état de suspension par en spécifiant l'indicateur CREATE_SUSPENDED dans le paramètre dwCreationFlags et conservez la valeur de retour dans une variable static et appelez-la comme vous voulez. Par exemple, je l'appelle mp3. Le type de cette variable static est bien entendu HANDLE.

Voici le ThreadProc pour le lpStartAddress de ce fil:

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

Tout ce que vous avez à faire maintenant est de ResumeThread(mp3); chaque fois que vous voulez rejouer votre mp3 et quelque chose se produira à chaque fois.

Vous pouvez #define play_my_mp3 ResumeThread(mp3); pour rendre votre code plus lisible.

Bien sûr, vous pouvez supprimer les codes while (true), SuspendThread et à partir de, si vous souhaitez lire votre fichier mp3 uniquement ne fois et faites ce que vous voulez quand ce sera fini.

Si vous seulement supprimez l'appel SuspendThread, alors le son sera reproduit encore et encore et fera quelque chose à chaque fois qu'il sera terminé. Cela équivaut à:

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

dans les fenêtres.

Pour mettre en pause le * .mp3 au milieu:

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

et pour le reprendre:

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

Pour l'arrêter au milieu:

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

Notez que vous ne pouvez pas reprendre un son qui a été arrêté, mais seulement en pause, mais vous pouvez le rejouer en exécutant la commande play. Lorsque vous avez fini de jouer à ce * .mp3, n'oubliez pas de:

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

Toutes ces actions s'appliquent également aux fichiers wave (travailler avec), mais avec les fichiers wave, vous pouvez utiliser "waveaudio" au lieu de "mpegvideo". Vous pouvez également les jouer directement sans les ouvrir:

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

Si vous ne souhaitez pas spécifier de descripteur pour un module:

sndPlaySound("*.wav", SND_FILENAME);

Si vous ne voulez pas attendre la fin de la lecture:

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

Pour lire le fichier wave encore et encore:

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

Notez que vous devez spécifier les drapeaux SND_ASYNC Et SND_LOOP, Car vous n'attendez jamais qu'un son, qui se répète d'innombrables fois, soit terminé!

Vous pouvez également fopen le fichier wave et copier tous ses octets dans un tampon (un énorme/énorme (très grand) tableau d'octets) avec la fonction fread puis:

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

Soit OpenFile ou CreateFile ou CreateFile2 Et soit ReadFile ou ReadFileEx fonctions peuvent être utilisées à la place de fopen et fread fonctions.

J'espère que cela répond parfaitement à votre question.

40
user2133061

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

SFML n'a pas de support mp3 comme un autre l'a suggéré. Ce que je fais toujours, c'est utiliser Audacity et transformer toute ma musique en ogg, et laisser tous mes effets sonores en wav.

Charger et jouer un wav est simple (exemple grossier):

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

La diffusion d'un fichier musical ogg est également simple:

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

Si vous voulez lire le fichier * .mp3 ou * .wav, je pense que la façon la plus simple serait d'utiliser SFML .

4
Xardaska

Essayez avec du code c ++ simple dans 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;
}
2
Kulamani

J'utiliserais FMOD pour le faire pour votre jeu. Il a la capacité de lire n'importe quel fichier principalement pour les sons et est assez simple à implémenter en C++. utiliser FMOD et Dir3ect X ensemble peut être puissant et pas si difficile. Si vous êtes familier avec les classes Singleton, je créerais une classe Singleton d'un gestionnaire de son dans votre cpp principal gagnant et y aurais accès à chaque fois pour charger ou jouer de la nouvelle musique ou des effets sonores. voici un exemple de gestionnaire audio

    #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
2
Josh

Utilisez une bibliothèque pour (a) lire le (s) fichier (s) audio et (b) les lire. (Je recommanderais d'essayer les deux vous-même à un moment donné de votre temps libre, mais ...)

Peut-être (* nix):

Windows: DirectX.

2
user3392484