63 lines
2.1 KiB
JavaScript
63 lines
2.1 KiB
JavaScript
// 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);
|
|
}
|
|
|