P0: Rust engine, wire daemon and audio-reactive descent surface
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
import type { Command } from './types';
|
||||
|
||||
const MINUS = '\u2212';
|
||||
|
||||
export function fmtDb(level: number): string {
|
||||
if (!(level > 0.0001)) return MINUS + '\u221e';
|
||||
const db = 20 * Math.log10(level);
|
||||
return (db >= 0 ? '+' : MINUS) + Math.abs(db).toFixed(1) + ' dB';
|
||||
}
|
||||
|
||||
export function fmtTime(bar: number, bpm: number): string {
|
||||
const seconds = Math.max(0, bar - 1) * 4 * (60 / Math.max(40, bpm));
|
||||
const minutes = Math.floor(seconds / 60);
|
||||
const rest = seconds - minutes * 60;
|
||||
return String(minutes).padStart(2, '0') + ':' + rest.toFixed(1).padStart(4, '0');
|
||||
}
|
||||
|
||||
export function fmtBar(bar: number): string {
|
||||
return (Math.round(bar * 10) / 10).toFixed(1);
|
||||
}
|
||||
|
||||
export function fmtTempo(bpm: number): string {
|
||||
return Number.isInteger(bpm) ? String(bpm) : bpm.toFixed(1);
|
||||
}
|
||||
|
||||
export function commandLabel(command: Command): string {
|
||||
switch (command.type) {
|
||||
case 'play': return 'play';
|
||||
case 'stop': return 'stop';
|
||||
case 'strike': return `strike ${command.vein} ${command.velocity.toFixed(2)}`;
|
||||
case 'set_tempo': return `tempo ${fmtTempo(command.bpm)}`;
|
||||
case 'set_vein_gain': return `${command.vein} gain ${command.gain.toFixed(2)}`;
|
||||
case 'get_snapshot': return 'snapshot';
|
||||
}
|
||||
}
|
||||
|
||||
export function eventLabel(event: { kind: string }): string {
|
||||
return event.kind.replace('_', ' ');
|
||||
}
|
||||
Reference in New Issue
Block a user