Transformer Color
Tier: Color | ComponentType: 29 | Params: 5
Low-frequency saturation with high-frequency rolloff and resonance bump, modeling the nonlinear behavior of audio transformers.
Overview
TransformerColor simulates the tonal character of iron-core audio transformers found in vintage mixing consoles, tape machines, and microphone preamps. These transformers exhibit two key behaviors: the ferromagnetic core saturates low-frequency content (introducing soft, warm distortion), while parasitic capacitance and winding inductance create a natural high-frequency rolloff with an optional resonance peak just before the cutoff.
The implementation splits the input signal into low and high frequency bands using a one-pole crossover filter. The low band is processed through tanh saturation scaled by the drive parameter, adding subtle harmonic content that increases with signal level. The high band passes through a separate one-pole rolloff filter that progressively attenuates upper frequencies. An optional resonance bump near the rolloff frequency, created via a bandpass approximation from two cascaded one-pole filters, recreates the characteristic "air" peak found in many transformer-coupled circuits.
At low drive settings, the effect adds subtle weight and presence. At higher drive values, the low-end saturation becomes more pronounced, compressing transients and thickening the bass. The crossover frequency determines where saturation begins, and the rolloff frequency controls the high-frequency character from dark (low rolloff) to open (high rolloff).
File Locations
| Path | |
|---|---|
| Header | Sources/FolioDSP/include/FolioDSP/Color/TransformerColor.h |
| Implementation | Sources/FolioDSP/src/Color/TransformerColor.cpp |
| Tests | Tests/FolioDSPTests/TransformerColorTests.swift |
| Bridge | Sources/FolioDSPBridge/src/FolioDSPBridge.mm (TransformerColorBridge) |
Parameters
| Index | Name | Description | Min | Max | Default Min | Default Max | Default | Unit |
|---|---|---|---|---|---|---|---|---|
| 0 | Drive | Saturation intensity applied to the low band | 1.0 | 20.0 | 1.0 | 5.0 | 2.0 | |
| 1 | Crossover | Frequency dividing low (saturated) and high (rolloff) bands | 50 | 2000 | 100 | 1000 | 300 | Hz |
| 2 | Rolloff | One-pole lowpass cutoff applied to the high band | 2000 | 20000 | 4000 | 16000 | 10000 | Hz |
| 3 | Resonance | Peak gain near the rolloff frequency | 0.0 | 12.0 | 0.0 | 6.0 | 2.0 | dB |
| 4 | Mix | Dry/wet blend | 0 | 100 | 0 | 100 | 100 | % |
Processing Algorithm
The process() function executes these steps for each input sample:
1. Crossover Split
A one-pole lowpass filter separates the signal into low and high bands:
2. Low Band Saturation
The low band is passed through tanh saturation with a normalization factor:
where \(d\) is the drive parameter. The denominator normalizes the output level so that increasing drive does not dramatically change the overall level, only the saturation character.
3. High Band Rolloff
A one-pole lowpass filter attenuates upper harmonics in the high band:
4. Resonance Bump
When resonance is greater than 0 dB, a bandpass approximation adds a peak near the rolloff frequency. Two cascaded one-pole filters create the bandpass:
The bandpass signal \((s_0 - s_1)\) has peak gain near the rolloff frequency and falls off on both sides, mimicking a transformer's resonance hump.
5. Recombine
6. DC Blocker
A first-order highpass filter removes any DC offset from the saturation stage:
7. Dry/Wet Mix
Core Equations
Where \(x_{\text{low}}\) and \(x_{\text{high}}\) are the crossover-split bands, \(d\) = drive, and \(G_{\text{res}}\) = linear resonance gain.
Snapshot Fields
| Field | Type | Range | Unit | Description |
|---|---|---|---|---|
| Input Level | Float | 0--1 | Smoothed input amplitude | |
| Output Level | Float | 0--1 | Smoothed output amplitude | |
| Low Band Level | Float | 0--1 | Smoothed low band amplitude | |
| High Band Level | Float | 0--1 | Smoothed high band amplitude | |
| Drive Amount | Float | 1--20 | Current drive value | |
| Gain Reduction | Float | -60--0 | dB | Output-to-input ratio in dB, clamped to non-positive |
| Transfer Curve | Float[16] | -1--1 | 16-point saturation transfer function |
Implementation Notes
- Gain reduction is computed as \(20 \log_{10}(\text{outputLevel} / \text{inputLevel})\), clamped to \(\leq 0\), with a guard against division by zero.
- Transfer curve is computed in the snapshot emission path (not per-sample), sampling 16 points from \(x = -1\) to \(+1\) through the current saturation function.
- DC blocker uses the standard first-order highpass:
y = x - xprev + R * ywhereR = 1 - (2pi*10/sr). - Level tracking uses exponential smoothing with coefficient 0.01 for display-rate visualization.
- The resonance bandpass is only computed when
resLin > 0, avoiding unnecessary work when resonance is at 0 dB. - All parameters use
std::atomic<float>for lock-free thread safety. - Snapshot emission is decimated to ~60 fps (every 735 samples at 44.1 kHz).
Equation Summary
y = sat(lo) + rolloff(hi) + resonance