0

I wrote a program in Processing that uses the external library "Minim" for audio playback. I am new to this library so my understanding of the library is fairly lackluster. My program can run for days with no problem, but eventually I will get the following error:

Emblems_Sounds.pde:42:0:42:0: OutOfMemoryError: Java heap space OutOfMemoryError: You may need to increase the memory settings in preferences. An OutOfMemoryError means that your code is either using up too much memory because of a bug or that your sketch may need more memory to run.

I am referencing about 20 audio files in my code, ranging from 500 KB to 5MB with most around 1MB. My max available memory is set to 2000 MB in the Processing IDE, which seems more than enough. Therefore, my hypotheses is that I have a bug, and I believe that bug is that I am unintentionally loading these audio files over and over to new memory locations and not reallocating their memory space. I am having a hard time figuring out how I might be doing so from looking at my code. Again, I'm not well versed with Minim so I do not understand the subtleties of this library and how I might be doing something resulting in a memory leak. I'm also fairly new to Processing/Java. If anyone who is more versed in Processing/Java/Minim can take a look at my code and point me to some lines that raise some red flags, I would appreciate it.

Some pertaining information about my code: This is only one file of a 3 file system. This file only controls the audio application for the program. I have ten touch sensors and a list of unique 3 combination codes that trigger audio and lighting events. These events map audio files to different Dante devices, which the PC recognized as sound cards. When an event happens, I route the audio to the correct Dante device and then play the audio. Also, at the beginning of my code, I have multiple declarations of type AudioOutput and AudioPlayer which are not used. These were loaded in mistake (I forgot to take them out) but I decided to keep the code true to it's form when the bug occurred.

Minim minim1 = new Minim(this);
String danteZone = "";
AudioOutput output1;
AudioOutput output2;
AudioOutput output3;
AudioOutput output4;
AudioOutput output5;
AudioOutput output6;

AudioPlayer player1; 
AudioPlayer player2;
AudioPlayer player3; 
AudioPlayer player4;
AudioPlayer player5; 
AudioPlayer player6;

Mixer.Info[] mixerInfo;

//Variable to play audio 
boolean played = false; 

//Audio variables 
int audioZones = 6; //Will be 6 

void playEffect(String filename, String danteZone){
  Mixer mixer1 = AudioSystem.getMixer(mixerInfo[0]);
  mixerInfo = AudioSystem.getMixerInfo();
  for (int i = 0; i < mixerInfo.length; i++){
    if (mixerInfo[i].getName().equals(danteZone)){
       mixer1 = AudioSystem.getMixer(mixerInfo[i]);
    }
  }
  
  minim1.setOutputMixer(mixer1);
    
  if (output1 != null){
    output1.close();
  }
  
  output1 = minim1.getLineOut(Minim.STEREO);

  player1 = minim1.loadFile(filename);
 
   if (output1 != null){
     player1.play();
  } 
}

void audioEvent(int code){
  
  String wav = ".wav";
  String fileName = str(code);
  fileName = fileName + wav;
  println(fileName);
  //Using repetive if statements for code to be clearer
   
    if (zoneIdentifier[0] == true){
      //Zone 12 
      danteZone = zone12;   
      playEffect(fileName, danteZone);
    }
    
    if (zoneIdentifier[1] == true){
      //Zone 13 
      danteZone = zone13;     
      playEffect(fileName, danteZone);
    }
    
    if (zoneIdentifier[2] == true){
      //Zone 14  
      danteZone = zone14;
      playEffect(fileName, danteZone);
    }
    
    if (zoneIdentifier[3] == true){
      //Zone 15  
      danteZone = zone15;     
      playEffect(fileName, danteZone);
    }
    
    if (zoneIdentifier[4] == true){
      //Zone 16 
      danteZone = zone16;    
      playEffect(fileName, danteZone);      
    }
    
    if (zoneIdentifier[5] == true){
      //Zone 17
      danteZone = zone17;
      playEffect(fileName, danteZone);
    }   
  }


void loopAmbience(int i){
  String filename = " ";
  String danteCard = " ";
  //println(mixerInfo[i].getName());
  danteCard = mixerInfo[i].getName();
  //println(danteCard);
  println();
  Mixer mixer1 = AudioSystem.getMixer(mixerInfo[i]);
  if (danteCard.startsWith("Zone14")){
    filename = "Zone14Ambience.wav";
  }
  else if (danteCard.startsWith("Zone17")){
    filename = "Zone17Ambience.wav";
  }
  else if (danteCard.startsWith("Zone12")){
    filename = "Zone12Ambience.wav";
  }
  else{
   return; 
  }

  minim1.setOutputMixer(mixer1);
  
  
  if (output1 != null){
    output1.close();
  }
  
  output1 = minim1.getLineOut(Minim.STEREO);

  player1 = minim1.loadFile(filename);
 
   if (output1 != null){
     player1.loop();
  } 
}
Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
  • 1
    The problem you are describing is a memory leak. You may need a tool to detect the leak. – fdermishin Dec 08 '20 at 18:08
  • Does this answer your question? [How to find a Java Memory Leak](https://stackoverflow.com/questions/40119/how-to-find-a-java-memory-leak) – fdermishin Dec 08 '20 at 18:08
  • Ideally you shouldn't care about memory leaks in Java. Otherwise I dont know about Processing. Take a look at your program and see if you are doing something terrible.. If you start your learning from detecting memory leaks you are onthe wrong Path. – gpasch Dec 08 '20 at 21:20
  • I'm not proficient with this library but just eyeballing the code makes me think that your problem is related to the `playEffect()` method. I wouldn't ventrue a fix, though, as I'm unaware of the details with this library, but there are several objects which are instantiated every time you need them which could be stored in memory once then re-used (again, only if it's not against your workflow). – laancelot Dec 09 '20 at 00:21

0 Answers0