Frequency Detection in Reaktor
In this tutorial, I’ll cover a basic frequency detector in Reaktor. I’ll start with the most basic possible frequency detector, explain it’s shortcomings, and then design a better version with a little bit of math and extra work. Let’s get down to it!
SIMPLE FREQUENCY DETECTION
A basic model can be put together using only two modules – an A to E Trig, and a Timer. Simply connect them like so, and you’re done:
This is a very simple design to follow. Every time the incoming audio switches from a negative value to a positive one, the A to E Trig module sends an output. The Timer module then outputs the frequency as determined by the last two events that it has received.
This macro will return a fairly accurate view of the incoming frequency. Unfortunately, however, it has a degree of error which causes it to flutter a few Hertz above and below the actual frequency.
The reason for this error is explained in the first anti-aliasing tutorial, which can be found here. Simply put, due to digital sampling, it is unlikely that the incoming waveform will be sampled exactly as it crosses zero – instead we are usually left with a slightly positive value less than one sampling period away from the zero crossing. This degree of error can cause trouble in our algorithm.
Let’s use an example. The A to E Trig module only outputs an event if the previous value was negative and the current value is positive. Let’s say a waveform crosses zero and gets sampled equal to 0.005 at the next sampling point, triggering the A to E module. The waveform then repeats, crosses the zero point again, and this time gets sampled equal to 0.004. Again, the A to E module will trigger, giving us an approximate frequency.
However, the waveform itself has not completed a full cycle since the last time we triggered the Timer module – it has travelled from 0.005 to 0.004, still 0.001 away from completing a full wavecycle! As a result, the Timer module will output a frequency slightly higher than the actual frequency. In short, the time that we calculate will always be off by a fraction of a sampling period.
Fortunately, this problem is not so hard to fix with a little bit of math.
IMPROVED FREQUENCY DETECTION
To make an improved version of the basic frequency detector, we need a little bit more information about the waveform we are working with. When a zero-crossing occurs, we first need to know how far the wave has moved in the last sampling period, and second, we need to know where the waveform was the last time a zero-crossing happened.
These pieces of information are readily available to us:
The ‘T’ module is a Unit Delay, which simply delays the signal by a single sampling period. We can find the distance travelled in the last sampling period simply by subtracting the previous sample from the current one.
You may also notice I’ve replaced the ‘A’ input to the A to E Trig module with the incoming wave. This way, the module outputs the value of the zero-crossing when one happens.
So, we can find the value of the last zero-crossing simply by using the Order module to trigger the Value module (containing the last zero-crossing), then storing the new zero-crossing for use next time. We subtract the current value from the previous one to give us an idea of how far away we are from an exact wavecycle (if the values are equal, that’s means we’ve found an exact wavecycle; in almost all circumstances, however, we will detect that we are slightly more or less than an exact cycle).
Now we know how far we’ve travelled in the last sampling period, and how close we are to being an exact wavecycle. When we divide as we do at the end of the macro, we are left with a number that represents the amount of time away from a full cycle we are, in sampling periods. A negative value means that we are a little short of a full wavecycle, and a positive value means we have gone a little past a full wavecycle.
So now we have calculated the error, in sampling periods. The plan is to convert the value from sampling periods to milliseconds, and to use the ‘T’ output of the timer (which translates the frequency into milliseconds). We can add the two values together, then convert back to frequency.
To convert, 1000/Hz = Time in Ms, and 1000/Ms = Frequency in Hz. Pretty simple, right?
Here’s what the finished product looks like:
I’ve included an ensemble with this tutorial that includes both of the frequency detectors described today. The error in Hertz is calculated for each detector. As you can see, the second method works far better than the first, with the error often being 1/10,000th or less than the error of the first method.
The simpler the waveform, the better the method will work, with sawtooths perhaps being the most accurate of all.
I hope you have found today’s tutorial to be helpful. Please let me know if you have any questions or suggestions in the comments.