Signatur
Beschreibung
AudioData ist die rohe, unkomprimierte Audio-Einheit der WebCodecs API. Ein Objekt enthält eine feste Anzahl von Frames (ein Frame = ein Sample pro Kanal) für einen oder mehrere Kanäle, dazu die Metadaten format, sampleRate, numberOfFrames, numberOfChannels, timestamp und duration. Zeitstempel und Dauer werden in Mikrosekunden angegeben.
Solche Objekte entstehen typischerweise als Ausgabe eines AudioDecoder, beim Lesen eines Mikrofon-Tracks über MediaStreamTrackProcessor oder durch direktes Erzeugen mit new AudioData(init). Umgekehrt dienen sie als Eingabe für den AudioEncoder, zum Beispiel um selbst erzeugtes oder bearbeitetes Audio nach Opus oder AAC zu kodieren.
Wichtige Methoden sind:
allocationSize(options): berechnet, wie viele Bytes fürcopyTo()nötig sind.copyTo(destination, options): kopiert die Samples einer Ebene (plane) in einen Puffer, wahlweise mit Umwandlung in ein anderes Format.clone(): erzeugt eine weitere Referenz auf dieselben Mediendaten.close(): gibt den Speicher sofort frei.
Das Sample-Format entscheidet über die Speicheranordnung: Bei interleaved-Formaten ("u8", "s16", "s32", "f32") liegen die Samples aller Kanäle abwechselnd in einer einzigen Ebene. Bei planar-Formaten ("f32-planar" usw.) hat jeder Kanal eine eigene Ebene. AudioData ist transferierbar und lässt sich daher ohne Kopie per postMessage() an Worker weitergeben.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $init Pflicht | Object | Initialisierungsobjekt für den Konstruktor new AudioData(init). |
|
| $init.format Pflicht | "u8"|"s16"|"s32"|"f32"|"u8-planar"|"s16-planar"|"s32-planar"|"f32-planar" | Sample-Format und Speicheranordnung (interleaved oder planar). | |
| $init.sampleRate Pflicht | number | Abtastrate in Hz, z. B. 48000. |
|
| $init.numberOfFrames Pflicht | number | Anzahl der Frames, also der Samples pro Kanal. | |
| $init.numberOfChannels Pflicht | number | Anzahl der Audiokanäle (1 = mono, 2 = stereo …). | |
| $init.timestamp Pflicht | number | Startzeitpunkt der Daten in Mikrosekunden. | |
| $init.data Pflicht | ArrayBuffer|TypedArray|DataView | Puffer mit den Samples. Er muss mindestens numberOfFrames × numberOfChannels × Bytes pro Sample groß sein. |
|
| $init.transfer | Array<ArrayBuffer> | [] | Puffer, die ohne Kopie übernommen werden. Danach sind sie beim Aufrufer detached, also nicht mehr nutzbar. |
Rückgabewert
AudioData-Objekt zurück. Die Eigenschaften format, sampleRate, numberOfFrames, numberOfChannels, timestamp und duration (in µs) sind schreibgeschützt. Nach close() ist format gleich null und die übrigen Werte sind 0.Beispiele
AudioData aus einem erzeugten Sinuston erstellen
const sampleRate = 48000;
const numberOfFrames = 480; // 10 ms
const samples = new Float32Array(numberOfFrames);
for (let i = 0; i < numberOfFrames; i++) {
samples[i] = Math.sin(2 * Math.PI * 440 * i / sampleRate) * 0.5;
}
const audioData = new AudioData({
format: 'f32-planar',
sampleRate,
numberOfFrames,
numberOfChannels: 1,
timestamp: 0,
data: samples
});
console.log(audioData.format, audioData.duration);
audioData.close();
Decoder-Ausgabe kanalweise auslesen und freigeben
const decoder = new AudioDecoder({
output: (audioData) => {
const channels = [];
for (let ch = 0; ch < audioData.numberOfChannels; ch++) {
const opts = { planeIndex: ch, format: 'f32-planar' };
const buffer = new Float32Array(audioData.allocationSize(opts) / 4);
audioData.copyTo(buffer, opts);
channels.push(buffer);
}
console.log(`${audioData.timestamp} µs, ${channels.length} Kanäle`);
audioData.close(); // Speicher sofort freigeben!
},
error: (e) => console.error('Decoder-Fehler:', e)
});
decoder.configure({ codec: 'opus', sampleRate: 48000, numberOfChannels: 2 });
AudioData in einen Web-Audio-AudioBuffer umwandeln
const toAudioBuffer = (audioData, ctx) => {
const buffer = ctx.createBuffer(
audioData.numberOfChannels,
audioData.numberOfFrames,
audioData.sampleRate
);
for (let ch = 0; ch < audioData.numberOfChannels; ch++) {
const target = new Float32Array(audioData.numberOfFrames);
audioData.copyTo(target, { planeIndex: ch, format: 'f32-planar' });
buffer.copyToChannel(target, ch);
}
return buffer;
};
// Verwendung:
// const ctx = new AudioContext();
// const src = ctx.createBufferSource();
// src.buffer = toAudioBuffer(audioData, ctx);
// src.connect(ctx.destination); src.start();
Mikrofon-Samples lesen und in einen Worker übertragen
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
const [track] = stream.getAudioTracks();
const processor = new MediaStreamTrackProcessor({ track });
const reader = processor.readable.getReader();
const worker = new Worker('audio-worker.js');
while (true) {
const { value: audioData, done } = await reader.read();
if (done) break;
// Übertragen statt kopieren – im Hauptthread danach nicht mehr verwenden
worker.postMessage(audioData, [audioData]);
}