SFML community forums

Help => Audio => Topic started by: Phyton on September 02, 2019, 06:02:12 pm

Title: sf::Sound nullptr problem with std::map
Post by: Phyton on September 02, 2019, 06:02:12 pm
Hi Forum,
so this is a rather complicated problem with sf::Sound.
I face a problem when i create a std::map with an std::string as the key-value and a sf::Sound as the second argument ! I know its not recommended to save an sf::Sound to container as it always needs to point to an sf::SoundBuffer ! But in my case i wanted to go with that solution so i created an std::vector that would store my sf::SoundBuffer ! Before i go on heres the Code:
Header(minimal example):
std::map <std::string, sf::Sound> Sounds;
std::vector<sf::SoundBuffer> soundBuffer;
 
So here are both map and vector !
Now the implementation from a function that stores a loaded sf::SoundBuffer in a Vector and an sf::Sound to
a Map
Implementation:
sf::SoundBuffer buffer;
if (buffer.loadFromFile(path))
                {
                        soundBuffer.push_back(buffer);
                        //sound_.setBuffer(soundBuffer.back());  
                        //Sounds.insert(std::pair<std::string, sf::Sound>(name, sf::Sound{soundBuffer.back()}));
                        Sounds.emplace(name, sf::Sound{ soundBuffer.back() });
                        return true;
                }
 
As you can see, i tried out a lot of things

So wheres now the problem ? When i try to play multiple sounds only the last one added is functioning.The other two(in my case i added 3 sounds as an wav) get nullptr(first screenshot).
And the sf::SoundBuffer Vector is perfectly working !
I have no idea what i did wrong(i think it isnt an out of scope problem, because it should be prevented through the Vector).
I hope u can help me !
Thanks

Title: Re: sf::Sound nullptr problem with std::map
Post by: eXpl0it3r on September 02, 2019, 08:42:33 pm
You got the problem backwards. The issue with references isn't that the sound object are in a map, but the issue is that your buffer is in a vector.
The vector guarantees contiguous memory, so when you push_back more objects, the memory needs to be reallocated at one point. This reallocation happens by moving all objects to a new memory location and it's that, that breaks the reference the sound object may hold to the sound buffer.

As such, it's recommended for sound buffers, textures and fonts to not store them in vectors, but use a "stable" container such as a map.

As for your sound objects, I personally recommend a std::deque, as you can push_back new sounds and pop_front sounds that finished playing.
Title: Re: sf::Sound nullptr problem with std::map
Post by: Phyton on September 02, 2019, 09:08:00 pm
Big thank to you !
I should have known(because obviously a sf::SoundBuffer is quite large) that a push_back moved the content to other adress spaces !
I decided to store my buffers in an std::list and it works like a charme !
 ;)