// 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); }