Skip to content

SlickEQ Custom Models Guide

By Vladislav Goncharov, Shane Johnson

What Is SlickEQ

SlickEQ is a 3-band tone-shaping equalizer. If 3 bands are not enough for your specific EQ sculpting, then a multi band equalizer like below will be better suited.

This is not tone-shaping equalization

One goal of tone-shaping EQ is to help you not get wrapped up with a lot of technical details, thus keeping your brain free for the overall vision of the track. This allows you to stay focused in the creative zone without the worry of technicalities, such as frequencies, Q factors, bell shapes and so on. Do you need more bass? Just boost it. Do you need more treble? Just add it. If the track has too much low-mid, just reduce it. The goal is to prepare a first draft mix as fast as possible while keeping you fresh. The limitations and hidden things under the hood are key to this mode of working.

How can you integrate a tone-shaping EQ into your workflow? By utilizing several insert slots of different EQ types, which will separate tone-shaping tasks from surgical tasks. You could also use several passes. For example:

  • Pass 1 – organize the project, prepare a fader mix, finish editing tasks.
  • Pass 2 – apply tone shaping EQs, one-knob compressors, use presets in reverbs and delays,  you’ve now got the first draft to show the client.
  • Pass 3 – surgical EQs, tweaking, and applying first feedback from the client.

In addition to the 3 bands and high-pass filter, the GE version of SlickEQ also has a low-pass filter, tilt filter, all-pass filter, EQ curve display, FFT analyzer, and “SmartOps” for getting initial EQ settings in a semi-automatic way. Following the “keep your brain free” principle, it’s better to make your first adjustments with the display off. During your subsequent tweaks, the use of the display would allow you to quickly read what’s going on when cycling from track to track.

All knobs in SlickEQ have a Stepped mode which can be configured in Settings. You can enable it using the right mouse button while adjusting a control. The stepped mode uses “snapmaps” to define the step positions. This trick will also allow you to keep your brain free from actual frequencies, gain values, and other technicalities.

From a technical point of view, the 3 bands of SlickEQ are 3 biquad (second order) filters connected in series. There’s an internal procedure which reads the Gain and Frequency knob position along with the mode for each band. These then get transformed into bell and shelf filters, where the Q factor is dependent on the band’s gain and selected model (American, British, German, Soviet and Japanese). The selected model also defines the color of the plugin window.

In version 1.3.4 of SlickEQ and SlickEQ GE, we added the ability to redefine knob ranges, snap maps, and use mathematical expressions to define the 3 EQ band filters. This redefinition can have different settings for each of the EQ models. It’s stored in the plugin state of the DAW session and can be recalled regardless of global plugin settings. Furthermore, the new model can be stored as a preset or transferred using the copy and paste action.

Important: Since the free version of SlickEQ doesn’t offer a “Narrow Bell” band mode, some model features will be missing.

Custom Model Example 1: “Digital”

To use the presets in this guide, copy the XML data and paste it into a plugin instance by selecting the “Paste State” command from the plugin context menu (right-click on the plugin UI).

“Paste State” command in SlickEQ GE

Here’s the preset for SlickEQ GE:

<TDRVOSSlickEQGE lowBandGainParam="0.0" lowBandFreqParam="200"
lowBandShapeParam="Shelf" lowBandLagParam="Off" midBandGainParam="0.0"
midBandFreqParam="2500" midBandShapeParam="Bell" highBandGainParam="0.0"
highBandFreqParam="5000" highBandShapeParam="Shelf"
eqModelParam="American" eqSatParam="Off" lpBypassParam="On"
lpFreqParam="22000" lpModeParam="Steep" hpBypassParam="On"
hpFreqParam="15" hpModeParam="Normal" tiltFreqParam="650"
tiltValueParam="0.0" tiltBypassParam="On" tiltTypeParam="Normal"
outSatModelParam="Linear" outSatDriveParam="6.0" outGainParam="0.0"
bypassParam="Off" modeParam="Stereo" lowBandBypassParam="Off"
midBandBypassParam="Off" highBandBypassParam="Off" autoGainParam="On"
qualityParam="Full" displayScaleParam="Scale: Auto"
showFreqMagnitudeParam="On" hideBottomBarParam="Off"
showFFTAnalyzerParam="Off"

CUSTOM_MODEL_American_NAME="Digital"

CUSTOM_MODEL_American_EXPRESSION="
seq(
	set_BELL_BOOST_Q(0.7),
	set_BELL_CUT_Q(1.4),
	set_BELL_NARROW_Q_MULTIPLIER(2),
	set_BELL_SHELF_Q(0.7),
	filter(band, if(
		typeBell,
		peak(gain, if(greater(gain, 1), BELL_BOOST_Q, BELL_CUT_Q) * if(typeBellNarrow, BELL_NARROW_Q_MULTIPLIER, 1), freq),
		equal(band, 0),
		lowshelf(gain, 0.7, freq),
		highshelf(gain, 0.7, freq)
	))
)
"
/>

If you’re using SlickEQ then paste this preset instead:

<TDRVOSSlickEQ lowBandGainParam="0.0" lowBandFreqParam="200" 
lowBandShapeParam="Shelf" midBandGainParam="0.0" midBandFreqParam="2500" 
highBandGainParam="0.0" highBandFreqParam="5000" 
highBandShapeParam="Shelf" eqModelParam="American" eqSatParam="Off" 
hpFreqParam="Off" outSatModelParam="Linear" outSatDriveParam="6.0" 
outGainParam="0.0" bypassParam="Off" modeParam="Stereo" 
lowBandBypassParam="Off" midBandBypassParam="Off" 
highBandBypassParam="Off" autoGainParam="On" qualityParam="Full" 

CUSTOM_MODEL_American_NAME="Digital"

CUSTOM_MODEL_American_EXPRESSION="
seq(
	set_BELL_BOOST_Q(0.7),
	set_BELL_CUT_Q(1.4),
	set_BELL_SHELF_Q(0.7),
	filter(band, if(
		typeBell,
		peak(gain, if(greater(gain, 1), BELL_BOOST_Q, BELL_CUT_Q), freq),
		equal(band, 0),
		lowshelf(gain, 0.7, freq),
		highshelf(gain, 0.7, freq)
	))
)
"
/>

Once the XML data is copied and pasted successfully, you’ll have the following.

“Digital” Model in SlickEQ GE

The “American” model will now be redefined to “Digital”. The asterisk (*) means the user-defined expression is used and all other models are left as is. If you want to return to the default “American” mode, right-click on the preset menu and select “Reset to Original State”.

“Reset to Original State” command in SlickEQ GE

In this “Digital” model the EQ bands will now have a “fixed Q” behavior. In addition, the bell cuts will be narrower than boosts.

Upon inspecting the XML data you’ll notice the name of the model, Q values for bell boost and cuts, how the Q value is modified if the “Narrow” mode is selected, and Q values for the shelves.

Custom Model Example 2: “Parametric”

In this next model, SlickEQ becomes a full parametric equalizer! The FREQ control of the MID band becomes Q control for the LOW band. Also, the GAIN control of the MID band becomes Q control for the HIGH band. Furthermore, the frequency ranges for the LOW and HIGH bands are now 10 Hz – 40 kHz, however the MID band disappears.

The filter type buttons for the LOW and HIGH bands change their type from bell to shelf. The “Narrow” button inverts the gain for both bands upside down, just for fun.

“Parametric” model in SlickEQ GE

The Q range for the bell filters go from 0.1 to 6. For the shelf filters, it goes from 0.3 to 1.6. You can control the Q values but won’t be able to see their exact value. Here’s the translation table to help you get the exact Q value from the FREQ and GAIN position.

MID FREQLOW Bell QLOW Shelf QMID GAINHIGH Bell QHIGH Shelf Q
3000.300.342.70.300.35
5000.500.393.90.490.39
7000.700.434.80.710.44
10001.000.505.60.990.50
20002.000.727.31.990.72
40004.001.139.03.981.16

For simplicity, a snapmap table is added for the MID FREQ and GAIN knob settings.

Here’s the preset for SlickEQ GE:

<TDRVOSSlickEQGE lowBandGainParam="0.0" lowBandFreqParam="200" 
lowBandShapeParam="Bell" lowBandLagParam="Off" midBandGainParam="5.6" 
midBandFreqParam="1000" midBandShapeParam="Bell" highBandGainParam="0.0" 
highBandFreqParam="5000" highBandShapeParam="Bell" 
eqModelParam="British" eqSatParam="Off" lpBypassParam="On" 
lpFreqParam="22000" lpModeParam="Steep" hpBypassParam="On" 
hpFreqParam="15" hpModeParam="Normal" tiltFreqParam="650" 
tiltValueParam="0.0" tiltBypassParam="On" tiltTypeParam="Normal" 
outSatModelParam="Linear" outSatDriveParam="6.0" outGainParam="0.0" 
bypassParam="Off" modeParam="Stereo" lowBandBypassParam="Off" 
midBandBypassParam="Off" highBandBypassParam="Off" autoGainParam="On" 
qualityParam="Full" displayScaleParam="Scale: Auto" 
showFreqMagnitudeParam="On" hideBottomBarParam="Off" 
showFFTAnalyzerParam="Off"

CUSTOM_MODEL_British_NAME="Parametric"

CUSTOM_MODEL_British_LOW_FREQ_MIN="10"
CUSTOM_MODEL_British_LOW_FREQ_MAX="40000"
CUSTOM_MODEL_British_LOW_FREQ_DEFAULT="200"

CUSTOM_MODEL_British_HIGH_FREQ_MIN="10"
CUSTOM_MODEL_British_HIGH_FREQ_MAX="40000"
CUSTOM_MODEL_British_HIGH_FREQ_DEFAULT="5000"

CUSTOM_MODEL_British_MID_FREQ_MIN="100"
CUSTOM_MODEL_British_MID_FREQ_MAX="6000"
CUSTOM_MODEL_British_MID_FREQ_DEFAULT="1000"

CUSTOM_MODEL_British_MID_GAIN_MIN="0"
CUSTOM_MODEL_British_MID_GAIN_MAX="10"
CUSTOM_MODEL_British_MID_GAIN_DEFAULT="5.6"

CUSTOM_MODEL_British_MID_FREQ_SNAPMAP="300,500,700,1000,2000,4000"
CUSTOM_MODEL_British_MID_GAIN_SNAPMAP="2.7,3.9,4.8,5.6,7.3,9.0"


CUSTOM_MODEL_British_EXPRESSION="
seq(
	set_BAND_1_GAIN(if(not(typeBellNarrow_1), gain_0, 1 / gain_0)),
	set_BAND_2_GAIN(if(not(typeBellNarrow_1), gain_2, 1 / gain_2)),
	set_BAND_1_FREQ(freq_0),
	set_BAND_2_FREQ(freq_2),

	set_BAND_1_Q(if(typeBell_0,
		(freq_1 - 100) / (6000 - 100) * (6 - 0.1) + 0.1,
		(freq_1 - 100) / (6000 - 100) * (1.6 - 0.3) + 0.3
	)),
	set_BAND_2_Q(if(typeBell_2,
		(exp(log(100) + lin2db(gain_1) / 10 * (log(6000) - log(100))) - 100) / (6000 - 100) * (6 - 0.1) + 0.1,
		(exp(log(100) + lin2db(gain_1) / 10 * (log(6000) - log(100))) - 100) / (6000 - 100) * (1.6 - 0.3) + 0.3
	)),

	filter(0, if(typeBell_0, peak(BAND_1_GAIN, BAND_1_Q, BAND_1_FREQ), lowshelf(BAND_1_GAIN, BAND_1_Q, BAND_1_FREQ))),
	filter(1, unity()),
	filter(2, if(typeBell_2, peak(BAND_2_GAIN, BAND_2_Q, BAND_2_FREQ), highshelf(BAND_2_GAIN, BAND_2_Q, BAND_2_FREQ)))
)
"
/>

Here’s the preset for SlickEQ:

<TDRVOSSlickEQ lowBandGainParam="0.0" lowBandFreqParam="200" 
lowBandShapeParam="Bell" midBandGainParam="5.6" midBandFreqParam="1000" 
highBandGainParam="0.0" highBandFreqParam="5000" highBandShapeParam="Bell" 
eqModelParam="British" eqSatParam="Off" hpFreqParam="Off" 
outSatModelParam="Linear" outSatDriveParam="6.0" outGainParam="0.0" 
bypassParam="Off" modeParam="Stereo" lowBandBypassParam="Off" 
midBandBypassParam="Off" highBandBypassParam="Off" autoGainParam="On" 
qualityParam="Full" 

CUSTOM_MODEL_British_NAME="Parametric"

CUSTOM_MODEL_British_LOW_FREQ_MIN="10"
CUSTOM_MODEL_British_LOW_FREQ_MAX="40000"
CUSTOM_MODEL_British_LOW_FREQ_DEFAULT="200"

CUSTOM_MODEL_British_HIGH_FREQ_MIN="10"
CUSTOM_MODEL_British_HIGH_FREQ_MAX="40000"
CUSTOM_MODEL_British_HIGH_FREQ_DEFAULT="5000"

CUSTOM_MODEL_British_MID_FREQ_MIN="100"
CUSTOM_MODEL_British_MID_FREQ_MAX="6000"
CUSTOM_MODEL_British_MID_FREQ_DEFAULT="1000"

CUSTOM_MODEL_British_MID_GAIN_MIN="0"
CUSTOM_MODEL_British_MID_GAIN_MAX="10"
CUSTOM_MODEL_British_MID_GAIN_DEFAULT="5.6"

CUSTOM_MODEL_British_MID_FREQ_SNAPMAP="300,500,700,1000,2000,4000"
CUSTOM_MODEL_British_MID_GAIN_SNAPMAP="2.7,3.9,4.8,5.6,7.3,9.0"

CUSTOM_MODEL_British_EXPRESSION="
seq(
	set_BAND_1_GAIN(gain_0, gain_0),
	set_BAND_2_GAIN(gain_2, gain_2),
	set_BAND_1_FREQ(freq_0),
	set_BAND_2_FREQ(freq_2),

	set_BAND_1_Q(if(typeBell_0,
		(freq_1 - 100) / (6000 - 100) * (6 - 0.1) + 0.1,
		(freq_1 - 100) / (6000 - 100) * (1.6 - 0.3) + 0.3
	)),
	set_BAND_2_Q(if(typeBell_2,
		(exp(log(100) + lin2db(gain_1) / 10 * (log(6000) - log(100))) - 100) / (6000 - 100) * (6 - 0.1) + 0.1,
		(exp(log(100) + lin2db(gain_1) / 10 * (log(6000) - log(100))) - 100) / (6000 - 100) * (1.6 - 0.3) + 0.3
	)),

	filter(0, if(typeBell_0, peak(BAND_1_GAIN, BAND_1_Q, BAND_1_FREQ), lowshelf(BAND_1_GAIN, BAND_1_Q, BAND_1_FREQ))),
	filter(1, unity()),
	filter(2, if(typeBell_2, peak(BAND_2_GAIN, BAND_2_Q, BAND_2_FREQ), highshelf(BAND_2_GAIN, BAND_2_Q, BAND_2_FREQ)))
)
"
/>

Upon inspecting the XML data, you’ll notice that it redefines the “British” model and also changes the range of the frequency parameters. In addition, there are expressions that convert the mid band gain and frequency values to the Q factor, while also maintaining a logarithmic scale.

Can you combine the “Digital” and “Parametric” presets? Yes, you can! In this case, the “American” model becomes the “Digital”, and the “British” model becomes the “Parametric”. The other models remain unchanged.

Custom Model Description Language

The custom model description consists of the following parts:

  • initial values of the parameters using the regular SlickEQ XML preset
  • name of the model
  • ranges of the parameters
  • snapmaps of the parameters
  • filter calculation expressions

XML Preset Attributes

The name of each attribute contains the name of the EQ model redefined in the preset. This model will represent the EQ tonal color of your own custom model. There are 5 models in SlickEQ GE and 4 models in SlickEQ.

SlickEQ GE Models:

  • American (purple)
  • British (yellow)
  • German (blue)
  • Soviet (red)
  • Japanese (green)

SlickEQ Models:

  • American (purple)
  • British (yellow)
  • German (blue)
  • Soviet (red)

For simplicity, all attribute names below are for the American model (they contain “American” in the middle). You can replace it using any model name from the above list to change the EQ tonal color.

CUSTOM_MODEL_American_NAME

– This attribute defines the name of the model. In the SlickEQ GUI, an asterisk (*) is added to the end of the name to distinguish custom models from the factory ones.

CUSTOM_MODEL_American_LOW_FREQ_MIN
CUSTOM_MODEL_American_LOW_FREQ_MAX
CUSTOM_MODEL_American_LOW_FREQ_DEFAULT

CUSTOM_MODEL_American_MID_FREQ_MIN
CUSTOM_MODEL_American_MID_FREQ_MAX
CUSTOM_MODEL_American_MID_FREQ_DEFAULT

CUSTOM_MODEL_American_HIGH_FREQ_MIN
CUSTOM_MODEL_American_HIGH_FREQ_MAX
CUSTOM_MODEL_American_HIGH_FREQ_DEFAULT

– These attributes define the range of the frequency parameters for the LOW, MID and HIGH bands. The DEFAULT value sets its initial value, which is also set when double clicking on its associated knob. Please note that you can’t use suffix modifiers, such as 40k, when defining these frequency parameters, hence use 40000 instead.

If the range for a band is not defined, then the default SlickEQ range will be used:

  • LOW – 30 Hz .. 1 kHz
  • MID – 100 Hz .. 10 kHz
  • HIGH – 500 Hz .. 40 kHz

CUSTOM_MODEL_American_LOW_GAIN_MIN
CUSTOM_MODEL_American_LOW_GAIN_MAX
CUSTOM_MODEL_American_LOW_GAIN_DEFAULT

CUSTOM_MODEL_American_MID_GAIN_MIN
CUSTOM_MODEL_American_MID_GAIN_MAX
CUSTOM_MODEL_American_MID_GAIN_DEFAULT

CUSTOM_MODEL_American_HIGH_GAIN_MIN
CUSTOM_MODEL_American_HIGH_GAIN_MAX
CUSTOM_MODEL_American_HIGH_GAIN_DEFAULT

– These attributes define the range of the gain parameters for the LOW, MID and HIGH bands. The DEFAULT value sets its initial value, which is also set when double clicking on its associated knob. If the DEFAULT value is not specified then 0 dB is used.

CUSTOM_MODEL_American_LOW_FREQ_SNAPMAP
CUSTOM_MODEL_American_LOW_GAIN_SNAPMAP
CUSTOM_MODEL_American_MID_FREQ_SNAPMAP
CUSTOM_MODEL_American_MID_GAIN_SNAPMAP
CUSTOM_MODEL_American_HIGH_FREQ_SNAPMAP
CUSTOM_MODEL_American_HIGH_GAIN_SNAPMAP

– These attributes define the snapmaps for the parameters used in stepped mode. Comma-separated values are used to list each stepped value (for example “100,500,1k,5k,10k”), or you can use “::<min>:<max>:<step>” (for example “::0:10:1”; if the <min> or <max> value is skipped, then the min/max value set for the parameter is used). If snapmaps are not specified then the default values will be used.

CUSTOM_MODEL_American_EXPRESSION

– This one is where all the magic comes from. This attribute contains the expression, which is executed on any LOW/MID/HIGH band parameter change. The expression can set the filter of the changed band or set new filters for all 3 bands, thus allowing band interaction implementation.

Though the attribute value contains a single expression, you can also split it on multiple lines for easier reading. The simplest expression is “filter(unity())”, which sets a 0 dB straight line. The calculated expression always returns a value, which gets ignored. On any error during parsing or executing of the expression, a banner at the top of the plugin window will display the error message.

Expression error displayed in the banner

Expression Syntax

The expression itself is as simple as possible. The expression contains:

  • floating point constants (64-bit floating point internal precision)
  • symbols (such as “band”, see “Expression Symbols”)
  • function calls (such as “log()”, see “Expression Functions”)
  • operators: + – * /  (plus, minus, multiply, divide).

The expression is always executed entirely. For function calls, each parameter value is calculated even if the value is not used. All names are case sensitive. There are no data types. All operations are performed on floating point values. All functions return floating point values.

There are no Boolean constants or logical operators. All conditions and logical operators are implemented as functions. A value of 1 represents “true” and a value of 0 represents “false”.

If you need to split the expression into several sub-expressions, you can use user-defined variables (see “set_XXX()” function) or use the seq() function call. This can have any number of executed parameters and the value of the last expression will be returned.

Example:

CUSTOM_MODEL_American_EXPRESSION="seq(
	set_A(20 + 30),
	set_B(40 * 50),
	A + B
)"

Expression Symbols

The expression symbols contain any number of characters including digits and underscores. These are the predefined symbols:

  • band – (0 for LOW, 1 for MID, 2 for HIGH) is the band number, to which the changed parameter belongs
  • Nyquist – ½ of internal sample rate, in Precise and Eco modes the plugin runs oversampled, oversampling amount depends on sample rate used, in Live mode the plugin runs without oversampling
  • PI – “pi” constant (3.14159…)

There are symbols that represent per-band parameters. The band number is specified after the underscore (for example, “gain_1” or “typeBell_0”). If the underscore is skipped then the current band number (see “band”) will be used (for example “freq” or “type”):

  • type – band’s type (0 or 1) for LOW band 0 means “lowshelf” and 1 means “bell”, for MID band 0 means “bell” and 1 means “narrow bell”, for HIGH band 0 means “highshelf” and 1 means “bell” (Note: The free version of SlickEQ doesn’t offer the “narrow bell” shape)
  • freq – band’s frequency in Hz (for example 1000 for 1 kHz)
  • gain – band’s gain in linear scale (for example 1 for 0 dB, 2 for 6 dB and so on), use “lin2db” function to convert linear scale gain value to dB scale
  • typeBell – is 1, if the band has “bell” shape, 0 otherwise
  • typeBellNarrow – is 1, if the band has “narrow bell” shape, 0 otherwise (Note: The free version of SlickEQ doesn’t offer the “narrow bell” shape)
  • typeLowShelf – is 1, if the band has “low-shelf” shape, 0 otherwise
  • typeHighShelf – is 1, if the band has “high-shelf” shape, 0 otherwise

If there’s a user-defined variable under this symbol name, then the value of the variable gets returned (see “set_XXX” function).

If the symbol name is unknown, then a “symbol not found” error message will get displayed.

Expression Functions

The expression functions contain any number of characters including digits and underscores. The function parameters get listed after the open parenthesis. There are several categories of functions.

Logical functions:

  • greater(a, b) – returns 1, if a > b, 0 otherwise (example: “greater(freq, 100)”)
  • greater_equal(a, b) – returns 1, if a >= b, 0 otherwise
  • less(a, b) – returns 1, if a < b, 0 otherwise
  • less_equal(a, b) – returns 1, if a <= b, 0 otherwise
  • equal(a, b) – returns 1, if a = b, 0 otherwise (example: “equal(type, 0)”)
  • eq(a, b) – the same as equal(a, b)
  • not_equal(a, b) – returns 1, if a <> b, 0 otherwise
  • and(a, b, …) – returns 1, if all parameters are 1, 0 otherwise (example: “and(equal(band, 0), equal(type, 1))”)
  • or(a, b, …) – returns 1, if any or the parameters is 1, 0 otherwise (example: “or(equal(band, 0), equal(band, 1))
  • not(a) – returns 1, if a = 0, 0 otherwise
  • in(x, a, b, …) – returns 1, if x is equal to any of a, b, … values, 0 otherwise
  • if(x1, a, x2, b, x3, c, …, z) – returns a, if x1 = 1, returns b, if x2 = 1 and so on, returns z otherwise (example: “if(greater(gain, 1), 0.7, 1.4)”)
  • case(val, x1, a, x2, b, …, z) – returns a, if val = x1, returns b if val = x2 and so on, returns z otherwise (example: “case(band, 0, 0.3, 1, 0.7, 0.4)”)

Sequence functions:

  • seq(a, b, …) – returns the last parameter value. This function is used to execute the sequence of expressions. It’s better to split these expressions into multiple lines for easier reading.

Mathematical functions:

  • min(a, b, …) – minimum value from the parameters (example: “min(freq, 10000)”)
  • max(a, b, …) – maximum value from the parameters (example: “max(gain, 0)”)
  • sin(x) –  sine of x in radians
  • cos(x) –  cosine of x in radians
  • tan(x) –  tangent of x in radians
  • tanh(x) –  hyperbolic tangent of x
  • exp(x) – retuns e^x
  • exp2(x) – returns 2^x
  • log(x) – returns ln(x)
  • log10(x) – returns log10(x)
  • sqrt(x) –  square root of x
  • pow(a, b) – returns a^b (Important: There’s no “^” operator in the expressions so instead of x^3 you should use x*x*x or pow(x, 3))
  • abs(x) – returns |x|
  • db2lin(x) – converts dB scale value to linear scale (for example db2lin(0) returns 1)
  • lin2db(x) – converts linear scale value to dB scale (for example lin2db(1) returns 0)
  • pwl(x, x0, y0, x1, y1, …, xN, yN) – piecewise linear interpolation, where (x0, y0), (x1, y1), … define the points of the lines and x is the input value, if x < x0, y0 is returned, if x > xN, yN is returned.

Set user-defined variables:

  • set_XXX(a) – XXX is the name of user variable (for example “set_GAIN_DB(lin2db(gain))”, where GAIN_DB is the name), after this call you may use the name specified. The variable name is case sensitive. The variables exists for current expression calculation only and are cleared on the next expression run. Important: Since every parameter of every function is calculated regardless of their value, you can only set the value of a variable once! For example, you can’t use “if(greater(gain, 1), set_GAIN_DB(lin2db(gain)), set_GAIN_DB(0))” because set_GAIN_DB will be called 2 times regardless of its gain value! You should use “set_GAIN_DB(if(greater(gain, 1), lin2db(gain), 0)” instead! To help solve such issues, a “Variable redefinition” error gets displayed if a variable is set to a value more than once.

The filter design functions design a filter, store it in an internal table and returns the “handle” of this filter. This handle value should be passed to the “filter()” function to actually set the filter obtained by the handle from the table.

Here are the following filter design functions:

  • lowshelf(G, Q, freq) – designs RBJ low-shelf filter where “freq” is frequency in Hz, Q is Q factor and G is the gain in linear scale. Filter function: H(s) = A * (s^2 + (sqrt(A)/Q)*s + A)/(A*s^2 + (sqrt(A)/Q)*s + 1), where A = sqrt(G)
  • highshelf(G, Q, freq) – designs RBJ high-shelf filter where “freq” is frequency in Hz, Q is Q factor and G is the gain in linear scale. Filter function: H(s) = A * (A*s^2 + (sqrt(A)/Q)*s + 1)/(s^2 + (sqrt(A)/Q)*s + A), where A = sqrt(G)
  • peak(G, Q, freq) – designs peak filter where “freq” is frequency in Hz, Q is Q factor and G is the gain in linear scale. Filter function: H(s) = (s^2 + s*(A/Q) + 1) / (s^2 + s/(A*Q) + 1), where A = sqrt(G)
  • biquad(A, B, C, D, E, F, freq) – specifies filter function: H(s) = (A * s^2 + B * s + C) / (D * s^2 + E * s + F), BLT transform is applied so the H(1i) becomes “freq” frequency (example: “biquad(0, 0, 1, 1, 1/Q, 1, freq)” defines lowpass filter with given Q and freq)
  • parallel(A, B, C, D, E, F, G, H, freq1, freq2) – specifies filter function, which is sum of 2 first-order filters: H(s) = H1(s) + H2(s), where H1(s) = (A*s + B) / (C*s + D) and H2(s) = (E*s + F) / (G*s + H), BLT transform is applied to both first order filters separately, so H1(1i) becomes freq1 and H2(1i) becomes freq2 then the filters are combined
  • unity() – specifies straight 0 dB line filter: H(s) = 1.

Set filter function:

  • filter(band, f)band is EQ band number (0 for LOW, 1 for MID, 2 for HIGH), f is filter handle from a filter design function (example: “filter(band, peak(gain, 1, freq))”). Note: You may set all filters on single expression run, for example:seq(filter(0, peak(gain_0, 1, freq_0)), filter(1, peak(gain_1, 1, freq_1)), filter(2, peak(gain_2, 1, freq_2)))”. Important: The filter() function for each band should be called once!

If the function name is unknown, then an “unknown function” error message will get displayed.

How to Write the Expressions and Keep Your Sanity

Tip: Set the SlickEQ controls to their initial values, select the EQ model, then copy the preset and paste it into your favorite text editor as starting point. You can then start slowly adding things one by one.

There can be 3 main problems encountered when making the expressions:

Problem 1. Logical expressions. It’s not trivial to write something like if band=0 and type=1 or band=1 or band=2 and type=1 using expressions. Try to write the expression in a human readable form first and then replace parts of the expression to function calls one by one. For example:

  • band=0 and type=1 or band=1 or band=2 and type=1
  • eq(band, 0) and eq(type, 1) or eq(band, 1) or eq(band, 2) and eq(type, 2)
  • and(eq(band, 0), eq(type, 1)) or eq(band, 1) or and(eq(band, 2), eq(type, 2))
  • or(and(eq(band, 0), eq(type, 1)), eq(band, 1), and(eq(band, 2), eq(type, 2)))

Problem 2. Parenthesis. The “Expected “)”” is the most frequent error you’ll get and the message won’t give you any clues where the problem is located at. The solution is to use a text editor with parenthesis highlighting, so you can see if everything is okay before you paste the preset.

Problem 3. The model doesn’t work and it’s impossible to say why. There aren’t any debugging resolutions with this one. The only solution here is a step by step approach, which is to add functions and expressions one by one to see which step it stops working on.

What You Can’t Do with the Models

The models cover only the LOW, MID and HIGH bands. You can’t redefine the high-pass filter, low-pass filter, or tilt filter behavior in SlickEQ GE. You can change the range of the GAIN and FREQ parameters, however, you can’t change their parameter type or their precision (GAIN knob is always dB and FREQ knob is always Hz in logarithmic scale, GAIN knob has 0.1 dB precision and FREQ knob has precision 1 Hz or 0.1 kHz precision depending on the value).

Please note that it’s not possible to model stereo tolerances (different left and right parameters in the models). The “Dual Mono” process mode in SlickEQ GE introduces tolerances, but only at the knob level. When configuring different left/right parameters using the Dual Mono process mode (e.g., setting the left gain knob to 6 dB and the right gain knob to 5.7 dB), it’s not possible to determine which channel gets executed when an expression gets called.

Since there are only 3 biquad filters connected in series, you won’t be able to implement any form of parallel equalization, flat top filters, or high order shelves. The 3 biquads, 6 knobs and 3 switches encompass the simplicity that SlickEQ was designed for

Analog-Based Model: API 550A

The API 550A is a 3 band equalizer with stepped gain and frequency controls. The LF and HF bands can either be a shelf or bell shape. There is also a “FLTR” control, which engages a smooth bandpass filter for gently cutting low and high frequencies.

API 550A used for the measurements

In addition to the stepped gain control, another key feature is its “proportional Q” behavior for bells. This means that the Q factor gets increased with gain.

The actual Q values were measured for the bell curves from the hardware unit and then interpolated. This allows for smooth gain control with the same Q behavior.

The actual frequency value of the shelf filters were also measured from the hardware unit and interpolated. This provides smooth frequency control with the same shelf filter shape.

The bell center frequency and gain values in this model are also ideal (you’ll get what you’ll set).

Though the API 550A hardware doesn’t have a “narrow bell” mode, it is added to the model, thus multiplying the Q factor by 2.

In the SlickEQ GE preset, both HPF and LPF frequencies are roughly set to match the “FLTR” bandpass behavior. As a result, just turn both filters on to emulate this switch.

Here’s the preset for SlickEQ GE:

<TDRVOSSlickEQGE lowBandGainParam="0.0" lowBandFreqParam="200" 
lowBandShapeParam="Shelf" lowBandLagParam="Off" midBandGainParam="0.0" 
midBandFreqParam="1500" midBandShapeParam="Bell" highBandGainParam="0.0" 
highBandFreqParam="10000" highBandShapeParam="Shelf" 
eqModelParam="American" eqSatParam="Off" lpBypassParam="On" 
lpFreqParam="17500" lpModeParam="Smooth" hpBypassParam="On" 
hpFreqParam="50" hpModeParam="Normal" tiltFreqParam="650" 
tiltValueParam="0.0" tiltBypassParam="On" tiltTypeParam="Normal" 
outSatModelParam="Linear" outSatDriveParam="0.0" outGainParam="0.0" 
bypassParam="Off" modeParam="Stereo" lowBandBypassParam="Off" 
midBandBypassParam="Off" highBandBypassParam="Off" autoGainParam="On" 
qualityParam="Full" displayScaleParam="Scale: +- 12 dB" 
showFreqMagnitudeParam="Off" hideBottomBarParam="Off" 
showFFTAnalyzerParam="Off" 

CUSTOM_MODEL_American_NAME="API 550A"

CUSTOM_MODEL_American_LOW_FREQ_SNAPMAP="50,100,200,300,400"
CUSTOM_MODEL_American_LOW_GAIN_SNAPMAP="-12,-9,-6,-4,-2,0,2,4,6,9,12"
CUSTOM_MODEL_American_MID_FREQ_SNAPMAP="400,800,1.5k,3k,5k"
CUSTOM_MODEL_American_MID_GAIN_SNAPMAP="-12,-9,-6,-4,-2,0,2,4,6,9,12"
CUSTOM_MODEL_American_HIGH_FREQ_SNAPMAP="5k,7k,10k,12.5k,15k"
CUSTOM_MODEL_American_HIGH_GAIN_SNAPMAP="-12,-9,-6,-4,-2,0,2,4,6,9,12"

CUSTOM_MODEL_American_LOW_FREQ_MIN="50"
CUSTOM_MODEL_American_LOW_FREQ_MAX="400"
CUSTOM_MODEL_American_LOW_FREQ_DEFAULT="200"
CUSTOM_MODEL_American_LOW_GAIN_MIN="-12"
CUSTOM_MODEL_American_LOW_GAIN_MAX="12"

CUSTOM_MODEL_American_MID_FREQ_MIN="400"
CUSTOM_MODEL_American_MID_FREQ_MAX="5000"
CUSTOM_MODEL_American_MID_FREQ_DEFAULT="1500"
CUSTOM_MODEL_American_MID_GAIN_MIN="-12"
CUSTOM_MODEL_American_MID_GAIN_MAX="12"

CUSTOM_MODEL_American_HIGH_FREQ_MIN="5000"
CUSTOM_MODEL_American_HIGH_FREQ_MAX="15000"
CUSTOM_MODEL_American_HIGH_FREQ_DEFAULT="10000"
CUSTOM_MODEL_American_HIGH_GAIN_MIN="-12"
CUSTOM_MODEL_American_HIGH_GAIN_MAX="12"

CUSTOM_MODEL_American_EXPRESSION="
seq(
filter(band, if(
	typeBell,
	peak(gain, (0.256+5.026e-2*abs(lin2db(gain))-2.014e-3*abs(pow(lin2db(gain),2)))*if(typeBellNarrow,2,1), freq),
	equal(band, 0),
        if(greater(gain, 1),
		biquad(0, 1, gain, 0, 1, 1, 1/(2.387e-3+7.859e-4*lin2db(gain))*freq/50),
		biquad(0, 1, 1, 0, 1, 1/gain, 1/(2.387e-3+7.859e-4*lin2db(1/gain))*freq/50)),
        if(greater(gain, 1),
		biquad(0, gain, 1, 0, 1, 1, (435.361+213.105*lin2db(gain))*freq/5000),
		biquad(0, 1, 1, 0, 1/gain, 1, (435.361+213.105*lin2db(1/gain))*freq/5000))
)))
"
/>

Here’s the preset for SlickEQ:

<TDRVOSSlickEQ lowBandGainParam="0.0" lowBandFreqParam="200" 
lowBandShapeParam="Shelf" midBandGainParam="0.0" midBandFreqParam="1500" 
highBandGainParam="0.0" highBandFreqParam="10000" 
highBandShapeParam="Shelf" eqModelParam="American" eqSatParam="Off" 
hpFreqParam="Off" outSatModelParam="Linear" outSatDriveParam="0.0" 
outGainParam="0.0" bypassParam="Off" modeParam="Stereo" 
lowBandBypassParam="Off" midBandBypassParam="Off" 
highBandBypassParam="Off" autoGainParam="On" qualityParam="Full" 

CUSTOM_MODEL_American_NAME="API 550A"

CUSTOM_MODEL_American_LOW_FREQ_SNAPMAP="50,100,200,300,400"
CUSTOM_MODEL_American_LOW_GAIN_SNAPMAP="-12,-9,-6,-4,-2,0,2,4,6,9,12"
CUSTOM_MODEL_American_MID_FREQ_SNAPMAP="400,800,1.5k,3k,5k"
CUSTOM_MODEL_American_MID_GAIN_SNAPMAP="-12,-9,-6,-4,-2,0,2,4,6,9,12"
CUSTOM_MODEL_American_HIGH_FREQ_SNAPMAP="5k,7k,10k,12.5k,15k"
CUSTOM_MODEL_American_HIGH_GAIN_SNAPMAP="-12,-9,-6,-4,-2,0,2,4,6,9,12"

CUSTOM_MODEL_American_LOW_FREQ_MIN="50"
CUSTOM_MODEL_American_LOW_FREQ_MAX="400"
CUSTOM_MODEL_American_LOW_FREQ_DEFAULT="200"
CUSTOM_MODEL_American_LOW_GAIN_MIN="-12"
CUSTOM_MODEL_American_LOW_GAIN_MAX="12"

CUSTOM_MODEL_American_MID_FREQ_MIN="400"
CUSTOM_MODEL_American_MID_FREQ_MAX="5000"
CUSTOM_MODEL_American_MID_FREQ_DEFAULT="1500"
CUSTOM_MODEL_American_MID_GAIN_MIN="-12"
CUSTOM_MODEL_American_MID_GAIN_MAX="12"

CUSTOM_MODEL_American_HIGH_FREQ_MIN="5000"
CUSTOM_MODEL_American_HIGH_FREQ_MAX="15000"
CUSTOM_MODEL_American_HIGH_FREQ_DEFAULT="10000"
CUSTOM_MODEL_American_HIGH_GAIN_MIN="-12"
CUSTOM_MODEL_American_HIGH_GAIN_MAX="12"

CUSTOM_MODEL_American_EXPRESSION="
seq(
filter(band, if(
	typeBell,
	peak(gain, (0.256+5.026e-2*abs(lin2db(gain))-2.014e-3*abs(pow(lin2db(gain),2))), freq),
	equal(band, 0),
        if(greater(gain, 1),
		biquad(0, 1, gain, 0, 1, 1, 1/(2.387e-3+7.859e-4*lin2db(gain))*freq/50),
		biquad(0, 1, 1, 0, 1, 1/gain, 1/(2.387e-3+7.859e-4*lin2db(1/gain))*freq/50)),
        if(greater(gain, 1),
		biquad(0, gain, 1, 0, 1, 1, (435.361+213.105*lin2db(gain))*freq/5000),
		biquad(0, 1, 1, 0, 1/gain, 1, (435.361+213.105*lin2db(1/gain))*freq/5000))
)))
"
/>

The API 550A is the ideal candidate for tone shaping tasks. Use it!

Analog-Based Model: Pultec EQP-1A Clone

The Pultec EQP-1A offers a passive equalizer circuit followed by a tube makeup amplifier. The passive equalizer circuit has a low-shelf boost and low-shelf cut that uses separate gain controls with common stepped frequency values. It also has a bell boost with gain, Q control and stepped frequencies, and a high-shelf cut with gain control and stepped frequencies. Thus it’s a 4 band equalizer with some limitations.

The most famous feature of the Pultec EQP-1A is the ability to use its parallel connected low-shelf boost and low-shelf cut controls simultaneously, which transforms the curve to the low-shelf boost with a bell cut in the mid-range.

The model is based on a simplified analog model which excludes the “all-to-all” bands interaction. A hardware Pultec clone was used for the measurements.

Pultec clone used for the measurements

The measurements taken were of the actual frequency values for the bell and shelves, including the gain knob behavior (“potentiometer tapers”). This means that if you set the BOOST to 5, you’ll get the same boost in dB as in the hardware unit.

Since the EQP-1A has 8 knobs and SlickEQ only has 6, two modes were introduced. These are mode “A” and mode “B”, which are switched by the HIGH shelf/bell control.

If the HIGH band type is set to “shelf”, then mode “A” is selected. In this mode it is not possible to do a simultaneous boost/cut. The knob mapping is as follows:

  • LOW GAIN and FREQ control low-shelf boost, if LOW band set to “shelf”
  • LOW GAIN and FREQ control low-shelf cut, if LOW band set to “bell”
  • MID GAIN and FREQ control bell boost with bandwidth set to “sharp” in “Narrow bell” mode and bandwidth set to “broad” in “Bell” mode
  • HIGH GAIN and FREQ control high-shelf cut
SlickEQ GE knob mapping for mode “A”

If the HIGH band type is set to “bell”, then mode “B” is selected. In this mode it’s possible to simultaneously boost and cut. There’s also a bandwidth control for the bell-boost, however, there’s no high-shelf cut controls. The knob mapping is as follows:

  • LOW GAIN and FREQ control low-shelf boost
  • MID GAIN and FREQ control bell boost
  • HIGH FREQ controls bell boost bandwidth from minimum (sharp) to maximum (broad)
  • HIGH GAIN controls low-shelf cut
  • LOW and MID band modes are inactive
SlickEQ GE knob mapping for mode “B”

The snapmaps for frequency knobs portray the stepped frequency on the hardware controls (the clone used for measurements has extended frequency steps), and in-between values are interpolated.

The gain knobs depict the hardware unit gain knob positions from 0 to 10. The clone used for measurements has soft-steps on its knobs, thus allowing for controllable value changes from 0 to 10 with steps of 0.25. This is also represented in the snapmaps.

In the SlickEQ GE preset, the low-pass filter is activated by default and represents the measured bandwidth of the hardware unit.

Here’s the preset for SlickEQ GE:

<TDRVOSSlickEQGE lowBandGainParam="0.0" lowBandFreqParam="30" 
lowBandShapeParam="Shelf" lowBandLagParam="Off" midBandGainParam="0.0" 
midBandFreqParam="8000" midBandShapeParam="Narrow Bell" highBandGainParam="0.0" 
highBandFreqParam="10000" highBandShapeParam="Shelf" eqModelParam="German" 
eqSatParam="Off" lpBypassParam="Off" lpFreqParam="32700" 
lpModeParam="Smooth" hpBypassParam="On" hpFreqParam="15" 
hpModeParam="Normal" tiltFreqParam="650" tiltValueParam="0.0" 
tiltBypassParam="On" tiltTypeParam="Normal" outSatModelParam="Linear" 
outSatDriveParam="13.4" outGainParam="0.0" bypassParam="Off" 
modeParam="Stereo" lowBandBypassParam="Off" midBandBypassParam="Off" 
highBandBypassParam="Off" autoGainParam="On" qualityParam="Full" 
displayScaleParam="Scale: Auto" showFreqMagnitudeParam="Off" 
hideBottomBarParam="Off" showFFTAnalyzerParam="Off"

CUSTOM_MODEL_German_NAME="EQP-WA"

CUSTOM_MODEL_German_LOW_FREQ_SNAPMAP="20,30,60,100,200,400,800"
CUSTOM_MODEL_German_LOW_FREQ_MIN="20"
CUSTOM_MODEL_German_LOW_FREQ_MAX="800"
CUSTOM_MODEL_German_LOW_FREQ_DEFAULT="30"

CUSTOM_MODEL_German_MID_FREQ_SNAPMAP="3000,4000,5000,8000,10000,12000,16000"
CUSTOM_MODEL_German_MID_FREQ_MIN="3000"
CUSTOM_MODEL_German_MID_FREQ_MAX="16000"
CUSTOM_MODEL_German_MID_FREQ_DEFAULT="8000"

CUSTOM_MODEL_German_HIGH_FREQ_SNAPMAP="3000,4000,5000,10000,20000"
CUSTOM_MODEL_German_HIGH_FREQ_MIN="3000"
CUSTOM_MODEL_German_HIGH_FREQ_MAX="20000"
CUSTOM_MODEL_German_HIGH_FREQ_DEFAULT="10000"

CUSTOM_MODEL_German_LOW_GAIN_MIN="0"
CUSTOM_MODEL_German_LOW_GAIN_MAX="10"

CUSTOM_MODEL_German_MID_GAIN_MIN="0"
CUSTOM_MODEL_German_MID_GAIN_MAX="10"

CUSTOM_MODEL_German_HIGH_GAIN_MIN="0"
CUSTOM_MODEL_German_HIGH_GAIN_MAX="10"

CUSTOM_MODEL_German_LOW_GAIN_SNAPMAP=":::0.25"
CUSTOM_MODEL_German_MID_GAIN_SNAPMAP=":::0.25"
CUSTOM_MODEL_German_HIGH_GAIN_SNAPMAP=":::0.25"

CUSTOM_MODEL_German_EXPRESSION="
seq(

set_LF_BOOST_GAIN_IN(
	if(eq(type_2,0),
		if(eq(type_0,0),gain_0,1),
		gain_0
	)
),
set_LF_CUT_GAIN_IN(
	if(eq(type_2,0),
		if(eq(type_0,1),gain_0,1),
		gain_2
	)
),
set_LF_FREQ_IN(freq_0),
set_BELL_GAIN_IN(gain_1),
set_BELL_FREQ_IN(freq_1),
set_BELL_BANDWIDTH_POSITION(
	if(eq(type_2,0),
		if(eq(type_1,0),10,0),
		(log(freq_2)-log(3000))/(log(16000)-log(3000))*10
	)
),
set_HF_CUT_GAIN_IN(if(eq(type_2,0),gain_2,1)),
set_HF_CUT_FREQ_IN(if(eq(type_2,0),freq_2,10000)),

filter(0, seq(
	set_LF_BOOST_POSITION(lin2db(LF_BOOST_GAIN_IN)),
	set_LF_BOOST_DB(if(
		less_equal(LF_BOOST_POSITION,5),
		max(lin2db(0.967+LF_BOOST_POSITION*0.266),0),
		lin2db(-5.383+2.058*LF_BOOST_POSITION-0.104*LF_BOOST_POSITION*LF_BOOST_POSITION)
	)),
	set_LF_CUT_POSITION(lin2db(LF_CUT_GAIN_IN)),
	set_LF_CUT_DB(if(
		less_equal(LF_CUT_POSITION,5),
		max(lin2db(0.635+0.7*LF_CUT_POSITION),0),
		min(lin2db(-11.821+LF_CUT_POSITION*3.105),23.8)
	)),
	set_LF_BOOST_K(db2lin(LF_BOOST_DB)-1),
	set_LF_CUT_K(db2lin(LF_CUT_DB)-1),
	set_LF_freq_BOOST(exp(-4.02+4.316*log(LF_FREQ_IN)-0.621*pow(log(LF_FREQ_IN),2)+0.037*pow(log(LF_FREQ_IN),3))),
	set_LF_freq_CUT(exp(-2.926+4.446*log(LF_FREQ_IN)-0.662*pow(log(LF_FREQ_IN),2)+0.04*pow(log(LF_FREQ_IN),3))),
	if(
		and(greater(LF_BOOST_K,0),greater(LF_CUT_K,0)),
		parallel(1,1,1,LF_CUT_K+1,
			0,LF_BOOST_K,1,1,
			LF_freq_CUT/LF_CUT_K,
			LF_freq_BOOST/LF_BOOST_K),
		greater(LF_BOOST_K,0),
		biquad(0,1,1+LF_BOOST_K,0,1,1,LF_freq_BOOST/LF_BOOST_K),
		greater(LF_CUT_K,0),
		biquad(0,1,1,0,1,1+LF_CUT_K,LF_freq_CUT/LF_CUT_K),
		unity()
	)
)),
filter(1, seq(
	set_BELL_GAIN_POSITION(lin2db(BELL_GAIN_IN)),
	set_BELL_FREQ(exp(38.645-12.931*log(BELL_FREQ_IN)+1.673*pow(log(BELL_FREQ_IN),2)-0.067*pow(log(BELL_FREQ_IN),3))),
	set_BELL_Q(pwl(log(BELL_FREQ_IN), log(3000), 1.73, log(4000), 1.37, log(5000), 1.74, log(8000), 1.17, log(10000), 0.54, log(12000), 0.60, log(16000), 0.80)),
	set_BELL_RG(if(less_equal(BELL_GAIN_POSITION,5), max(-812.132+1791.849*BELL_GAIN_POSITION,0), min(5954.716+435.37*BELL_GAIN_POSITION,10000))),
	set_BELL_RQ(if(less_equal(BELL_BANDWIDTH_POSITION,5), 738.601+77.701*BELL_BANDWIDTH_POSITION, min(-330.912+320.829*BELL_BANDWIDTH_POSITION,2382))),
	set_BELL_CL(21/(60400 * BELL_Q)),
	set_BELL_A(BELL_RG*BELL_RG/10500*BELL_CL),
	set_BELL_B(BELL_CL*(BELL_RQ+BELL_RG-BELL_RG*BELL_RG/10500)),
	biquad(1, BELL_A+BELL_B, 1, 1, BELL_B, 1, BELL_FREQ)
)),
filter(2,seq(
	set_HF_CUT_POSITION(lin2db(HF_CUT_GAIN_IN)),
	set_HF_CUT_DB(lin2db(
		if(less(HF_CUT_POSITION,5),
			pow(max(-0.201+0.296*HF_CUT_POSITION,0),2)+1,
			pow(0.902+0.067*HF_CUT_POSITION,2)+1
		)
	)),
	set_HF_CUT_freq(exp(-9.373+2.845*log(HF_CUT_FREQ_IN)-0.098*pow(log(HF_CUT_FREQ_IN),2))),
	set_HF_CUT_G(db2lin(HF_CUT_DB)-1),
	set_HF_CUT_K(max(0.268+2.109*sqrt(HF_CUT_G)-1.385*HF_CUT_G,0)),
	biquad(0,HF_CUT_K,1,0,HF_CUT_K+HF_CUT_G,1,HF_CUT_freq)
))
)
"
/>

Here’s the preset for SlickEQ:

<TDRVOSSlickEQ lowBandGainParam="0.0" lowBandFreqParam="30" 
lowBandShapeParam="Shelf" midBandGainParam="0.0" midBandFreqParam="8000" 
highBandGainParam="0.0" highBandFreqParam="10000" 
highBandShapeParam="Shelf" eqModelParam="German" eqSatParam="Off" 
hpFreqParam="Off" outSatModelParam="Linear" outSatDriveParam="13.4" 
outGainParam="0.0" bypassParam="Off" modeParam="Stereo" 
lowBandBypassParam="Off" midBandBypassParam="Off" 
highBandBypassParam="Off" autoGainParam="On" qualityParam="Full" 

CUSTOM_MODEL_German_NAME="EQP-WA"

CUSTOM_MODEL_German_LOW_FREQ_SNAPMAP="20,30,60,100,200,400,800"
CUSTOM_MODEL_German_LOW_FREQ_MIN="20"
CUSTOM_MODEL_German_LOW_FREQ_MAX="800"
CUSTOM_MODEL_German_LOW_FREQ_DEFAULT="30"

CUSTOM_MODEL_German_MID_FREQ_SNAPMAP="3000,4000,5000,8000,10000,12000,16000"
CUSTOM_MODEL_German_MID_FREQ_MIN="3000"
CUSTOM_MODEL_German_MID_FREQ_MAX="16000"
CUSTOM_MODEL_German_MID_FREQ_DEFAULT="8000"

CUSTOM_MODEL_German_HIGH_FREQ_SNAPMAP="3000,4000,5000,10000,20000"
CUSTOM_MODEL_German_HIGH_FREQ_MIN="3000"
CUSTOM_MODEL_German_HIGH_FREQ_MAX="20000"
CUSTOM_MODEL_German_HIGH_FREQ_DEFAULT="10000"

CUSTOM_MODEL_German_LOW_GAIN_MIN="0"
CUSTOM_MODEL_German_LOW_GAIN_MAX="10"

CUSTOM_MODEL_German_MID_GAIN_MIN="0"
CUSTOM_MODEL_German_MID_GAIN_MAX="10"

CUSTOM_MODEL_German_HIGH_GAIN_MIN="0"
CUSTOM_MODEL_German_HIGH_GAIN_MAX="10"

CUSTOM_MODEL_German_LOW_GAIN_SNAPMAP=":::0.25"
CUSTOM_MODEL_German_MID_GAIN_SNAPMAP=":::0.25"
CUSTOM_MODEL_German_HIGH_GAIN_SNAPMAP=":::0.25"

CUSTOM_MODEL_German_EXPRESSION="
seq(

set_LF_BOOST_GAIN_IN(
	if(eq(type_2,0),
		if(eq(type_0,0),gain_0,1),
		gain_0
	)
),
set_LF_CUT_GAIN_IN(
	if(eq(type_2,0),
		if(eq(type_0,1),gain_0,1),
		gain_2
	)
),
set_LF_FREQ_IN(freq_0),
set_BELL_GAIN_IN(gain_1),
set_BELL_FREQ_IN(freq_1),
set_BELL_BANDWIDTH_POSITION(
	if(eq(type_2,0),
		10,
		(log(freq_2)-log(3000))/(log(16000)-log(3000))*10
	)
),
set_HF_CUT_GAIN_IN(if(eq(type_2,0),gain_2,1)),
set_HF_CUT_FREQ_IN(if(eq(type_2,0),freq_2,10000)),

filter(0, seq(
	set_LF_BOOST_POSITION(lin2db(LF_BOOST_GAIN_IN)),
	set_LF_BOOST_DB(if(
		less_equal(LF_BOOST_POSITION,5),
		max(lin2db(0.967+LF_BOOST_POSITION*0.266),0),
		lin2db(-5.383+2.058*LF_BOOST_POSITION-0.104*LF_BOOST_POSITION*LF_BOOST_POSITION)
	)),
	set_LF_CUT_POSITION(lin2db(LF_CUT_GAIN_IN)),
	set_LF_CUT_DB(if(
		less_equal(LF_CUT_POSITION,5),
		max(lin2db(0.635+0.7*LF_CUT_POSITION),0),
		min(lin2db(-11.821+LF_CUT_POSITION*3.105),23.8)
	)),
	set_LF_BOOST_K(db2lin(LF_BOOST_DB)-1),
	set_LF_CUT_K(db2lin(LF_CUT_DB)-1),
	set_LF_freq_BOOST(exp(-4.02+4.316*log(LF_FREQ_IN)-0.621*pow(log(LF_FREQ_IN),2)+0.037*pow(log(LF_FREQ_IN),3))),
	set_LF_freq_CUT(exp(-2.926+4.446*log(LF_FREQ_IN)-0.662*pow(log(LF_FREQ_IN),2)+0.04*pow(log(LF_FREQ_IN),3))),
	if(
		and(greater(LF_BOOST_K,0),greater(LF_CUT_K,0)),
		parallel(1,1,1,LF_CUT_K+1,
			0,LF_BOOST_K,1,1,
			LF_freq_CUT/LF_CUT_K,
			LF_freq_BOOST/LF_BOOST_K),
		greater(LF_BOOST_K,0),
		biquad(0,1,1+LF_BOOST_K,0,1,1,LF_freq_BOOST/LF_BOOST_K),
		greater(LF_CUT_K,0),
		biquad(0,1,1,0,1,1+LF_CUT_K,LF_freq_CUT/LF_CUT_K),
		unity()
	)
)),
filter(1, seq(
	set_BELL_GAIN_POSITION(lin2db(BELL_GAIN_IN)),
	set_BELL_FREQ(exp(38.645-12.931*log(BELL_FREQ_IN)+1.673*pow(log(BELL_FREQ_IN),2)-0.067*pow(log(BELL_FREQ_IN),3))),
	set_BELL_Q(pwl(log(BELL_FREQ_IN), log(3000), 1.73, log(4000), 1.37, log(5000), 1.74, log(8000), 1.17, log(10000), 0.54, log(12000), 0.60, log(16000), 0.80)),
	set_BELL_RG(if(less_equal(BELL_GAIN_POSITION,5), max(-812.132+1791.849*BELL_GAIN_POSITION,0), min(5954.716+435.37*BELL_GAIN_POSITION,10000))),
	set_BELL_RQ(if(less_equal(BELL_BANDWIDTH_POSITION,5), 738.601+77.701*BELL_BANDWIDTH_POSITION, min(-330.912+320.829*BELL_BANDWIDTH_POSITION,2382))),
	set_BELL_CL(21/(60400 * BELL_Q)),
	set_BELL_A(BELL_RG*BELL_RG/10500*BELL_CL),
	set_BELL_B(BELL_CL*(BELL_RQ+BELL_RG-BELL_RG*BELL_RG/10500)),
	biquad(1, BELL_A+BELL_B, 1, 1, BELL_B, 1, BELL_FREQ)
)),
filter(2,seq(
	set_HF_CUT_POSITION(lin2db(HF_CUT_GAIN_IN)),
	set_HF_CUT_DB(lin2db(
		if(less(HF_CUT_POSITION,5),
			pow(max(-0.201+0.296*HF_CUT_POSITION,0),2)+1,
			pow(0.902+0.067*HF_CUT_POSITION,2)+1
		)
	)),
	set_HF_CUT_freq(exp(-9.373+2.845*log(HF_CUT_FREQ_IN)-0.098*pow(log(HF_CUT_FREQ_IN),2))),
	set_HF_CUT_G(db2lin(HF_CUT_DB)-1),
	set_HF_CUT_K(max(0.268+2.109*sqrt(HF_CUT_G)-1.385*HF_CUT_G,0)),
	biquad(0,HF_CUT_K,1,0,HF_CUT_K+HF_CUT_G,1,HF_CUT_freq)
))
)
"
/>

Now you’ve got your own Pultec, yeah!

Analog-Based Model: Pultec MEQ5 Clone

The Pultec MEQ-5 is a mid-range equalizer offering 2 bell boost bands and 1 bell cut band. All 3 bands have stepped frequencies. The MEQ-5 equalizer is often paired with the EQP-1A.

A hardware clone called the MID-500 was used for the measurements of this model . The clone has a solid state makeup amplifier, while the original uses tubes.

MEQ5 clone used for the measurements

The measurements taken were of the actual frequency and Q values, including the gain knob behavior (“potentiometer tapers”). This unit’s crazy knob behavior has a very smooth action up to 7 and then the gain literally explodes in the 7-9 range. If you want to feel it, try adjusting it with display closed.

The LOW and HIGH SlickEQ bands represent the LOW and HIGH boost bells of the hardware unit. The MID SlickEQ band represents the unit’s MID cut bell.

Snapmaps for frequency controls portray the frequency steps on the hardware unit, and in-between values are interpolated.

To simplify gain adjustments in the model, the gain snapmaps were added to obtain +0.5, 1, 2, 3, 4, 6, 8, 10, 12 dB values for boosts and -2, -3, -4, -6, -8, -10, -12 dB for cuts.

The filter type switches in their default position (“Bell”) match original unit. In the “Shelf” and “Narrow band” positions, however, they flip the corresponding band from boost to cut and vice versa. This makes the model more useful because this EQ offers wide cuts and narrow boosts, though often an inverse action is required.

Here’s the preset for SlickEQ GE:

<TDRVOSSlickEQGE lowBandGainParam="0.0" 
lowBandFreqParam="200" lowBandShapeParam="Bell" lowBandLagParam="Off" 
midBandGainParam="0.0" midBandFreqParam="500" midBandShapeParam="Bell" 
highBandGainParam="0.0" highBandFreqParam="5000" 
highBandShapeParam="Bell" eqModelParam="Soviet" eqSatParam="Off" 
lpBypassParam="On" lpFreqParam="22000" lpModeParam="Steep" 
hpBypassParam="On" hpFreqParam="15" hpModeParam="Normal" 
tiltFreqParam="650" tiltValueParam="0.0" tiltBypassParam="On" 
tiltTypeParam="Normal" outSatModelParam="Linear" outSatDriveParam="7.5" 
outGainParam="0.0" bypassParam="Off" modeParam="Stereo" 
lowBandBypassParam="Off" midBandBypassParam="Off" 
highBandBypassParam="Off" autoGainParam="On" qualityParam="Full" 
displayScaleParam="Scale: Auto" showFreqMagnitudeParam="Off" 
hideBottomBarParam="Off" showFFTAnalyzerParam="Off"

CUSTOM_MODEL_Soviet_NAME="MID-500"

CUSTOM_MODEL_Soviet_LOW_FREQ_SNAPMAP="200,300,500,700,1000"
CUSTOM_MODEL_Soviet_MID_FREQ_SNAPMAP="200,250,300,500,700,1000,1500,2000,3000,4000,5000,7000"
CUSTOM_MODEL_Soviet_HIGH_FREQ_SNAPMAP="1500,2000,3000,4000,5000"

CUSTOM_MODEL_Soviet_LOW_FREQ_MIN="200"
CUSTOM_MODEL_Soviet_LOW_FREQ_MAX="1000"
CUSTOM_MODEL_Soviet_LOW_FREQ_DEFAULT="200"
CUSTOM_MODEL_Soviet_LOW_GAIN_MIN="0"
CUSTOM_MODEL_Soviet_LOW_GAIN_MAX="10"

CUSTOM_MODEL_Soviet_MID_FREQ_MIN="200"
CUSTOM_MODEL_Soviet_MID_FREQ_MAX="7000"
CUSTOM_MODEL_Soviet_MID_FREQ_DEFAULT="500"
CUSTOM_MODEL_Soviet_MID_GAIN_MIN="0"
CUSTOM_MODEL_Soviet_MID_GAIN_MAX="10"

CUSTOM_MODEL_Soviet_HIGH_FREQ_MIN="1500"
CUSTOM_MODEL_Soviet_HIGH_FREQ_MAX="5000"
CUSTOM_MODEL_Soviet_HIGH_FREQ_DEFAULT="3000"
CUSTOM_MODEL_Soviet_HIGH_GAIN_MIN="0"
CUSTOM_MODEL_Soviet_HIGH_GAIN_MAX="10"

CUSTOM_MODEL_Soviet_LOW_GAIN_SNAPMAP="3.207,4.852,7.126,7.498,7.793,8.222,8.531,8.775,9"
CUSTOM_MODEL_Soviet_MID_GAIN_SNAPMAP="2.844,3.719,4.934,6.217,6.958,7.499,7.934,8.626,9.176,9.639"
CUSTOM_MODEL_Soviet_HIGH_GAIN_SNAPMAP="3.075,4.715,7.05,7.574,7.9,8.379,8.753,9.143"

CUSTOM_MODEL_Soviet_EXPRESSION="
filter(band, case(band,
	0,
	seq(
		set_LF_GAIN_POSITION(lin2db(gain_0)),
		set_LF_GAIN(if(
			less(LF_GAIN_POSITION, 7),
			max(-0.475 + 0.304 * LF_GAIN_POSITION, 0),
			less(LF_GAIN_POSITION, 8.95),
			-239.437 + 99.162 * LF_GAIN_POSITION - 13.914 * pow(LF_GAIN_POSITION, 2) + 0.667 * pow(LF_GAIN_POSITION, 3),
			-8.7 + 4.1 * LF_GAIN_POSITION - 0.2 * pow(LF_GAIN_POSITION, 2)
		)),
		set_LF_S_GAIN(if(greater(LF_GAIN, 1), sqrt(LF_GAIN - 1), 0)),
		set_LF_Q0(1 / (2.230 + 2.285 * LF_S_GAIN - 0.00949 * pow(LF_S_GAIN, 2) - 0.174 * pow(LF_S_GAIN, 3))),
		set_LF_QF(pwl(log(freq_0), log(200), 0.29, log(300), 0.36, log(500), 0.27, log(700), 0.38, log(1000), 0.31)),
		set_LF_Q(LF_Q0 / 0.29 * LF_QF),
		set_LF_FREQ_VAL(exp(-1.462 + 1.529 * log(freq_0) - 0.048 * pow(log(freq_0), 2))),
		if(eq(type,1),
			biquad(1, db2lin(LF_GAIN)/LF_Q, 1, 1, 1/LF_Q, 1, LF_FREQ_VAL),
			biquad(1, 1/LF_Q, 1, 1, db2lin(LF_GAIN)/LF_Q, 1, LF_FREQ_VAL)
		)
	),
	1,
	seq(
		set_MF_GAIN_POSITION(lin2db(gain_1)),
		set_MF_GAIN(if(
			less(MF_GAIN_POSITION, 1.6),
			0,
			less(MF_GAIN_POSITION, 3),
			3.33 - 3.88 * MF_GAIN_POSITION + 1.2 * pow(MF_GAIN_POSITION, 2),
			less(MF_GAIN_POSITION, 12),
			-4.132 + 4.268 * MF_GAIN_POSITION - 0.941 * pow(MF_GAIN_POSITION, 2) + 0.0831 * pow(MF_GAIN_POSITION, 3),
			-1.967 + MF_GAIN_POSITION * 1.6
		)),
		set_MF_Q0(0.198 + 0.0155 * MF_GAIN + 0.00769 * pow(MF_GAIN, 2)),
		set_MF_QF(pwl(log(freq_1), log(200), 1.74, log(250), 2.12, log(300), 1.6, log(500), 1.6, log(700), 2.3, log(1000), 2.32,
			log(1500), 2.13, log(2000), 1.62, log(3000), 2.59, log(4000), 3.42, log(5000), 4.84, log(7000), 6.96)),
		set_MF_Q(MF_Q0 / 1.74 * MF_QF),
		set_MF_FREQ_VAL(exp(-10.438 + 5.499 * log(freq_1) - 0.641 * pow(log(freq_1), 2) + 0.030 * pow(log(freq_1), 3))),
		if(eq(type,0),
			biquad(1, 1/MF_Q, 1, 1, db2lin(MF_GAIN)/MF_Q, 1, MF_FREQ_VAL),
			biquad(1, db2lin(MF_GAIN)/MF_Q, 1, 1, 1/MF_Q, 1, MF_FREQ_VAL)
		)
	),
	2,
	seq(
		set_HF_GAIN_POSITION(lin2db(gain_2)),
		set_HF_GAIN(if(
			less(HF_GAIN_POSITION, 7),
			max(-0.438 + 0.305 * HF_GAIN_POSITION, 0),
			less(HF_GAIN_POSITION, 9),
			61.766 - 18.143 * HF_GAIN_POSITION + 1.371 * pow(HF_GAIN_POSITION, 2),
			-124.4 + 27.5 * HF_GAIN_POSITION - 1.4 * pow(HF_GAIN_POSITION, 2)
		)),
		set_HF_S_GAIN(if(greater(HF_GAIN, 1), sqrt(HF_GAIN - 1), 0)),
		set_HF_Q0(1 / (0.248 + 0.180 * HF_S_GAIN + 0.0894 * pow(HF_S_GAIN, 2) - 0.0398 * pow(HF_S_GAIN, 3))),
		set_HF_QF(pwl(log(freq_2), log(1500), 2.07, log(2000), 2.81, log(3000), 3.12, log(4000), 4.1, log(5000), 5.23)),
		set_HF_Q(HF_Q0 / 2.07 * HF_QF),
		set_HF_FREQ_VAL(exp(-5.521 + 2.416 * log(freq_2) - 0.091 * pow(log(freq_2), 2))),
		if(eq(type,1),
			biquad(1, db2lin(HF_GAIN)/HF_Q, 1, 1, 1/HF_Q, 1, HF_FREQ_VAL),
			biquad(1, 1/HF_Q, 1, 1, db2lin(HF_GAIN)/HF_Q, 1, HF_FREQ_VAL)
		)
	)
))
"
/>

Here’s the preset for SlickEQ:

<TDRVOSSlickEQ lowBandGainParam="0.0" lowBandFreqParam="200" 
lowBandShapeParam="Bell" midBandGainParam="0.0" midBandFreqParam="500" 
highBandGainParam="0.0" highBandFreqParam="3000" highBandShapeParam="Bell" 
eqModelParam="Soviet" eqSatParam="Off" hpFreqParam="Off" 
outSatModelParam="Linear" outSatDriveParam="7.5" outGainParam="0.0" 
bypassParam="Off" modeParam="Stereo" lowBandBypassParam="Off" 
midBandBypassParam="Off" highBandBypassParam="Off" autoGainParam="On" 
qualityParam="Full" 

CUSTOM_MODEL_Soviet_NAME="MID-500"

CUSTOM_MODEL_Soviet_LOW_FREQ_SNAPMAP="200,300,500,700,1000"
CUSTOM_MODEL_Soviet_MID_FREQ_SNAPMAP="200,250,300,500,700,1000,1500,2000,3000,4000,5000,7000"
CUSTOM_MODEL_Soviet_HIGH_FREQ_SNAPMAP="1500,2000,3000,4000,5000"

CUSTOM_MODEL_Soviet_LOW_FREQ_MIN="200"
CUSTOM_MODEL_Soviet_LOW_FREQ_MAX="1000"
CUSTOM_MODEL_Soviet_LOW_FREQ_DEFAULT="200"
CUSTOM_MODEL_Soviet_LOW_GAIN_MIN="0"
CUSTOM_MODEL_Soviet_LOW_GAIN_MAX="10"

CUSTOM_MODEL_Soviet_MID_FREQ_MIN="200"
CUSTOM_MODEL_Soviet_MID_FREQ_MAX="7000"
CUSTOM_MODEL_Soviet_MID_FREQ_DEFAULT="500"
CUSTOM_MODEL_Soviet_MID_GAIN_MIN="0"
CUSTOM_MODEL_Soviet_MID_GAIN_MAX="10"

CUSTOM_MODEL_Soviet_HIGH_FREQ_MIN="1500"
CUSTOM_MODEL_Soviet_HIGH_FREQ_MAX="5000"
CUSTOM_MODEL_Soviet_HIGH_FREQ_DEFAULT="3000"
CUSTOM_MODEL_Soviet_HIGH_GAIN_MIN="0"
CUSTOM_MODEL_Soviet_HIGH_GAIN_MAX="10"

CUSTOM_MODEL_Soviet_LOW_GAIN_SNAPMAP="3.207,4.852,7.126,7.498,7.793,8.222,8.531,8.775,9"
CUSTOM_MODEL_Soviet_MID_GAIN_SNAPMAP="2.844,3.719,4.934,6.217,6.958,7.499,7.934,8.626,9.176,9.639"
CUSTOM_MODEL_Soviet_HIGH_GAIN_SNAPMAP="3.075,4.715,7.05,7.574,7.9,8.379,8.753,9.143"

CUSTOM_MODEL_Soviet_EXPRESSION="
filter(band, case(band,
	0,
	seq(
		set_LF_GAIN_POSITION(lin2db(gain_0)),
		set_LF_GAIN(if(
			less(LF_GAIN_POSITION, 7),
			max(-0.475 + 0.304 * LF_GAIN_POSITION, 0),
			less(LF_GAIN_POSITION, 8.95),
			-239.437 + 99.162 * LF_GAIN_POSITION - 13.914 * pow(LF_GAIN_POSITION, 2) + 0.667 * pow(LF_GAIN_POSITION, 3),
			-8.7 + 4.1 * LF_GAIN_POSITION - 0.2 * pow(LF_GAIN_POSITION, 2)
		)),
		set_LF_S_GAIN(if(greater(LF_GAIN, 1), sqrt(LF_GAIN - 1), 0)),
		set_LF_Q0(1 / (2.230 + 2.285 * LF_S_GAIN - 0.00949 * pow(LF_S_GAIN, 2) - 0.174 * pow(LF_S_GAIN, 3))),
		set_LF_QF(pwl(log(freq_0), log(200), 0.29, log(300), 0.36, log(500), 0.27, log(700), 0.38, log(1000), 0.31)),
		set_LF_Q(LF_Q0 / 0.29 * LF_QF),
		set_LF_FREQ_VAL(exp(-1.462 + 1.529 * log(freq_0) - 0.048 * pow(log(freq_0), 2))),
		if(eq(type,1),
			biquad(1, db2lin(LF_GAIN)/LF_Q, 1, 1, 1/LF_Q, 1, LF_FREQ_VAL),
			biquad(1, 1/LF_Q, 1, 1, db2lin(LF_GAIN)/LF_Q, 1, LF_FREQ_VAL)
		)
	),
	1,
	seq(
		set_MF_GAIN_POSITION(lin2db(gain_1)),
		set_MF_GAIN(if(
			less(MF_GAIN_POSITION, 1.6),
			0,
			less(MF_GAIN_POSITION, 3),
			3.33 - 3.88 * MF_GAIN_POSITION + 1.2 * pow(MF_GAIN_POSITION, 2),
			less(MF_GAIN_POSITION, 12),
			-4.132 + 4.268 * MF_GAIN_POSITION - 0.941 * pow(MF_GAIN_POSITION, 2) + 0.0831 * pow(MF_GAIN_POSITION, 3),
			-1.967 + MF_GAIN_POSITION * 1.6
		)),
		set_MF_Q0(0.198 + 0.0155 * MF_GAIN + 0.00769 * pow(MF_GAIN, 2)),
		set_MF_QF(pwl(log(freq_1), log(200), 1.74, log(250), 2.12, log(300), 1.6, log(500), 1.6, log(700), 2.3, log(1000), 2.32,
			log(1500), 2.13, log(2000), 1.62, log(3000), 2.59, log(4000), 3.42, log(5000), 4.84, log(7000), 6.96)),
		set_MF_Q(MF_Q0 / 1.74 * MF_QF),
		set_MF_FREQ_VAL(exp(-10.438 + 5.499 * log(freq_1) - 0.641 * pow(log(freq_1), 2) + 0.030 * pow(log(freq_1), 3))),
		biquad(1, 1/MF_Q, 1, 1, db2lin(MF_GAIN)/MF_Q, 1, MF_FREQ_VAL)
	),
	2,
	seq(
		set_HF_GAIN_POSITION(lin2db(gain_2)),
		set_HF_GAIN(if(
			less(HF_GAIN_POSITION, 7),
			max(-0.438 + 0.305 * HF_GAIN_POSITION, 0),
			less(HF_GAIN_POSITION, 9),
			61.766 - 18.143 * HF_GAIN_POSITION + 1.371 * pow(HF_GAIN_POSITION, 2),
			-124.4 + 27.5 * HF_GAIN_POSITION - 1.4 * pow(HF_GAIN_POSITION, 2)
		)),
		set_HF_S_GAIN(if(greater(HF_GAIN, 1), sqrt(HF_GAIN - 1), 0)),
		set_HF_Q0(1 / (0.248 + 0.180 * HF_S_GAIN + 0.0894 * pow(HF_S_GAIN, 2) - 0.0398 * pow(HF_S_GAIN, 3))),
		set_HF_QF(pwl(log(freq_2), log(1500), 2.07, log(2000), 2.81, log(3000), 3.12, log(4000), 4.1, log(5000), 5.23)),
		set_HF_Q(HF_Q0 / 2.07 * HF_QF),
		set_HF_FREQ_VAL(exp(-5.521 + 2.416 * log(freq_2) - 0.091 * pow(log(freq_2), 2))),
		if(eq(type,1),
			biquad(1, db2lin(HF_GAIN)/HF_Q, 1, 1, 1/HF_Q, 1, HF_FREQ_VAL),
			biquad(1, 1/HF_Q, 1, 1, db2lin(HF_GAIN)/HF_Q, 1, HF_FREQ_VAL)
		)
	)
))
"
/>

Analog-Based Model: Fender Tone Stack EQ

The tone stacks in guitar amplifiers often offer 3 controls for bass, middle and treble, plus a passive EQ circuit.

It’s basically 3 connected shelving filters. The bass and treble bands are for shelving boosts, while the mid band is for cuts. The default “all knobs at noon” position gives a mid-scoop-like behavior. To completely eliminate the mid-scoop effect, set the mid control to 10.

This model is based on the tone stack EQ used in Fender amplifiers.

Tone stack circuit used

More information can be found here: www.guitarscience.net/tsc/fender.htm

This specific circuit model has the following simplifications:

  • RIN = 0
  • R1 = 10k
  • RT = B50k
  • RB = A50k
  • RM = A10k
  • C1 = 740p
  • C2 = INF (bypassed)
  • C3 = 470n
  • RL = INF

The LOW, MID and HIGH GAIN knobs control bass, middle and treble. The LOW and HIGH FREQ knobs control C1 and C3, thus allowing for frequency changes of the shelves.

The band types and MID FREQ controls do nothing.

With “auto gain” turned on, this model becomes a good candidate for tone shaping EQ. It’s fast and simple with crazy band interaction.

Here’s the preset for SlickEQ GE:

<TDRVOSSlickEQGE lowBandGainParam="5.0" lowBandFreqParam="41" 
lowBandShapeParam="Shelf" lowBandLagParam="Off" midBandGainParam="10.0" 
midBandFreqParam="2500" midBandShapeParam="Bell" highBandGainParam="5.0" 
highBandFreqParam="6773" highBandShapeParam="Shelf" 
eqModelParam="Japanese" eqSatParam="Off" lpBypassParam="On" 
lpFreqParam="22000" lpModeParam="Steep" hpBypassParam="On" 
hpFreqParam="15" hpModeParam="Normal" tiltFreqParam="650" 
tiltValueParam="0.0" tiltBypassParam="On" tiltTypeParam="Normal" 
outSatModelParam="Linear" outSatDriveParam="6.0" outGainParam="0.0" 
bypassParam="Off" modeParam="Stereo" lowBandBypassParam="Off" 
midBandBypassParam="Off" highBandBypassParam="Off" autoGainParam="On" 
qualityParam="Full" displayScaleParam="Scale: Auto" 
showFreqMagnitudeParam="Off" hideBottomBarParam="Off" 
showFFTAnalyzerParam="Off"

CUSTOM_MODEL_Japanese_NAME="ToneStack"

CUSTOM_MODEL_Japanese_LOW_FREQ_SNAPMAP=":::1"
CUSTOM_MODEL_Japanese_MID_FREQ_SNAPMAP=":::1"
CUSTOM_MODEL_Japanese_HIGH_FREQ_SNAPMAP=":::1"

CUSTOM_MODEL_Japanese_LOW_GAIN_MIN="0"
CUSTOM_MODEL_Japanese_LOW_GAIN_MAX="10"
CUSTOM_MODEL_Japanese_LOW_GAIN_DEFAULT="5"

CUSTOM_MODEL_Japanese_MID_GAIN_MIN="0"
CUSTOM_MODEL_Japanese_MID_GAIN_MAX="10"
CUSTOM_MODEL_Japanese_MID_GAIN_DEFAULT="10"

CUSTOM_MODEL_Japanese_HIGH_GAIN_MIN="0"
CUSTOM_MODEL_Japanese_HIGH_GAIN_MAX="10"
CUSTOM_MODEL_Japanese_HIGH_GAIN_DEFAULT="5"

CUSTOM_MODEL_Japanese_LOW_FREQ_MIN="10"
CUSTOM_MODEL_Japanese_LOW_FREQ_MAX="200"
CUSTOM_MODEL_Japanese_LOW_FREQ_DEFAULT="41"

CUSTOM_MODEL_Japanese_HIGH_FREQ_MIN="2000"
CUSTOM_MODEL_Japanese_HIGH_FREQ_MAX="20000"
CUSTOM_MODEL_Japanese_HIGH_FREQ_DEFAULT="6773"


CUSTOM_MODEL_Japanese_EXPRESSION="
seq(
filter(0, unity()),
filter(2, unity()),
filter(1, seq(
	set_BASS_POSITION(lin2db(gain_0)/10),
	set_MID_POSITION(lin2db(gain_1)/10),
	set_TREBLE_POSITION(lin2db(gain_2)/10),
	set_BASS_TAPER(1/80 * exp(2 * log(9) * BASS_POSITION) - 1/80),
	set_MID_TAPER(1/80 * exp(2 * log(9) * MID_POSITION) - 1/80),
	set_TREBLE_TAPER(TREBLE_POSITION),
	set_R1(10e3),
	set_RB_MAX(50e3),
	set_RM_MAX(10e3),
	set_RT(50e3),
	set_RB(RB_MAX * BASS_TAPER),
	set_RM(RM_MAX * MID_TAPER),
	set_K(TREBLE_TAPER),
	set_C1(1 / (2 * PI * freq_2 * RT)),
	set_C3((R1 + RB_MAX) / (2 * PI * freq_0 * R1 * RB_MAX)),
	set_MAKEUP(db2lin(18)),
	set_wH((R1 + RM) / ((R1 * RT + RM *(RT + R1)) * C1)),
	if(greater(RB, 0),
		seq(
			set_GH((RM * (RT + R1) + R1 * RT * K) / (R1 * RT + RM * (RT + R1))),
			set_wL((R1 + RM + RB) / ((R1 + RM) * RB * C3)),
			set_GL((RB + RM) / (C1 * C3 * RB * (R1 * RT + RM * (RT + R1))) / (wL * wH)),
			set_GM(((((RM + RB) * (RT + R1) + R1 * RT * K) * C1 + RM * C3 * RB) / (C1 * C3 * RB * (R1 * RT + RM * (RT + R1))) - wL * (GL + GH)) / (wH - wL)),
			parallel(GM * MAKEUP, GL * MAKEUP, 1, 1, (GH - GM) * MAKEUP, 0, 1, 1, wL / (2 * PI), wH / (2 * PI))
		),
		seq(
			set_GH_2(RM / (R1 + RM)),
			set_GM_2((RM * (RT + R1) + R1 * RT * K) / (R1 * RT + RM * (RT + R1))),
			parallel(0, GM_2 * MAKEUP, 0, 1, 0, (GH_2 - GM_2) * MAKEUP, 1, 1, 10, wH / (2 * PI))
		)
	)
)))"

/>

Here’s the model for SlickEQ:

<TDRVOSSlickEQ lowBandGainParam="5.0" lowBandFreqParam="41" 
lowBandShapeParam="Shelf" midBandGainParam="10.0" midBandFreqParam="2500" 
highBandGainParam="5.0" highBandFreqParam="6773" 
highBandShapeParam="Shelf" eqModelParam="Soviet" eqSatParam="Off" 
hpFreqParam="Off" outSatModelParam="Linear" outSatDriveParam="6.0" 
outGainParam="0.0" bypassParam="Off" modeParam="Stereo" 
lowBandBypassParam="Off" midBandBypassParam="Off" 
highBandBypassParam="Off" autoGainParam="On" qualityParam="Full" 

CUSTOM_MODEL_Soviet_NAME="ToneStack"

CUSTOM_MODEL_Soviet_LOW_FREQ_SNAPMAP=":::1"
CUSTOM_MODEL_Soviet_MID_FREQ_SNAPMAP=":::1"
CUSTOM_MODEL_Soviet_HIGH_FREQ_SNAPMAP=":::1"

CUSTOM_MODEL_Soviet_LOW_GAIN_MIN="0"
CUSTOM_MODEL_Soviet_LOW_GAIN_MAX="10"
CUSTOM_MODEL_Soviet_LOW_GAIN_DEFAULT="5"

CUSTOM_MODEL_Soviet_MID_GAIN_MIN="0"
CUSTOM_MODEL_Soviet_MID_GAIN_MAX="10"
CUSTOM_MODEL_Soviet_MID_GAIN_DEFAULT="10"

CUSTOM_MODEL_Soviet_HIGH_GAIN_MIN="0"
CUSTOM_MODEL_Soviet_HIGH_GAIN_MAX="10"
CUSTOM_MODEL_Soviet_HIGH_GAIN_DEFAULT="5"

CUSTOM_MODEL_Soviet_LOW_FREQ_MIN="10"
CUSTOM_MODEL_Soviet_LOW_FREQ_MAX="200"
CUSTOM_MODEL_Soviet_LOW_FREQ_DEFAULT="41"

CUSTOM_MODEL_Soviet_HIGH_FREQ_MIN="2000"
CUSTOM_MODEL_Soviet_HIGH_FREQ_MAX="20000"
CUSTOM_MODEL_Soviet_HIGH_FREQ_DEFAULT="6773"

CUSTOM_MODEL_Soviet_EXPRESSION="
seq(
filter(0, unity()),
filter(2, unity()),
filter(1, seq(
	set_BASS_POSITION(lin2db(gain_0)/10),
	set_MID_POSITION(lin2db(gain_1)/10),
	set_TREBLE_POSITION(lin2db(gain_2)/10),
	set_BASS_TAPER(1/80 * exp(2 * log(9) * BASS_POSITION) - 1/80),
	set_MID_TAPER(1/80 * exp(2 * log(9) * MID_POSITION) - 1/80),
	set_TREBLE_TAPER(TREBLE_POSITION),
	set_R1(10e3),
	set_RB_MAX(50e3),
	set_RM_MAX(10e3),
	set_RT(50e3),
	set_RB(RB_MAX * BASS_TAPER),
	set_RM(RM_MAX * MID_TAPER),
	set_K(TREBLE_TAPER),
	set_C1(1 / (2 * PI * freq_2 * RT)),
	set_C3((R1 + RB_MAX) / (2 * PI * freq_0 * R1 * RB_MAX)),
	set_MAKEUP(db2lin(18)),
	set_wH((R1 + RM) / ((R1 * RT + RM *(RT + R1)) * C1)),
	if(greater(RB, 0),
		seq(
			set_GH((RM * (RT + R1) + R1 * RT * K) / (R1 * RT + RM * (RT + R1))),
			set_wL((R1 + RM + RB) / ((R1 + RM) * RB * C3)),
			set_GL((RB + RM) / (C1 * C3 * RB * (R1 * RT + RM * (RT + R1))) / (wL * wH)),
			set_GM(((((RM + RB) * (RT + R1) + R1 * RT * K) * C1 + RM * C3 * RB) / (C1 * C3 * RB * (R1 * RT + RM * (RT + R1))) - wL * (GL + GH)) / (wH - wL)),
			parallel(GM * MAKEUP, GL * MAKEUP, 1, 1, (GH - GM) * MAKEUP, 0, 1, 1, wL / (2 * PI), wH / (2 * PI))
		),
		seq(
			set_GH_2(RM / (R1 + RM)),
			set_GM_2((RM * (RT + R1) + R1 * RT * K) / (R1 * RT + RM * (RT + R1))),
			parallel(0, GM_2 * MAKEUP, 0, 1, 0, (GH_2 - GM_2) * MAKEUP, 1, 1, 10, wH / (2 * PI))
		)
	)
)))"

/>

This brings to a close our maiden primer on creating SlickEQ custom models. We look forward to seeing you share your own custom models with the rest of the Tokyo Dawn Labs community on our Facebook, Twitter, and YouTube social media platforms.

Published inTech Articles
Copyright (c) 2020 Tokyo Dawn Records