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