|
| constexpr double | pulp::signal::chardelay::kMaxDelayMs = 2000.0 |
| | Maximum left-channel base delay and stereo-offset bounds.
|
| constexpr double | pulp::signal::chardelay::kTimeOffsetMin = 0.5 |
| constexpr double | pulp::signal::chardelay::kTimeOffsetMax = 1.5 |
| constexpr double | pulp::signal::chardelay::kMaxAddressableDelayMs = kMaxDelayMs * kTimeOffsetMax |
| constexpr int | pulp::signal::chardelay::kControlInterval = 32 |
| | Coefficient recomputation and stochastic-walk stepping cadence, in samples.
|
| constexpr double | pulp::signal::chardelay::kParamGlideS = 0.005 |
| | De-zipper glide for scalar params (feedback, crossfeed, duck, freeze, and the character table's per-sample outputs), in seconds.
|
| constexpr double | pulp::signal::chardelay::kUnsaturatedFeedbackMax = 0.98 |
| | Feedback ceiling for the characters with NO in-loop saturator.
|
| constexpr double | pulp::signal::chardelay::kSaturatedFeedbackMax = 1.1 |
| | Feedback ceiling for the saturating characters.
|
| constexpr double | pulp::signal::chardelay::kModRateMinHz = 0.05 |
| | Generic modulation LFO: log rate map and maximum depth as a fraction of delay time.
|
| constexpr double | pulp::signal::chardelay::kModRateMaxHz = 10.0 |
| constexpr double | pulp::signal::chardelay::kModMaxDepth = 0.05 |
| constexpr double | pulp::signal::chardelay::kLoopToneHpMinHz = 20.0 |
| | User-facing in-loop tone stage.
|
| constexpr double | pulp::signal::chardelay::kLoopToneHpMaxHz = 2000.0 |
| constexpr double | pulp::signal::chardelay::kLoopToneLpMinHz = 200.0 |
| constexpr double | pulp::signal::chardelay::kLoopToneLpMaxHz = 20000.0 |
| constexpr double | pulp::signal::chardelay::kLoopToneNyquistFraction = 0.45 |
| | Keep the TPT prewarp strictly below Nyquist.
|
| constexpr double | pulp::signal::chardelay::kLoopToneResMin = 0.5 |
| | Resonance range for both loop-tone filters.
|
| constexpr double | pulp::signal::chardelay::kLoopToneResMax = 2.0 |
| constexpr double | pulp::signal::chardelay::kStereoDecorr = 0.95 |
| | Right-channel depth scaler for every shared-LFO modulation.
|
| constexpr std::uint32_t | pulp::signal::chardelay::kPrngSeed = 74207u |
| | PRNG seed.
|
| constexpr double | pulp::signal::chardelay::kTimeSlewCleanMs = 15.0 |
| constexpr double | pulp::signal::chardelay::kTimeSlewVintageMs = 50.0 |
| constexpr double | pulp::signal::chardelay::kTimeSlewTapeMs = 250.0 |
| constexpr double | pulp::signal::chardelay::kTimeSlewBbdMs = 80.0 |
| constexpr double | pulp::signal::chardelay::kTimeSlewDiffusionMs = 15.0 |
| constexpr std::array< double, 3 > | pulp::signal::chardelay::kCleanAxis = {0.0, 0.5, 1.0} |
| constexpr std::array< double, 3 > | pulp::signal::chardelay::kCleanLoopLpHz = {20000.0, 12000.0, 6000.0} |
| constexpr std::array< double, 3 > | pulp::signal::chardelay::kCleanLoopHpHz = {20.0, 20.0, 120.0} |
| constexpr double | pulp::signal::chardelay::kLoopLpBypassHz = 20000.0 |
| | A loop lowpass at or above this cutoff is BYPASSED rather than run.
|
| constexpr std::array< double, 4 > | pulp::signal::chardelay::kVintageAxis = {0.0, 0.33, 0.67, 1.0} |
| constexpr std::array< double, 4 > | pulp::signal::chardelay::kVintageInternalRateHz |
| constexpr std::array< double, 4 > | pulp::signal::chardelay::kVintageBits = {14.0, 12.0, 12.0, 10.0} |
| constexpr double | pulp::signal::chardelay::kVintageAntiAliasFraction = 0.45 |
| | Anti-alias / reconstruction cutoff as a fraction of the internal rate.
|
| constexpr double | pulp::signal::chardelay::kVintageEmphasisHz = 3183.0 |
| | 3183 Hz is the 50 µs time constant — the published CD/FM-era emphasis standard (IEC 60908), not a tuned value.
|
| constexpr double | pulp::signal::chardelay::kVintageEmphasisDb = 9.0 |
| constexpr std::array< double, 4 > | pulp::signal::chardelay::kTapeAxis = {0.0, 0.33, 0.67, 1.0} |
| constexpr std::array< double, 4 > | pulp::signal::chardelay::kTapeDrive = {1.5, 2.5, 4.0, 6.0} |
| constexpr std::array< double, 4 > | pulp::signal::chardelay::kTapeBias = {0.0, 0.10, 0.20, 0.30} |
| constexpr std::array< double, 4 > | pulp::signal::chardelay::kTapeWowDepthMs = {0.0, 0.15, 0.5, 1.2} |
| constexpr std::array< double, 4 > | pulp::signal::chardelay::kTapeFlutterDepthMs = {0.0, 0.05, 0.15, 0.4} |
| constexpr std::array< double, 4 > | pulp::signal::chardelay::kTapeLossLpHz = {12000.0, 9000.0, 6000.0, 3500.0} |
| constexpr std::array< double, 4 > | pulp::signal::chardelay::kTapeBumpDb = {1.5, 2.0, 3.0, 4.0} |
| constexpr std::array< double, 4 > | pulp::signal::chardelay::kTapePhysicalFeedbackCompensation |
| | Physical-loop compensation at each age knot.
|
| constexpr double | pulp::signal::chardelay::kTapeEmphasisDb = 3.0 |
| | Record/playback EQ bracketing the saturator: boost HF into saturation, cut it after, so the saturator works the highs harder than the lows.
|
| constexpr double | pulp::signal::chardelay::kTapeEmphasisHz = 1600.0 |
| constexpr double | pulp::signal::chardelay::kTapeBumpHz = 60.0 |
| | Loss stand-in head bump (the physical tier replaces this with a speed-dependent center; see kHeadBumpIps/kHeadBumpHz).
|
| constexpr double | pulp::signal::chardelay::kTapeBumpQ = 1.5 |
| constexpr double | pulp::signal::chardelay::kTapeDcBlockHz = 15.0 |
| | In-loop DC blocker.
|
| constexpr double | pulp::signal::chardelay::kWowRateHz = 1.0 |
| | Wow: periodic + stochastic.
|
| constexpr double | pulp::signal::chardelay::kWowOuTheta = 1.5 |
| constexpr double | pulp::signal::chardelay::kWowOuSigma = 0.6 |
| constexpr double | pulp::signal::chardelay::kWowOuNoiseLpHz = 10.0 |
| constexpr double | pulp::signal::chardelay::kFlutterBaseHz = 8.0 |
| | Flutter: published band 5–100 Hz.
|
| constexpr std::array< double, 3 > | pulp::signal::chardelay::kFlutterAmplitudes = {1.0, 0.5, 0.25} |
| constexpr std::array< double, 3 > | pulp::signal::chardelay::kFlutterPhases = {0.0, 0.33, 0.71} |
| constexpr double | pulp::signal::chardelay::kFlutterPhaseRight = 0.41 |
| | Right-channel flutter phase offset, in cycles.
|
| constexpr std::array< double, 3 > | pulp::signal::chardelay::kBbdAxis = {0.0, 0.5, 1.0} |
| constexpr std::array< double, 3 > | pulp::signal::chardelay::kBbdStages = {4096.0, 2048.0, 1024.0} |
| | PUBLISHED chip stage counts (Panasonic MN3005 / MN3008 / MN3007 datasheets), not design parameters: they are what sets each device's delay-per-clock and therefore its bandwidth at a given time.
|
| constexpr std::array< double, 3 > | pulp::signal::chardelay::kBbdDrive = {0.10, 0.30, 0.50} |
| constexpr std::array< double, 3 > | pulp::signal::chardelay::kBbdJitterAmount = {0.0, 0.3, 0.6} |
| constexpr std::array< double, 3 > | pulp::signal::chardelay::kBbdFlutterDepth = {0.0, 0.005, 0.015} |
| constexpr std::size_t | pulp::signal::chardelay::kBbdMaxStages = 4096 |
| | Largest stage count any table knot may request; sizes the bucket buffer.
|
| constexpr int | pulp::signal::chardelay::kBbdOversample = 16 |
| | Internal oversampling of the clocked core.
|
| constexpr double | pulp::signal::chardelay::kBbdBandwidthDivisor = 3.0 |
| | Bandwidth law: the usable passband must sit well below the clock's Nyquist (the published aliasing constraint in both BBD papers).
|
| constexpr double | pulp::signal::chardelay::kBbdBandwidthMinHz = 300.0 |
| constexpr double | pulp::signal::chardelay::kBbdBandwidthMaxHz = 10000.0 |
| constexpr double | pulp::signal::chardelay::kBbdFilterCutoffScale = 2.1 |
| | The clock law names the complete wet path's audible -3 dB edge.
|
| constexpr double | pulp::signal::chardelay::kBbdCompanderTauMs = 10.0 |
| | Compander: hardware τ is set by an external capacitor, so real units vary.
|
| constexpr double | pulp::signal::chardelay::kBbdCompanderFloor = 0.01 |
| constexpr double | pulp::signal::chardelay::kBbdCompanderDriveScale = 0.3 |
| | The compander holds loop level near the rail, so the waveshaper's drive is backed off when it runs behind one.
|
| constexpr double | pulp::signal::chardelay::kBbdDriveGainSpan = 9.0 |
| | Asymmetric soft clip: gain map and DC offset for even-harmonic content.
|
| constexpr double | pulp::signal::chardelay::kBbdShape = 0.25 |
| constexpr double | pulp::signal::chardelay::kBbdJitterMax = 5e-4 |
| | Clock jitter, as a fraction of the clock period. [1e-4–2e-3].
|
| constexpr double | pulp::signal::chardelay::kBbdJitterSmoothness = 0.5 |
| constexpr double | pulp::signal::chardelay::kBbdFlutterRateBaseHz = 0.3 |
| | BBD flutter rate map, Hz.
|
| constexpr double | pulp::signal::chardelay::kBbdFlutterRateSpanHz = 1.2 |
| constexpr std::array< double, 4 > | pulp::signal::chardelay::kDiffusionStageMs |
| constexpr std::array< double, 4 > | pulp::signal::chardelay::kDiffusionStageGain = {0.75, 0.75, 0.625, 0.625} |
| constexpr std::array< double, 3 > | pulp::signal::chardelay::kDiffusionAxis = {0.0, 0.5, 1.0} |
| constexpr std::array< double, 3 > | pulp::signal::chardelay::kDiffusionSizeScale = {0.5, 1.0, 1.7} |
| constexpr std::array< double, 3 > | pulp::signal::chardelay::kDiffusionGainScale = {0.7, 1.0, 1.12} |
| constexpr double | pulp::signal::chardelay::kDiffusionGainMax = 0.85 |
| | Stability / metallicity guard.
|
| constexpr double | pulp::signal::chardelay::kDiffusionModDepthSamples = 2.0 |
| | Anti-metallic modulation of stages 1 and 3 (Dattorro modulates his diffusers).
|
| constexpr std::array< double, 2 > | pulp::signal::chardelay::kDiffusionModRatesHz = {0.40, 0.53} |
| constexpr double | pulp::signal::chardelay::kDiffusionLoopHpHz = 20.0 |
| | Diffusion loop filters. [LP is a design parameter].
|
| constexpr double | pulp::signal::chardelay::kDiffusionLoopLpHz = 9000.0 |
| constexpr std::array< double, 3 > | pulp::signal::chardelay::kDiffusionTankAxis = {0.0, 0.5, 1.0} |
| constexpr std::array< double, 2 > | pulp::signal::chardelay::kDiffusionTankDelayAMs = {30.51, 44.79} |
| | Branch delays in ms, mutually prime-ish so their comb nulls never align.
|
| constexpr std::array< double, 2 > | pulp::signal::chardelay::kDiffusionTankDelayBMs = {37.13, 53.27} |
| constexpr std::array< double, 2 > | pulp::signal::chardelay::kDiffusionTankApAMs = {22.58, 60.48} |
| | The two decay-diffuser allpasses per branch. [design parameters].
|
| constexpr std::array< double, 2 > | pulp::signal::chardelay::kDiffusionTankApBMs = {30.24, 89.24} |
| constexpr double | pulp::signal::chardelay::kDiffusionTankApGain1 = 0.70 |
| constexpr double | pulp::signal::chardelay::kDiffusionTankApGain2 = 0.50 |
| constexpr std::array< double, 3 > | pulp::signal::chardelay::kDiffusionTankSizeScale = {0.6, 1.0, 1.6} |
| | Tank size scaler and recirculation decay by character amount.
|
| constexpr std::array< double, 3 > | pulp::signal::chardelay::kDiffusionTankDecay = {0.0, 0.62, 0.80} |
| constexpr std::array< double, 3 > | pulp::signal::chardelay::kDiffusionTankMix = {0.0, 0.55, 0.85} |
| | How much of the character's output is the tank rather than the bare diffuser.
|
| constexpr std::array< double, 3 > | pulp::signal::chardelay::kDiffusionTankDampHz = {12000.0, 7000.0, 4200.0} |
| | In-tank damping.
|
| constexpr std::array< double, 3 > | pulp::signal::chardelay::kDiffusionTankModDepth = {0.0, 14.0, 42.0} |
| | Tank modulation — this is what makes the cloud granular rather than static.
|
| constexpr std::array< double, 2 > | pulp::signal::chardelay::kDiffusionTankModRatesHz = {0.83, 1.27} |
| constexpr std::array< double, 2 > | pulp::signal::chardelay::kDiffusionTankTapFraction = {0.37, 0.71} |
| | Extra scattered taps read at their own modulated offsets, as a fraction of the branch delay.
|
| constexpr double | pulp::signal::chardelay::kDiffusionTankLowGuardHz = 90.0 |
| | In-tank low cut.
|
| constexpr double | pulp::signal::chardelay::kDiffusionTankDelaySlewMs = 5.0 |
| | Live character automation moves tank taps toward their new positions over a short continuous glide instead of changing fractional reads at control-rate boundaries.
|
| constexpr int | pulp::signal::chardelay::kReverseFadeSamples = 96 |
| | Raised-cosine splice fade at each end of a reversed segment, in samples.
|
| constexpr double | pulp::signal::chardelay::kReverseLineMs = 30.0 |
| | Delay the CLOCK-DOMAIN characters' own line runs at while reverse is engaged, in milliseconds.
|
| constexpr double | pulp::signal::chardelay::kDuckAttackS = 0.005 |
| constexpr double | pulp::signal::chardelay::kDuckReleaseS = 0.250 |
| constexpr double | pulp::signal::chardelay::kDuckThreshold = 0.1 |
| constexpr double | pulp::signal::chardelay::kJaSaturationMagnetization = 3.5e5 |
| | PUBLISHED γ-Fe2O3 material constants (Jiles, Thoelke & Devine 1992, reproduced in Chowdhury 2019).
|
| constexpr double | pulp::signal::chardelay::kJaAnhystereticShape = 2.2e4 |
| constexpr double | pulp::signal::chardelay::kJaPinning = 2.7e4 |
| constexpr double | pulp::signal::chardelay::kJaReversibility = 0.2 |
| constexpr double | pulp::signal::chardelay::kJaInterdomainCoupling = 1.6e-3 |
| constexpr int | pulp::signal::chardelay::kJaMaxIterations = 8 |
| | Newton-Raphson budget.
|
| constexpr double | pulp::signal::chardelay::kJaConvergenceThreshold = 6e-8 |
| constexpr double | pulp::signal::chardelay::kJaLangevinClamp = 30.0 |
| | Langevin argument clamp — keeps coth() and its derivative in the range where the rational approximation is accurate and the solver well-scaled.
|
| constexpr double | pulp::signal::chardelay::kJaSilenceThreshold = 1e-7 |
| | Below this |H| and |dH/dt|, magnetization is snapped to 0 so a silent loop cannot hold a frozen DC magnetization.
|
| constexpr std::size_t | pulp::signal::chardelay::kHysteresisHalfBandTaps = kHouseHalfBandTaps |
| | Hysteresis oversampling factor and half-band design.
|
| constexpr double | pulp::signal::chardelay::kHysteresisHalfBandStopbandDb = kHouseHalfBandStopbandDb |
| constexpr double | pulp::signal::chardelay::kJaMakeupToleranceDb = 1.0 |
| | Makeup-gain tolerance around unity small-signal gain, in dB.
|
| constexpr std::size_t | pulp::signal::chardelay::kLossFirOrder48k = 96 |
| | Wallace playback loss (Wallace 1951; physical ranges from Bertram 1994) is split across two realizations — see tape_loss.hpp for why.
|
| constexpr int | pulp::signal::chardelay::kLossIirFitPoints = 64 |
| | The smooth spacing × thickness tilt goes to a fitted IIR cascade: how many log-spaced points the least-squares fit is evaluated at, and how many simplex iterations it gets.
|
| constexpr std::size_t | pulp::signal::chardelay::kSpacingPoleSections = 3 |
| | Sections in each fitted cascade.
|
| constexpr std::size_t | pulp::signal::chardelay::kSpacingShelfSections = 8 |
| constexpr std::size_t | pulp::signal::chardelay::kThicknessPoleSections = 1 |
| constexpr std::size_t | pulp::signal::chardelay::kThicknessShelfSections = 2 |
| constexpr std::size_t | pulp::signal::chardelay::kLossPoleSections |
| constexpr std::size_t | pulp::signal::chardelay::kLossShelfSections |
| constexpr std::size_t | pulp::signal::chardelay::kLossSearchDimension |
| | Search dimension of ONE shape fit (the larger of the two).
|
| constexpr std::array< double, kSpacingPoleSections > | pulp::signal::chardelay::kSpacingShapePoleX |
| | THE FITTED SHAPES, as shipped.
|
| constexpr std::array< double, kSpacingShelfSections > | pulp::signal::chardelay::kSpacingShapeShelfX |
| constexpr std::array< double, kSpacingShelfSections > | pulp::signal::chardelay::kSpacingShapeShelfDb |
| constexpr std::array< double, kThicknessPoleSections > | pulp::signal::chardelay::kThicknessShapePoleX |
| constexpr std::array< double, kThicknessShelfSections > | pulp::signal::chardelay::kThicknessShapeShelfX |
| constexpr std::array< double, kThicknessShelfSections > | pulp::signal::chardelay::kThicknessShapeShelfDb |
| constexpr double | pulp::signal::chardelay::kLossShapeMinX = 1e-3 |
| | Normalized-frequency range each shape is fitted over, and how many log-spaced points.
|
| constexpr double | pulp::signal::chardelay::kLossShapeMaxX = 4.0 |
| constexpr int | pulp::signal::chardelay::kLossIirFitIterations = 4000 |
| | Simplex iterations per start, restarts per start, and how many starts.
|
| constexpr int | pulp::signal::chardelay::kLossIirFitRestarts = 3 |
| constexpr int | pulp::signal::chardelay::kLossIirFitStarts = 16 |
| constexpr double | pulp::signal::chardelay::kLossShelfMinDb = -40.0 |
| | Deepest cut any one shelf may ask for.
|
| constexpr double | pulp::signal::chardelay::kLossBankCrossfadeS = 0.030 |
| | NOTE: there are no age knots and no interpolation along the age axis.
|
| constexpr double | pulp::signal::chardelay::kTapeCoatingThicknessM = 12e-6 |
| | Fixed tape geometry, in metres.
|
| constexpr double | pulp::signal::chardelay::kTapeHeadGapM = 3e-6 |
| constexpr std::array< double, 5 > | pulp::signal::chardelay::kTapeSpeedsIps = {1.875, 3.75, 7.5, 15.0, 30.0} |
| | The IEC/NAB standard tape-speed set, in inches per second (published).
|
| constexpr std::array< double, 5 > | pulp::signal::chardelay::kHeadBumpIps = {1.875, 3.75, 7.5, 15.0, 30.0} |
| | Head-bump center against speed.
|
| constexpr std::array< double, 5 > | pulp::signal::chardelay::kHeadBumpHz = {35.0, 45.0, 60.0, 80.0, 105.0} |
| constexpr std::array< double, 3 > | pulp::signal::chardelay::kAgeAxis = {0.0, 0.5, 1.0} |
| | Age macro.
|
| constexpr std::array< double, 3 > | pulp::signal::chardelay::kAgeSpacingUm = {5.0, 12.0, 25.0} |
| constexpr std::array< double, 3 > | pulp::signal::chardelay::kAgeHissDbfs = {-120.0, -78.0, -60.0} |
| constexpr std::array< double, 3 > | pulp::signal::chardelay::kAgeChewDepth = {0.0, 0.2, 0.6} |
| constexpr std::array< double, 3 > | pulp::signal::chardelay::kAgeDegrade = {0.0, 0.2, 0.5} |
| constexpr double | pulp::signal::chardelay::kHissLpHz = 4000.0 |
| | Hiss: white noise through a 1-pole lowpass, injected AFTER the delay line so it accumulates per repeat the way real tape self-noise does.
|
| constexpr double | pulp::signal::chardelay::kChewCleanScaleS = 1.5 |
| | Chew — an intermittent dropout modeled as a two-state machine.
|
| constexpr double | pulp::signal::chardelay::kChewDegradedScaleS = 0.4 |
| constexpr double | pulp::signal::chardelay::kChewVariance = 1.5 |
| constexpr double | pulp::signal::chardelay::kChewTransitionS = 0.008 |
| constexpr double | pulp::signal::chardelay::kChewPower = 2.0 |
| constexpr double | pulp::signal::chardelay::kChewLpHz = 3000.0 |
| constexpr double | pulp::signal::chardelay::kDegradeMinLpHz = 500.0 |
| | Degrade — continuous wear.
|
| constexpr double | pulp::signal::chardelay::kDegradeGainDipDb = -1.5 |
| constexpr int | pulp::signal::chardelay::kDegradeUpdateSamples = 1024 |