73 lines
2.3 KiB
JavaScript
73 lines
2.3 KiB
JavaScript
class PCMAudioProcessor extends AudioWorkletProcessor {
|
|
constructor() {
|
|
super()
|
|
this._inRate = sampleRate // z.B. 48000
|
|
this._pos = 0 // Phase in Eingangssamples [0, step)
|
|
this._carry = null // letztes Eingangssample des vorigen Blocks
|
|
this._outRate = 24000
|
|
}
|
|
|
|
process(inputs) {
|
|
const chs = inputs[0]
|
|
if (!chs || chs.length === 0) return true
|
|
|
|
const inF32 = chs[0] // mono Float32
|
|
const step = this._inRate / this._outRate
|
|
|
|
// src ggf. mit carry präfixieren, damit i+1 existiert
|
|
let src = inF32
|
|
if (this._carry !== null) {
|
|
const tmp = new Float32Array(1 + inF32.length)
|
|
tmp[0] = this._carry
|
|
tmp.set(inF32, 1)
|
|
src = tmp
|
|
}
|
|
|
|
// Anzahl ausgebbarer Samples (lineare Interp.: i+1 < src.length)
|
|
const avail = src.length - 1 - this._pos
|
|
const outLen = avail > 0 ? Math.ceil(avail / step) : 0
|
|
|
|
const outI16 = new Int16Array(outLen)
|
|
|
|
let pos = this._pos
|
|
for (let k = 0; k < outLen; k++) {
|
|
const i = Math.floor(pos)
|
|
const frac = pos - i
|
|
|
|
const x0 = src[i]
|
|
const x1 = src[i + 1] // existiert garantiert durch -1 in avail
|
|
|
|
// Linearinterp. + Clamping
|
|
let y = x0 + frac * (x1 - x0)
|
|
if (y > 1) y = 1
|
|
else if (y < -1) y = -1
|
|
|
|
// Float32 -> int16 (runden, saturieren)
|
|
const s = y <= -1 ? -0x8000 : Math.round(y * 0x7fff)
|
|
outI16[k] = s
|
|
|
|
pos += step
|
|
}
|
|
|
|
// Phase für nächsten Block relativ zu dessen src verschieben
|
|
// (src[0] == letztes Sample des aktuellen Eingangs)
|
|
this._pos = pos - (src.length - 1)
|
|
if (this._pos < 0) this._pos = 0 // numerische Sicherheit
|
|
|
|
// letztes echtes Eingangssample als carry behalten
|
|
this._carry = src[src.length - 1]
|
|
|
|
// zero-copy an die UI (Transfer des Buffers)
|
|
try {
|
|
this.port.postMessage(outI16, [outI16.buffer])
|
|
} catch {
|
|
// Fallback ohne Transferliste (z. B. in älteren Browsern)
|
|
this.port.postMessage(outI16)
|
|
}
|
|
|
|
return true
|
|
}
|
|
}
|
|
|
|
registerProcessor("audio-processor-worklet", PCMAudioProcessor)
|