-
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)
-
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();
-
not sure it's the cleanest way though..
I think it is ;)
-
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();
}
...
-
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
-
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.
-
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?
-
Do you think dynamically allocated memory magically frees itself?
-
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 -_-
-
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?
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.
-
You must link to debug libraries in debug mode. Mixing debug and release with Visual C++ leads to undefined behaviours.
-
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
-
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?
-
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;
}
-
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.
-
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+
-
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.
-
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 ;)
-
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 ;)
-
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 ;)