processing / processing-sound

Audio library for Processing built with JSyn
https://processing.org/reference/libraries/sound/
GNU Lesser General Public License v2.1
149 stars 50 forks source link

Repeated use of Envelopes eventually causes java.lang.NullPointerException #29

Closed mhamilt closed 1 year ago

mhamilt commented 5 years ago

Hello,

I'm getting the following console error after intermittent intervals when using the processing.sound library. The sound cuts out, but the sketch continues to run.


Error
java.lang.NullPointerException
    at com.jsyn.ports.InputMixingBlockPart.getValues(Unknown Source)
    at com.jsyn.ports.UnitBlockPort.getValues(Unknown Source)
    at com.jsyn.unitgen.SineOscillator.generate(Unknown Source)
    at com.jsyn.unitgen.UnitGenerator.pullData(Unknown Source)
    at com.jsyn.ports.PortBlockPart.pullData(Unknown Source)
    at com.jsyn.ports.UnitInputPort.pullData(Unknown Source)
    at com.jsyn.unitgen.UnitGenerator.pullData(Unknown Source)
    at com.jsyn.ports.PortBlockPart.pullData(Unknown Source)
    at com.jsyn.ports.UnitInputPort.pullData(Unknown Source)
    at com.jsyn.unitgen.UnitGenerator.pullData(Unknown Source)
    at com.jsyn.ports.PortBlockPart.pullData(Unknown Source)
    at com.jsyn.ports.UnitInputPort.pullData(Unknown Source)
    at com.jsyn.unitgen.UnitGenerator.pullData(Unknown Source)
    at com.jsyn.ports.PortBlockPart.pullData(Unknown Source)
    at com.jsyn.ports.UnitInputPort.pullData(Unknown Source)
    at com.jsyn.unitgen.UnitGenerator.pullData(Unknown Source)
    at com.jsyn.engine.SynthesisEngine.synthesizeBuffer(Unknown Source)
    at com.jsyn.engine.SynthesisEngine.generateNextBuffer(Unknown Source)
    at com.jsyn.engine.SynthesisEngine$EngineThread.run(Unknown Source)

I have not had a chance to test for long periods on another OS, but will do as soon as possible.


Setup
OS macOS 10.13.6
Processing 3.5.3
SoundLibrary 2.1.0

Code
//------------------------------------------------------------------------------------
import processing.sound.*;
//------------------------------------------------------------------------------------
int[] note = {96, 93, 91, 89, 86, 84, 81, 79, 77, 74, 72, 69, 67, 65, 62, 60};
Env[] env;
SinOsc[] sine;
float attackTime = 0.004;
float sustainTime = 0.004;
float sustainLevel = 0.5;
float releaseTime = 0.7;
int beat = 0;
int framesPerBeat = 7;
//------------------------------------------------------------------------------------
void setup()
{
  background(0);
  sine = new SinOsc[note.length];
  env  = new Env[note.length];
  for (int i = 0; i < note.length; ++i)
  {
    sine[i] = new SinOsc(this);
    sine[i].freq(midi2Hz(note[i]));
    sine[i].amp(0.303);
    env[i] = new Env(this);
  }
}
//------------------------------------------------------------------------------------
void draw()
{
  if (frameCount % framesPerBeat == 0)
  {
    env[beat].play(sine[beat], attackTime, sustainTime, sustainLevel, releaseTime);
    beat++;
    beat %= note.length;
  }
}
//------------------------------------------------------------------------------------
float midi2Hz(int midiNoteNumber)
{
  return pow(2, float(midiNoteNumber - 69)/12.0) * 440.0f;
}
kevinstadler commented 5 years ago

Thank you for the detailed report!

I'm not sure why that particular exception is thrown but I think this might have to do with the fact that envelope re-use is not properly implemented yet under the hood, which means that repeated invocation of envelopes can actually become a burden on the program memory. Approximately how long (or approximately how many enveloper triggers) into running does the sketch stop playing?

Just looking back at the code the fix would have to go in here, I wonder if simply making sure that the player object is removed from the synthesis engine after it's finished might already do the trick: https://github.com/processing/processing-sound/blob/9c250cb7f4f279837c1b5cbaba118a0d866379bd/src/processing/sound/Env.java#L35-L54

mhamilt commented 5 years ago

Approximately how long (or approximately how many enveloper triggers) into running does the sketch stop playing?

Sadly, the exception is thrown at fairly random intervals. I have had it occur anywhere between a couple of minutes to just under an hour, but never longer.

I'll see if I can knock up a soak test script that will report back the number of envelope trigger and the running time.

kevinstadler commented 5 years ago

That would be great, thanks, it sounds like maybe the issue lies somewhere else after all...