Filters for synths—the 4-pole

The last post noted that the two most popular synthesizer filters are the 2-pole state variable, and the 4-pole “Moog style”. And we started with the state variable—simple, popular, and delivering multiple filter outputs (lowpass, bandpass…) simultaneously. Here, we’ll follow up with comments on the filter associated with Moog (and especially the Minimoog). In general, we’ll refer to this as a 4-pole synth filter.

While this filter is usually thought of as a lowpass filter, the other popular filter types can be derived easily. Many people first saw this in the Oberheim Xpander (and Matrix-12) synths of the ’80s, the idea came from Bernie Hutchins’ Electronotes in the ’70s. So don’t feel that you must go the direction of the state variable is you want multiple filter types, including 2-pole response.

Lowpass response is the overwhelming choice for typical synth use. Note that a 4-pole lowpass is not necessarily better then a 2-pole (as in the state variable)—they are just choices. You might want a 4-pole for the darker Minimoog bass sounds, and a 2-pole for the brassy OB8-style sounds.

Basic construction

The 4-pole is implemented by a string of four one-pole lowpass filter in series. We need corner peaking and resonance control for a synth filter, and we get that by feeding back the output to the input. While trivial in the analog domain, this feedback is the tricky part in the digital recreations. The reason is that it’s not a continuous system, and the obvious way to handle it is to put a delay in that part, so the output of the current sample period is available as input for the next. But this creates some bad side effects, particularly for tuning. In the past, people dealt with this by accounting for those errors.
4-pole

Approaching analog

But it’s not just tuning errors—if it were, that would be simple to fix. The Minimoog popularity, in part, is that it is designed to easily overdrive the filter, to get a “fat” tone. This is another thing that is simple in the analog domain, but doing the same in the digital domain produces noticeably digital artifacts. And if you goal is to make something that sound analog, this is a source of spectacular “fail”.

So instead of this simple delay approach in the 4-pole feedback path, modern ideas use more complex techniques to avoid the large-scale errors in an effort to get closer to how the analog counterpart works. And part of the effort is in dealing with an overdriven feedback path. The result reduced digital artifacts, makes the filter’s behavior more closely resemble its analog counterpart when overdriven, and also gives a smoother, more predictable and more musical sound at high resonance.

Note that these techniques are often called “zero feedback delay” (ZDF) filters. That is meant to highlight the fact a trivial delay is not used. I’m not a huge fan of that, since it’s not meaningful to someone who doesn’t know of the delay it refers to, and of course there are always sources of internal delay in an such filter design. But I mention ZDF so that if you’ve heard it before, be assured that we are talking about those sort of techniques here.

Serious reading

A great resource for this topic is Vadim Zavalishin’s The Art of VA Filter Design (“VA” for “Virtual Analog”).

Posted in Digital Audio, Filters, IIR Filters, Synthesizers | 3 Comments

Filters for synths–starting out

We haven’t developed a synth filter here yet…

Filters we’ve presented

Biquads. While they are useful for many simple cases of filtering, they are not a good choice for analog synthesizer emulation. Most notably, they are poorly suited to time-varying parameters such as smooth filter sweeps.

Hal Chamberlin’s digital state variable filter, which has the advantage of independent control of filter frequency and resonance (Q), as well as simultaneous output of lowpass, bandpass, highpass, and notch filtering. While this served in many synthesizers over the years, using oversampling to fix its most glaring problem (limited frequency control range before losing stability), more modern design approaches offer far better performance.

What analog synths use

It’s helpful to discuss what most people are used to before getting to digital implementations.

For analog synthesizer emulation, two basic analog designs stand out, having withstood the test of time the best. The 24 dB/octave (“four pole”) Moog style (“transistor ladder”) lowpass filter, and the 12 dB/octave (“two pole”) state variable with its multiple outputs.

There are other designs, including the “diode ladder” design by Roland, the Steiner-Parker filter (basically Sallen-Key)—these are some of the ways voltage control was solved in analog filters, resulting in characteristic sounds. We’ll limit discussion to the two standouts.

Where to start

The state-variable filter is the best place to start—simple and versatile.

And my choice for your first stop, for a simple filter that’s scarcely more complex than a Chamberlin svf is Andrew Simper’s trapezoidally integrated svf. There is enough detail and code in his pdf for anyone to implement a useable, flexible, and good sounding synthesizer filter—also useable for other filtering applications such as equalization.

http://www.cytomic.com/files/dsp/SvfLinearTrapOptimised2.pdf

Dig into that for a start! (And further reading from Andy)

Bonus audio sample

Here is the sound of two of our sawtooth wavetable oscillators, detuned, through the SVF coded directly from Andy’s paper, with frequency swept from 20 kHz down through the audio range by our ADSR; note that such a sweep would blow up the Chamberlin implementation without oversampling:

SVF lowpass sweep from 20 kHz

Posted in Digital Audio, Filters, IIR Filters, Synthesizers | Leave a comment

Audio Signal Processing for Music Applications

I’d like to recommend this excellent—and free—online course:

Audio Signal Processing for Music Applications
by Prof Xavier Serra, Prof Julius O Smith, III

The brief: In this course you will learn about audio signal processing methodologies that are specific for music and of use in real applications. You will learn to analyse, synthesize and transform sounds using the Python programming language.

This is the second session of the course, which will start on September 21, 2015. Enrollment is open here:

https://www.coursera.org/course/audio

I took the first session last fall. My primary motivation was to try a MOOC (Massive Open Online Course), and I wanted to pick a topic I already had knowledge in, to better evaluate the experience. For me, this topic was one in which I had an idea of the basic techniques used, but not the details and no practical experience, so it was a good fit. Plus, the course requires the use of Python, which I had interest in and wanted an excuse to learn.

Professor Serra delivers the course videos, and does an excellent job—clear and well-paced. The course helps to give a better understanding of musical components of sound, and the techniques used to alter individual aspects (especially pitch and duration, independently).

The ten-week course is not easy, and requires at least a few hours per week—a relatively small percentage of the large number of enrollees completed the course with a passing grade (yes, I passed). It requires a relatively modest amount of programming, as the sms-tools package handles most of the work, but will be tough for non-programmers. However, you can watch the videos even if you do not wish to do the weekly assignments and quizzes. The assignments will give you a much better understanding, of course.

Posted in Uncategorized | 1 Comment

Dither—The Naked Truth video

This video presents the “naked truth” on dither and truncation error, by stripping away the original signal of a musical clip and listening at different bit levels. I boost the error to a normalized audio volume for easy comparison of sound quality between different sample sizes, so your listening environment is not critical, but headphones will be a plus.

Posted in Digital Audio, Dither, Video | 1 Comment

Dither widget

This is the widget I used for the animated dither chart in my Audio Dither Explained video. “Run” animates the dither process, otherwise it changes only when you change the amplitude setting. “Connect” connects the dots; this is simply a visual aid, making it easily to follow the sequence of samples.

Posted in Digital Audio, Dither, Widgets | Leave a comment

Audio Dither Explained video

This video discusses the how and why of dither.

Posted in Digital Audio, Dither, Video | Leave a comment

More about source code

I was admonished (in not a nice way—not terribly rude, but quite to the point that I don’t know what I’m doing) by an anonymous visitor, who concluded that I don’t know much about C++ and maybe should have written it in a different language (why, when the purpose is to give people C++ code?). I would reply to him if he had left a real email address, but maybe I should make a few things clear to all.

I supply bare bones code. I try to leave out anything not necessary, and avoid even fairly obvious optimizations (and some less obvious that would make the code more difficult to understand. For instance, the wavetables could be one sample larger and let you avoid testing for wrap-around and the resulting branch). See About source code examples.

There is a common misconception that if your class is suitable for subclassing, then the destructor must be declared virtual. This is not true. If it were, the C++ architects would have simply built it in.

So, to some (including the anonymous commenter), it may seem confusing that I don’t declare destructors as virtual, which they might conclude to imply no subclassing, while declaring variables as protected (not private), implying support for subclassing. There is a method to this apparent madness: First, I don’t expect that the object will be subclassed by you, and I want to keep it efficient. So, I don’t declare destructors virtual, which would create some overhead we don’t need. However, if you do choose to subclass, then it’s important that you have access to certain variables, hence the protected declarations where appropriate.

However, that fact is that base class destructors need not be virtual when subclassed—that’s a requirement only if you want to delete them via the base class. By not declaring them virtual, we get the lack of vtable in the typically case (of no subclasses), while still allowing subclassing.

Also, I don’t mess with namespaces, and avoid templates even though they would be useful—again, trying to focus on the code that implements the DSP algorithm. I try to fit as much of the pertinent code on the screen for you as possible, so while I like comments in my code, I keep them brief.

And I don’t go through and declare every non-changing variable as const. This is not open source code. I’m not trying to protect you or some group you are working on code with from yourselves. I’m giving you seeds, not a framework, and it’s not in a Git repository. If I keep it simple enough, I figure you’ll be able to pull the bits out that matter for you into your own code. I don’t have time for both open source and tutorials—you can find a ton of open source oscillators, filters, and modulators on the internet, and I think you’ll find that the authors do not teach you how and why the code works. The latter is few and far between, and that’s why I’m here.

I’m open to suggestions, but realize that I do think about my choices, even if it’s not apparent. So, please, let’s make it a discussion. And the anonymous fellow is invited to point us to his contributions to the public. 😉

Posted in Source Code | 7 Comments

Pole-Zero placement v2

Pole mag
Pole angle
Zero mag
Zero angle
Sample rate (Hz)
Plot

A new pole-zero calculator

An JavaScript remake of the old Java-based pole-zero placement applet—visit that page for tips on pole-zero locations for standard biquads. The main additions are input fields for precision pole-zero placement, and an option to display the response with a log frequency scale.

The basic idea is that poles blow, zeros suck. Think of poles as controlling a frequency-dependent feedback or resonance—the impulse response of a pole inside the unit circle decays, while one outside is like runaway feedback (think of a mic feeding back into a loudspeaker). A pole on the unit circle gives a sustained oscillation (but watch out for numerical errors—keep your poles inside the unit circle, typically). Zeros absorb a particular frequency; when on the unit circle, they absorb the corresponding frequency completely.

So, poles push the frequency response up around their corresponding frequency, and zeros pull down around theirs. Keep in mind that the frequency response graph is normalized, just as the filter coefficients are. So, while a pole pushes up the response, it appears as though all other frequencies are being pushed down instead. Of course, normalization is important in practical application, but be aware of it when visualizing how poles and zeros interact.

Posted in Biquads, Digital Audio, Filters, IIR Filters, Widgets | 9 Comments

Biquad calculator v2

Type:

Plot:
Sample rate (Hz)
Fc (Hz)
Q
Gain (dB)

Here’s an update of the biquad calculator. It adds one-pole highpass and lowpass filters, and frequency, Q, and gain sliders. The sliders cover the range of typical audio settings, and are valuable for getting a quick feel for how the filters respond. But for precise settings and a wider range of parameters, type settings into the edit fields. (For this reason, the connection between sliders and edit fields are one-way—sliders update the edit fields, but changing the fields does not change the sliders positions accordingly.)

Review the biquad direct forms here; direct form I is best for fixed point processors, while direct for II transposed is best for floating point implementations.

Posted in Biquads, Digital Audio, Filters, IIR Filters, Widgets | 48 Comments

Envelope generators—ADSR widget

Attack
Decay
Sustain
Release
Attack Curve
Decay/Release Curve
Plot:

This is the widget I used in making the ADSR video. It’s a JavaScript recreation of my C++ source code.

Posted in Envelope Generators, Synthesizers, Widgets | 7 Comments