tunelet

TypeScript API

Functions

defaultConfig

function defaultConfig(): ProcessorConfig

Returns a complete, independent default configuration for JavaScript.

Change its fields and give it to Tunelet or to setConfig. The randomSeed field is a JavaScript bigint, so it keeps all 64 bits. After the binding decodes them, floating-point controls have the precision of the Rust f32 type.

Errors

If the conversion to a JavaScript object fails, this function returns a JavaScript Error.

initSync

function initSync(module: { module: SyncInitInput } | SyncInitInput): InitOutput

Instantiates the given module, which can either be bytes or a precompiled WebAssembly.Module.

Returns:

loadTunelet

function loadTunelet(source?: InitInput | Promise<InitInput>): Promise<InitOutput>

Initializes the Wasm module one time for this imported package instance.

If you give no argument, the function finds the packaged binary relative to this module. Node.js reads a file: URL, and browsers fetch the served asset. An import of the package does not load Wasm. In browsers, serve the assets over HTTP(S), or give the bytes or a compiled module as the source.

For a custom deployment, you can give one of these sources:

  • A URL.
  • A fetch Response.
  • A byte buffer (BufferSource).
  • A compiled WebAssembly.Module.
  • A promise for one of these.

A string source obeys fetch rules. For a Node.js file: source, use a URL object. A compiled module must use imports that agree with the packaged bindings.

Concurrent calls share one promise, and the first call selects the source. After a successful initialization, later calls use it again and do not load Wasm again, whatever their arguments are. If an attempt fails, the promise rejects and the function clears the cached promise. Then you can try again. File, network and Wasm errors go to the caller. The function does not try a different load method after an error.

  • source: The optional Wasm source. The default is the binary in this package.

Returns: The initialized Wasm exports. Use the re-exported Tunelet class for processors.

Classes

Tunelet

A stateful PCM processor that JavaScript uses as the Tunelet class.

The input is signed 16-bit mono PCM. The output is planar stereo or an in-place mono downmix. The quantization, latency and configuration behavior are the same as in the native processor. Buffer lengths count frames, not bytes.

These rules apply to the buffers:

  • Separate stereo output arrays must not overlap.
  • The input can overlap an output, because the class copies the input first.
  • All buffers must stay attached until each call is complete.

If a call that processes audio fails, it throws a JavaScript Error before the audio state or the output changes. The class rejects malformed configuration objects and malformed event objects. It also rejects values that are out of range. The class decodes objects inside the methods that can fail. Thus, if a conversion fails, Rust releases the temporary values as usual.

constructor(sample_rate: number, max_block_frames: number, config?: ProcessorConfig | null);

Prepares a processor and its reusable PCM buffers.

sample_rate must be 44100 or 48000. max_block_frames must be an integer in 1..=4294967295. It is a limit for each call, and smaller blocks and empty blocks are also valid. If you omit config, the processor uses the default configuration. The constructor validates the settings before it allocates the processor or the PCM buffers. In TypeScript, use new Tunelet(sampleRate, maxBlockFrames, config).

Errors

The constructor throws if one of these conditions occurs:

  • The rate is not 44100 or 48000.
  • The block limit is not an integer or is out of range.
  • The configuration object is malformed or a field is missing.
  • The configuration is not valid.
  • The reservation of a PCM buffer fails.

The available Wasm memory must also have sufficient space for the DSP histories.

beginDrain(): number

Starts a finite tail budget and returns its frame count as a number.

Call this method one time after the final input block. Another call starts the full budget again, but it does not clear the histories. See beginDrain for completion.

config(): ProcessorConfig

Returns a copy of the active configuration as a new JavaScript object.

A change to the object has no effect until setConfig or a timed event applies it.

Errors

If the conversion to a JavaScript object fails, this method throws.

drain(left: Int16Array, right: Int16Array): number

Renders stereo tail frames into Int16Array buffers of equal length.

The method returns the number of rendered frames and fills the unused output with zeros. If the drain is not active or is complete, the method returns zero. Empty arrays do not use the budget. Completion resets the histories and the feedback in the final drain call, also when that call returns audio.

Errors

The method throws if the channel lengths are not equal or if a block is larger than maxBlockFrames. After an error, both output arrays and the drain state do not change.

drainMono(audio: Int16Array): number

Renders a mono tail block and returns its frame count.

The method fills the unused output with zeros. The downmix, completion and feedback behavior are the same as for drainMono.

Errors

If the block is larger than maxBlockFrames, this method throws before the output or the state changes.

feedback(): Feedback

Returns a new feedback object and does not clear the peak window.

processedFrames is a bigint, so its 64-bit count stays exact. latencyFrames is a number. See Feedback for each measurement.

targetMidiNote is undefined in these cases, which are also the cases where voiced is false:

  • The kept pitch estimate is unvoiced. This includes the time before the first detection and after a reset or a drain completion.
  • The estimated frequency is outside the inclusive reporting bounds minFrequencyHz and maxFrequencyHz of the pitch configuration.

Errors

If the conversion to a JavaScript object fails, this method throws.

formantEnvelope(max_frequency_hz: number, input: Float32Array, output: Float32Array): boolean

Writes the formant envelopes of the current model into two Float32Array buffers of equal length.

input gets the vocal-tract envelope that the LPC analysis found. output gets the envelope after the width and stretch controls. Point k of n is at the frequency maxFrequencyHz * k / (n - 1). The values are linear magnitudes with no absolute level. Scale them for a display.

maxFrequencyHz must be finite, more than zero and not more than half of the sample rate.

The method returns true if the envelopes are valid. It returns false and fills the two arrays with zeros if the formant stage is disabled or if the current model has no synthesis filter. The audio does not change.

The class keeps a buffer for the points. Only the first call and a call with more points than before reserve memory.

Errors

The method throws if the array lengths are not equal, if the frequency is not valid or if the reservation of the buffer fails. The arrays then do not change.

free(): void
process(input: Int16Array, left: Int16Array, right: Int16Array, events?: BlockEvents | null): void

Processes mono input into left and right Int16Array buffers of equal length.

If the call is successful, it writes every output sample. Optional events apply before their frame, and their offsets obey the rules of TimedEvent[]. An empty block must have no events. A successful call cancels a drain, also for an empty block. The call uses the existing JavaScript and Rust PCM buffers again.

Errors

The method throws if the channel lengths are not equal. It also throws if the block is larger than maxBlockFrames or an event is not valid. The call checks the lengths and the block size before it decodes and validates the events. If an error occurs, the output buffers and the DSP state do not change.

processMono(audio: Int16Array, events?: BlockEvents | null): void

Replaces the audio in a mono Int16Array with the stereo downmix.

The timing, the events and the drain cancellation are the same as for process. Peak feedback measures the stereo output before the downmix, as in the native processor.

Errors

The method throws if the block is too large or an event is not valid. It throws before the audio of the caller or the DSP state changes.

reset(): void

Resets the audio histories and feedback, as the native processor does.

The configuration, the random stream and some controller and filter state do not change. This method cancels any active drain. For a fully new instance, construct a new Tunelet.

setConfig(config: ProcessorConfig): void

Decodes and validates a configuration, then replaces the complete configuration with it.

State retention and drain cancellation follow the native processor. The conversion ignores additional properties of the JavaScript object.

Errors

The method throws if an object is not valid or a field is missing. After an error, all processor state and any active drain stay the same.

tailFrames(): number

Returns the tail budget of the current configuration, not the remaining drain count.

takeFeedback(): Feedback

Returns the feedback and clears only the stereo peak window.

The other feedback fields and all audio histories do not change.

Errors

If the conversion to a JavaScript object fails, this method throws. The method clears the peak only after it successfully makes a feedback object.

takeTelemetry(): Telemetry

Returns the telemetry and clears only its three peak windows.

The peak window of the feedback and all audio histories do not change.

Errors

If the conversion to a JavaScript object fails, this method throws. The method clears the peaks only after it successfully makes a telemetry object.

telemetry(): Telemetry

Returns a new telemetry object and does not clear its peak windows.

The telemetry is for meters and displays. It gives the ratio and the gain of each voice, the input and output peaks, the pitch clarity and the state of the effects. processedFrames is a bigint. See Telemetry for each measurement.

Errors

If the conversion to a JavaScript object fails, this method throws.

readonly latencyFrames: number

The nominal resynthesis delay in frames.

Other signal paths have different timing. See the latencyFrames property for the timing of the dry path and the voices.

readonly maxBlockFrames: number

The maximum frame count for each call that processes or drains audio.

The constructor sets this value, and the value does not change.

readonly sampleRate: number

The sample rate of the input and the output in hertz.

The constructor sets this value, and the value does not change.

Interfaces

AlienConfig

Reverse playback of recent stereo audio in repeated loops with fades.

Alien comes after resynthesis. Its input history and loop phase advance also when Alien is disabled. Thus, when you enable Alien, it can play audio that it recorded during bypass. A change of the loop length keeps the history and clamps the current phase into the new loop. The boundary fades are 200 frames long at all sample rates.

enabled: boolean

Selects reversed playback instead of the direct input. The default is false. The recording and the phase continue to advance in both states.

loopFrames: number

The loop length in frames, 1..=96000. The default is 95,999. This value is a frame count at the two rates. Thus, its duration in seconds changes with the sample rate. A short loop can be fully inside the fades.

CorrectionConfig

The controls for pitch-class correction, with target selection in the period domain.

Correction is enabled by default, with all chromatic notes and a retune time of zero. Target selection and the smoothing of the correction ratio occur at each update of the pitch tracking. When a period is tracked, this update usually occurs every five frames. If the active note table is empty or correction is disabled, the ratio moves toward 1.0 at the same rate.

Correction MIDI replaces the active note table. It does not change this configuration. A change to notes or to enabled loads the configured mask again. Reset releases the correction keys 0..=126. It keeps key 127 and the active note table. Key 127 has no effect on the note table.

At construction, the chromatic table uses 44.1 kHz periods, also for a 48 kHz processor. Each of these events loads the periods for the prepared rate:

  • An initial mask that is not chromatic.
  • A later change to the mask or to enabled.
  • A correction MIDI event.
enabled: boolean

Enables the selection of correction targets. The default is true.

If you disable correction, the ratio moves toward 1.0 with retune_ms at the next tracking updates. The ratio does not change to 1.0 immediately.

notes: NoteMask

The configured target pitch classes. The default is NoteMask::CHROMATIC.

All boolean masks are valid. MIDI can replace the active table. This replacement stays until this mask or enabled changes.

retuneMs: number

The half-life of the smoothing in milliseconds, 0..=400. The default is 0.

If the value is zero, the ratio changes to the target at the next tracking update. A value that is not zero is a half-life. It is not a fixed time to get exactly to the target.

Feedback

A snapshot of the pitch analysis and the output level that you can copy.

Get it with Processor::feedback or Processor::take_feedback. The pitch fields describe the tracked input and the correction target. The peak measures the final clipped stereo output. Default gives a snapshot with all zeros and no target. It does not read the nominal latency of a prepared processor.

resampleRatio: number

The pitch-correction ratio from the last processed frame, where 1 is unity.

It does not include the configured pitch shift or the ratios of individual voices. It is zero before processing, after a reset or after a change of stereo output.

periodSamples: number

The reported input pitch period in samples, with fractional samples.

It is zero if the input is unvoiced or outside the reporting bounds of PitchConfig.

frequencyHz: number

The reported input pitch frequency in hertz.

The value comes from the sample rate and the current tracked period. It is zero if the estimate is not reported.

targetMidiNote: number | undefined

The correction target or the input pitch, as a MIDI note number.

The value is the selected correction pitch class if all of these conditions are true:

  • Correction is enabled.
  • The active note table is not empty.
  • A tracking update selected a target after the last table change, reset or tracking restart.

The pitch class is in the octave nearest to the reported input. In other cases, the value is the input pitch as a fractional MIDI note. It is not the final pitch of shifted output or harmony output.

The value is None if voiced is false, and only then. This occurs if the input is unvoiced or if its frequency is outside the current reporting bounds. A target table that has no selected target does not give None.

voiced: boolean

This field is true if the current pitch estimate is positive and inside the current reporting bounds.

This is not an amplitude gate or a confidence score. A tracking result can stay between detector updates.

peakLevel: number

The largest absolute clipped stereo sample, divided by 32768.

The peak window starts at construction, at a reset, at a change of stereo output or at a call to Processor::take_feedback. The value is in 0..=32767/32768. The mono downmix occurs after this measurement. Processor::feedback does not clear the value.

processedFrames: bigint

The number of frames processed since construction or the last reset, with drain frames included.

The count saturates at u64::MAX. Drain completion resets it in the last drain call.

latencyFrames: number

The nominal resynthesis latency, as Processor::latency_frames gives.

FormantConfig

The controls for vocal-tract changes and synthesized aspiration during resynthesis.

This stage is disabled by default. If it is enabled, it does these steps:

  1. It estimates an LPC model.
  2. It removes the spectral envelope of the input.
  3. It applies a changed model to the resampled audio.

If width and stretch are 1, the model dimensions do not change. But the fixed-point analysis and synthesis path does not give a bit-identical copy of the input. Aspiration occurs only if the formant path is enabled.

enabled: boolean

Enables formant analysis and synthesis. The default is false.

width: number

The vocal-tract width factor, 0.5..=2. The default is 1.

The square of the width scales the estimated tract areas. The width also scales the amplitude of the synthesized output.

stretch: number

The vocal-tract length factor, 0.5..=2. The default is 1.

It controls the interpolation of the area model and thus the filter order.

aspirationMix: number

The aspiration level, 0..=1, without a unit. The default is 0.

If the value is 0.01 or less, the stage makes no noise. Active aspiration follows the signal amplitude. It uses the random stream of the processor, together with other stages. During each drain call, the processor sets the aspiration to zero. The configuration that the host sees does not change.

aspirationCutoffHz: number

The high-pass cutoff for aspiration in hertz, 500..=10000. The default is 4000.

The stage limits the cutoff to 0.48 × sample rate and truncates it to whole hertz. A change to this value updates the coefficients. The filter history does not change.

HarmonyConfig

The configuration of four harmony voices that follow intervals, chords or MIDI.

Positive intervals make the pitch higher. The defaults are:

  • MIDI channels 0..=3 as the source.
  • The key of C and the major scale.
  • Unison intervals.
  • A tonic major chord in root position.
  • A register of 50%.
  • A closed voicing and zero portamento.
  • Four voices for the interval sources.

These settings configure all sources. Only the fields for the selected source change the target notes. Validation always checks all fields.

Harmony makes its voices from the tracked input. MIDI controls the pitch and the gain. It is not an independent oscillator. The gain in decibels is linear in the velocity: velocities 1..=127 give approximately -23.72 to +12 dB. A velocity of zero releases the note.

The gain attack, the gain release and the period portamento advance at the controller cadence. This cadence is usually every 101 frames. A MIDI event can make the next control step occur sooner. The envelopes and the portamento advance only while the input is voiced.

source: HarmonySource

The pitch source. The default is HarmonySource::MidiChannels.

key: PitchClass

The pitch class of the tonic. The default is C. Smart intervals, named chords and degree chords use it. It does not transpose direct MIDI notes.

scale: HarmonyScale

The scale for smart intervals and degree chords. The default is major.

chromaticIntervals: [number, number, number, number]

Four fixed semitone offsets, each in -24..=24. The default is all zeros. HarmonySource::FixedInterval uses them. A value of 12 makes the pitch one octave higher.

diatonicIntervals: [number, number, number, number]

Four offsets in scale steps, each in -14..=14. The default is all zeros. HarmonySource::SmartInterval uses them. Seven steps make the pitch one octave higher.

chord: ChordName

The named chord for HarmonySource::ChordByName. The default is major.

degree: ChordDegree

The chord on a scale degree for HarmonySource::ChordByDegree. The default is I.

inversion: Inversion

The inversion for named chords and degree chords. The default is root position.

registerPercent: number

The chord register from low to high, 0..=100%.

The default is 50%. All chord sources use it, which includes MIDI chords. The value is truncated to a whole percentage before it selects the octave shift.

voicingSpreadPercent: number

The chord voicing from close to open, 0..=100%.

The default is 0%. All chord sources use it. The value is truncated to a whole percentage. The result selects discrete octave positions, not continuous detuning.

portamentoMs: number

The half-life of the target-period smoothing in milliseconds, 0..=10000. The default is 0. The smoothing applies at each control step. The coefficient assumes 100 frames for each step. At the usual cadence of 101 frames, the half-life is approximately 1% longer. If the value is zero, the voice uses the target period immediately. The gain envelopes still apply. A note on a free voice can start without a glide. In the interval sources, if the input moves more than one semitone bin, each voice starts at its new target without a glide.

voices?: number

The number of voices that sound in the interval sources, 0..=4.

The default is 4. HarmonySource::FixedInterval and HarmonySource::SmartInterval use the first voices voices. The other voices release with the usual gain envelope. The chord and MIDI sources ignore this field. In JavaScript, the field is optional and a missing value gives the default.

PitchConfig

The acquisition sensitivity and the bounds for pitch reports to the host.

threshold: number

The normalized cycle-difference threshold for acquisition, 0.002..=0.2.

The default is 0.1. Larger values accept less exact cycle agreement. This value controls acquisition. It is not an output gain or an amplitude gate.

minFrequencyHz: number

The lower bound of the feedback in hertz (inclusive), 40..=2000.

The default is 40. It must be strictly less than max_frequency_hz. These bounds do not change the tracking, the correction or the resampling. A feedback query applies the current bounds to the kept analysis. It does not process another sample.

maxFrequencyHz: number

The upper bound of the feedback in hertz (inclusive), 40..=2000.

The default is 1100. It must be strictly greater than min_frequency_hz. Results outside the bounds are reported as unvoiced, with zero frequency and zero period.

ProcessorConfig

The settings for the complete signal chain, in the order of the stages.

The default enables chromatic pitch correction, one choir voice and unity output gain. Punch, Warm, formants, Alien and reverb are disabled. This configuration does active pitch processing. It is not a bypass with zero latency.

Change a copy, then apply it with Processor::set_config or ControlEvent::Configure. The validation examines all fields before a change has an effect. This includes the fields of disabled stages.

punch: PunchConfig

The input dynamics and saturation stage, which applies first.

It is disabled by default.

warm: WarmConfig

The asymmetric saturation stage after Punch.

It is disabled by default.

resynthesis: ResynthesisConfig

The stage for pitch tracking, correction, voice resynthesis and formant control.

The default is ResynthesisConfig::default.

alien: AlienConfig

The reverse-loop effect after resynthesis.

It is disabled by default.

reverb: ReverbConfig

The echo or reverberation stage after Alien.

It is disabled by default.

outputGain: number

The linear gain after all effects, 0..=64.

The default is 1 (unity). Zero mutes the output, but the internal processing continues. The gain is quantized in steps of 1/256 before the fixed-point multiplication and the final PCM clipping. Thus, a positive value below 1/256 also mutes the output.

PunchConfig

The input gain and the transient enhancement with arctangent saturation.

Punch comes before Warm and before pitch detection. It finds the peak of each window of 100 processed frames. Two envelope followers set the drive from these peaks. When Punch is disabled, it does not process audio, and its envelope and window state do not change.

A gain change updates the cached drive at the next boundary of the peak window. A reset calculates that drive again immediately from the configured gain.

enabled: boolean

Enables this input stage. The default is false.

gainDb: number

The input gain in decibels, -96..=12.

The default is 0 dB. The saturation drive from this gain changes at the next 100-frame peak boundary.

impact: number

The transient emphasis without a unit, 0..=1.

The default is 0.5. It sets the release half-life of the adaptive follower: 5000 ms at 0, 250 ms at 0.5 and 1 ms at 1. The attack uses attack_ms.

ceilingDb: number

The output ceiling of the saturation in dBFS, -96..=0.

The default is -3 dBFS. Later stages and the final gain can make the final output higher than this level.

attackMs: number

The attack half-life of the peak follower in milliseconds, 0.01..=5000.

The default is 10 ms. The coefficients include the effect of the 100-frame update interval.

ResynthesisConfig

The controls for pitch correction, pitch shift, voice arrangement and formants.

The defaults render one choir voice with these settings:

  • Chromatic correction.
  • A pitch shift of 1.0.
  • Disabled formants.
  • No harmonic modulation.
  • No dry mix.
  • No stereo pan.

Validation applies to all controls, also when their stage or voice mode is not active.

The dry path takes the audio after Punch and Warm and delays it by 1,543 frames. The wet voice readers have more delay, which changes with the pitch. After this stage, the two paths go through Alien, reverb and the final output gain.

pitch: PitchConfig

The acquisition sensitivity and the reporting bounds. The default is PitchConfig::default.

correction: CorrectionConfig

The target notes and the retune time. The default is enabled chromatic correction with a retune time of zero.

pitchRatio: number

The pitch multiplier, 0.25..=4. The default is 1.

A value of 0.5 lowers the pitch by one octave. A value of 2 raises the pitch by one octave. This value multiplies the correction ratio and the ratio of each voice. A value above 1 also enables the anti-alias low-pass filters.

formant: FormantConfig

The vocal-tract changes and aspiration. They are disabled by default.

mode: MultiVoiceMode

The voice arrangement. The default is MultiVoiceMode::Choir.

Harmony renders the lead voice and a maximum of four harmony voices.

choirVoices: number

The total number of choir voices, with the lead voice, 1..=16. The default is 1.

The other voices read the delayed lead history with random pitch drift. The code adds the voices and does not divide the sum by the number of voices. Thus, more voices can increase the output level and the clipping. Harmony does not use this value.

choirDetune: number

The drift control for secondary voices, 10..=100, without a unit. The default is 50.

The unit is not cents. The lead voice has no random choir drift. Thus, a choir with one voice does not get this detune.

choirDelay: number

The scale of the choir delay table, 20..=200, without a unit. The default is 60.

A value of 200 uses the full fixed table of frame offsets. The unit is not milliseconds. The table offset of the lead voice is zero at all settings.

choirSpreadPercent: number

The stereo width of the choir, 0..=100%. The default is 100%.

The code uses this value only if stereo_output enables the voice pan and the choir has more than one voice.

stereoOutput: boolean

Enables a stereo pan for each voice. The default is false.

This value is independent of the buffer layout of the process method. A change to this value resets some audio histories and the feedback. Processor::set_config gives the details.

harmony: HarmonyConfig

The controls for the four harmony voices. The default is MIDI-channel allocation.

Validation applies to these controls, and they can receive MIDI, also while Choir is selected.

harmonyGain: number

The pan gain of the harmony voices, 0..=1. The default is 0.5.

The code applies this gain only if stereo_output is true. The harmony path without pan does not use this control. It does not scale the lead voice.

harmonicModulation: number

The modulation depth, 0..=24, without a unit. The default is 0 (off).

The code multiplies the control by two and truncates it to an integer. Then it uses the result for a cosine modulation after the wet voices are mixed. The value is not an interval in semitones.

dryMix: number

The dry fraction at the resynthesis stage, 0..=1. The default is 0.

The code truncates this value to Q8. The wet weight is 1.0 minus the Q8 dry weight. The dry path starts after Punch and Warm and has a delay of 1,543 frames. Alien, reverb and the output gain still occur after this stage.

randomSeed: bigint

The seed for choir drift and aspiration, which use the same stream. The default is 0x1234_abcd.

Only the low 32 bits select the sequence. If a configuration change gives a different 64-bit value, the processor starts the stream again from the low 32 bits. This is also true for a change to only the high bits. Reset keeps the current position in the stream. The enabled stages set the number of random values that the code reads.

ReverbConfig

The reverb after Alien, with controls for the network, the wet mix and the decay.

The reverb is disabled by default. In bypass, the stage returns the input and does not advance the delay network or the damping filters. If the stage is enabled and the mix is zero, the network still operates. A reset clears the delay buffer but keeps the memories of the damping filters. The mix, diffusion and decay controls are quantized to Q14. The function of each control changes with the network.

enabled: boolean

Enables the selected network. The default is false. In bypass, the histories do not change.

mode: ReverbMode

The topology of the delay network. The default is ReverbMode::Echo.

mix: number

The wet fraction, 0..=1.

The default is 0.5. The dry weight is 1 - mix. Schroeder and Binaural use a mono dry signal. The other modes keep the stereo dry input. If the network is enabled, a zero mix still advances it.

diffusion: number

The diffusion control without a unit, 0..=1.

The default is 0.5. MediumHall and LargeHall scale their allpass coefficients with it. Binaural uses it as the gain of its early taps. In Echo, it sets the distance of the feedback tap. Schroeder and SmallRoom do not use it.

decay: number

The feedback control without a unit, 0..=1.

The default is 0.6. The prepared coefficient is approximately decay / 1.05. It is less than unity also at the maximum. This value is not a decay time in seconds. Some paths also use fixed feedback coefficients. Binaural does not use this control.

brightnessHz: number

The low-pass cutoff in hertz for networks with damped paths, 80..=20000.

The default is 4000 Hz. The preparation also limits it to 0.49 × sample rate. A change of the cutoff keeps the sample histories of the filters.

Telemetry

A snapshot of the voices, the levels and the effect state that you can copy.

Get it with Processor::telemetry or Processor::take_telemetry. The telemetry is for meters and displays. No audio calculation reads it. Default gives a snapshot with all zeros.

The three peak fields measure a window. The window starts at construction, at a reset, at a change of stereo output or at a call to Processor::take_telemetry. This window is independent of the peak window of Feedback.

processedFrames: bigint

The number of frames processed since construction or the last reset, as Feedback::processed_frames gives.

inputPeak: number

The largest absolute input sample in the window, divided by 32768.

The measurement is before Punch and Warm. The value is in 0..=1.

outputPeak: [number, number]

The largest absolute clipped sample of the left and the right output in the window, divided by 32768.

The measurement is after the output gain. Each value is in 0..=32767/32768.

reverbWetPeak: number

The largest absolute wet contribution of the reverb in the window, where 1 is full scale.

The contribution is the wet signal times the mix, before the output gain. It is the larger of the two channels. While the reverb is disabled, the window gets no new values.

clarity: number

How periodic the tracked input is, in 0..=1.

The value is 1 for a signal that repeats exactly at the tracked period. It is 0 for a signal with no relation between cycles and during pitch acquisition. Use it as a confidence score for Feedback::voiced. The tracker updates the related sums on each frame.

tracking: boolean

This field is true if the pitch tracker follows a period. It is false during pitch acquisition.

voiceCount: number

The number of valid entries in voice_ratios and voice_gains.

The value is 5 in Harmony mode. In Choir mode, it is ResynthesisConfig::choir_voices, in 1..=16.

voiceRatios: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number]

The pitch ratio of each voice on the last frame, where 1 is the input pitch.

Entry zero is the lead voice. In Harmony mode, entries 1 to 4 are the harmony voices. In Choir mode, the entries after the lead are the secondary voices. Each ratio includes the correction, the configured pitch shift and the ratio of the voice. The entries after voice_count are zero.

voiceGains: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number]

The linear gain of each voice, in the order of voice_ratios.

The lead and the choir voices have a gain of 1. The gain of a harmony voice includes the MIDI velocity gain, in 0..=3.98095703125. MIDI velocity 127 gives the maximum, approximately +12 dB. The gain is zero for a voice that does not sound. It does not include the configured harmony level or the pan. The harmony controller updates it every 101 frames.

punchGain: number

The current drive of Punch, divided by its base drive.

The value is the ratio of the two input envelopes times the configured input gain. It is more than 1 at an attack. Punch updates it every 100 frames. The value is 1 while Punch is disabled.

warmGain: number

The linear gain that Warm applies before its saturation curve and removes after it.

The value is the inverse of the input peak envelope. For input below -30 dB, it is the gain of +30 dB. Warm updates it every 100 frames. The value is 1 while Warm is disabled.

alienLoopFrames: number

The length of the Alien loop in frames, as AlienConfig::loop_frames gives.

alienPhaseFrames: number

The current frame in the Alien loop. It is less than alien_loop_frames.

The reverse reader is two times this number of frames behind the recording position. The value advances also while Alien is disabled.

formantGeneration: number

The wrapping count of formant analyses since construction.

The count increases every 441 frames while the formant stage is enabled. Compare two values to find if Processor::formant_envelope can give a new result.

TimedEvent

A control that applies immediately before the zero-based input frame offset.

Offsets must be less than the current block length. They must not decrease in the event slice. Events with equal offsets execute in slice order. Thus, a later change at the same frame sees the earlier changes. An empty block accepts no events.

Offsets are local to this call, not a total count of processed frames. This timing tells when the state changes. Smoothing, the analysis interval and the signal latency also control when the audible result occurs.

The processor validates each event before it starts to process the block. If one event is not valid, the processor rejects the full block. This includes the valid events that are earlier in the slice.

offset: number

The frame offset in the block.

event: ControlEvent

The control change.

WarmConfig

Asymmetric input saturation, followed by a 50 Hz high-pass filter.

Warm operates after Punch and before pitch detection. Its adaptive normalization updates every 100 enabled frames. When Warm is disabled, the envelope and filter histories do not change. When Warm is enabled again, they continue from their last state, unless the processor was reset.

enabled: boolean

Enables the saturation stage. The default is false.

driveDb: number

The drive in decibels, 0..=6. The default is 3 dB. The output gain changes by -0.35 dB for each dB of drive. At 0 dB, the envelope normalization and the output high-pass filter still operate.

Types

BlockEvents

type BlockEvents = TimedEvent[]

The events for one call that processes audio (TimedEvent[] in TypeScript).

Each offset is a zero-based frame index in the current block. Each offset must be in the block and must not be less than the offset before it. Events with equal offsets execute in array order. An empty block accepts no events. If there are no events, omit the optional argument. Then the binding does not decode an array.

ChordDegree

type ChordDegree =
  | "i"
  | "ii"
  | "iiSeventh"
  | "iii"
  | "iiiSeventh"
  | "iv"
  | "ivSeventh"
  | "v"
  | "vSeventh"
  | "vi"
  | "viSeventh"
  | "vii"
  | "viiSeventh"

A diatonic chord with its root on a degree of the selected HarmonyScale.

Triads use the root, third and fifth scale degrees. Seventh chords also use the seventh. Degrees above the seventh go into higher octaves. The degree names do not set a major or minor quality. The selected scale supplies the tones. The default is the tonic triad, I.

ChordName

type ChordName =
  | "major"
  | "majorSixth"
  | "majorSeventh"
  | "majorSeventhSuspendedFourth"
  | "minor"
  | "minorSixth"
  | "minorSeventh"
  | "minorSeventhFlatFifth"
  | "diminished"
  | "diminishedSeventh"
  | "dominantSeventh"
  | "dominantSeventhFlatFifth"
  | "augmented"
  | "augmentedSeventh"
  | "suspendedFourth"
  | "suspendedSecond"
  | "suspendedSeventh"

A named chord for HarmonySource::ChordByName.

Each variant lists the semitones above the root. These values do not include the inversion, the key transposition, the register or the voicing spread. Triads use three voices.

ControlEvent

type ControlEvent =
  | { type: "configure"; value: ProcessorConfig }
  | { type: "resynthesis"; value: ResynthesisConfig }
  | { type: "punch"; value: PunchConfig }
  | { type: "warm"; value: WarmConfig }
  | { type: "alien"; value: AlienConfig }
  | { type: "reverb"; value: ReverbConfig }
  | { type: "outputGain"; value: number }
  | { type: "midi"; value: MidiEvent }
  | { type: "correctionMidi"; value: MidiEvent }
  | { type: "reset" }

A configuration or MIDI control that applies before a frame in the block.

Give controls to a process call as TimedEvent values. The call borrows the slice only for that call. There is no heap allocation and no deferred queue. A stage event replaces all settings of that stage. To change one field, start from the current configuration of the processor. Configuration changes have the same effects on state as Processor::set_config.

CorrectionScale

type CorrectionScale = "major" | "minor" | "chromatic"

A scale for NoteMask::from_key_scale.

HarmonyScale

type HarmonyScale =
  | "major"
  | "majorWithoutSeventh"
  | "majorFlatSeventh"
  | "minor"
  | "harmonicMinor"
  | "minorNaturalSixth"
  | "minorMajorSeventh"

The scale that smart intervals and chords by degree use.

HarmonySource

type HarmonySource =
  | "fixedInterval"
  | "smartInterval"
  | "chordByDegree"
  | "chordByName"
  | "chordViaMidi"
  | "midiOmni"
  | "midiChannels"

The source of target periods for the four harmony voices.

The default is MidiChannels. The static interval and chord sources use the related HarmonyConfig fields. The MIDI sources use ControlEvent::Midi. The configuration of the sources that are not selected is still validated and kept.

InitInput

type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module

Inversion

type Inversion = "root" | "first" | "second"

The chord inversion raises the lowest chord tones by one octave.

The inversion applies before the register and the spread. It applies only to named chords and degree chords. Root position is the default. The first inversion moves one tone and the second inversion moves two tones. The voicing of MIDI chords uses the played notes, not this control.

MidiEvent

type MidiEvent =
  | { type: "noteOn"; channel: number; note: number; velocity: number }
  | { type: "noteOff"; channel: number; note: number }
  | { type: "allNotesOff" }

The supported MIDI note controls, with zero-based channel numbers.

Use ControlEvent::Midi for harmony. Use ControlEvent::CorrectionMidi for the independent correction keyboard. The typed representation can contain u8 values that are not valid. validate and the event preflight of the processor check the MIDI ranges. Note numbers use A4 = 69 at 440 Hz.

MultiVoiceMode

type MultiVoiceMode = "choir" | "harmony"

The method that resynthesis uses to render its voices.

NoteMask

type NoteMask = [boolean, boolean, boolean, boolean, boolean, boolean, boolean, boolean, boolean, boolean, boolean, boolean]

The permitted correction pitch classes, in the order C, C♯, D, D♯, E, F, F♯, G, G♯, A, A♯, B.

A true flag enables that pitch class in all octaves.

The default is CHROMATIC. All combinations of flags are valid. This includes NONE. If the mask is empty, the correction ratio moves toward unity with the configured retune half-life. An empty mask does not clear the histories.

PitchClass

type PitchClass =
  | "c"
  | "cSharp"
  | "d"
  | "dSharp"
  | "e"
  | "f"
  | "fSharp"
  | "g"
  | "gSharp"
  | "a"
  | "aSharp"
  | "b"

One of the twelve notes in an octave.

ReverbMode

type ReverbMode = "echo" | "schroeder" | "smallRoom" | "binaural" | "mediumHall" | "largeHall"

The echo or reverberation network. The default is Echo.

All modes share one delay buffer. A mode change uses the same buffer contents and damping filter memories. Thus a transition can play audio from the previous network. The stereo layout of the buffer does not make all modes give different left and right signals. Schroeder gives the same value on the two channels.

SyncInitInput

type SyncInitInput = BufferSource | WebAssembly.Module