Recover analyzer DSP and realtime pipeline corrections
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
// Phoenix binary WebSocket packet decoders. Keep this module dependency-free so
|
||||
// protocol compatibility can be tested without a browser.
|
||||
|
||||
export function decodePhoenixSpectroBuffer(buffer) {
|
||||
if (!(buffer instanceof ArrayBuffer) || buffer.byteLength < 20) return null;
|
||||
const view = new DataView(buffer);
|
||||
if (view.getUint32(0, true) !== 0x50585350) return null;
|
||||
const seq = view.getUint32(4, true);
|
||||
const sampleRate = view.getUint32(8, true);
|
||||
const fftSize = view.getUint32(12, true);
|
||||
const count = view.getUint32(16, true);
|
||||
if (count < 1 || buffer.byteLength !== 20 + count * 4) return null;
|
||||
return {
|
||||
seq,
|
||||
sampleRate,
|
||||
fftSize,
|
||||
bins: new Float32Array(buffer, 20, count),
|
||||
};
|
||||
}
|
||||
|
||||
export function decodePhoenixVisualsBuffer(buffer) {
|
||||
if (!(buffer instanceof ArrayBuffer) || buffer.byteLength < 32) return null;
|
||||
const view = new DataView(buffer);
|
||||
if (view.getUint32(0, true) !== 0x50585653 || view.getUint16(4, true) !== 1) return null;
|
||||
const flags = view.getUint16(6, true);
|
||||
const seq = view.getUint32(8, true);
|
||||
const xyCount = view.getUint32(12, true);
|
||||
const waveColumns = view.getUint32(16, true);
|
||||
const waveChannels = view.getUint16(20, true);
|
||||
const waveColumnSamples = view.getUint32(24, true);
|
||||
const waveSampleRate = view.getUint32(28, true);
|
||||
if (waveChannels > 2) return null;
|
||||
const xyBytes = xyCount * 8;
|
||||
const waveValues = waveColumns * waveChannels * 2;
|
||||
const expectedBytes = 32 + xyBytes + waveValues * 4;
|
||||
if (!Number.isSafeInteger(expectedBytes) || buffer.byteLength !== expectedBytes) return null;
|
||||
|
||||
let offset = 32;
|
||||
let left = null;
|
||||
let right = null;
|
||||
if ((flags & 1) && xyCount > 0) {
|
||||
left = new Float32Array(xyCount);
|
||||
right = new Float32Array(xyCount);
|
||||
for (let index = 0; index < xyCount; index++) {
|
||||
left[index] = view.getFloat32(offset, true);
|
||||
right[index] = view.getFloat32(offset + 4, true);
|
||||
offset += 8;
|
||||
}
|
||||
} else {
|
||||
offset += xyBytes;
|
||||
}
|
||||
|
||||
let wave = null;
|
||||
if ((flags & 2) && waveValues > 0 && (waveChannels === 1 || waveChannels === 2)) {
|
||||
const data = new Float32Array(waveValues);
|
||||
for (let index = 0; index < waveValues; index++) {
|
||||
data[index] = view.getFloat32(offset + index * 4, true);
|
||||
}
|
||||
wave = {
|
||||
data,
|
||||
columns: waveColumns,
|
||||
channels: waveChannels,
|
||||
columnSamples: waveColumnSamples,
|
||||
sampleRate: waveSampleRate,
|
||||
};
|
||||
}
|
||||
return { seq, left, right, wave };
|
||||
}
|
||||
Reference in New Issue
Block a user