framerate() damper hack

versions0095+
contributorswatz
started on2006-02-28 13:09

UPDATE: This hack as described does not work, as it turns out that the framerate variable is not actually used by Processing to control the delay. I had to disable Processing's framerate handling and do it myself. Will describe a method for doing this when I get the time. - watz

Advanced hack for an obscure framerate() problem, recommended only for users who are building Java projects with the Processing source.

The framerate() command in Processing tries to make a sketch run at a given frame rate by slowing it down when it's running too fash, producing smooth motion. It can never be used to speed up a sketch, but it is recommended to specify a framerate() for any serious projects to prevent them running at inconsistent speeds on faster hardware.

A typical sketch that has an even CPU load will have good results using framerate() in this way. However, a sketch that has a heavy CPU load and then drops to a much lighter load, will experience some weirdness. When the load decreases, the perceived framerate will suddenly speed up, becoming much too fast for a period of time (typically 30-50 frames) before slowing back down to the correct rate. This can visually disruptive, and is likely to be interpreted by users as a bug.

Why it happens and what you can do

The reason for this speedup / slowdown lies inside processing.core.PApplet. The display() function is the core loop of Processing, and takes care of drawing and timing issues. To avoid sudden changes in the framerate, there is a damper used to interpolate changing values.

The framerate damper code in Processing 0095 looks like the following:

// processing.core.PApplet
// 
  synchronized public void display() {
            ...
            float elapsed = (float)
              (System.currentTimeMillis() - framerateLastMillis);
            if (elapsed != 0) {
              framerate =
                (framerate * 0.9f) + ((1.0f / (elapsed / 1000.0f)) * 0.1f);
            ...
  }

The framerate is changed so that it moves 10% towards the new value for each frame. This normally smooths out any minor changes in the framerate. But when a sketch has a dramatic drop in framerate, it will delay each frame too little for a while, causing the described speedup.

If you do experience surges in framerate to the point that it seems like a problem, you can modify the weight of the damper like this:

            if (elapsed != 0) {
              framerate =
                (framerate * 0.2f) + ((1.0f / (elapsed / 1000.0f)) * 0.8f);

This new code will move 80% towards the new framerate value, causing a much quicker interpolation to a new value.

This technique is advanced, as it requires modifying a core function in the actual PApplet code. It's advisable to make a local copy of the source just for the project where you have the problem, so that other projects will not have to share the hack.

If you are not using the processing.core source to compile your project then you will need to override display() in the class that extends PApplet. Simply copy the entire display() function code from PApplet.java and make the adjustment above. Provided you've copied display() correctly, this should not interfere with regular Processing execution.

Context

I will give an example of a situation where this behavior might be disruptive. I first found it when creating a performance system for live visuals. In such a system I will typically use a central class extending PApplet, with individual visual systems as plugging into it.

Systems can be turned off and on, and obviously they have different demands on the CPU. The results is that a CPU-heavy system followed by a CPU-light one will produce the described speedup followed by a slowdown. In live performance this is really ugly, since it looks to the spectators as a visual hiccup. As a result, I have had to change the damper function to interpolate much more quickly.

Related Links

For copies of the Processing source code, see http://dev.processing.org.

hacks/framerate.txt · Last modified: 2007-07-13 02:12 (external edit)