Signatur
Beschreibung
copyTo() ist der Weg, um an die rohen PCM-Samples eines AudioData-Objekts zu kommen, z. B. nach dem Dekodieren mit einem AudioDecoder oder bei der Aufnahme über MediaStreamTrackProcessor. Die Methode schreibt die Daten synchron in einen von dir bereitgestellten ArrayBuffer, ein TypedArray oder eine DataView.
Welche Daten kopiert werden, legst du über das Pflicht-Objekt options fest. Bei planaren Formaten (z. B. "f32-planar") hat jeder Kanal eine eigene Ebene, und planeIndex entspricht dem Kanal. Bei verschachtelten Formaten (z. B. "s16") gibt es nur eine Ebene mit allen Kanälen abwechselnd, dann ist planeIndex immer 0. Mit frameOffset und frameCount kopierst du nur einen Ausschnitt.
Über format kannst du die Daten beim Kopieren in ein anderes Sample-Format umwandeln lassen. Garantiert ist dabei nur die Umwandlung nach "f32-planar". Das ist genau das Layout, das die Web Audio API (AudioBuffer.copyToChannel()) erwartet. planeIndex bezieht sich immer auf das Zielformat.
Die nötige Puffergröße in Bytes für dieselben Optionen liefert vorab AudioData.allocationSize(options).
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $destination Pflicht | ArrayBuffer | TypedArray | DataView | Zielpuffer, in den die Samples geschrieben werden. Er muss mindestens allocationSize(options) Bytes groß sein. |
|
| $options Pflicht | object | Legt fest, was kopiert wird. Hat die folgenden Eigenschaften. | |
| $options.planeIndex Pflicht | number | Index der Ebene, die kopiert wird. Bei planaren Formaten ist das der Kanal, bei verschachtelten Formaten nur 0. |
|
| $options.frameOffset | number | 0 | Ab welchem Frame kopiert wird. |
| $options.frameCount | number | numberOfFrames - frameOffset | Wie viele Frames kopiert werden. |
| $options.format | "u8" | "s16" | "s32" | "f32" | "u8-planar" | "s16-planar" | "s32-planar" | "f32-planar" | Format des AudioData-Objekts | Sample-Format im Ziel. Garantiert unterstützt wird nur die Umwandlung nach "f32-planar", andere Ziele können einen NotSupportedError auslösen. |
Rückgabewert
destination.Beispiele
Interleaved-Daten in einzelne Kanäle aufteilen
// 4 Frames Stereo, verschachtelt: L0, R0, L1, R1, ...
const samples = new Float32Array([0, 1, 0.5, -1, 0.25, 0.75, -0.5, -0.25]);
const audioData = new AudioData({
format: 'f32',
sampleRate: 48000,
numberOfFrames: 4,
numberOfChannels: 2,
timestamp: 0,
data: samples,
});
const left = new Float32Array(audioData.numberOfFrames);
const right = new Float32Array(audioData.numberOfFrames);
// Umwandlung nach f32-planar: planeIndex = Kanal im Zielformat
audioData.copyTo(left, { planeIndex: 0, format: 'f32-planar' });
audioData.copyTo(right, { planeIndex: 1, format: 'f32-planar' });
console.log(left);
console.log(right);
audioData.close();
Dekodierte Audiodaten mit der Web Audio API abspielen
const audioCtx = new AudioContext();
const decoder = new AudioDecoder({
output: (audioData) => {
const { numberOfChannels, numberOfFrames, sampleRate } = audioData;
const buffer = audioCtx.createBuffer(numberOfChannels, numberOfFrames, sampleRate);
for (let ch = 0; ch < numberOfChannels; ch++) {
const channel = new Float32Array(numberOfFrames);
audioData.copyTo(channel, { planeIndex: ch, format: 'f32-planar' });
buffer.copyToChannel(channel, ch);
}
audioData.close(); // Speicher sofort freigeben
const source = audioCtx.createBufferSource();
source.buffer = buffer;
source.connect(audioCtx.destination);
source.start();
},
error: (e) => console.error('Dekodierfehler:', e),
});
decoder.configure({ codec: 'opus', sampleRate: 48000, numberOfChannels: 2 });
// decoder.decode(new EncodedAudioChunk({ ... }));
Ausschnitt kopieren und Puffer mit allocationSize() anlegen
const pcm = new Int16Array(2 * 1000); // 1000 Frames Stereo s16
pcm.fill(1234);
const audioData = new AudioData({
format: 's16',
sampleRate: 44100,
numberOfFrames: 1000,
numberOfChannels: 2,
timestamp: 0,
data: pcm,
});
// Frames 100 bis 199, Format bleibt s16 verschachtelt (nur Ebene 0)
const options = { planeIndex: 0, frameOffset: 100, frameCount: 100 };
const bytes = audioData.allocationSize(options);
const target = new ArrayBuffer(bytes);
audioData.copyTo(target, options);
console.log(bytes, new Int16Array(target)[0]);
audioData.close();