Files
skills/docs/media/audio-fx/audio-fx-plugin-glados/src/glados/glados.md
2026-05-29 08:20:56 +01:00

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 construction preset option or applyGladosPreset(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.
  • applyGladosPreset is named distinctly from AbstractAudioFxPlugin.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 extends AbstractAudioFxPlugin)
    • new GLaDOSPlugin(options?: GLaDOSPluginOptions) — throws AUDIO_FX.INVALID_OPTIONS on 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 throws AUDIO_FX.INVALID_OPTIONS on out-of-range.
  • getGLaDOSPresets() — read-only view of the six built-in presets.
  • Types: GLaDOSPreset literal 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.