SFML не воспроизводится звук

Рейтинг: 0Ответов: 1Опубликовано: 20.06.2023

Я захотел написать свой менеджер для управлением звуками, и получилось так, что по завершению программы звук не воспроизводится, но если я уберу добавление 2 и 3-его звука, все будет работать (причем неважно, какой будет файл walking_1.wav или walking_2.wav).

Audio.hpp

#pragma once

#include <SFML/Audio.hpp>
#include "specialtools.hpp"

class Audio{
    public:
    
    vector<sf::SoundBuffer>         sBuffers;
    vector<shared_ptr<sf::Sound>>   sh_ptr_sounds;
    vector<string>                  names;

    void newSound(string name, string fname){
        sBuffers.push_back(sf::SoundBuffer{});
        sBuffers[sBuffers.size()-1].loadFromFile(fname);
        cout<<"[ADD NEW SOUND] last buffer index: "<<sBuffers.size()-1<<endl;

        sh_ptr_sounds.push_back(make_shared<sf::Sound>(sf::Sound{}));
        sh_ptr_sounds[sh_ptr_sounds.size()-1]->setBuffer(sBuffers[sBuffers.size()-1]);
        cout<<"[ADD NEW SOUND] last sound index: "<<sh_ptr_sounds.size()-1<<endl;

        names.push_back(name);
        cout<<"[ADD NEW SOUND] name: "<<name<<endl;
        cout<<endl;
    }

    void playSound(string name){
        cout<<"Index of sound: "<<index(names, name)<<endl;
        sh_ptr_sounds[index(names, name)]->play();
    }

    Audio(){}
};

main.cpp

#include "Audio.hpp"

int main(){
    Audio aud;
    aud.newSound("1", "res/Sounds/walking_1.wav");
    aud.newSound("2", "res/Sounds/walking_2.wav");
    aud.newSound("3", "res/Sounds/walking_3.wav");
    aud.playSound("1");
    cin.get();
}

Вывод:

[ADD NEW SOUND] last buffer index: 0
[ADD NEW SOUND] last sound index: 0
[ADD NEW SOUND] name: 1

[ADD NEW SOUND] last buffer index: 1
[ADD NEW SOUND] last sound index: 1
[ADD NEW SOUND] name: 2

[ADD NEW SOUND] last buffer index: 2
[ADD NEW SOUND] last sound index: 2
[ADD NEW SOUND] name: 3

Index of sound: 0

В specialtools.hpp хранится только функция index, и подключаются библиотеки iostream, memory и vector.

Ответы

▲ 0Принят

Экземпляры sf::Sound сохраняют ссылку на передаваемые в них экземпляры sf::SoundBuffer, соответственно переданные экземпляры sf::SoundBuffer должны оставаться валидными, пока используются. Однако при добавлении новых объектов в sBuffers все ссылки на хранившиеся там ранее объекты протухают

Тут имеет смысл держать один контейнер, который не будет инвалидировать ссылки на свои элементы.

   class t_Sound
   {
       sf::SoundBuffer m_buffer;
       sf::Sound m_sound;
       ::std::string m_name;

       public: explicit
       t_Sound(::std::string const & name, ::std::string const & fname)
       :   m_buffer{LoadFromFile(fname)}
       ,   m_sound{m_buffer}
       ,   m_name{name}
       {}

       private:
       t_Sound(t_Sound const &) = delete;

       private: void
       operator =(t_Sound const &) = delete;

       private: static sf::SoundBuffer
       LoadFromFile(::std::string const & fname)
       {
           sf::SoundBuffer buffer{};
           if (not buffer.loadFromFile(fname))
           {
               throw ::std::runtime_error{fname};
           }
           return buffer;
       }
   };

   ::std::vector<::std::shared_ptr<t_Sound>> m_sounds;

   void
   newSound(::std::string const & name, ::std::string const & fname)
   {
       m_sounds.emplace_back(::std::make_shared<t_Sound>(name, fname));
   }