SFML community forums

Help => Audio => Topic started by: MaximumTrainer on October 16, 2014, 06:22:52 pm

Title: [SOLVED] Qt Resources - Loading a sound from a ressource
Post by: MaximumTrainer on October 16, 2014, 06:22:52 pm
Hi guys,

First thanks SFML, I just tried it for the first time and it works so easily!

In my Qt project, all my sounds are mapped to resources,
I would like to play the sound from the resource instead of from the hard drive.

I can play the sound fine when I load from the disk, however, is there a way to use the ressource syntax to load a sound?

Thanks in advance!

    if (!buffer.loadFromFile(":/sound/resume")) {
        qDebug() << "cant play";
        return 0;
    }
//    if (!buffer.loadFromFile("C:\\Dropbox\\PowerVelo2\\sound\\CadenceTooHigh.wav")) {
//        qDebug() << "cant play";
//        return 0;
//    }
    sf::Sound sound(buffer);
    sound.play();

I suspect I may have to use "loadFromMemory" as the file should be in memory (it is inside the .exe)
Title: Re: Qt Resources - Loading a sound from a ressource
Post by: MaximumTrainer on October 16, 2014, 06:35:01 pm
Got it! not sure it's the cleanest way though..


    QResource mySound(":/sound/resume");


    if (!buffer.loadFromMemory(mySound.data(), mySound.size())) {
        qDebug() << "cant play";
        return 0;
    }
    sf::Sound sound(buffer);
    sound.play();
Title: Re: [SOLVED] Qt Resources - Loading a sound from a ressource
Post by: Laurent on October 16, 2014, 08:04:31 pm
Quote
not sure it's the cleanest way though..
I think it is ;)
Title: Re: [SOLVED] Qt Resources - Loading a sound from a ressource
Post by: MaximumTrainer on October 17, 2014, 07:58:07 pm
I think i'm not freeing the ressource properly after using SFML
I get this error : The program has unexpectedly finished.
If I comment the use of my SoundPlayer, no error -_-

int main(int argc, char *argv[]) {

    SoundPlayer *soundPlayer = new SoundPlayer();
    app.setProperty("SoundPlayer", QVariant::fromValue<SoundPlayer*>(soundPlayer));
    //do stuff with the player

       /// App terminated, Trying to force resource delete so I don't get the error..
    soundPlayer->~SoundPlayer();
}

//------------------------------------- soundPlayer.cpp
#include "soundplayer.h"
#include <QDebug>


SoundPlayer::~SoundPlayer() {


    qDebug() << "DESTRUCTOR SOUNDPLAYER";
    freeMemory();

}

void SoundPlayer::freeMemory() {

    qDebug() << "freeing memory";

    soundAchievement.resetBuffer();
    soundAchievement.~Sound();

    //    bufferSoundAchievement.~SoundBuffer();

    qDebug() << "end freeing memory";
}

SoundPlayer::SoundPlayer(QObject *parent) : QObject(parent)
{

    QResource qrcAchievement(":/sound/fireTorch");
    bufferSoundAchievement.loadFromMemory(qrcAchievement.data(), qrcAchievement.size());
    soundAchievement =  sf::Sound(bufferSoundAchievement);
}


void SoundPlayer::setVolume(double volume) {

    qDebug() << "setVolume soundPlayer";
    soundAchievement.setVolume(volume);
}

void SoundPlayer::playSoundAchievement() {
    soundAchievement.play();
}
...

 
Title: Re: Qt Resources - Loading a sound from a ressource (how to properly free memory)
Post by: MaximumTrainer on October 17, 2014, 10:02:18 pm
After further debugging, I found that as soon as I create a class with a "sf::SoundBuffer" private member, I get this error.

e.g:
class SoundPlayer
{

public:
    explicit SoundPlayer();

private :
    sf::SoundBuffer bufferSoundAchievement;

};
Q_DECLARE_METATYPE(SoundPlayer*)

#endif // SOUNDPLAYER_H

As soon as I create a pointer to this class, my program crashes, if I comment the sf::SoundBuffer, it doesn't crash. still investigating
Title: Re: Qt Resources - Loading a sound from a ressource (how to properly free memory)
Post by: Laurent on October 17, 2014, 10:08:21 pm
Please provide a complete and minimal example that reproduces the problem.

And:
soundAchievement.~Sound();
Never ever call a destructor yourself. The compiler does it automatically when the object is destroyed.
Title: Re: Qt Resources - Loading a sound from a ressource (how to properly free memory)
Post by: MaximumTrainer on October 17, 2014, 10:24:04 pm
Minimal example :


int main(int argc, char *argv[]) {
 SoundPlayer *soundPlayer = new SoundPlayer();
}

// SoundPlayer.h
#ifndef SOUNDPLAYER_H
#define SOUNDPLAYER_H

#include <QResource>
#include <QtCore>

#include "SFML/Audio.hpp"
#include <iomanip>
#include <iostream>


class SoundPlayer
{

public:
    SoundPlayer();
private :
    sf::SoundBuffer bufferSoundAchievement;
};
Q_DECLARE_METATYPE(SoundPlayer*)

#endif // SOUNDPLAYER_H


// SoundPlayer.cpp
SoundPlayer::SoundPlayer()
{}


log :
Starting C:\Dropbox\build-PowerVelo2-Desktop_Qt_5_2_1_MSVC2012_32bit-Release\release\MaximumTrainer.exe...
The program has unexpectedly finished.
C:\Dropbox\build-PowerVelo2-Desktop_Qt_5_2_1_MSVC2012_32bit-Release\release\MaximumTrainer.exe crashed

Note :
I can use the soundPlayer just fine to play sounds, setVolume, etc.  The crash happen only when the application is closing.
Merci beaucoup!

In case you need, my Qt project file:
QT       += core gui widgets webkit webkitwidgets
QT       -= sql

TARGET = MaximumTrainer
TEMPLATE = app


CONFIG += qwt qt thread
RC_FILE = myapp.rc

DEFINES += NOMINMAX

#SFML
INCLUDEPATH += C:/Dropbox/SFML-master/include
LIBS +=  C:/Dropbox/SFML-2.1-win-vc11-32bits/lib/sfml-audio.lib


debug :
https://www.dropbox.com/s/7xjnjgk7hqvt465/debugSound.png?dl=0 (https://www.dropbox.com/s/7xjnjgk7hqvt465/debugSound.png?dl=0)
Is it possible that my app close and the buffer is still open?
Title: Re: Qt Resources - Loading a sound from a ressource (how to properly free memory)
Post by: zsbzsb on October 18, 2014, 12:12:47 am
Do you think dynamically allocated memory magically frees itself?
Title: Re: Qt Resources - Loading a sound from a ressource (how to properly free memory)
Post by: MaximumTrainer on October 18, 2014, 12:17:27 am
Do you think dynamically allocated memory magically frees itself?

Well I'm not using "new" on the buffer and it is a member of the "SoundPlayer" object, so the buffer should get deleted when my SoundPlayer object is deleted.

Not sure what happen when the program is over, I supposed all the pointer and data used is deleted by default, could be wrong, worked too much with Java -_-
Title: Re: Qt Resources - Loading a sound from a ressource (how to properly free memory)
Post by: zsbzsb on October 18, 2014, 02:14:06 am
so the buffer should get deleted when my SoundPlayer object is deleted.

Again, I repeat my question - do you think dynamically allocated memory magically frees itself?

Quote
I supposed all the pointer and data used is deleted by default

Go learn C++ before using SFML, just because you may know something in Java doesn't give you any credit in C++. Sorry if this sounds rude, but its just the way things are. Assuming that just because Java objects created with the 'new' keyword will be automatically deleted is a very bad way to go about programming (its because Java includes a built in GC). As said in many threads before, go RTFM - meaning a good C++ book.
Title: Re: Qt Resources - Loading a sound from a ressource (how to properly free memory)
Post by: Laurent on October 18, 2014, 09:36:07 am
You must link to debug libraries in debug mode. Mixing debug and release with Visual C++ leads to undefined behaviours.
Title: Re: Qt Resources - Loading a sound from a ressource (how to properly free memory)
Post by: MaximumTrainer on October 18, 2014, 04:44:08 pm
Thanks for your kind help Laurent.

Yes I am new with C++ (1 year). I didn't delete the SoundPlayer because it is created in the main and lives for as long as my program lives.  I know C++ doesn't have a GC like Java.

Anyway, I don't think the problem is memory. I created a small test program below where everything is created on the stack.

int main() {

    sf::SoundBuffer buffer;
    if (!buffer.loadFromFile("C:/Dropbox/PowerVelo2/sound/resume.wav"))
        return 1;

    // Display sound informations
    std::cout << "canary.wav :" << std::endl;
    std::cout << " " << buffer.getSampleRate()           << " samples / sec" << std::endl;
    std::cout << " " << buffer.getChannelCount()         << " channels"      << std::endl;

    // Create a sound instance and play it
    sf::Sound sound(buffer);
    sound.play();

    // Loop while the sound is playing
    while (sound.getStatus() == sf::Sound::Playing)
    {
        QThread::msleep(200);
        qDebug() << "looping...waiting for sound to be over";
    }

    qDebug() << "done";

    return EXIT_SUCCESS;
}
 

log :
Starting C:\Dropbox\build-PowerVelo2-Desktop_Qt_5_2_1_MSVC2012_32bit-Release\release\MaximumTrainer.exe...
canary.wav :
 44100 samples / sec
 2 channels
looping...waiting for sound to be over
looping...waiting for sound to be over
looping...waiting for sound to be over
looping...waiting for sound to be over
looping...waiting for sound to be over
done
The program has unexpectedly finished.
C:\Dropbox\build-PowerVelo2-Desktop_Qt_5_2_1_MSVC2012_32bit-Release\release\MaximumTrainer.exe crashed
Title: Re: Qt Resources - Loading a sound from a ressource (how to properly free memory)
Post by: Laurent on October 18, 2014, 06:10:32 pm
No, the problem is not caused by the memory leak, but this is something that you definitely have to consider.

Can you show your new project file now that you've fixed the debug libraries error?
Title: Re: Qt Resources - Loading a sound from a ressource (how to properly free memory)
Post by: MaximumTrainer on October 20, 2014, 04:34:31 pm
Yes will definitely delete the object before the main program closes, I heard it's bad practice to let the OS do the job :)

Finally I was able to run the project in debug mode

Here is the debug message I get :
https://www.dropbox.com/s/5l62b7ol0hod81u/debugModeSFML.png?dl=0 (https://www.dropbox.com/s/5l62b7ol0hod81u/debugModeSFML.png?dl=0)
I put a breakpoint and see that the error is triggered right after my main is over (after the return)

Here is the minimal example :
#Pro File
TARGET = testSound

SOURCES += main.cpp

#SFML
INCLUDEPATH += C:/Dropbox/SFML-2.1-windows-vc11-32bits/include
LIBS +=  C:/Dropbox/SFML-2.1-windows-vc11-32bits/lib/sfml-audio-d.lib


main.cpp
#include <QDebug>
#include <QThread>

#include <SFML/Audio.hpp>


int main() {

    qDebug() << "start main";

    sf::SoundBuffer buffer;
    if (!buffer.loadFromFile("C:/Dropbox/PowerVelo2/sound/resume.wav")) {
        qDebug() << "error open file";
        return 1;
    }
    else {
        qDebug() << "good";
    }


    // Create a sound instance and play it
    sf::Sound sound(buffer);
    sound.play();

    // Loop while the sound is playing
    while (sound.getStatus() == sf::Sound::Playing)
    {
        QThread::msleep(200);
        qDebug() << "looping...waiting for sound to be over" << sound.getStatus();
    }

    qDebug() << "done";

    return EXIT_SUCCESS;
}

Title: Re: Qt Resources - Loading a sound from a ressource (how to properly free memory)
Post by: Laurent on October 20, 2014, 04:46:12 pm
Might be this bug: https://github.com/SFML/SFML/issues/30

A fix is pending, you'll find the corresponding branch at the end of the discussion.
Title: Re: Qt Resources - Loading a sound from a ressource (how to properly free memory)
Post by: MaximumTrainer on October 20, 2014, 05:06:14 pm
Might be this bug: https://github.com/SFML/SFML/issues/30

A fix is pending, you'll find the corresponding branch at the end of the discussion.

Thanks for the link Laurent, I read the discussion and will follow the progress.

In the meantime, I was able to get rid of the error by replacing the openal32.dll provided in 2.1 by the one found at :
http://kcat.strangesoft.net/openal.html#download
I'll have to make sure I can use this dll in production but I think it is legit.

SFML rocks! A+
Title: Re: Qt Resources - Loading a sound from a ressource (how to properly free memory)
Post by: Laurent on October 20, 2014, 06:39:36 pm
Yes, you can use it in production. SFML uses an older version of OpenAL-Soft, but the API never changes so you can replace it with this latest version. No problem.
Title: Re: Qt Resources - Loading a sound from a ressource (how to properly free memory)
Post by: MaximumTrainer on October 20, 2014, 06:47:24 pm
Great to know!
Just curious, if the new OpenAL-Soft seems to fix this problem, why not include it in SFML? may be over my head here..  good luck ;)
Title: Re: Qt Resources - Loading a sound from a ressource (how to properly free memory)
Post by: Laurent on October 20, 2014, 08:32:56 pm
It doesn't fix it, just seems to play more nicely with the ugly internals of sfml-audio in certain situations. It's SFML that needs to be fixed, not OpenAL ;)
Title: Re: Qt Resources - Loading a sound from a ressource (how to properly free memory)
Post by: MaximumTrainer on October 20, 2014, 08:45:56 pm
Got it! The proposition to had control of the AudioDevice to the user seems good. I'll wait for 2.2, during that time I'm using the other dll as a temporary solution.  Great project again, i'm gonna check to help with my limited c++ experience ;)