Any way to sync amplitude changes to zero crossings in the sine generator?

Status
Not open for further replies.

Thyratron

New member
First, thanks for creating the Teensy audio board and library. For me it is one of the most useful things to come along in a long time.
What I am trying to do is to create custom envelopes for sine waves. The problem is the clicks and pops that occur when changing the amplitude any significant amount in real time. As I read some of the other comments on the forum, I’m guessing this is a relatively common issue. Perhaps the best solution to this (though I’m open to other suggestions) is to only change the amplitude of the sine generator at zero crossings.
Unfortunately, my programing skills aren’t up to me mucking around with this, but if someone out there with the right skills would like to take a shot at it, I and perhaps many others would be grateful.
A similar feature might be nice for the mixer object, but I’m guessing that detecting and managing the zero crossings might be more challenging with arbitrary waveforms.
 
The problem is the clicks and pops that occur when changing the amplitude any significant amount in real time.
...so the solution might be to limit the rate this is changing with digital low-pass filter or some sort of 'slew limit' on how fast the applied envelope signal is allowed to change.


For zero crossing you can check the current and lagged values to find crossings in one direction (useful estimating wavelength).
Code:
zx  = (in > 0)&(in1 <= 0);
in1 = in;
zx TRUE IFF signal crossed upwards since last sample.

To get both crossings you'd need to extract signs of current and lagged samples; the crossing is where signCurrent!=signLagged.
I'm sure there's bit-mask trick to find when the sign bits are not the same or you can use inequalities with zero (from which I understand the compiler will replace with an efficient method).

Or you could look for signal below some absolute level since you don't really care that it's a crossing just that the values are low enough you won't here a click.
 
Last edited:
The problem is the clicks and pops that occur when changing the amplitude any significant amount..
I saw something like this in industry (Leitch Technology). The way the embedded developer chose to solve the problem was to very quickly decrease the volume to of the first frequency to zero and then bring it back up again with the next frequency. It was probably less than a tenth of a second. No pops!
 
For zero crossing you can check the current and lagged values to find crossings in one direction (useful estimating wavelength).
Code:
zx  = (in > 0)&(in1 <= 0);
in1 = in;
zx TRUE IFF signal crossed upwards since last sample.

alternatively,
Code:
zx=(in*in1)<=0;
in1=in;
is TRUE in case of zero crossing;
problem here is if "in ==0" you get two consecutives TRUE values, but this may not harm you.

maybe also checking explicitly only sign bit
Code:
zx = (in^in1)&(1<<15); // 16 bit integer (use 31 for 32 bit integers)
in1=in;
which is also TRUE in case of sign change
 
Talked to the original developer I referenced earlier. His feedback was:

Think of sitting at a mixing console - the fader doesn't go from top to bottom instantly - neither should your software - change the gain multiplier gradually over a period of time. When switching signals, it is common to take one signal from 100%-0% over a period of time and take the other from 0%-100% over the same period.
 
Last edited:
the fader doesn't go from top to bottom instantly - neither should your software
That's what I meant.
...so the solution might be to limit the rate this is changing with digital low-pass filter or some sort of 'slew limit' on how fast the applied envelope signal is allowed to change.
 
I often use the DC object and multiply it with the signal. The DC object has the option to set the time the change in value should be gradually changed over.
amplitude(level, milliseconds);

But as Thyratron said, it would be nice to have that inside the mixer... might look at that one day..
 
Perhaps the best solution to this (though I’m open to other suggestions) is to only change the amplitude of the sine generator at zero crossings.
I'm quite sure this isn't the best solution.
From a signal processing point of view, what you're doing is multiplying your sinus signal with a step function. Even if your step (the amplitude jump) happens at the zero crossing, you'll still hear a pop. I guess your idea of switching the amplitude at a zero-crossing comes from a graphical representation of your signal, where the amplitude step is not so obviously visible, because its just a kink at the zero-crossing. But this doesn't mean you won't hear it. The "pop" you hear is the step-function itself and where it happens in relation to your sinus function isn't that important, you're applying the same discontinuity to the sinus-signal. I'd go with the other suggestions and slow down the amplitude change using a simple ramp or low-pass filtering of the step.
 
Status
Not open for further replies.
Back
Top