Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: multiple concurrent sound effects  (Read 3868 times)

0 Members and 1 Guest are viewing this topic.

Moonglum

  • Newbie
  • *
  • Posts: 10
    • View Profile
multiple concurrent sound effects
« on: May 17, 2023, 09:27:04 am »
Hi All.

I am writing a game which requires the player to launch up to 9 missiles in quick succession. There is a sound effect for the launch of the missile and a sound effect for each explosion. The only way I can avoid the next sound effect cutting off the previous sound effect is for each missile to have two sound definitions, one for shoot and one for explosion. I cant use arrays as this will stop the sound playing and I cant use functions for the same reason. Relevant sections of code are as follows: This is for the explosions ...

    sf::SoundBuffer missileBuffer0;
    sf::SoundBuffer missileBuffer1;
    sf::SoundBuffer missileBuffer2;
    sf::SoundBuffer missileBuffer3;
    sf::SoundBuffer missileBuffer4;
    sf::SoundBuffer missileBuffer5;
    sf::SoundBuffer missileBuffer6;
    sf::SoundBuffer missileBuffer7;
    sf::SoundBuffer missileBuffer8;
    sf::SoundBuffer missileBuffer9;
    sf::Sound missile0;
    sf::Sound missile1;
    sf::Sound missile2;
    sf::Sound missile3;
    sf::Sound missile4;
    sf::Sound missile5;
    sf::Sound missile6;
    sf::Sound missile7;
    sf::Sound missile8;
    sf::Sound missile9;

... and this is the explosion hit sound effect playback.

                                    switch (i)
                                    {
                                    case 0:
                                        if (!missileBuffer0.loadFromFile("rockhit.flac"))
                                        {
                                            cout << "No sound file";
                                        }
                                        missile0.setBuffer(missileBuffer0);
                                        missile0.play();
                                        break;

                                    case 1:
                                        if (!missileBuffer1.loadFromFile("rockhit.flac"))
                                        {
                                            cout << "No sound file";
                                        }
                                        missile1.setBuffer(missileBuffer1);
                                        missile1.play();
                                        break;

                                    case 2:
                                        if (!missileBuffer2.loadFromFile("rockhit.flac"))
                                        {
                                            cout << "No sound file";
                                        ...

... and so on, you get the idea. It does work but seems to be terrible code. I feel I have missed something very important which will avoid the need for this. Please can someone tell me if there is a better way to get this done?

Many thanks

Moon.
« Last Edit: May 17, 2023, 09:28:45 am by eXpl0it3r »

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11030
    • View Profile
    • development blog
    • Email
Re: multiple concurrent sound effects
« Reply #1 on: May 17, 2023, 09:36:09 am »
What you're missing is that the assumption you've made about not being able to use arrays or functions is wrong, or rather the understanding of why you "can't" use them is wrong.

As a first step you probably want to use a class to run your application in, this allows you to have the sound and sound buffers as member variables and extend the lifetime scope beyond the current method, without using global variables.

Next I'd recommend using something like a ResourceHolder to manage the loading of your sound buffers. So you have to only load it once and can reuse it, while the resource is being properly managed.

And finally, to handle sounds in a nice way, I can recommend to use a std::deque<sf::Sound>, which allows you to pop_front() sounds that have finished playing and push_back() new sound instances without disturbing other already playing sounds.
Alternatively you can also use some other container to hold multiple instances of a sound, but you need to understand how they work. A std::vector for example will be moved in memory if you just keep push_back()-ing new instances, which then can lead to pausing of the current sounds being played.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

kojack

  • Sr. Member
  • ****
  • Posts: 343
  • C++/C# game dev teacher.
    • View Profile
Re: multiple concurrent sound effects
« Reply #2 on: May 17, 2023, 10:39:17 am »
Also, if you are using the same audio file in each one, you only need a single SoundBuffer. You can have many Sound objects all sharing a single SoundBuffer (that you can load at the beginning so it doesn't cause a delay during the game).
So if your game has 2 different sound effects to play, you only need 2 SoundBuffers, then as many Sounds as you'd like.

The way my sound manager used to work was I had a vector of Sound pointers. For each sound I played I'd push a new sound object into the vector (pointers aren't hurt by the vector reallocating as it grows). Every update I'd loop over the sound vector and check to see if each sound had finished playing. If they had finished, I'd delete them and remove them from the vector.

These days I do it similar, but using the Entt entity component system to store the sounds.
(That's getting a bit complicated if you aren't used to ECS style programming)

Hapax

  • Hero Member
  • *****
  • Posts: 3379
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: multiple concurrent sound effects
« Reply #3 on: May 19, 2023, 09:09:54 pm »
Although it's not been updated for a bit, you could try this:
https://github.com/Hapaxia/SfmlSoundSystem

It was designed to make using sounds in SFML more intuitive than doing it all manually.
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*