import { AudioDocument } from "@suaveplan/audio-core"; const PAGE_SIZE = 1024; /** * Build an `AudioDocument` from pre-computed channel data. Splits each * channel into pages of `PAGE_SIZE` samples. */ export function buildDoc( channels: Float32Array[], sampleRate: number ): AudioDocument { const sourceLength = channels[0]?.length ?? 0; const pages: { channelData: Float32Array[]; startSample: number }[] = []; for (let start = 0; start < sourceLength; start += PAGE_SIZE) { const len = Math.min(PAGE_SIZE, sourceLength - start); const pageData: Float32Array[] = channels.map((ch) => ch.subarray(start, start + len) ); pages.push({ channelData: pageData, startSample: start }); } return new AudioDocument({ sampleRate, channels: channels.length, sourceLength, pages, }); } /** * Generate a sine-wave channel buffer at the given amplitude, frequency, and * duration. Amplitude is linear (1.0 = 0 dBFS). */ export function sine( amplitude: number, frequencyHz: number, sampleRate: number, durationSeconds: number ): Float32Array { const n = Math.round(durationSeconds * sampleRate); const out = new Float32Array(n); const w = (2 * Math.PI * frequencyHz) / sampleRate; for (let i = 0; i < n; i++) out[i] = amplitude * Math.sin(w * i); return out; } /** Constant-DC channel. */ export function constant(value: number, n: number): Float32Array { const out = new Float32Array(n); out.fill(value); return out; } /** Concatenate channel segments. */ export function concat(...segments: Float32Array[]): Float32Array { let total = 0; for (const s of segments) total += s.length; const out = new Float32Array(total); let p = 0; for (const s of segments) { out.set(s, p); p += s.length; } return out; }