Avoiding clicks when changing sinOsc amplitude realtime

I’m finding some annoying audio glitches when changing a processing.sound sinOsc oscillator amplitude in realtime, for example with the mouse.
While moving the mouse, the amplitude step difference is big enough to be heard as a discontinuity on the waveform, thus the glitching.

Is there any way to smooth out this amplitude values and get rid of the glitches?
i’ve seen in some supercollider or max/msp implementations of oscillators there is some amplitude smoothing methods, but it doesn’t look that is the case with processing.sound

have any one found this and have a suggestion?

Attaching here the code of the simplest sinOSC example, where you can reproduce the glitches by fastly moving your mouse:

/**
 * This is a sine wave oscillator. The method .play() starts the oscillator. There
 * are several setter functions for configuring the oscillator, such as .amp(),
 * .freq(), .pan() and .add(). If you want to set all of them at the same time you can
 * use .set(float freq, float amp, float add, float pan)
 */

import processing.sound.*;

SinOsc sine;

void setup() {
  size(640, 360);
  background(255);

  // create and start the sine oscillator.
  sine = new SinOsc(this);
  sine.play();
}

void draw() {

  // Map mouseY from 0.0 to 1.0 for amplitude
  float amplitude = map(mouseY, 0, height, 1.0, 0.0);
  sine.amp(amplitude);

  // Map mouseX from 20Hz to 1000Hz for frequency  
  float frequency = map(mouseX, 0, width, 80.0, 1000.0);
  sine.freq(frequency);

  // Map mouseX from -1.0 to 1.0 for panning the audio to the left or right
  float panning = map(mouseX, 0, width, -1.0, 1.0);
  sine.pan(panning);
}

Hi @eltrem, this is a common problem in audio sometimes called “zipper” noise. It is because there are technically two loops happening at the same time, the audio loop (or audio processor) and the draw loop. The audio loop is happening many more times per second, commonly 44,100 times per second, and the draw loop is usually 60 times per second.

So when you update the amplitude in the draw() method hundreds of audio samples have been calculated since the last update, which creates a staircase effect in your amplitude value.

So you are correct that you have to smooth the values but to get rid of the clicks this has to happen in the audio loop. However, in the Processing sound library I don’t see any way to do this in the audio loop, but perhaps there is a way I’m not aware of.

Instead you have to smooth in the draw() method but because of the framerate being 60 fps there will be some lag, so you could try something like this: smooth = smooth - .02 * (smooth - amp); sine.amp(smooth); where you declare smooth as a global variable like, float smooth = 0; at the top of your sketch.
This worked ok when I tested it but there is lag. I upped the frame rate to 120 frameRate(120) in the setup method and that helped a little. However, depending on what your application is this may not be optimal.

But from what I can tell, the Processing sound library doesn’t offer a sample level method to change the amplitude. I could be wrong though. You could look into the Env class which shouldn’t click when the amplitude changes, but this isn’t applicable to using the mouse or a knob to change the amplitude.

1 Like

Thank you very much Robert!

yes, looks like we’re fighting the old battle between control rate and audio rate here. I tried doing the signal smoothing with the algorithm you suggested, and although it improves slightly, there’s still some audible glitches.

In an audio development environment, like supercollider or max, this could be solved converting from datarate to audiorate and using a low pass filter to smooth out the discontinuities, but unfortunately it is not an option here.

Unless i’m missing something, it doesn’t look like minim is capable of this too.
Do you know of any library that can accomplish this?
i’d like to keep the software as minimal as possible, so i’d preffer not to have supercollider or pd running in parallel, and would be great if there was some contributed library that can handle this kind of stuff

Thanks for your help and patience!

Thanks @eltrem. Yes, there is Pd4P3 which is available in the contribution manager. It’s my own lib, but the problem you present is one of the many reasons I created it. Pd4P3 provides access to the audio loop via a method called runAlgorithm().
I don’t have an example of parameter smoothing yet in the current version but there is one available via github here:
Pd4P3/SmoothingExample.pde at main · robertesler/Pd4P3 (github.com)

2 Likes

@robertesler
great library nice working

1 Like

Wow! that’s amazing Robert, just what i was looking for!

hands at work then!

1 Like