Can't use .bmp and .wav at the same time?

Général

archonik

il y a 6 ans

I'm having this very weird issue. I'm working on a simple rhythm game for Gamebuino Meta and while the core seems to be working fine, I am having trouble with one aspect.

When you start the game, it loads the songs from the memory card. It also loads cover art for the music.

The sequence goes:

  • boot
  • load graphics from SD for song selection
  • song selected
  • unload graphics via clear();
  • load .wav from SD
  • play music
  • have fun

If I only load the graphics -- everything works fine, I can browse song cover art no problem and choose a song to play... But the music fails to load! gb.sound.play reports -1.

If I disable loading cover art and load songs via a text menu... the music loads just fine!


Here's the code I'm using to load cover art:
Image cover;

void refreshCover(int choice) {
  cover.clear();
  String paths = "music/" + songs[choice] + ".bmp";
  char pathx[50];
  strcpy(pathx, paths.c_str());
  cover.init(80, 64, pathx);
}

And here's the simple code for loading music:

cover.clear();

String audio("music/" + songs[choice] + ".wav");
    if (music == -1) music = gb.sound.play(audio.c_str());


They both work on their own. But if I use both, only the cover art loads properly and no music is loaded.

What I believe happens is that the currently loaded cover eats up all the memory and there is no left to load music.
But I use cover.clear(); before I call audio so I should retrieve that memory back, no? Am I missing something really obvious?

Kicker: if I load the artwork from a const uint8_t instead of a file on SD, it works just fine!
This only seems to be an issue when files are loaded from a SD card.

Any ideas?

Sorunome

NEW il y a 6 ans

The symptoms you are describing sound like you are running out of RAM - loading a BMP from the SD card creates an internal buffer in which the BMP image is loaded.

Same with starting to play a wav file - it creates an internal 2k buffer for playback.

Try displaying your RAM usage, maybe that can help.

archonik

NEW il y a 6 ans

That makes sense. Is there no way to release the buffer once I no longer need the images?
cover.clear(); doesn't seem to work.

Or, alternatively, is there a way to convert the images from SD card into constants as part of a loading screen? So that they can be stored in flash memory thus leaving RAM empty?

And thanks for the info on the size of the wav buffer. This will come in handy!

Sorunome

il y a 6 ans

Or, alternatively, is there a way to convert the images from SD card into constants as part of a loading screen? So that they can be stored in flash memory thus leaving RAM empty?

const stuff is in flash, so you'd need some kind of dynamic flashing for that and proper memory management for that....such a thing is way out-of-scope for the library.

Duh, sorry. I realized what the solution is myself. I just changed the scope of the cover object and now it gets properly freed.

You can also re-use images, with myImage.init() where in the init the same parameters are taken as the constructor.

archonik

NEW il y a 6 ans

Duh, sorry. I realized what the solution is myself. I just changed the scope of the cover object and now it gets properly freed.

That's what I get for overthinking simple issues!

Sorunome

NEW il y a 6 ans

archonik archonik

Or, alternatively, is there a way to convert the images from SD card into constants as part of a loading screen? So that they can be stored in flash memory thus leaving RAM empty?

const stuff is in flash, so you'd need some kind of dynamic flashing for that and proper memory management for that....such a thing is way out-of-scope for the library.

Duh, sorry. I realized what the solution is myself. I just changed the scope of the cover object and now it gets properly freed.

You can also re-use images, with myImage.init() where in the init the same parameters are taken as the constructor.

Sorunome

NEW il y a 6 ans

Looking at the rockstar assets it seems like you can improve quite a bit - there are many small assets. Why not just store them in flash? That way they will have a way smaller memory footprint and you save SD loading time.

Then, the full screen assets.....using some nice tricks you can get them to load. Let's say your BMP is full-res indexed (what it probably is), so 160x128 @ 4-bit depth, you could do something like gb.display.init("MYFILE.BMP"); and BOOM the gb.display image itself will be inited and used as the ram buffer. As that is a ram buffer you can still draw other things ontop of it. For erasing it, you'd have to call gb.display.nextFrame();, that way you could also easily do animated backgrounds or something. (The loader itself actually uses this for the screen previews). To go back to normal, you can just re-init as indexed, as you already did in some places gb.display.init(160, 128, ColorMode::index);

archonik

il y a 6 ans

Ah! Amazing idea, thank you so much for this! I think I'm very close to having it optimized properly. I'm not very familiar with CPP so I'm learning a lot as I go.

archonik

NEW il y a 6 ans

Sorunome Sorunome

Ah! Amazing idea, thank you so much for this! I think I'm very close to having it optimized properly. I'm not very familiar with CPP so I'm learning a lot as I go.