Signatur
Beschreibung
Die Eigenschaft curve eines WaveShaperNode enthält die Übertragungskurve des Waveshapers. Jedes Eingangssample im Bereich -1 bis +1 wird auf eine Stelle in diesem Array abgebildet, und der dort gespeicherte Wert wird ausgegeben. Zwischen zwei Stützpunkten wird linear interpoliert. curve[0] gehört zum Eingang -1, das letzte Element zum Eingang +1 und das mittlere Element zum Eingang 0.
Mit curve baust du nichtlineare Effekte: Gitarren-Verzerrung (Distortion, Overdrive), weiche Sättigung à la Röhre (z. B. mit Math.tanh), harte Begrenzung (Hard Clipping), Bitcrusher-artige Treppenkurven oder eine Gleichrichtung. Ist die Kurve linear (also y = x), ändert sich das Signal nicht.
Beim Zuweisen kopiert der Browser das Array intern. Änderst du danach das ursprüngliche Float32Array, hat das keine Wirkung. Um die Kurve zu ändern, musst du erneut ein Array zuweisen. Mit null (dem Standardwert) reicht der Knoten das Signal unverändert durch.
Weil nichtlineare Kurven hohe Obertöne erzeugen, die Aliasing verursachen können, kombiniert man curve meist mit der Eigenschaft oversample ("2x" oder "4x").
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $value | Float32Array | null | null | Die neue Übertragungskurve mit mindestens 2 Elementen. Die Werte liegen üblicherweise zwischen -1 und 1. null schaltet die Formung ab, das Signal läuft dann unverändert durch. |
Rückgabewert
null, wenn keine Kurve gesetzt ist.Beispiele
Klassische Distortion-Kurve auf einen Oszillator anwenden
const ctx = new AudioContext();
// Erzeugt eine Verzerrungskurve; amount steuert die Stärke
const makeDistortionCurve = (amount = 50, samples = 44100) => {
const curve = new Float32Array(samples);
const deg = Math.PI / 180;
for (let i = 0; i < samples; i++) {
const x = (i * 2) / samples - 1; // -1 … +1
curve[i] = ((3 + amount) * x * 20 * deg) / (Math.PI + amount * Math.abs(x));
}
return curve;
};
const osc = new OscillatorNode(ctx, { type: 'sine', frequency: 220 });
const shaper = new WaveShaperNode(ctx, { oversample: '4x' });
shaper.curve = makeDistortionCurve(400);
osc.connect(shaper).connect(ctx.destination);
osc.start();
osc.stop(ctx.currentTime + 2);
console.log(shaper.curve.length);
Weiche Röhren-Sättigung mit Math.tanh für ein Mikrofon-Signal
const ctx = new AudioContext();
const makeTanhCurve = (drive = 3, samples = 2048) => {
const curve = new Float32Array(samples);
const norm = Math.tanh(drive);
for (let i = 0; i < samples; i++) {
const x = (i / (samples - 1)) * 2 - 1;
curve[i] = Math.tanh(drive * x) / norm; // auf ±1 normiert
}
return curve;
};
const start = async () => {
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
const mic = ctx.createMediaStreamSource(stream);
const shaper = ctx.createWaveShaper();
shaper.curve = makeTanhCurve(5);
shaper.oversample = '2x';
mic.connect(shaper).connect(ctx.destination);
console.log('Sättigung aktiv:', shaper.curve !== null);
};
document.querySelector('#start').addEventListener('click', start);
Effekt per Schieberegler steuern und mit null umgehen (Bypass)
const ctx = new AudioContext();
const shaper = new WaveShaperNode(ctx);
// Harte Begrenzung: alles über threshold wird abgeschnitten
const makeClipCurve = (threshold, samples = 1024) => {
const curve = new Float32Array(samples);
for (let i = 0; i < samples; i++) {
const x = (i / (samples - 1)) * 2 - 1;
curve[i] = Math.max(-threshold, Math.min(threshold, x));
}
return curve;
};
const slider = document.querySelector('#clip');
slider.addEventListener('input', () => {
const t = Number(slider.value); // 0.05 … 1
// Array neu zuweisen, weil nachträgliche Änderungen ignoriert werden
shaper.curve = t >= 1 ? null : makeClipCurve(t);
console.log(shaper.curve === null ? 'Bypass' : `Clip bei ${t}`);
});
// Wichtig · Fallstricke
- Die Kurve wird kopiert: Nach dem Zuweisen haben Änderungen am ursprünglichen
Float32Arraykeine Wirkung. Um die Kurve zu ändern, musst du immer ein neues Array zuweisen. - Ein Array mit weniger als 2 Elementen löst einen
InvalidStateErroraus. NurFloat32Arrayist erlaubt, normale Arrays funktionieren nicht zuverlässig. - Eingangswerte außerhalb von
-1…+1werden auf den ersten bzw. letzten Kurvenwert begrenzt. - Nullpunkt beachten: Bei einer geraden Anzahl von Elementen liegt der Eingang
0zwischen zwei Stützpunkten. Liefert die Kurve dort nicht exakt0, entsteht ein Gleichspannungsanteil (DC-Offset), der auch in Stille hörbar oder messbar sein kann. Eine ungerade Länge oder ein nachgeschalteter Hochpass (BiquadFilterNode) helfen dagegen. - Starke Verzerrung erzeugt Aliasing. Setze deshalb
oversampleauf"2x"oder"4x". Das kostet etwas CPU. - Sehr lange Kurven (z. B. 44100 Werte) sind unkritisch, bringen aber ab ein paar tausend Stützpunkten kaum hörbaren Gewinn.
- Die Eigenschaft wird in allen aktuellen Browsern unterstützt (Chrome, Firefox, Safari, Edge). In sehr alten Safari-Versionen war nur
webkitAudioContextverfügbar. - Verzerrung erhöht die Lautstärke oft deutlich. Setze zum Schutz des Gehörs ausreichend Pegelreserve, z. B. über einen
GainNodenach dem Shaper.