5.5 KiB
glados
(no submodules)
Purpose
GLaDOSPlugin is the universal voice-effect insert. It runs the input signal through a fixed six-stage chain — granular pitch shift → formant tilt → robotic-intensity tremolo → soft-clip distortion → low-pass filter → short feedback reverb — and exposes a typed setter for each stage plus six named presets. The plugin is an insert (io.inputs[0].count === io.outputs[0].count === "preserve"), so it accepts any input channel count and emits the same shape.
The plugin extends AbstractAudioFxPlugin, runs identically across browser / server / worklet renderers, and validates every setter at the boundary: out-of-range values throw AUDIO_FX.INVALID_OPTIONS with the offending value attached. Six built-in presets cover the GLaDOS family (mainline, test chamber, cake deception) plus Wheatley, Cave Johnson, and a generic robotic voice.
Features
- Six chained stages, each with a typed setter:
setPitchShift,setFormantShift,setRoboticIntensity,setDistortionAmount,setLowPassCutoff,setReverbAmount. - Six built-in presets (
glados-mainline,glados-test-chamber,glados-cake-deception,wheatley,cave-johnson,robotic-generic) selected via the constructionpresetoption orapplyGladosPreset(name). getGLaDOSPresets()exposes the read-only preset table so editors can render preset dropdowns and preview the values.- Per-stage range validation:
pitchShift/formantShift∈ [-12, 12] semitones,roboticIntensity/distortionAmount/reverbAmount∈ [0, 1],lowPassCutoff∈ [20, 20 000] Hz. applyGladosPresetis named distinctly fromAbstractAudioFxPlugin.applyPreset(snapshot)so the two methods do not collide.
Usage: Basic Example
import { GLaDOSPlugin } from "@suaveplan/audio-fx-plugin-glados";
const glados = new GLaDOSPlugin({ preset: "glados-mainline" });
chain.add(glados);
Usage: Advanced Example
import { GLaDOSPlugin, getGLaDOSPresets } from "@suaveplan/audio-fx-plugin-glados";
const presetNames = Object.keys(getGLaDOSPresets()) as ReadonlyArray<
keyof ReturnType<typeof getGLaDOSPresets>
>;
const voice = new GLaDOSPlugin({ preset: "wheatley" });
await voice.setup(
{ sampleRate: 48_000, channels: 2, blockSize: 512 },
ctx
);
// Customise the wheatley preset with extra reverb.
voice.setReverbAmount(0.4);
voice.setLowPassCutoff(5_500);
// Preview every preset on the same line of dialogue.
for (const name of presetNames) {
voice.applyGladosPreset(name);
await player.playDemo();
}
API Reference
GLaDOSPlugin(class extendsAbstractAudioFxPlugin)new GLaDOSPlugin(options?: GLaDOSPluginOptions)— throwsAUDIO_FX.INVALID_OPTIONSon malformed options.applyGladosPreset(name: GLaDOSPreset): void,getCurrentPreset(): GLaDOSPreset,getGladosConfig(): GLaDOSConfig.setPitchShift(-12..12),setFormantShift(-12..12),setRoboticIntensity(0..1),setDistortionAmount(0..1),setLowPassCutoff(20..20000),setReverbAmount(0..1)— each throwsAUDIO_FX.INVALID_OPTIONSon out-of-range.
getGLaDOSPresets()— read-only view of the six built-in presets.- Types:
GLaDOSPresetliteral union,GLaDOSConfig,GLaDOSPluginOptions,GLaDOSPresetData.
Implementation Notes
The pitch-shift stage is a per-channel granular ring buffer with linear-interpolated fractional read — the same shape used by PitchShifterPlugin but with a smaller window because vocal content does not need the larger windows that drum or instrumental material benefits from. For pitch shifts within the GLaDOS-typical range (-5 to +5 semitones) this produces an audibly clean result. Going further out is supported but the perceptual artefacts increase.
The formant-tilt stage is a simple gain shift (10^(formantShift / 8)) rather than a true formant analyzer. A real formant-shift implementation needs spectral analysis + cepstrum manipulation, which is much heavier and would not measurably improve the GLaDOS character. The simple gain matches what most game-audio implementations use for "robotic voice" effects.
The robotic-intensity stage is a 30 Hz tremolo modulating amplitude — fast enough to read as "robotic clicking" rather than "vibrato". The depth is mapped linearly from the roboticIntensity knob so the user-facing range [0, 1] translates to 0 (no tremolo) through 1 (full chopping). The 30 Hz rate is faster than typical tremolo because that's what makes the voice sound mechanical rather than emotional.
The distortion stage is a tanh soft-clip with parallel dry/wet routing — same shape as the DistortionPlugin's waveshaper mode but with a fixed drive that scales with the user's distortionAmount knob.
The low-pass is a one-pole filter (the same shape used by MicrophoneSimulationPlugin), and the reverb is a short feedback delay (REVERB_DELAY_MS = 30 ms per channel). Both are intentionally simpler than their dedicated sibling-plugin counterparts because the GLaDOS character does not need surgical control — the user wants "more or less" of each colour, not a fully parametric filter and convolution.
Preset application replaces the entire config in one shot via { ...PRESETS[preset] }. Individual setter overrides applied after applyGladosPreset will stick; the next preset application replaces them. The preset payload encodes both the preset name and the live config so applyPreset(snap) restores any per-stage overrides made after the preset was originally applied.