fix: final-review findings (median pass tick, R11 secondary metrics, R12 chord duration, render version, dsp resample)
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
This commit is contained in:
co-authored by
Claude Sonnet 5.5
parent
2b7d5ffbeb
commit
b631bd2c7e
+1
-26
@@ -68,30 +68,5 @@ export async function writeWav(path: string, a: Audio): Promise<void> {
|
||||
}
|
||||
|
||||
export { toMono } from "../dsp/mono.ts";
|
||||
export { resample } from "../dsp/resample.ts";
|
||||
|
||||
const sinc = (x: number) => (x === 0 ? 1 : Math.sin(Math.PI * x) / (Math.PI * x));
|
||||
|
||||
/** Windowed-sinc (Blackman) resampler; low-passes at the lower Nyquist when downsampling. */
|
||||
export function resample(x: Float32Array, from: number, to: number): Float32Array {
|
||||
if (from === to) return x.slice();
|
||||
const ratio = to / from;
|
||||
const outLen = Math.round(x.length * ratio);
|
||||
const out = new Float32Array(outLen);
|
||||
const cutoff = Math.min(1, ratio); // in units of input Nyquist
|
||||
const half = 16 / cutoff; // kernel half-width in input samples (16 zero-crossings)
|
||||
for (let j = 0; j < outLen; j++) {
|
||||
const t = j / ratio;
|
||||
const lo = Math.max(0, Math.ceil(t - half)), hi = Math.min(x.length - 1, Math.floor(t + half));
|
||||
let acc = 0, wsum = 0;
|
||||
for (let i = lo; i <= hi; i++) {
|
||||
const d = i - t;
|
||||
const w = 0.42 + 0.5 * Math.cos((Math.PI * d) / half) + 0.08 * Math.cos((2 * Math.PI * d) / half);
|
||||
const k = cutoff * sinc(cutoff * d) * w;
|
||||
acc += x[i]! * k;
|
||||
wsum += k;
|
||||
}
|
||||
// Normalise to unity DC gain so edges and non-integer ratios stay calibrated.
|
||||
out[j] = wsum !== 0 ? acc / wsum : 0;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user