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

Author Topic: Ogg Vorbis files don't play correctly on big-endian systems  (Read 2850 times)

0 Members and 1 Guest are viewing this topic.

tgnottingham

  • Newbie
  • *
  • Posts: 4
    • View Profile
Ogg Vorbis files don't play correctly on big-endian systems
« on: October 18, 2017, 01:36:12 am »
Ogg Vorbis files sound like static when played on big-endian systems using SFML. This is because ov_read in SoundFileReaderOgg.cpp requires you to specify the endianness that you want the samples in, and it's currently always passed 0, corresponding to little-endian.

I've tested a solution that checks system endianness to pass the right argument to ov_read on both x86-64 (little-endian) and big-endian PowerPC, and it seems to fix the problem.

FWIW, I've read the discussion on endianness in https://github.com/SFML/SFML/pull/357, and I believe this is one of those rare cases where we have to check endianness, because, for whatever reason, ov_read can't be invoked to automatically use the native byte order.

Example Ogg Vorbis File
Documentation for ov_read

Example code (invoke on big-endian system with sound file name argument):

Code: [Select]
#include <SFML/Audio.hpp>
#include <SFML/System.hpp>

int main(int argc, char** argv)
{
    sf::SoundBuffer sb;
    sb.loadFromFile(argv[1]);

    sf::Sound s(sb);
    s.play();
    sf::sleep(sf::seconds(2.5));
}

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Ogg Vorbis files don't play correctly on big-endian systems
« Reply #1 on: October 18, 2017, 08:24:47 am »
Interesting, thanks for taking the time to investigate this issue. How did you check the native byte order?
Laurent Gomila - SFML developer

tgnottingham

  • Newbie
  • *
  • Posts: 4
    • View Profile
Re: Ogg Vorbis files don't play correctly on big-endian systems
« Reply #2 on: October 18, 2017, 11:23:14 pm »
Code: [Select]
bool is_big_endian()
{   
    sf::Uint16 n = 1;
    return *reinterpret_cast<char*>(&n) == 0;
}

It's not 100% portable, but I'm guessing it's portable enough for the systems SFML is likely to run on. I'm also guessing it gets mostly optimized away when you turn up optimization. But these are just guesses. Maybe someone with more expertise on endianness can chime in. Or I'll do some research.