-
#include <SFML/Audio.hpp>
#include <SFML/System/FileInputStream.hpp>
#include <iostream>
#include <cstdio>
int main() {
std::cout << "Starting..." << std::endl;
sf::Music fileMusic;
if (!fileMusic.openFromFile("sample.ogg")) {
std::cerr << "Too early boom?" << std::endl;
return 3;
}
sf::Music music;
sf::FileInputStream stream;
if (!stream.open("sample.ogg")) {
std::cerr << "Too early boom?" << std::endl;
return 2;
}
if (!music.openFromStream(stream)) {
std::cerr << "BOOM!" << std::endl;
return 1;
}
std::cout << "Done" << std::endl;
return 0;
}
sample.ogg is orchestra.ogg from the examples folder.
Loading from a file works, but trying to load music from an InputStream seems to fail. Am I doing something wrong, or has this broken on master? This used to work until I updated to the latest master.
-
A big chunk of the audio module has been changed to remove libsndfile as such there might well be an issue on the current master.
Can you provide the ogg file?
-
Well the majority of the audio module has been rewritten to remove libsndfile as such there might well be an issue on the current master.
Can you provide the ogg file?
It's orchestra.ogg from the sound example in the SFML examples folder, though I can recreate it by converting to an MP3 file as well, and in the code that I found this issue in originally WAV files from loading SoundEffects from a stream also falls down.
Porting to a FLAC file via Audacity, interestingly, does seem to work. So this stands as a temporary fix for me, but obviously not ideal.
Commenting out the openFromStream logic logs:
Starting...
AL lib: (EE) UpdateDeviceParams: Failed to set 44100hz, got 48000hz instead
AL lib: (EE) GetHrtf: Incompatible format: Stereo 48000hz
Done
And the AL lib stuff still gets logged if commenting out the stream loading, so I suspect it's a red-herring and it's the stream reading logic that falls down (Graphics still load from streams correctly).
-
Sorry to double post but to add more to the current state of Audio playing:
So FLAC files can play from a stream, but they do not loop successfully. Changing the above code to setLoop(true) and call .play() results in music playing once and never looping, and the exiting of the application to hang on exit.
Hitting CTRL+C results in "AL lib: (EE) alc_cleanup: 1 device not closed" being logged.
Calling getStatus() on the music file still reports a status of sf::Sound::Playing
The above applies to both openFromStream and openFromFile music.
-
FLAC streams in master have an issue (https://github.com/SFML/SFML/pull/817).
-
FLAC streams in master have an issue (https://github.com/SFML/SFML/pull/817).
So that's an unrelated issue, good to know.
Btw I've tried the openFromStream on Ubuntu with the orchestra.ogg and I get the same error so...yeah, github issue time (https://github.com/SFML/SFML/issues/822)? :) Using streams instead of files is a fairly common usecase I reckon, since it lets you write a generic file loader that can abstract away reading from zip files and file files.
-
so...yeah, github issue time?
I don't think so... you should have waited for our answer ;)
Now everything internally uses streams, so openFromFile and the others all use the same stream-based implementation. If your stream doesn't work, I'd say check its implementation first. You can compare it to the new FileInputStream class of SFML (which works, if openFromFile works):
https://github.com/SFML/SFML/blob/master/src/SFML/System/FileInputStream.cpp
And by the way, OpenAL logs are unlikely to be related to what we changed in the management of sound files -- we didn't touch playback at all. Are you sure that you didn't get an OpenAL update recently?
-
Ah fair enough :) Sorry, still unsure on proper protocol with github issues but you're right, should of waited ^^
The InputStream in the original example was taken from http://www.sfml-dev.org/tutorials/2.2/system-stream.php, but I updated the code above to use sf::FileInputStream and re-ran it. Still goes "BOOM!", so the internal openFromStream implementation falls own on something the openFromFile does not.
This used to work perfectly and still does for images, and (known issue aside) FLAC files. I haven't touched this part of the code, updating SFML to a new build of master broke what was previously working. And this happens on both Windows and Linux for me.
-
So far I've narrowed it down to ov_test_callback (https://github.com/SFML/SFML/blob/master/src/SFML/Audio/SoundFileReaderOgg.cpp#L77) which returns OV_ENOTVORBIS (Bitstream contains no Vorbis data).
I'm not sure how one would now validate that the data from the stream is valid/invalid...
One difference I noticed is, that when calling stream.tell() within the SoundFileReaderOgg::check(InputStream& stream) function, it will report different values for sf::Music file and sf::FileInputStream.
(sf::Music)
size: 153776
tell: 0
size: 153776
tell: 4096
err: 0
(sf::FileInputStream)
size: 153776
tell: 8192
size: 153776
tell: 18432
err: -132
Modification:
bool SoundFileReaderOgg::check(InputStream& stream)
{
OggVorbis_File file;
sf::err() << "size: " << stream.getSize() << "\ntell: " << stream.tell() << "\n\n";
int check = ov_test_callbacks(&stream, &file, NULL, 0, callbacks);
sf::err() << "size: " << stream.getSize() << "\ntell: " << stream.tell() << "\nerr: " << check << "\n\n";
if (check == 0)
{
ov_clear(&file);
return true;
}
else
{
return false;
}
}
So to me it seems that ov_test_callbacks isn't reading from the start or similar...
-
It's indeed an issue in SFML.
In SoundFileFactory.cpp (https://github.com/SFML/SFML/blob/master/src/SFML/Audio/SoundFileFactory.cpp#L120):
SoundFileReader* SoundFileFactory::createReaderFromStream(InputStream& stream)
{
// Register the built-in readers/writers on first call
ensureDefaultReadersWritersRegistered();
// Test the filename in all the registered factories
for (ReaderFactoryArray::const_iterator it = s_readers.begin(); it != s_readers.end(); ++it)
{
if (it->check(stream))
return it->create();
}
// No suitable reader found
return NULL;
}
Should be:
SoundFileReader* SoundFileFactory::createReaderFromStream(InputStream& stream)
{
// Register the built-in readers/writers on first call
ensureDefaultReadersWritersRegistered();
// Test the stream for all the registered factories
for (ReaderFactoryArray::const_iterator it = s_readers.begin(); it != s_readers.end(); ++it)
{
stream.seek(0);
if (it->check(stream))
return it->create();
}
// No suitable reader found
return NULL;
}