Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
pulp::signal::tape Namespace Reference

Published tables and closed forms, free of any instance so a test can assert the SHIPPED constant rather than a copy of it. More...

Classes

struct  EqTimeConstants
 One standard's pair of time constants, in SECONDS. More...
struct  HeadGapGeometry
 Reproduce and record gap widths for one speed class, in METRES. More...
struct  ArchetypePreset
 The complete baked preset for one machine. More...

Functions

EqTimeConstants eq_time_constants (TapeCurve curve, double speed_ips) noexcept
 The published time-constant table, selected by (curve, speed).
double eq_corner_hz (double tau_s) noexcept
 Corner frequency of a time constant, in Hz. f = 1 / (2π·t).
double eq_record_response_db (const EqTimeConstants &tc, double hz) noexcept
 The analog record (pre-emphasis) prototype H(s) = (1 + s·t₁)/(1 + s·t₂), in dB, normalized to 0 dB at kEqReferenceHz.
double eq_playback_response_db (const EqTimeConstants &tc, double hz) noexcept
 The playback (de-emphasis) network is the exact reciprocal of the record network, so its response is the negation.
HeadGapGeometry head_gap_geometry (double speed_ips) noexcept
 Gap widths by speed class.
double speed_m_per_s (double speed_ips) noexcept
 Tape speed in metres per second.
double gap_loss_magnitude (double hz, double gap_m, double speed_ips) noexcept
 Westmijze's reproduce gap loss: |sin(π·g/λ) / (π·g/λ)|, λ = v/f.
double gap_loss_db (double hz, double gap_m, double speed_ips) noexcept
double gap_null_hz (double gap_m, double speed_ips) noexcept
 First extinction null, where λ = g: f = v / g.
double age_print_through_db (double age01) noexcept
double age_bias_drift (double age01) noexcept
double first_order_shelf_db (double corner_hz, double gain_linear, double hz, double sample_rate) noexcept
 Magnitude, in dB, of the REALIZED chardelay::FirstOrderShelf — the TPT one-pole shelf this module uses for both the bias shelf and the crosstalk tilt.
ArchetypePreset archetype_preset (TapeArchetype archetype) noexcept
 Baked defaults per §5 of the source spec.
double snap_speed_ips (TapeArchetype archetype, double requested_ips) noexcept
 Nearest legal speed for an archetype.

Variables

constexpr std::array< double, 5 > kSpeedsIps = {1.875, 3.75, 7.5, 15.0, 30.0}
 The halving speed ladder, in inches per second.
constexpr double kMetresPerInch = 0.0254
 Inches to metres. Exact by definition of the international inch.
constexpr double kEqReferenceHz = 1000.0
 The frequency every EQ curve in this module is normalized to be unity at.
constexpr std::array< double, 3 > kAgeAxis = {0.0, 0.5, 1.0}
 The reused kAgeAxis table drives spacing, hiss, chew and degrade, and kTapeAxis drives wow/flutter depth — all reused verbatim.
constexpr std::array< double, 3 > kAgePrintThroughDb = {-80.0, -55.0, -38.0}
 Storage print grows with age.
constexpr std::array< double, 3 > kAgeBiasDriftUnits = {0.0, 0.15, 0.4}
 An aging bias supply drifts toward OVER-bias — the documented failure direction, since oscillator components drift high more often than low.

Detailed Description

Published tables and closed forms, free of any instance so a test can assert the SHIPPED constant rather than a copy of it.

Function Documentation

◆ age_bias_drift()

double pulp::signal::tape::age_bias_drift ( double age01)
inlinenoexcept

◆ age_print_through_db()

double pulp::signal::tape::age_print_through_db ( double age01)
inlinenoexcept

◆ archetype_preset()

ArchetypePreset pulp::signal::tape::archetype_preset ( TapeArchetype archetype)
inlinenoexcept

Baked defaults per §5 of the source spec.

ampex_350_440 legal speeds {15, 7.5} [design parameter — the documented two-speed Ampex 350 configuration; 440-class descendants add 30 ips and are offered as a superset by selecting the Studer row instead]. studer_a800 {30, 15, 7.5} and its ≥40 dB crosstalk figure are PUBLISHED. cassette_deck is fixed at 1.875 ips by the cassette standard.

Crosstalk: −40 dB for the A800 is published (100 Hz–12 kHz). −38 dB for the Ampex class [dp, range −45 .. −30 dB] and −30 dB for cassette [dp, range −35 .. −22 dB] are honest design choices positioned against that one verified figure — no comparable published number surfaced for either. Cassette's narrower track pitch making crosstalk worse than open-reel is the documented direction; the magnitude is ours.

Starting age01: 0.2 for the Ampex class [dp, range 0.1–0.35 — "a machine with some hours on it"], 0.05 for the Studer [dp, 0.0–0.15 — well-maintained flagship], 0.3 for cassette [dp, 0.2–0.5 — consumer-grade wear expectation].

◆ eq_corner_hz()

double pulp::signal::tape::eq_corner_hz ( double tau_s)
inlinenoexcept

Corner frequency of a time constant, in Hz. f = 1 / (2π·t).

◆ eq_playback_response_db()

double pulp::signal::tape::eq_playback_response_db ( const EqTimeConstants & tc,
double hz )
inlinenoexcept

The playback (de-emphasis) network is the exact reciprocal of the record network, so its response is the negation.

◆ eq_record_response_db()

double pulp::signal::tape::eq_record_response_db ( const EqTimeConstants & tc,
double hz )
inlinenoexcept

The analog record (pre-emphasis) prototype H(s) = (1 + s·t₁)/(1 + s·t₂), in dB, normalized to 0 dB at kEqReferenceHz.

This is what the realized filter is measured against. It is stated here as a closed form rather than as a table of expected decibels so an acceptance test computes its expectations from the shipped time constants instead of restating them.

◆ eq_time_constants()

EqTimeConstants pulp::signal::tape::eq_time_constants ( TapeCurve curve,
double speed_ips )
inlinenoexcept

The published time-constant table, selected by (curve, speed).

Reel speeds are matched against the ladder rather than compared for equality, because set_speed_ips snaps to the ladder and a caller may hand in 15.000000001. Speeds below a curve's lowest tabulated row fall back to that row: NAB's 3180/50 µs pair is the documented reel-to-reel figure and there is no separate published row for a NAB machine run at 3.75 ips.

◆ first_order_shelf_db()

double pulp::signal::tape::first_order_shelf_db ( double corner_hz,
double gain_linear,
double hz,
double sample_rate )
inlinenoexcept

Magnitude, in dB, of the REALIZED chardelay::FirstOrderShelf — the TPT one-pole shelf this module uses for both the bias shelf and the crosstalk tilt.

Stated in closed form rather than measured by rendering because two callers need it: the crosstalk stage normalizes its tilt at kEqReferenceHz using it, and the suite asserts the bias shelf against it. Deriving it from the analog prototype instead would leave a bilinear-warping error inside a tolerance, which is exactly the kind of slop that hides a real coefficient bug. From the TPT recurrence y = g·x + (1−g)·s, s' = 2g·x + (1−2g)·s: H_lp(z) = g(1 + z⁻¹) / (1 − (1−2g)z⁻¹), and the shelf is G + (1−G)·H_lp.

◆ gap_loss_db()

double pulp::signal::tape::gap_loss_db ( double hz,
double gap_m,
double speed_ips )
inlinenoexcept

◆ gap_loss_magnitude()

double pulp::signal::tape::gap_loss_magnitude ( double hz,
double gap_m,
double speed_ips )
inlinenoexcept

Westmijze's reproduce gap loss: |sin(π·g/λ) / (π·g/λ)|, λ = v/f.

Note this is exactly the gap term of the reused Wallace model, evaluated at THIS module's speed-class gap rather than at the delay tier's fixed 3 µm — the argument k·g/2 there is (2πf/v)·g/2 = π·g/λ here. Same published formula, a different head.

◆ gap_null_hz()

double pulp::signal::tape::gap_null_hz ( double gap_m,
double speed_ips )
inlinenoexcept

First extinction null, where λ = g: f = v / g.

◆ head_gap_geometry()

HeadGapGeometry pulp::signal::tape::head_gap_geometry ( double speed_ips)
inlinenoexcept

Gap widths by speed class.

Published typical RANGES; the specific value inside each range is a design parameter.

Studio 15/30 ips reproduce 3.5 µm [design parameter, range 2–5 µm — the documented professional reproduce-gap range], record 10 µm [dp, 8–13 µm]. Consumer reel 7.5/3.75 ips reproduce 5 µm [dp, 3–7 µm], record 12 µm [dp, 8–15 µm]. Cassette 1.875 ips reproduce 0.8 µm [dp, 0.5–1.2 µm — the documented sub-micron cassette reproduce-gap range], record 3 µm [dp, 2–5 µm]. Record gaps run wider than reproduce gaps throughout, which is convention rather than accident: the recording side has the lower resolution requirement.

◆ snap_speed_ips()

double pulp::signal::tape::snap_speed_ips ( TapeArchetype archetype,
double requested_ips )
inlinenoexcept

Nearest legal speed for an archetype.

A cassette deck never reports 30 ips no matter what it is asked for.

◆ speed_m_per_s()

double pulp::signal::tape::speed_m_per_s ( double speed_ips)
inlinenoexcept

Tape speed in metres per second.

Variable Documentation

◆ kAgeAxis

std::array<double, 3> pulp::signal::tape::kAgeAxis = {0.0, 0.5, 1.0}
inlineconstexpr

The reused kAgeAxis table drives spacing, hiss, chew and degrade, and kTapeAxis drives wow/flutter depth — all reused verbatim.

These two columns are new phenomena a feedback-loop delay has no way to model: print-through needs storage time, and bias drift is a maintenance state rather than a per-repeat one. [all design parameters]

◆ kAgeBiasDriftUnits

std::array<double, 3> pulp::signal::tape::kAgeBiasDriftUnits = {0.0, 0.15, 0.4}
inlineconstexpr

An aging bias supply drifts toward OVER-bias — the documented failure direction, since oscillator components drift high more often than low.

Added to whatever bias_c the user set, then clamped. [dp]

◆ kAgePrintThroughDb

std::array<double, 3> pulp::signal::tape::kAgePrintThroughDb = {-80.0, -55.0, -38.0}
inlineconstexpr

Storage print grows with age.

[dp] Sets the print_through_db range: the baked parameter's −80 .. −38 dB bounds ARE this table's extremes.

◆ kEqReferenceHz

double pulp::signal::tape::kEqReferenceHz = 1000.0
inlineconstexpr

The frequency every EQ curve in this module is normalized to be unity at.

1 kHz is the tape-alignment reference and the frequency every published record/reproduce curve is quoted relative to. See the header's note on why the raw prototype cannot be used unnormalized.

◆ kMetresPerInch

double pulp::signal::tape::kMetresPerInch = 0.0254
inlineconstexpr

Inches to metres. Exact by definition of the international inch.

◆ kSpeedsIps

std::array<double, 5> pulp::signal::tape::kSpeedsIps = {1.875, 3.75, 7.5, 15.0, 30.0}
inlineconstexpr

The halving speed ladder, in inches per second.

Published convention: 30/15/7.5 ips professional, 7.5/3.75 ips domestic reel, and 1.875 ips (4.75 cm/s) as the fixed Compact Cassette speed.