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
+62
View File
@@ -0,0 +1,62 @@
// Song serialization — the prepare step (EVOLUTION.md).
//
// The whole analysis is deterministic, so a song's *processed* form can be
// written out once and loaded instead of re-derived from the WAV. This module
// is the single serializer for both sides: node's tools/prepare.js writes the
// artifact, the browser deserializes it. `deserializeSong` rebuilds the song
// through the SAME buildSong call the live path uses, so a prepared song is
// bit-identical to one analysed from the WAV — prepare is a cache, never a
// parallel pipeline.
import { buildSong } from './song.js';
const VERSION = 1;
/** Compact everything downstream (world, camera, metrics) needs. */
export function serializeSong(song) {
const a = song.analysis;
return {
version: VERSION,
seed: song.seed,
fps: a.fps,
frames: a.frames,
duration: a.duration,
sampleRate: a.sampleRate,
energy: Array.from(a.energy),
flux: Array.from(a.flux),
dominantHz: Array.from(a.dominantHz),
flatness: Array.from(a.flatness),
onsets: a.onsets,
sections: a.sections,
summary: a.summary,
};
}
/** Rebuild the analysis object the pipeline expects. */
export function deserializeAnalysis(obj) {
return {
fps: obj.fps,
frames: obj.frames,
duration: obj.duration,
sampleRate: obj.sampleRate,
energy: Float32Array.from(obj.energy),
flux: Float32Array.from(obj.flux),
dominantHz: Float32Array.from(obj.dominantHz),
flatness: Float32Array.from(obj.flatness),
onsets: obj.onsets,
sections: obj.sections,
summary: obj.summary,
};
}
/**
* Rebuild a song from a prepared artifact. Same code path as the live WAV
* pipeline (buildSong over a reconstructed analysis), so the world, the camera
* and the metrics cannot drift from it.
* @param {object} obj serializedSong() output
*/
export function deserializeSong(obj) {
if (obj.version !== VERSION) throw new Error(`prepared song version mismatch: ${obj.version}`);
return buildSong(deserializeAnalysis(obj), obj.seed);
}