import { existsSync } from "node:fs"; import { TRIM_SETS, stemPath } from "@/lib/trim"; import { readWavWindow, encodeWav } from "@/lib/wav"; export const dynamic = "force-dynamic"; // A window of the stem, to audition a trim against. // // Served as WAV, always, and with NO gain applied. // // The clip audio route normalises against a fixed reference region so that // widening the view does not change the level. Here the simpler answer is the // right one: applying no gain at all has the same property -- what you hear at // one width is what you hear at another -- and it is also what actually gets // cut, since apply-hook-trims only ever atrims and fades. A hook is a couple of // seconds, so there is nothing for an encoder to save. export async function GET(request: Request, ctx: { params: Promise<{ set: string }> }) { const { set: id } = await ctx.params; const set = TRIM_SETS[id]; if (!set) return new Response("no such trim set", { status: 404 }); const url = new URL(request.url); const from = Number(url.searchParams.get("from")); const to = Number(url.searchParams.get("to")); if (!Number.isFinite(from) || !Number.isFinite(to) || to <= from) { return new Response("bad window", { status: 400 }); } // A runaway window would decode the whole stem into memory on every request. if (to - from > 120) return new Response("window too long", { status: 400 }); const file = stemPath(set); if (!existsSync(file)) return new Response("stem missing", { status: 404 }); const region = await readWavWindow(file, Math.max(0, from), to); const buf = encodeWav(region.x, region.sampleRate); return new Response(new Uint8Array(buf), { headers: { "content-type": "audio/wav", "content-length": String(buf.length), "cache-control": "no-store", }, }); }