A classic channel vocoder: analysis bank → envelopes → matched synthesis bank.
More...
|
| | VocoderT () |
| void | prepare (double sample_rate) |
| | Fixes the sample rate, recomputes every coefficient, and clears state.
|
| void | reset () |
| int | latency_samples () const |
| | 0 for every configuration. See this file's latency note.
|
| void | set_band_count (int n) |
| | Band count, 10 .
|
| void | set_band_range_hz (double f_lo, double f_hi) |
| | Analysis and synthesis span.
|
| void | set_carrier_source (CarrierSource source) |
| CarrierSource | carrier_source () const |
| void | set_internal_wave (InternalWave wave) |
| void | set_internal_pulse_width (SampleType w01) |
| void | set_internal_pitch_hz (SampleType hz) |
| | The internal carrier's frequency.
|
| double | internal_pitch_hz () const |
| void | set_noise_mix (SampleType m01) |
| void | set_attack_ms (SampleType ms) |
| | Follower attack as a 10→90 % time in ms, floored per band.
|
| void | set_release_ms (SampleType ms) |
| | Follower release as a 10→90 % time in ms, floored per band.
|
| void | set_unvoiced_sensitivity (SampleType s01) |
| void | set_sibilance_mix (SampleType m01) |
| void | set_formant_shift_semitones (SampleType st) |
| | Formant shift in semitones, converted to a fractional band-index offset through the bank's own ratio, so the control means the same thing at every band count and every span.
|
| void | set_formant_freeze (bool on) |
| | Latches the band levels.
|
| bool | formant_freeze () const |
| void | set_output_trim_db (SampleType db) |
| void | set_dry_wet (SampleType w01) |
| | 0 = the (DC-blocked) modulator passes through, 1 = fully vocoded.
|
| void | process (SampleType modulator, SampleType carrier_ext, SampleType &out_dry) |
| int | band_count () const |
| double | band_ratio () const |
| double | band_q () const |
| double | section_q () const |
| double | bands_per_octave () const |
| double | shift_bands () const |
| double | band_center_hz (int k) const |
| double | attack_eff_ms (int k) const |
| double | release_eff_ms (int k) const |
| double | analysis_band (int k) const |
| | The 4th-order analysis output for band k on the most recent sample — the filter's own signal, before rectification.
|
| double | band_envelope (int k) const |
| | The live follower output for band k, ignoring freeze and shift.
|
| double | synthesis_gain (int k) const |
| | The level actually applied to synthesis band k — post-freeze, post-shift.
|
| double | unvoiced () const |
| | The smoothed voicing decision: 0 fully voiced, 1 fully unvoiced.
|
| double | zcr_hz () const |
| | Measured zero-crossing rate of the modulator, Hz.
|
| double | zcr_window_ms () const |
| | Effective ZCR window length in ms.
|
|
| static constexpr int | kMaxBands = 20 |
| | Storage cap.
|
| static constexpr int | kMinBands = 10 |
| static constexpr std::size_t | kBandSlots = static_cast<std::size_t>(kMaxBands) |
| static constexpr double | kDcBlockHz = 10.0 |
| | DC-blocker corner for both the modulator and the carrier path, Hz.
|
| static constexpr double | kMaxSampleRate = 192000.0 |
| | Highest sample rate the fixed ZCR window is sized for.
|
| static constexpr double | kCascadeBWFactor = 0.6435942529055827 |
| | Bandwidth factor for two identical cascaded 2nd-order bandpass sections.
|
| static constexpr double | kPreEmphasis = 0.95 |
| | Pre-emphasis coefficient, y[n] = x[n] − a·x[n−1], applied to the modulator only.
|
| static constexpr double | kRippleCycles = 2.0 |
| | Release floor, in cycles of each band's own centre frequency.
|
| static constexpr double | kAttackCycles = 0.5 |
| | Attack floor, same units and the same honest gap.
|
| static constexpr double | kZcrLo = 1500.0 |
| | Zero-crossing rate mapped to [0, 1] between these edges.
|
| static constexpr double | kZcrHi = 4500.0 |
| | [design parameter] default 4500 Hz, range 3000 .. 6000 Hz.
|
| static constexpr double | kZcrWindowMs = 20.0 |
| | Sliding-window length for the crossing count.
|
| static constexpr double | kSibilanceCornerHz = 3500.0 |
| | What counts as sibilance.
|
| static constexpr double | kUvEnter = 0.6 |
| | Schmitt thresholds on the raw decision.
|
| static constexpr double | kUvLeave = 0.4 |
| static constexpr double | kSensSpan = 0.5 |
| | How far unvoiced_sensitivity can bias the raw decision.
|
| static constexpr double | kUvSmoothMs = 8.0 |
| | One-pole smoothing on the decision, as a 10→90 % time to match the follower convention this file uses everywhere.
|
| static constexpr double | kEnergyEpsilon = 1e-12 |
| | Guards the high-frequency energy ratio's divide when every band is silent.
|
| static constexpr double | kUnvoicedNoise = 0.9 |
| | How much noise a fully unvoiced decision substitutes into the carrier.
|
| static constexpr std::uint32_t | kNoiseSeed = 0x9E3779B9u |
| | Noise seed.
|
| static constexpr double | kDefaultPitchHz = 110.0 |
| | Internal carrier pitch, Hz.
|
| static constexpr double | kMinPitchHz = 20.0 |
| static constexpr double | kMaxPitchHz = 2000.0 |
| static constexpr double | kOutputHeadroomTrim = 0.5 |
| | Static trim on the summed synthesis bank.
|
| static constexpr double | kWorstCaseGain = 2.0 |
| | The pre-trim reconstruction bound Forge's registry cites.
|
| static constexpr double | kFreqLoMinHz = 60.0 |
| static constexpr double | kFreqLoMaxHz = 400.0 |
| static constexpr double | kFreqHiMinHz = 3000.0 |
| static constexpr double | kFreqHiMaxHz = 12000.0 |
| static constexpr double | kAttackMinMs = 0.1 |
| static constexpr double | kAttackMaxMs = 50.0 |
| static constexpr double | kReleaseMinMs = 2.0 |
| static constexpr double | kReleaseMaxMs = 200.0 |
| static constexpr double | kPulseWidthMin = 0.05 |
| static constexpr double | kPulseWidthMax = 0.95 |
| static constexpr double | kFormantShiftMinSt = -24.0 |
| static constexpr double | kFormantShiftMaxSt = 24.0 |
| static constexpr double | kOutputTrimMinDb = -24.0 |
| static constexpr double | kOutputTrimMaxDb = 12.0 |
template<typename SampleType = float>
class pulp::signal::VocoderT< SampleType >
A classic channel vocoder: analysis bank → envelopes → matched synthesis bank.
Mono in, mono out, one sample at a time.
template<typename SampleType = float>
0 = the (DC-blocked) modulator passes through, 1 = fully vocoded.
The spec contradicts itself here: this setter is in its declared class API, while its node-wiring note says dry/wet lives in node code and not in this template. Resolved in favour of the declared API — a node that wants to own the crossfade simply leaves this at 1.0, whereas a caller of a class that dropped a declared method has no recourse. Note that the out_dry parameter of process is unrelated: it means "before the
node's chorus", not "the dry signal".
template<typename SampleType = float>
Bandwidth factor for two identical cascaded 2nd-order bandpass sections.
Derived identity, not a citation. For n identical cascaded sections, |H|^n = 1/√2 at the cascade's −3 dB edges gives 1 + x² = 2^(1/n) where x = Q_section·(ω/ω_c − ω_c/ω), so the cascade's −3 dB bandwidth is narrower than one section's by √(2^(1/n) − 1). For n = 2: √(√2 − 1) = 0.6435942.... Each section therefore runs at Q_section = kCascadeBWFactor · Q_band, i.e. deliberately broader than the target, so that the cascade lands on it. The acceptance suite recomputes this from √(√2 − 1) rather than trusting the literal.
template<typename SampleType = float>
DC-blocker corner for both the modulator and the carrier path, Hz.
Not cosmetic: DcBlocker's own default pole puts the corner near 38 Hz at 48 kHz, which is inside the bank — it costs band 0 4.5 % at the 120 Hz default and 16 % at the 60 Hz the parameter table allows. The corner has to sit well below kFreqLoMinHz, and it has to be specified in Hz rather than as a pole so it means the same thing at every sample rate. [design parameter] default 10 Hz, range 2 .. 30 Hz.
template<typename SampleType = float>
Internal carrier pitch, Hz.
Not in the spec, and it has to be. The spec gives the internal oscillator a wave and a pulse width but no frequency — neither in the class API nor in the baked-params table — while saying pitch "is set by
the host/MIDI upstream". There is no upstream to set it through, and the module cannot make a sound without one, so this is added with a default and a range and reported as a spec gap. [design parameter] default 110 Hz (A2), range 20 .. 2000 Hz.
template<typename SampleType = float>
Pre-emphasis coefficient, y[n] = x[n] − a·x[n−1], applied to the modulator only.
Speech rolls off about −6 dB/oct, so without this the upper bands see almost nothing and consonants never earn a fair envelope level. [design parameter] default 0.95, range 0.0 (off) .. 0.97.
template<typename SampleType = float>
Release floor, in cycles of each band's own centre frequency.
The mechanism is textbook — a rectified sinusoid at f_c ripples at 2·f_c — but the count is an original engineering choice with no citable constant behind it (honest gap), which is why it ships as a named parameter rather than as a number inside a formula. [design parameter] default 2.0, range 1.0 .. 4.0.
template<typename SampleType = float>
What counts as sibilance.
Single-sourced deliberately: the same corner decides which bands feed the high-frequency energy ratio, which bands take noise substitution under an external carrier, and where the direct sibilance path starts. Three definitions of "high" would drift apart. [design parameter] default 3500 Hz, range 2500 .. 5000 Hz.