Start · Sprachen · JavaScript · Referenz · AudioData.copyTo()

AudioData.copyTo()

Methode

Kopiert die Samples einer Ebene (Plane) eines <code>AudioData</code>-Objekts in einen Zielpuffer, bei Bedarf mit Ausschnitt und Umwandlung des Sample-Formats.

seit JavaScript WebCodecs API – Chromium 94+, Firefox 130+, Safari Kategorie: webapi

Signatur

AudioData.prototype.copyTo(destination, options)

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

Typ
undefined
Beschreibung
Kein Rückgabewert. Die Daten stehen danach in 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();
Float32Array(4) [0, 0.5, 0.25, -0.5] Float32Array(4) [1, -1, 0.75, -0.25]

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();
400 1234