Create pointer to unsigned char[] and pass it to sf::SoundBuffer::loadFromMemory

177 views Asked by At

In my game I have a map std::map<Sound, sf::SoundBuffer> mySounds that I use as a resource holder for sounds.

Sound is an enum that looks like this:

enum class Sound {
  SOUND_ONE,
  SOUND_TWO,
  SOUND_THREE,
  NUMBER_OF_SOUNDS
};

Now, in order to load the sounds I currently use sf::SoundBuffer::loadFromFile, and the code looks like this:

std::vector<std::string> paths;
paths.resize(static_cast<unsigned int>(Sound::NUMBER_OF_SOUNDS));
paths[static_cast<std::size_t>(Sound::SOUND_ONE)] = "sound1.ogg";
paths[static_cast<std::size_t>(Sound::SOUND_TWO)] = "sound2.ogg";
paths[static_cast<std::size_t>(Sound::SOUND_THREE)] = "sound3.ogg";

for (std::size_t i = 0; i < static_cast<std::size_t>(Sound::NUMBER_OF_SOUNDS); ++i) {
  mySounds[static_cast<Sound>(i)].loadFromFile("./data/" + paths[i]);
}

This works fine.

Now to the problem:

For my release build I want to convert all sounds to byte arrays (using a tool called bin2h) and then use sf::SoundBuffer::loadFromMemory().

The arrays would look like this:

unsigned char RES_SOUND_ONE[] = {0x4f,0x67,0x67,0x53,...};
unsigned char RES_SOUND_TWO[] = {0x52,0x88,0x29,0x47,...};
unsigned char RES_SOUND_THREE[] = {0x96,0x65,0x59,0x02,...};

If I only had a single sound, I could simply write:

mySound.loadFromMemory(RES_SOUND_ONE, sizeof(RES_SOUND_ONE));

and it would work perfectly.

I have more than one sound though, so I was thinking of having a pointer inside the for-loop (initially just a null pointer).

Then I'd set the pointer to the appropriate byte array based on which loop index I'm currently at (see switch in the code below).

Then I'd pass that pointer to the data to the loadFromMemory function.

for (std::size_t i = 0; i < static_cast<std::size_t>(Sound::NUMBER_OF_SOUNDS); ++i) {
  void *buffer = nullptr;
  switch (static_cast<Sound>(i)) {
    case Sound::SOUND_ONE:   { buffer = (unsigned char*)RES_SOUND_ONE; } break;
    case Sound::SOUND_TWO:   { buffer = (unsigned char*)RES_SOUND_TWO; } break;
    case Sound::SOUND_THREE: { buffer = (unsigned char*)RES_SOUND_THREE; } break;
  }
  mySounds[static_cast<Sound>(i)].loadFromMemory(buffer, sizeof(buffer));
}

The SFML error message is:

Failed to open sound file from memory (format not supported)

I'm doing something very wrong

I also tried various other things like memcpy and it all results in failure lol

So basically what I'm asking is: How do I create a pointer to an unsigned char array and pass it to the SFML function sf::SoundBuffer::loadFromMemory(const void *data, size_t sizeInBytes)

1

There are 1 answers

0
geipel On BEST ANSWER

The problem is likely with your call to loadFromMemory().

In particular, the value for sizeof(buffer) is likely to be a constant based on how much memory a pointer takes. (For example 8 bytes on a 64-bit platform.)

I doubt that will be large enough to contain the sound info... :)

You want to pass the size of the array. To follow your pattern:

for (size_t i = 0; i < static_cast<size_t>(Sound::NUMBER_OF_SOUNDS); ++i)
{
    unsigned char *buf = nullptr;
    size_t siz = 0;
    switch (static_cast<Sound>(i))
    {
        case Sound::SOUND_ONE:
            buf = RES_SOUND_ONE;
            siz = sizeof (RES_SOUND_ONE);
            break;
        case Sound::SOUND_TWO:
            buf = RES_SOUND_TWO;
            siz = sizeof (RES_SOUND_TWO);
            break;
        case Sound::SOUND_THREE:
            buf = RES_SOUND_THREE;
            siz = sizeof (RES_SOUND_THREE);
            break;
    }
    mySounds[static_cast<Sound>(i)].loadFromMemory(buf, siz);
}