Initial Commit
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
import { readFile } from "node:fs/promises";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import type { BlockContext, ProcessorConfig } from "@suaveplan/audio-core";
|
||||
import type {
|
||||
ChainContext,
|
||||
ChainHandle,
|
||||
} from "@suaveplan/audio-fx-plugin-base/base";
|
||||
import { defaultAmbientState } from "@suaveplan/audio-fx-plugin-base/chain";
|
||||
import { describe, expect, it } from "@suaveplan/testing/runner";
|
||||
import { SpessaSynthPlugin } from "../src/plugin/spessasynth-plugin.js";
|
||||
|
||||
const FIXTURE_URL = new URL("./fixtures/tiny-piano.sf2", import.meta.url);
|
||||
const FIXTURE_PATH = fileURLToPath(FIXTURE_URL);
|
||||
|
||||
const SR = 48_000;
|
||||
const BLOCK = 512;
|
||||
|
||||
function newCtx(): ChainContext {
|
||||
const chain: ChainHandle = {
|
||||
id: "integration",
|
||||
name: "integration",
|
||||
channels: 2,
|
||||
sampleRate: SR,
|
||||
blockSize: BLOCK,
|
||||
slotCount: 1,
|
||||
};
|
||||
return {
|
||||
chain,
|
||||
position: { index: 0, total: 1 },
|
||||
predecessors: [],
|
||||
successors: [],
|
||||
ambient: defaultAmbientState(),
|
||||
buses: { get: () => undefined, list: () => [] },
|
||||
};
|
||||
}
|
||||
|
||||
function newConfig(): ProcessorConfig {
|
||||
return { sampleRate: SR, channels: 2, blockSize: BLOCK };
|
||||
}
|
||||
|
||||
function blockCtx(): BlockContext {
|
||||
return {
|
||||
blockOffsetSamples: 0,
|
||||
sampleRate: SR,
|
||||
channels: 2,
|
||||
opts: {},
|
||||
};
|
||||
}
|
||||
|
||||
function rms(buf: Float32Array): number {
|
||||
let sum = 0;
|
||||
for (let i = 0; i < buf.length; i++) sum += buf[i]! ** 2;
|
||||
return Math.sqrt(sum / buf.length);
|
||||
}
|
||||
|
||||
describe("integration: render via the vendored tiny-piano SF2 fixture", () => {
|
||||
it("renders a C-major chord with non-zero RMS through process()", {
|
||||
timeout: 30_000,
|
||||
}, async () => {
|
||||
const bytes = new Uint8Array(await readFile(FIXTURE_PATH));
|
||||
const plugin = new SpessaSynthPlugin();
|
||||
await plugin.init({
|
||||
soundFontBytes: bytes,
|
||||
sampleRate: SR,
|
||||
});
|
||||
await plugin.setup(newConfig(), newCtx());
|
||||
|
||||
// C major: C4, E4, G4.
|
||||
for (const note of [60, 64, 67]) {
|
||||
plugin.sendMidi({
|
||||
type: "noteOn",
|
||||
channel: 0,
|
||||
note,
|
||||
velocity: 100,
|
||||
});
|
||||
}
|
||||
|
||||
// Render half a second.
|
||||
const blocks = Math.ceil(SR / 2 / BLOCK);
|
||||
const merged = new Float32Array(blocks * BLOCK);
|
||||
for (let b = 0; b < blocks; b++) {
|
||||
const out: Float32Array[] = [
|
||||
new Float32Array(BLOCK),
|
||||
new Float32Array(BLOCK),
|
||||
];
|
||||
plugin.process([], out, blockCtx());
|
||||
merged.set(out[0]!, b * BLOCK);
|
||||
}
|
||||
const r = rms(merged);
|
||||
expect(r).toBeGreaterThan(0);
|
||||
plugin.dispose();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user