Search code examples
c++sfml

How to make a vector of sf::sound


I use the SFML library and more specifically the audio part of SFML. I would like to store multiple sf::Sound, so it occurred to me to make a class that handles sounds and to make a vector of sf::Sound. However, when I try to play a sound, only the last element of the list of my vector can be played, the rest does not play. I really can't understand why.

audio.hpp

#ifndef AUDIO_HPP
#define AUDIO_HPP
#pragma once

#include <SFML/Audio.hpp>
#include <vector>
#include <string>

enum {SELECTION_SOUND, DEAD_SOUND};
enum {MAIN_THEME_MUSIC, GAME_MUSIC, GAME_OVER_MUSIC};

class Audio
{
public:
    Audio();
    void setVolumeMusic(const float v);
    void setVolumeSound(const float v);
    float getVolumeSound() const;
    float getVolumeMusic() const;
    void playSound(const unsigned int soundExecute);
    void stopMusic();
    void deleteMusicTheme();
    ~Audio();
private:
    bool m_musicThemeUse;
    float m_volumeMusic, m_volumeSound;
    std::vector <sf::SoundBuffer> m_buffer;
    std::vector <bool> accessMusic, accessSound;
    std::vector <sf::Sound> m_sound;
    std::vector <sf::Music*> m_music;
    std::vector <std::string> m_nameFileMusic, m_nameFileSound;

    /*
    * m_musicThemeUse : If this variable is equal to "true" then, the main menu music is deleted from memory.
    * m_volumeMusic, m_volumeSound : Music/sound volume, it is fixed between 0.f and 100.f.
    * m_buffer: vector containing the audio files of the sounds.
    * accessMusic, accessSound : bool vector determining whether a music is available for playback or not. Useful when a file is deleted.
    * m_sound: vector containing the audio files of the sounds.
    * m_music: vector containing the audio files of the musics.
    * m_nameFileMusic, m_nameFileSound : vector of string containing the path of the audio files.
    */
};

#endif

The constructor of the Audio class.

Audio::Audio() : m_nameFileMusic{ "data/mainTheme.ogg", "data/game.ogg", "data/gameOver.ogg" }, m_nameFileSound{"data/selectionSound.ogg", "data/dead.ogg" },
m_musicThemeUse(true), m_volumeMusic(0.f), m_volumeSound(100.f)
{
    //Fill the values of accessMusic and accessSound to "true"
    accessMusic.assign(std::size(m_nameFileMusic), true);
    accessSound.assign(std::size(m_nameFileSound), true);

    //Loads music files.
    for (unsigned int i = 0; i < std::size(m_nameFileMusic); i++)
    {
        m_music.push_back(new sf::Music);
        if (!m_music[i]->openFromFile(m_nameFileMusic[i]))
            accessMusic[i] = false;
    }

    //Set the music files by setting the volume to them and activating repeat when the music files are finished.
    setVolumeMusic(m_volumeMusic);
    for(unsigned int i = 0; i < std::size(m_music); i++)
        if(m_nameFileMusic[i] != "data/gameOver.ogg")
            m_music[i]->setLoop(true);

    //Load sound files.
    const sf::SoundBuffer a;
    const sf::Sound b;
    for (unsigned int i = 0; i < std::size(m_nameFileSound); i++)
    {
        m_buffer.push_back(a);
        m_sound.push_back(b);
        if (!m_buffer[i].loadFromFile(m_nameFileSound[i]))
            accessSound[i] = false;
        else
            m_sound[i].setBuffer(m_buffer[i]);
    }
    //Fix the volume of the sound files.
    setVolumeSound(m_volumeSound);
    //If the main menu music file is available then play the music file.
    if(accessMusic[0])
        m_music[0]->play();

    m_sound[0].play();
}

Solution

  • When you copy SFML sound objects they stop playing. That's what happens when you relocate objects in an std::vector. I would recommend storing them in pointers as with

    using SoundPtr = std::shared_ptr<sf::Sound>;
    std::vector< SoundPtr > m_sound;