Skip to content

Analog Character: DelayLine Interpolation + ConsoleBus

Overview

Two targeted changes to reduce digital artifacts and add analog warmth to the signal path:

  1. DelayLine Hermite interpolation — eliminates metallic coloring in chorus/flanger/short-delay effects
  2. ConsoleBus component — models analog summing bus character at mixing junctions

DelayLine Hermite Interpolation

Problem

Linear interpolation between delay buffer samples introduces high-frequency artifacts (metallic coloring) at short delay times (< 20ms), which is especially audible in chorus and flanger effects.

Solution

Added a 3rd parameter Interpolation (enum: Linear=0, Hermite=1, default=1) and a readHermite() method alongside the existing readInterpolated().

Hermite cubic interpolation uses 4 buffer samples and a 3rd-order polynomial:

Given samples s[-1], s[0], s[1], s[2] and fractional position t:
  a = -0.5*s[-1] + 1.5*s[0] - 1.5*s[1] + 0.5*s[2]
  b =      s[-1] - 2.5*s[0] + 2.0*s[1] - 0.5*s[2]
  c = -0.5*s[-1]             + 0.5*s[1]
  d =                   s[0]
  output = ((a*t + b)*t + c)*t + d

Cost: ~3 extra multiplies per sample vs linear. The process() method branches on the atomic interpolation_ load to select the interpolation mode at runtime.

Buffer constraints

  • Linear: max delay = kMaxDelaySamples - 2 (needs idx+1)
  • Hermite: max delay = kMaxDelaySamples - 3 (needs idx+2)

Files changed

  • FolioDSP/.../Primitives/DelayLine.hkInterpolation param, interpolation_ atomic, readHermite() declaration
  • FolioDSP/.../Primitives/DelayLine.cppreadHermite() implementation, process() branching, parameter routing
  • FolioDSP/components.json — Interpolation parameter with enum labels
  • FolioDSP/.../Core/ComponentsData.cpp — enum labels array, 3rd ParameterDescriptor, param count 2→3

Recipe usage

Set "Interpolation": 1.0 on any DelayLine node to use Hermite (this is the default for new instances, but existing recipe JSON files may need updating). The prospero.json recipe was updated as a reference.


ConsoleBus Component

Design

A lightweight processor (ComponentType 68, category "Color") that models analog summing bus character. Ultra-subtle by default — designed to sit at mixing junctions or as a "stage" between effects.

Parameters

Index Name Range Default Unit Description
0 Drive 0–1 0.15 Raw Input gain into saturation
1 Tone 200–20000 12000 Hz One-pole LPF cutoff (HF rolloff)
2 Noise Floor -100–-40 -80 dB Shaped noise level (-100 = off)
3 Mix 0–100 100 % Dry/wet blend

Processing chain (per sample)

  1. Soft asymmetric saturation: tanh(x * (1 + drive)) + 0.1 * drive * x * x — the term generates even harmonics (transformer character), scaled by drive. Very gentle at default 0.15.
  2. HF rolloff: One-pole LPF at Tone frequency. Mimics summing amp bandwidth limitation.
  3. Noise floor: xorshift32 PRNG → one-pole LPF at ~1 kHz (pink-ish shaping) → scale by 10^(noiseFloorDb/20). Adds the analog "air" between samples.
  4. DC blocker: One-pole HP at ~10 Hz removes DC offset from the asymmetric saturation.
  5. Dry/wet mix.

No oversampling needed — at these low drive levels, aliasing products are below the noise floor.

Snapshot fields

  • inputLevel (float, 0–1)
  • outputLevel (float, 0–1)
  • driveAmount (float, 0–1) — current smoothed drive
  • gainReduction (float, 0–6 dB) — saturation compression

Files created

  • FolioDSP/.../Color/ConsoleBus.h
  • FolioDSP/.../Color/ConsoleBus.cpp

Files modified

  • FolioDSP/.../Core/Types.hConsoleBus = 68
  • FolioDSP/.../Core/Snapshots.hConsoleBusSnapshot
  • FolioDSP/.../FolioDSP.h — umbrella include
  • FolioDSP/components.json — full component entry
  • FolioDSP/.../Core/ComponentsData.cpp — params, snapshots, descriptor (array 68→69)
  • FolioDSPBridge.h / FolioDSPBridge.mmConsoleBusBridge
  • Packages/Touchstone/.../BridgeAdapter.swiftcase consoleBus = "Console Bus" + init case

Warm Bus Recipe

Reference recipe demonstrating the analog console channel strip pattern:

TubeWarmth → TapeSaturation → TransformerColor → ConsoleBus → DCBlocker

Exposed parameters: Warmth (tube drive), Saturation (tape drive), Air (transformer rolloff), Console (bus drive).

File: Packages/Touchstone/Sources/Touchstone/Recipes/warm_bus.json

Design notes

  • Why not oversample ConsoleBus? At Drive=0.15 (default), the saturation is so gentle that aliasing harmonics are 60+ dB below the fundamental. TubeWarmth and TransformerColor already have 2x oversampling for when heavier saturation is needed.
  • Why Hermite over higher-order interpolation? Hermite (4-point cubic) gives the best quality/cost tradeoff for audio delay lines. Lagrange or sinc interpolation would improve HF response further but at 2-5x the cost per sample — not justified for the typical use cases.
  • Noise PRNG choice: xorshift32 is sufficient for shaped noise floor — it's fast (3 XOR + shift ops), has a full 2^32 period, and the one-pole shaping filter masks any statistical imperfections.