The Spin auto-wah peak detector, part I

The auto-wah is one of the programs included with the "Guitar Amp Applications" project at the Spin web site. Download the "GA_DEMO_programs.zip" file here. The file we are going to analyze is GA_DEMO_WAH.spn.

This is one seriously dense bit of FV-1 code. I'm going to break it into two sections, it's so exhausting.

First three instructions.

  • absa

  • rdfx avg, 0.01

  • wrax avg, 0

absa - Absolute value is a full wave rectifier!

Next two are a single pole low pass filter. After some mucking about and annoying Frank at the Spin forum with my stupid questions, I settled down to this formula.

K = 1 - e^(-2 * pi * f/fs)

or, solving for f given K and fs,

f = - (ln(1 - K )/(2 * pi)) * fs

So, in the example, this works out to about 52.4 Hz.

Here's a link to Wolfram Alpha so you can try it yourself.

Next up,

  • rdax lavg,0.001

  • sof -0.01,0

  • rdax lavg,1

  • wrax temp,0

  • rdax avg,1

  • maxx temp,1 ;filter a long average

  • wrax lavg,0

"filter a long average" is the comment in the original code. Nothing else apparently warrants a comment (eye roll).

lavg is not previously referred to, so assume it’s zero to start.

So we read it in, then scale again by -0.01 (so now it’s -0.00001 * lavg)

And then add lavg again, so that’s 0.99999 * lavg, which gets written to temp.

Why didn’t we just do “rdax lavg, -0.00001”? Or "rdax lavg, 0.99999"?

Because the coefficient C in an RDAX or RDFX instruction is S1.14. So the smallest bit of this, 2^(-14) is the smallest number you can use. What is 2^(-14)?

It’s 0.000061035-something, which is bigger than 0.00001, meaning you can’t represent a number that small in these instructions. The biggest number less than one that you can represent is 1 - 2^(-14) or 16383/16384 or 0.99993896484375.

So you have to get close and then scale down further using a SOF.

I'll circle back later to calculate the -3 dB corner and gain of this filter.

So we get avg (the first filter's value) back into ACC, then do a MAXX against temp which is holding the second filter's value. Initially, like we just concluded, this value is zero, so the first filter's value is going to win and then that value gets stuffed into the second filter's register.

From here on out, if the first filter's value is larger than the second one, then the second one is updated to match. If the first filter's output is lower (it decays faster, remember) then the second one simply decays on its own, every cycle 0.99999 times the previous value. This is the peak hold function. It's like an ideal diode (Vf = 0) between the two filters. It's even better than that as there is no voltage division. DSP doesn't have to obey the rules of physics!

Upon further reflection I realize that the second stage is not, strictly speaking, a filter. It is a peak detector. A filter, if you feed it zeroes on the input, will decay more rapidly as it is influenced by both the input and its previous state. The peak detector is only influenced by the input when that value is greater than the register's previous state, and then it goes there immediately. Other than that it is only affected by its previous state.

That's all I can stands for the moment. I'll be back before too long with "the rest of the story".

Last updated