Out of memory error (Sound problem?)

I think its playing sound that creates the problem, here is the error:

  at com.jsyn.data.FloatSample.allocate (Unknown Source)
  at com.jsyn.data.FloatSample.<init> (Unknown Source)
  at com.jsyn.data.FloatSample.<init> (Unknown Source)
  at com.jsyn.util.soundfile.AudioFileParser.makeSample (Unknown Source)
  at com.jsyn.util.soundfile.WAVEFileParser.finish (Unknown Source)
  at com.jsyn.util.soundfile.AudioFileParser.load (Unknown Source)
  at com.jsyn.util.soundfile.CustomSampleLoader.loadFloatSample (Unknown Source)
  at com.jsyn.util.SampleLoader.loadFloatSample (Unknown Source)
  at processing.sound.SoundFile.<init> (Unknown Source)
  at com.example.MyApp.setup (Unknown Source)
  at processing.core.PApplet.handleDraw (PApplet.java:1838)
  at processing.core.PSurfaceNone.callDraw (PSurfaceNone.java:476)
  at processing.core.PSurfaceNone$AnimationThread.run (PSurfaceNone.java:516)

I have checked that I only load the sounds in void setup and not void loop. It works on most devices but some devices crash when they open the app.
The program runs around 1000 lines of code so I’ll try to only include the sound related lines of code. If you need more of the code, I will provide additional code.

import processing.sound.*;

SoundFile point;
SoundFile backgroundMusic;
SoundFile engine;

void setup(){
  point = new SoundFile(this, "coin.wav");
  backgroundMusic = new SoundFile(this, "Stardrive.wav");
  engine = new SoundFile(this, "rocketEngine.wav");

  backgroundMusic.amp(0.5);
  backgroundMusic.loop();
}

void loop(){
  if(thing happens){ //If an X coordinate is smaller than 0
    point.play();
  }
}

if(keyPressed){ //If w, a, s or d is pressed
  moving = 1;
}
  if (moving == 1){
    if (engine.isPlaying() == false) {
      if (soundIconOn == 1){
        engine.play();
      }
    }

  if(button is pressed){ //Mouse pos is over a button and mouse is pressed
          if(musicIconOn == 0){
        backgroundMusic.play();

          if(backgroundMusic.isPlaying() == false){
            backgroundMusic.loop();
          }

        musicIconOn = 1;
        
      } else if (musicIconOn == 1){
        backgroundMusic.pause();
        musicIconOn = 0;
      }
  }
}

void stop() {
  backgroundMusic.pause();
}

void resume(){
  backgroundMusic.play();
}

@Banansplitt ===

  • looking at the error log it seems that you are right (problem with sounds loading)

  • but without knowing the size of these sounds it s difficult to test and help (better could be that you put somewhere these sounds for downloading them)

  • not all devices are crashing: which phones are crashing (OS,…)

  • anyway if the error is related to the sounds size you can try to load the sounds using an AsyncTask in on create()

1 Like

The files are 47MB, 409KB and 15KB. So it would seem like its the 47MB file that’s crashing it? It crashes on android 6.0.
Maybe some devices aren’t powerful enough to run it? I used (almost) the same code to run the app on a Raspberry Pi (Linux) and it crashed there too.

Is this what you mean by AsyncTask? and if it is, it looks like you use it to download files when you open the app for the first time. Is that right?

@Bananasplitt ===

ok; in order to be sure try to put some little sound instead of the 47MB one: if it does not crah anymore you know who is the culprit! -As for the other point, yes, that is what i mean by AsyncTask and you can try to use it, though now, knowing that it s a really big file i am no sure that it will fit (because AsyncTask is supposed to run only some seconds, let us say 5 at max). If it does not work because of this limit there are other solutions, but begin with it.

1 Like

@Bananasplitt I’m the author of the Sound library, I think the problem isn’t necessarily with loading the file but simply that the RAM of some of your devices isn’t big enough to store the large audio sample in memory (or at least the Android system appears to refuse to allocate the amount of memory required). Since the sound library only supports playing sounds stored in RAM, the only fix I can think of right now is to reduce the size of the large audio sample by reducing the sample rate of the WAV file, if that is an option for your application…

I’d be very interested to know under what circumstances exactly the RAM allocation fails, like which Raspberry and phone models were you using?

I’m glad people are using the library on Android, if there’s any other issues you’ve come across please let us know!

1 Like

Thanks for letting me know. It is a Huawei P8 and a Raspberry Pi 3 B+. I have noticed that the app takes quite a bit of ram to run so that makes sense

You could try setting a large heap size in your manifest. This would double the allocated RAM for your app.

1 Like

@shedMusic === that could be a good solution, though Android is strongly against large heap size which can generate many problems for the other apps… I think also that it is interesting in the case described by @Banansplitt that you add some method to verify that the Manifest tag about heap was really used (because many phones ignore it). Code (android but easy to adapt) for doing that:

Context ctx = getApplicationContext();


(ActivityManager)am =  ctx.getSystemService(Context.ACTIVITY_SERVICE);
ctx.getSystemService(Context.ACTIVITY_SERVICE);
int memoirebase=am.getMemoryClass();
int grossememoire= am.getLargeMemoryClass();
println(........

@kevinstadler Hi, I’m having the same problem with the Processing Sound library on Android: A 51MB .wav audio file crashes my app because it runs out of RAM (On a Motorola Moto G4 Plus). What I don’t understand is, the phone has 4GB of RAM, so surely it should have plenty? Obviously Android will use some of that, but there must be at least 1GB or so left right?
In any case, do you think there’s any possible solution? I could use mp3 (Reduces it to 15MB), but it seems to take absolutely ages to load it… Also, when I’m done with a sound, how can I clear it from RAM?
Thanks!

@Hubbit200 first of all conversion to MP3 doesn’t actually reduce the memory usage, all audio samples are ultimately stored uncompressed in RAM, so as you’ve noticed all it does is increase the time to load the file.

Regarding clearing sounds from RAM, like in any Java program this is done through automatic garbage collection, so in theory all you need to do is make sure that there are no more references to the loaded audio file in your program, i.e. something like:

file = new SoundFile(this, "sample.mp3");
file.play();
...
file.stop();

file = null;

(I have a hunch that any loaded files might remain in memory anyway because of how the Sound library caches them, but if more people are concerned about being able to clear old sound files from RAM we could definitely add an argument/method for doing so!)

Ok, thanks @kevinstadler ! If you do get a chance, an argument/method to clear them from RAM would be nice, on PC it doesn’t matter as much, but lots of phones have very little memory!

I have had trouble with the gc clearing my old sound files I set to null; good to hear it seems to be an issue with the sound library and not my code.
Is a new argument/method available/soon to be available and if not is there a way I can jimmy rig it to open the ram? Currently working on a relatively large program which needs to be able to open and close pretty much an indefinite number of sound files (but only a few at a time).

@yodan I’ve just uploaded a test build of the next sound library version which includes two ways to disable caching, could you download sound.zip from here, extract it in your Processing/libraries/ folder and let me know if it fixes the garbage collection issue for you? https://github.com/processing/processing-sound/releases/tag/v2.3.0-test
Sounds like a cool project by the way, please share it with us when it’s done!

3 Likes

@kevinstadler
Seems to work just as advertised thanks!
Here is the memory monitor graph, where before it would just increase pretty steadily to the memory limit.


Below is the code I used to test it.

import processing.sound.*;

SoundFile test;
int track = 1;
float endTime = millis();
String musicName = "";
boolean clicked = false;

void setup() {
}

void draw() {
  if (clicked) {
    if (millis() > endTime) {
      if (test != null) {
        test.stop();
        test.removeFromCache();
        test = null;
      }
      if (new File(sketchPath("../background/thompson" + track + ".wav")).exists()) {
        test = new SoundFile(this, sketchPath("../background/thompson" + track + ".wav"));
      } else {
        track = 1;
        test = new SoundFile(this, sketchPath("../background/thompson" + track + ".wav"));
      }
      endTime = millis() + 3000;
      test.play();
      println("new song; track " + track);
      track++;
    }
  }
}

void mousePressed() {
  clicked = true;
}
2 Likes

thanks for your report,
could you please repair the code posting?
use the </> edit button ``` paste code here ```
or add the 2 lines with ``` manually