This example demonstrates two forms of graphic equalizers constructed using building blocks from Audio Toolbox™. It also shows how to export them as VST plugins to be used in a Digital Audio Workstation (DAW).
Equalizers are commonly used by audio engineers and consumers to adjust the frequency response of audio. For example, they can be used to compensate for bias introduced by speakers, or to add bass to a song. They are essentially a group of filters designed to provide a custom overall frequency response.
One of the more sophisticated equalization techniques is known as parametric equalization. Parametric equalizers provide control over three filter parameters: center frequency, bandwidth, and gain. Audio Toolbox provides the
multibandParametricEQ System object and the
Parametric EQ block for parametric equalization.
While parametric equalizers are useful when you want to fine-tune the frequency response, there are simpler equalizers for cases when you need fewer controls. Octave, two-third octave, and one-third octave have emerged as common bandwidths for equalizers based on the behavior of the human ear. Standards like IS0 266:1997(E), ANSI S1.11-2004, and IEC 61672-1:2013 define center frequencies for octave and fractional octave filters. This leaves only one parameter to tune: filter gain. Graphic equalizers provide control over the gain parameter while using standard center frequencies and common bandwidths.
In this example, you use two implementations of graphic equalizers. They differ in arrangement of constituent filters: One uses a bank of parallel octave- or fractional octave-band filters, and the other uses a cascade of biquad filters. The center frequencies in both implementations follow the ANSI S1.11-2004 standard.
One way to construct a graphic equalizer is to place a group of bandpass filters in parallel. The bandwidth of each filter is octave or fractional octave, and their center frequency is set so that together they cover the audio frequency range of [20, 20000] Hz.
The transfer function is a sum of transfer function of the branches.
You can tune the gains to boost or cut the corresponding frequency band while the simulation runs. Because the gains are independent of the filter design, tuning the gains does not have a significant computational cost. The parallel filter structure is well suited to parallel hardware implementation. The magnitude response of the bandpass filters should be close to zero at all other frequencies outside its bandwidth to avoid interaction between the filters. However, this is not practical, leading to inter-band interference.
You can use the
graphicEQ System object to implement a graphic equalizer with a parallel structure.
eq = graphicEQ('Structure', 'Parallel')
eq = graphicEQ with properties: EQOrder: 2 Bandwidth: '1 octave' Structure: 'Parallel' Gains: [0 0 0 0 0 0 0 0 0 0] SampleRate: 44100
This designs a parallel implementation of second order filters with 1-octave bandwidth. It takes ten octave filters to cover the range of audible frequencies. Each element of the
Gains property controls the gain of one branch of the parallel configuration.
Configure the object you created to boost low and high frequencies, similar to a rock preset.
eq.Gains = [4, 4.2, 4.6, 2.7, -3.7, -5.2, -2.5, 2.3, 5.4, 6.5, 6.5]
eq = graphicEQ with properties: EQOrder: 2 Bandwidth: '1 octave' Structure: 'Parallel' Gains: [1x10 double] SampleRate: 44100
visualize to view the magnitude response of the equalizer design.
You can test the equalizer implemented in
audioTestBench. The audio test bench sets up the audio file reader and audio device writer objects, and streams the audio through the equalizer in a processing loop. It also assigns a slider to each gain value and labels the center frequency it corresponds to, so you can easily change the gain and hear its effect. Modifying the value of the slider simultaneously updates the magnitude response plot.
A different implementation of the graphic equalizer uses cascaded equalizing filters (peak or notch) implemented as biquad filters. The transfer function of the equalizer can be written as a product of the transfer function of individual biquads.
To motivate the usefulness of this implementation, first look at the magnitude response of the parallel structure when all gains are 0 dB.
parallelGraphicEQ = graphicEQ('Structure', 'Parallel'); visualize(parallelGraphicEQ);
You will notice that the magnitude response is not flat. This is because the filters have been designed independently, and each has a transition width where the magnitude response droops. Moreover, because of non-ideal stopband, there is leakage from the stopband of one filter to the passband of its neighbor. The leakage can cause actual gains to differ from expected gains.
parallelGraphicEQ_10dB = graphicEQ('Structure', 'Parallel'); parallelGraphicEQ_10dB.Gains = 10*ones(1,10); visualize(parallelGraphicEQ_10dB);
Note that the gains are never 10 dB in the frequency response. A cascaded structure can mitigate this to an extent because the gain is inherent in the design of the filter. Setting the gain of all cascaded biquads to 0 dB leads to them being bypassed. Since there are no branches in this type of structure, this means you have a no-gain path between the input and the output.
graphicEQ implements the cascaded structure by default.
cascadeGraphicEQ = graphicEQ; visualize(cascadeGraphicEQ);
Moreover, when you set the gains to 10 dB, notice that the resultant frequency response has close to 10 dB of gain at the center frequencies.
cascadeGraphicEQ_10dB = graphicEQ; cascadeGraphicEQ_10dB.Gains = 10*ones(1,10); visualize(cascadeGraphicEQ_10dB);
The drawback of cascade design is that the coefficients of a biquad stage need to be redesigned whenever the corresponding gain changes. This isn't needed for the parallel implementation because gain is just a multiplier to each parallel branch. A parallel connection of bandpass filters also avoids accumulating phase errors and quantization noise found in the cascade.
graphicEQ object supports
2/3 octave, and
1/3 octave bandwidths. Reducing the bandwidth of individual filters allows you finer control over frequency response. To verify this, set the gains to boost mid frequencies, similar to a pop preset.
octaveGraphicEQ = graphicEQ; octaveGraphicEQ.Gains = [-2.1,-1.8,-1.4,2.7,4.2,4.6,3.1,-1,-1.8,-1.8,-1.4]; visualize(octaveGraphicEQ);
oneThirdOctaveGraphicEQ = graphicEQ; oneThirdOctaveGraphicEQ.Bandwidth = '1/3 octave'; oneThirdOctaveGraphicEQ.Gains = [-2,-1.9,-1.8,-1.6,-1.5,-1.4,0,1.2,2.7,... 3.2,3.8,4.2,4.4,4.5,4.6,4,3.5,3.1,1.5,-0.1,-1,-1.2,-1.6,-1.8,-1.8,... -1.8,-1.8,-1.7,-1.5,-1.4,-1.3]; visualize(oneThirdOctaveGraphicEQ);
To generate and port a VST plugin to a Digital Audio Workstation, run the
generateAudioPlugin command. For example, you can generate a two-third octave graphic equalizer through the commands shown below. You will need to be in a directory with write permissions when you run these commands.
twoThirdOctaveGraphicEQ = graphicEQ; twoThirdOctaveGraphicEQ.Bandwidth = '2/3 octave'; createAudioPluginClass(twoThirdOctaveGraphicEQ); generateAudioPlugin twoThirdOctaveGraphicEQPlugin
You can use the same features described in this example in Simulink through the
Graphic EQ block. It provides a slider for each gain value so you can easily boost or cut a frequency band while the simulation is running.