Signatur
Beschreibung
Die schreibgeschützte Eigenschaft detune liefert ein AudioParam-Objekt, mit dem sich die Tonhöhe und gleichzeitig die Abspielgeschwindigkeit eines Audio-Buffers in Cent verändern lässt. 100 Cent sind ein Halbton, 1200 Cent eine Oktave. Der Standardwert ist 0, also keine Verstimmung.
detune wirkt zusammen mit playbackRate. Die tatsächliche Abspielrate ergibt sich aus playbackRate * 2^(detune / 1200). Wie bei einer Bandmaschine ändern sich Tonhöhe und Tempo also gemeinsam. Eine Tonhöhenänderung ohne Tempoänderung (Pitch-Shifting) bietet detune nicht.
Der Parameter ist k-rate: Der Wert wird einmal pro Render-Block (128 Samples) ausgewertet und nicht für jedes Sample einzeln. Automatisierung ist trotzdem möglich, etwa mit setValueAtTime(), linearRampToValueAtTime() oder exponentialRampToValueAtTime(). Typische Einsätze sind Sampler, bei denen ein einzelnes Sample in verschiedenen Tonhöhen gespielt wird, zufällige leichte Verstimmung bei Soundeffekten in Spielen und Pitch-Bend-Effekte.
Rückgabewert
AudioParam mit defaultValue 0. Der Wertebereich ist nominal unbegrenzt (minValue/maxValue entsprechen dem größten darstellbaren Float-Wert). Die Einheit ist Cent. Den Wert setzt man über detune.value oder über die Automatisierungsmethoden.Beispiele
Sample eine Oktave höher abspielen
const ctx = new AudioContext();
const playSample = async (url, cents = 0) => {
const response = await fetch(url);
const arrayBuffer = await response.arrayBuffer();
const audioBuffer = await ctx.decodeAudioData(arrayBuffer);
const source = ctx.createBufferSource();
source.buffer = audioBuffer;
source.detune.value = cents; // 1200 Cent = eine Oktave
source.connect(ctx.destination);
source.start();
console.log('Detune:', source.detune.value);
};
document.querySelector('#play').addEventListener('click', () => {
playSample('/sounds/piano-c4.wav', 1200);
});
Einfacher Sampler: Halbtöne aus einem Sample erzeugen
const ctx = new AudioContext();
let pianoBuffer;
const loadBuffer = async () => {
const res = await fetch('/sounds/piano-c4.wav');
pianoBuffer = await ctx.decodeAudioData(await res.arrayBuffer());
};
// semitones: Abstand zum Grundton C4
const playNote = (semitones) => {
const src = new AudioBufferSourceNode(ctx, {
buffer: pianoBuffer,
detune: semitones * 100
});
src.connect(ctx.destination);
src.start();
};
await loadBuffer();
// C-Dur-Dreiklang: C, E, G
[0, 4, 7].forEach((st, i) => {
setTimeout(() => playNote(st), i * 300);
});
Pitch-Bend per Automatisierung und zufällige Variation
const ctx = new AudioContext();
const playWithBend = (buffer) => {
const src = ctx.createBufferSource();
src.buffer = buffer;
src.connect(ctx.destination);
const now = ctx.currentTime;
// Leichte Zufallsverstimmung (±30 Cent) gegen Wiederholungseffekte
const random = (Math.random() - 0.5) * 60;
src.detune.setValueAtTime(random, now);
// Innerhalb von 1 s einen Halbton nach unten ziehen
src.detune.linearRampToValueAtTime(random - 100, now + 1);
src.start(now);
return src;
};
// Wichtig · Fallstricke
- Nur lesbar: Eine Zuweisung wie
source.detune = 100hat keine Wirkung. Setzen Sie stattdessensource.detune.valueoder nutzen Sie die Optiondetuneim Konstruktornew AudioBufferSourceNode(). - Tempo ändert sich mit:
detuneverändert Tonhöhe und Abspieldauer gemeinsam. Bei+1200läuft das Sample doppelt so schnell und ist halb so lang. - k-rate: Sehr schnelle Modulationen (Vibrato im Audiobereich) werden nur pro 128-Sample-Block aufgelöst. Dafür ist ein
OscillatorNodemit a-rate-detunebesser geeignet. - Ein
AudioBufferSourceNodelässt sich nur einmal starten. Für jede Note brauchen Sie einen neuen Knoten. DerAudioBufferselbst kann wiederverwendet werden. - Kompatibilität: In allen modernen Browsern verfügbar. Ältere Safari-Versionen (vor 14.1) unterstützten
detuneaufAudioBufferSourceNodenicht bzw. nur mit dem PräfixwebkitAudioContext. Browser erlauben die Audiowiedergabe meist erst nach einer Nutzerinteraktion (Autoplay-Richtlinie). Falls nötig, rufen Siectx.resume()auf.