Complex Nonlinearities Episode 9: Subharmonics
Today we’ll be talking about nonlinear signal processing from a little bit different perspective. Typically, in audio signal processing, we use nonlinear elements to generate frequency content, however this generated frequency content is almost always at frequencies higher than the original signal.
For instance, the classic soft-clipping distortion effect generates signal at the odd harmonics of the original signal. As an example, the plot below shows the harmonic response of a soft-clipping distortion effect for a 100 Hz sine wave.
In today’s article, instead of frequency content above the original signal, we’ll be generating content at lower frequencies than the original signal, sometimes known as “subharmonics”.
From here we’ll look at the building blocks of generating low frequency content, and then show how to use this method to build a sort of “bass enhancer” effect.
As always, this article can be viewed as a Jupyter Notebook, for anyone wishing to see the code ued to generate these nice plots.
Creating Low Frequencies
Let’s start with a 2 kHz sine wave, and attempt to generate the first subharmonic frequency at 1 kHz. First, let’s build a simple function to determine whether the input signal is increasing or decreasing, and output 1 for increasing, and -1 for decreasing.
So with that pretty simple trick, we have a method for generating a square wave with the same frequency as the input. Now all we need to do is cut that frequency in half. We can accomplish this by simply switching our output between 1/-1 every other time the signal changes directions.
Now that works for generating a square wave at the desired frequency, but what if we would prefer the much more pleasant sounding sine wave? Well if we lowpass filter the generated square wave, we can get something pretty close.
The difference is a little bit easier to notice if we look at the Fourier transforms of the two signals.
Sure enough, the generated signal is at half the frequency of the original!
Building A Bass Enhancer
So we already know how to create a subharmonic tone generator, now let’s see if we can incorporate the generator into a simple bass enhancer effect, something we can use to beef up a weak bass guitar or kick drum without adding any nasty artifacts or unwanted distortion.
First off, we don’t our generator outputting any signal when there’s no incoming signal. To do this, we can create a a level detector, much like one that we would use for a compressor or gate, and multiply the output of the generator by the detected level.
The signal flow diagram above shows the described architecture where the output of the generator and lowpass filter is multiplied by the output of the level detector (LD).
We can give the level detector attack and release parameters, again similar to those used by a compressor, to help tune the characteristics of our bass enhancer. Specifically, by lengthening the release of our detector, we can make our generated bass signal seem to last longer, and “ring” out after the original sound has ended.
The plot below shows the output of the generator with level detector architecture, with an attack time of 1 millisecond, and a release time of 5 milliseconds.
Finally, we need just one more modification for a full-on bass enhancer effect: a lowpass filter before the generator. In the real world, the input signal for our effect won’t just be sine waves. In order to keep our generator from getting confused and creating signal at frequencies much higher than we would like, we can keep input more or less sine-like by filtering out all of the frequencies above where we want our effect to start creating subharmonics. The resulting architecture looks like this.
As an example of how this type of “bass enhancer” effect can work, I’ve implemented the architecture described above as an audio plugin (VST, AU), using the JUCE C++ framework. To demonstrate the usefulness of the effect, I’ve also recorded a short video demo, trying it out on a pure sine wave signal, as well as a more realistic audio clip. The source code is available on GitHub, and the video demo can be found below.
Thanks for reading through another article on nonlinear signal processing! Hopefully you’ve learned something new, and gained some inspiration for some of your own work moving forward. I’m hoping to have a couple more articles coming out in the next few weeks, so stay tuned!