feat(streamer): fft + log-bin spectrum analyzer
This commit is contained in:
parent
48955634af
commit
8bca1767bd
2 changed files with 158 additions and 0 deletions
41
streamer/tests/fft.test.ts
Normal file
41
streamer/tests/fft.test.ts
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
import { describe, expect, it } from "vitest";
|
||||
import { SpectrumAnalyzer } from "../src/fft.ts";
|
||||
|
||||
function sineFrame(freqHz: number, sampleRate = 48000, samples = 1024): Buffer {
|
||||
const buf = Buffer.alloc(samples * 2 * 2); // s16le stereo
|
||||
for (let i = 0; i < samples; i++) {
|
||||
const v = Math.round(Math.sin((2 * Math.PI * freqHz * i) / sampleRate) * 16000);
|
||||
buf.writeInt16LE(v, i * 4);
|
||||
buf.writeInt16LE(v, i * 4 + 2);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
describe("SpectrumAnalyzer", () => {
|
||||
it("produces N bars of normalized [0..1] floats", () => {
|
||||
const a = new SpectrumAnalyzer({ bars: 48, sampleRate: 48000 });
|
||||
a.feed(sineFrame(1000));
|
||||
const bars = a.bars();
|
||||
expect(bars).toHaveLength(48);
|
||||
bars.forEach((v) => {
|
||||
expect(v).toBeGreaterThanOrEqual(0);
|
||||
expect(v).toBeLessThanOrEqual(1);
|
||||
});
|
||||
});
|
||||
|
||||
it("a 1khz sine puts most energy in low bars (logarithmic binning)", () => {
|
||||
const a = new SpectrumAnalyzer({ bars: 48, sampleRate: 48000 });
|
||||
a.feed(sineFrame(1000));
|
||||
const bars = a.bars();
|
||||
const lowSum = bars.slice(0, 16).reduce((s, v) => s + v, 0);
|
||||
const highSum = bars.slice(32).reduce((s, v) => s + v, 0);
|
||||
expect(lowSum).toBeGreaterThan(highSum * 5);
|
||||
});
|
||||
|
||||
it("silence produces all-near-zero bars", () => {
|
||||
const a = new SpectrumAnalyzer({ bars: 72, sampleRate: 48000 });
|
||||
a.feed(Buffer.alloc(1024 * 4));
|
||||
const bars = a.bars();
|
||||
bars.forEach((v) => expect(v).toBeLessThan(0.01));
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue