Metabolism: rule program, song-driven life, tribe VMs; M2.7 design (strains & allegiances, living wells)

This commit is contained in:
Dejvino
2026-10-28 10:07:05 +01:00
parent 16f4b4a805
commit f939351689
28 changed files with 3199 additions and 601 deletions
+49
View File
@@ -0,0 +1,49 @@
// Prepare a song ahead of time so viewing is fast (EVOLUTION.md: "the prepare
// step"). Writes the full processed analysis + seed as a compact JSON artifact
// that the browser loads instead of re-analysing the WAV.
//
// node tools/prepare.js # drone, runner, dusk @ 12345
// node tools/prepare.js --songs runner # one song
// node tools/prepare.js --songs drone,runner --seeds 12345,777 --out out
//
// Artifacts land in <out>/prepared/<song>-<seed>.json. The WAV is still needed
// at viewing time for audio, but analysis is skipped. deserializeSong() must
// produce a world bit-identical to the live WAV path — test/prepare.test.js
// asserts that.
import { writeFileSync, mkdirSync } from 'node:fs';
import { resolve, dirname } from 'node:path';
import { fileURLToPath } from 'node:url';
import { loadSong } from './load.js';
import { serializeSong } from '../src/song/serialize.js';
const HERE = dirname(fileURLToPath(import.meta.url));
const ROOT = resolve(HERE, '..');
const BANK = resolve(ROOT, '../flow-state/test/songs');
function args(argv) {
const out = {};
for (let i = 2; i < argv.length; i += 2) out[argv[i].replace(/^--/, '')] = argv[i + 1];
return out;
}
const opt = args(process.argv);
const names = (opt.songs || 'drone,runner,dusk').split(',').map((s) => s.trim()).filter(Boolean);
const seeds = (opt.seeds || '12345').split(',').map(Number).filter((n) => Number.isFinite(n));
const outDir = resolve(ROOT, opt.out || 'out');
const dir = resolve(outDir, 'prepared');
mkdirSync(dir, { recursive: true });
let count = 0;
for (const name of names) {
for (const seed of seeds) {
const { song } = loadSong(resolve(BANK, `${name}.wav`), { fps: 30, seed });
const file = resolve(dir, `${name}-${seed}.json`);
const json = JSON.stringify(serializeSong(song));
writeFileSync(file, json);
const kb = (Buffer.byteLength(json) / 1024).toFixed(1);
console.log(`${file} ${kb.padStart(7)} KB ${song.name}`);
count++;
}
}
console.log(`prepared ${count} song${count === 1 ? '' : 's'} → ${dir}`);