Upload via GUI (47 Dateien)
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
// AudioWorklet-Prozessor für die isolierte "Nur Minecraft"-Tonaufnahme.
|
||||
//
|
||||
// loopback-capture liefert PCM-Häppchen unregelmäßig getaktet über IPC (mal
|
||||
// etwas früher, mal etwas später). Würde man sie direkt nacheinander als
|
||||
// einzelne AudioBufferSourceNode-Aufrufe abspielen, würde jede kleine
|
||||
// Verzögerung als hörbares Knacksen/Aussetzer auffallen. Stattdessen landen
|
||||
// ankommende Häppchen hier in einem Ringpuffer; der Audio-Rendering-Thread
|
||||
// liest in gleichmäßigem Takt (process() läuft alle 128 Samples) daraus.
|
||||
// Kleine Zeitschwankungen bei der Anlieferung werden so unhörbar
|
||||
// abgefedert. Läuft der Puffer doch mal leer, gibt es kurz Stille statt
|
||||
// eines Knacksens.
|
||||
class PcmRingBufferProcessor extends AudioWorkletProcessor {
|
||||
constructor() {
|
||||
super();
|
||||
this.capacity = sampleRate * 2; // 2 Sekunden Puffer je Kanal
|
||||
this.ring = [new Float32Array(this.capacity), new Float32Array(this.capacity)];
|
||||
this.writeIdx = 0;
|
||||
this.readIdx = 0;
|
||||
this.available = 0; // gepufferte Frames (nicht Samples)
|
||||
this.port.onmessage = (e) => this._enqueue(e.data);
|
||||
}
|
||||
|
||||
_enqueue([left, right]) {
|
||||
const n = left.length;
|
||||
for (let i = 0; i < n; i++) {
|
||||
const idx = (this.writeIdx + i) % this.capacity;
|
||||
this.ring[0][idx] = left[i];
|
||||
this.ring[1][idx] = right[i];
|
||||
}
|
||||
this.writeIdx = (this.writeIdx + n) % this.capacity;
|
||||
this.available = Math.min(this.capacity, this.available + n);
|
||||
}
|
||||
|
||||
process(_inputs, outputs) {
|
||||
const output = outputs[0];
|
||||
const frames = output[0].length;
|
||||
const playable = Math.min(frames, this.available);
|
||||
for (let i = 0; i < playable; i++) {
|
||||
const idx = (this.readIdx + i) % this.capacity;
|
||||
output[0][i] = this.ring[0][idx];
|
||||
output[1][i] = this.ring[1][idx];
|
||||
}
|
||||
for (let i = playable; i < frames; i++) { output[0][i] = 0; output[1][i] = 0; }
|
||||
this.readIdx = (this.readIdx + playable) % this.capacity;
|
||||
this.available -= playable;
|
||||
return true; // Prozessor am Leben halten, auch wenn gerade nichts ankommt
|
||||
}
|
||||
}
|
||||
|
||||
registerProcessor('pcm-player', PcmRingBufferProcessor);
|
||||
Reference in New Issue
Block a user