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

Author Topic: Sound not playing, debugging says no symbols loaded for sfml-audio-d-2.dll  (Read 6888 times)

0 Members and 1 Guest are viewing this topic.

Discover-

  • Newbie
  • *
  • Posts: 8
    • View Profile
Hello everybody,

Today I decided to re-write the design/logic in my Sound class (renamed to Audio) (it used to work before the re-write but the design was bad) by storing a std::string and a sf::SoundBuffer in a std::map in the class and then loading all .wav files into this map on start-up of the application (later on moving this to a separate thread, of course). A  new issue had arisen so I started throwing around breakpoints and came to the conclusion that it for whatever reason seems to not ever load the sfml-audio-d-2.dll, even though it is in place with all other .dll's. Here a screenshot of the error:


(take a look at the Watch window)

Showing that it did in fact find the song we are trying to play (different sound being played):


As for the .dll's:


Now as for the code, it can all be found on this GitHub repository, but I'll paste some code regarding the issue here anyhow.

audio.h
#pragma once

#include <vector>
#include <array>
#include <map>
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#include <iostream>

class Game;

class Audio
{
    public:
        Audio(Game* _game);
        ~Audio();

        bool Load(std::string filename);
        void Play(std::string filename, bool loop = false);
        void Stop(std::string filename);
        void SetVolume(std::string filename, float volume);
        float GetVolume(std::string filename);
        void SetLoop(std::string filename, bool val);
        bool IsLooping(std::string filename);
        sf::SoundSource::Status GetStatus(std::string filename);
        sf::Sound* GetPlayingSound(std::string filename);

    private:
        Game* game;
        std::map<std::string, sf::SoundBuffer> soundBuffers;
};
 

audio.cpp
#include "audio.h"
#include "game.h"
#include <SFML/Audio.hpp>

Audio::Audio(Game* _game)
{
    game = _game;
}

Audio::~Audio()
{

}

bool Audio::Load(std::string filename)
{
    sf::SoundBuffer buffer;

    if (buffer.loadFromFile(filename))
    {
        soundBuffers[filename] = buffer;
        return true;
    }
    else
        std::cout << "Audio::Load: Could not find audio file '" << filename << "'" << std::endl;

    return false;
}

void Audio::Play(std::string filename, bool loop /* = false */)
{
    std::map<std::string, sf::SoundBuffer>::iterator itr = soundBuffers.find(filename);

    if (itr != soundBuffers.end())
    {
        sf::Sound playingSound = sf::Sound((*itr).second);

        playingSound.play();

        if (loop)
            playingSound.setLoop(true);

        if (game->IsMusicMuted())
            playingSound.setVolume(0.0f);
    }
    else
        std::cout << "Audio::Play: Could not find audio file '" << filename << "'" << std::endl;
}

void Audio::Stop(std::string filename)
{
    if (filename == "all")
    {
        for (std::map<std::string, sf::SoundBuffer>::iterator itr = soundBuffers.begin(); itr != soundBuffers.end(); ++itr)
            sf::Sound((*itr).second).stop();
    }
    else
    {
        if (sf::Sound* playingSnd = GetPlayingSound(filename))
            playingSnd->stop();
        else
            std::cout << "Audio::Stop: Could not find audio file '" << filename << "'" << std::endl;
    }
}

void Audio::SetVolume(std::string filename, float volume)
{
    if (filename == "all")
    {
        for (std::map<std::string, sf::SoundBuffer>::iterator itr = soundBuffers.begin(); itr != soundBuffers.end(); ++itr)
            sf::Sound((*itr).second).setVolume(volume);
    }
    else
    {
        if (sf::Sound* playingSnd = GetPlayingSound(filename))
            playingSnd->setVolume(volume);
        else
            std::cout << "Audio::SetVolume: Could not find audio file '" << filename << "'" << std::endl;
    }
}

float Audio::GetVolume(std::string filename)
{
    if (sf::Sound* playingSnd = GetPlayingSound(filename))
        return playingSnd->getVolume();
    else
        std::cout << "Audio::GetVolume: Could not find audio file '" << filename << "'" << std::endl;

    return 0.0f;
}

void Audio::SetLoop(std::string filename, bool val)
{
    if (filename == "all")
    {
        for (std::map<std::string, sf::SoundBuffer>::iterator itr = soundBuffers.begin(); itr != soundBuffers.end(); ++itr)
            sf::Sound((*itr).second).setLoop(val);
    }
    else
    {
        if (sf::Sound* playingSnd = GetPlayingSound(filename))
            playingSnd->setLoop(val);
        else
            std::cout << "Audio::SetLoop: Could not find audio file '" << filename << "'" << std::endl;
    }
}

bool Audio::IsLooping(std::string filename)
{
    if (sf::Sound* playingSnd = GetPlayingSound(filename))
        return playingSnd->getLoop();
    else
        std::cout << "Audio::IsLooping: Could not find audio file '" << filename << "'" << std::endl;

    return false;
}

sf::SoundSource::Status Audio::GetStatus(std::string filename)
{
    if (sf::Sound* playingSnd = GetPlayingSound(filename))
        return playingSnd->getStatus();
    else
        std::cout << "Audio::GetStatus: Could not find audio file '" << filename << "'" << std::endl;

    return sf::SoundSource::Stopped;
}

sf::Sound* Audio::GetPlayingSound(std::string filename)
{
    std::map<std::string, sf::SoundBuffer>::iterator itr = soundBuffers.find(filename);

    if (itr != soundBuffers.end())
        return &sf::Sound((*itr).second);

    return NULL;
}

Loading the audio (done using the Dirent library to load all files from a given directory)
void Game::LoadAllAudio()
{
    DIR* dir;
    struct dirent* ent;
    std::stringstream ss;
    audio = new Audio(this);

    if ((dir = opendir("Audio")) != NULL)
    {
        while ((ent = readdir(dir)) != NULL)
        {
            if (ent->d_name[0] != '.') //! These seem to be the only hidden invisible files in there and the dirent library doesn't offer detection for it, so this will work. :)
            {
                ss << "Audio/" << ent->d_name;
                audio->Load(ss.str().c_str());
                ss.str(std::string());
            }
        }

        closedir(dir);
    }
}

Playing the audio (example)
Menu::Menu(Game* _game)
{
    game = _game;
    selectedOption = 1;
    currentMenu = MENU_MAIN;
    newMenu = MENU_NONE;
    movingCurrMenuOut = false;
    movingNewMenuIn = false;
    game->GetAudio()->Play("Audio/menu_music.wav", true);
}

Hope that is enough!

Thanks for reading,

Jasper
« Last Edit: June 25, 2013, 03:28:52 pm by Discover- »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Sorry to say that, but your new design is totally wrong :P

You're always constructing/using/returning temporary sf::Sound objects, how do you expect anything to work permanently? As soon as a sf::Sound is destroyed, everything that you've done on it is lost. All your functions are useless.

You must store both the sound buffers and the sounds that you create.
Laurent Gomila - SFML developer

Discover-

  • Newbie
  • *
  • Posts: 8
    • View Profile
Sorry to say that, but your new design is totally wrong :P

You're always constructing/using/returning temporary sf::Sound objects, how do you expect anything to work permanently? As soon as a sf::Sound is destroyed, everything that you've done on it is lost. All your functions are useless.

You must store both the sound buffers and the sounds that you create.

No need to be sorry, hehe.

I implemented your idea with a small twist (sf::SoundBuffer becoming sf::Sound in the std::map because there is no reason to store both, right?). Sadly, it's still not working.. (I get the same debug error, too)

#include "audio.h"
#include "game.h"
#include <SFML/Audio.hpp>

Audio::Audio(Game* _game)
{
    game = _game;
}

Audio::~Audio()
{

}

bool Audio::Load(std::string filename)
{
    sf::SoundBuffer buffer;

    if (buffer.loadFromFile(filename))
    {
        sounds[filename] = sf::Sound(buffer);
        return true;
    }
    else
        std::cout << "Audio::Load: Could not find audio file '" << filename << "'" << std::endl;

    return false;
}

void Audio::Play(std::string filename, bool loop /* = false */)
{
    std::map<std::string, sf::Sound>::iterator itr = sounds.find(filename);

    if (itr != sounds.end())
    {
        (*itr).second.play();

        if (loop)
            (*itr).second.setLoop(true);

        if (game->IsMusicMuted())
            (*itr).second.setVolume(0.0f);
    }
    else
        std::cout << "Audio::Play: Could not find audio file '" << filename << "'" << std::endl;
}

void Audio::Stop(std::string filename)
{
    if (filename == "all")
    {
        for (std::map<std::string, sf::Sound>::iterator itr = sounds.begin(); itr != sounds.end(); ++itr)
            (*itr).second.stop();
    }
    else
    {
        if (sf::Sound* playingSnd = GetPlayingSound(filename))
            playingSnd->stop();
        else
            std::cout << "Audio::Stop: Could not find audio file '" << filename << "'" << std::endl;
    }
}

void Audio::SetVolume(std::string filename, float volume)
{
    if (filename == "all")
    {
        for (std::map<std::string, sf::Sound>::iterator itr = sounds.begin(); itr != sounds.end(); ++itr)
            (*itr).second.setVolume(volume);
    }
    else
    {
        if (sf::Sound* playingSnd = GetPlayingSound(filename))
            playingSnd->setVolume(volume);
        else
            std::cout << "Audio::SetVolume: Could not find audio file '" << filename << "'" << std::endl;
    }
}

float Audio::GetVolume(std::string filename)
{
    if (sf::Sound* playingSnd = GetPlayingSound(filename))
        return playingSnd->getVolume();
    else
        std::cout << "Audio::GetVolume: Could not find audio file '" << filename << "'" << std::endl;

    return 0.0f;
}

void Audio::SetLoop(std::string filename, bool val)
{
    if (filename == "all")
    {
        for (std::map<std::string, sf::Sound>::iterator itr = sounds.begin(); itr != sounds.end(); ++itr)
            (*itr).second.setLoop(val);
    }
    else
    {
        if (sf::Sound* playingSnd = GetPlayingSound(filename))
            playingSnd->setLoop(val);
        else
            std::cout << "Audio::SetLoop: Could not find audio file '" << filename << "'" << std::endl;
    }
}

bool Audio::IsLooping(std::string filename)
{
    if (sf::Sound* playingSnd = GetPlayingSound(filename))
        return playingSnd->getLoop();
    else
        std::cout << "Audio::IsLooping: Could not find audio file '" << filename << "'" << std::endl;

    return false;
}

sf::SoundSource::Status Audio::GetStatus(std::string filename)
{
    if (sf::Sound* playingSnd = GetPlayingSound(filename))
        return playingSnd->getStatus();
    else
        std::cout << "Audio::GetStatus: Could not find audio file '" << filename << "'" << std::endl;

    return sf::SoundSource::Stopped;
}

sf::Sound* Audio::GetPlayingSound(std::string filename)
{
    std::map<std::string, sf::Sound>::iterator itr = sounds.find(filename);

    if (itr != sounds.end())
        return &(*itr).second;

    return NULL;
}
 

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Quote
there is no reason to store both, right?

Quote from: Laurent
You must store both the sound buffers and the sounds that you create.

Read the tutorial carefully, this is clearly explained.
Laurent Gomila - SFML developer

Discover-

  • Newbie
  • *
  • Posts: 8
    • View Profile
Quote
there is no reason to store both, right?

Quote from: Laurent
You must store both the sound buffers and the sounds that you create.

Read the tutorial carefully, this is clearly explained.

I'm sorry but I'm not seeing it. I assume you're pointing at this part of the tutorial?



If that is the part then I don't understand where I'm going wrong.

And what do you think of the previous design of the Sound class I implemented - was that bad, too?

Thanks for all the help, I appreciate it a lot!

Greetings,

Jasper
« Last Edit: June 25, 2013, 05:41:31 pm by Discover- »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Don't you feel like your Audio::Load function is similar to the loadSound function of the tutorial? Don't you make exactly the same mistake?

Quote
And what do you think of the previous design of the Sound class I implemented - was that bad, too?
Where can I see it?
Laurent Gomila - SFML developer

Discover-

  • Newbie
  • *
  • Posts: 8
    • View Profile
Don't you feel like your Audio::Load function is similar to the loadSound function of the tutorial? Don't you make exactly the same mistake?
Now that you're saying... Oops.  ;D
So you're suggesting to save the sf::Sound and sf::SoundBuffer along with the filename (std::string) and then do.. what exactly on Audio::Play?

Quote
And what do you think of the previous design of the Sound class I implemented - was that bad, too?
Where can I see it?
https://github.com/Discover-/Platformer-SFML/commit/a6422d51e9ad6fc4b05f85b5ef6689893f6a1ef9


Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Quote
So you're suggesting to save the sf::Sound and sf::SoundBuffer along with the filename (std::string) and then do.. what exactly on Audio::Play?
You should store one sound buffer per audio file, and then as many sounds as you need to play. You may play several sounds that use the same sound buffer at the same time (gun shot, foot step, ...), so it's not a good idea to link the sf::Sound to the sf::SoundBuffer/filename. That's the reason why SFML uses this design with two separate classes.

So you should redesign your whole Audio class, your current design cannot handle playing multiple instances of the same sound at the same time.

Quote
https://github.com/Discover-/Platformer-SFML/commit/a6422d51e9ad6fc4b05f85b5ef6689893f6a1ef9
Incorrect, but closer to the solution than your newer designs ;)
Laurent Gomila - SFML developer

Discover-

  • Newbie
  • *
  • Posts: 8
    • View Profile
Quote
So you're suggesting to save the sf::Sound and sf::SoundBuffer along with the filename (std::string) and then do.. what exactly on Audio::Play?
You should store one sound buffer per audio file, and then as many sounds as you need to play. You may play several sounds that use the same sound buffer at the same time (gun shot, foot step, ...), so it's not a good idea to link the sf::Sound to the sf::SoundBuffer/filename. That's the reason why SFML uses this design with two separate classes.

So you should redesign your whole Audio class, your current design cannot handle playing multiple instances of the same sound at the same time.

I'm not getting the part I bolded in your text. How am I supposed to store several sf::Sound instances and link them all to a single sf::SoundBuffer and std::string? Are we talking something like this:
std::map<std::string, std::pair<sf::SoundBuffer, std::list<sf::Sound> > > sounds;

I'm sorry for the many questions, I'm just having a really hard time understanding the audio system (as you can tell by now).

Also, when that part (thus the way you're saying it should work) is implemented, wouldn't it be better - in terms of design - to make the Audio class singleton?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
What do you think of

std::map<std::string, sf::SoundBuffer> buffers;
std::list<sf::Sound> activeSounds;

Do you use sfml-graphics? The sf::Sprite and sf::Texture classes?

Quote
wouldn't it be better - in terms of design - to make the Audio class singleton?
Singletons are never a "better" design choice. You can read many things about them on the internet.
Laurent Gomila - SFML developer