podcast-visualizer/find-loudness.ts

57 lines
1.4 KiB
TypeScript
Raw Normal View History

2020-06-06 22:19:36 +02:00
import { createReadStream } from "fs";
export type SwapPoint = {
position_start: number;
duration: number;
loud: boolean;
label: string;
};
export default async function (
file: import("fs").PathLike,
threshold_at_point: number,
inertia_samples: number,
label: string
): Promise<SwapPoint[]> {
const stream = createReadStream(file);
let position = 0;
const results: SwapPoint[] = [];
let last_swap_position = 0;
let keep_loud_until = 0;
let was_loud_last_time = false;
return new Promise((resolve, reject) => {
stream.on("readable", () => {
let chunk: Buffer | null;
while ((chunk = stream.read()) !== null) {
for (let i = 0; i < chunk.byteLength; i++) {
position++;
const byte = chunk[i];
const volume = Math.abs(byte - 128);
if (position >= keep_loud_until) {
const is_loud: boolean = volume > threshold_at_point;
if (is_loud != was_loud_last_time) {
const swap_point = {
position_start: last_swap_position,
duration: position - last_swap_position,
loud: was_loud_last_time,
label,
};
results.push(swap_point);
last_swap_position = position;
was_loud_last_time = is_loud;
}
}
if (volume > threshold_at_point) {
keep_loud_until = position + inertia_samples;
}
}
}
});
stream.on("end", () => {
resolve(results);
});
stream.on("error", reject);
});
}