Source identity
| Field | Recorded value |
|---|---|
| Source type | GitHub source |
| Original record | Janady13/ai-music-system / lib/music/generator.js |
| Date | Not specified in source |
| Repository | Janady13/ai-music-system |
| Revision | cd5207850253ee238f8a267c043b1e3c070ed81a |
| Branch | codex/create-ai-for-music-generation-ifwcfc |
| Path or archive member | lib/music/generator.js |
| Original SHA-256 | 4dc6104c2a49cbd6e7b958fab7ba0c2af61052c355e2a372bdb5c54e5ef31497 |
| Git blob SHA | 2ccd91ba67da8c5f08092c0a3ad1412589bba851 |
| Reading-copy SHA-256 | 4dc6104c2a49cbd6e7b958fab7ba0c2af61052c355e2a372bdb5c54e5ef31497 |
Recovered source transcript
Download complete source text ↓203 lines · 6.0 KB
const fs = require("fs");
const path = require("path");
const CORPUS_FILE = path.join(__dirname, "../../data/music_corpus.json");
let cache = null;
function loadCorpus() {
if (cache) return cache;
const data = JSON.parse(fs.readFileSync(CORPUS_FILE, "utf8"));
cache = data.map((entry) => ({
...entry,
fingerprint: buildFingerprint(entry)
}));
return cache;
}
function buildFingerprint(entry) {
const chroma = entry.scale === "minor" || entry.scale === "aeolian" ? -1 : 1;
const moodWeight = entry.mood.length / 10;
const density = entry.arrangement.reduce((acc, section) => acc + section.length, 0);
return {
chroma,
moodWeight,
density,
tempo: entry.tempo,
instrumentationSize: entry.primaryInstruments.length
};
}
function scoreInfluence(entry, params) {
const { genre, mood, tempo, duration } = params;
let score = 0;
if (genre && entry.genre === genre) score += 4;
if (mood && entry.mood === mood) score += 3;
if (tempo) score += 1 - Math.min(1, Math.abs(entry.tempo - tempo) / 80);
if (duration) {
const target = entry.arrangement.reduce((acc, section) => acc + section.length, 0);
score += 1 - Math.min(1, Math.abs(target - duration) / 160);
}
score += entry.fingerprint.moodWeight * 0.3;
return score;
}
function chooseInfluences(params, corpus) {
const ranked = corpus
.map((entry) => ({ entry, score: scoreInfluence(entry, params) }))
.sort((a, b) => b.score - a.score)
.slice(0, 3);
if (!ranked.length) throw new Error("No influences available");
return ranked;
}
function blendTempos(influences, params) {
const weights = influences.map((inf, idx) => (idx === 0 ? 0.5 : 0.25));
let tempo = 0;
influences.forEach((inf, i) => {
tempo += inf.entry.tempo * weights[i];
});
if (params.tempo) tempo = (tempo + params.tempo) / 2;
return Math.round(tempo);
}
function mergeInstruments(influences, requested) {
const pool = new Set(requested || []);
for (const inf of influences) {
inf.entry.primaryInstruments.forEach((instrument) => pool.add(instrument));
}
return Array.from(pool).slice(0, 12);
}
function deriveSections(influences, duration) {
const base = influences[0].entry.arrangement.map((section) => ({ ...section }));
const totalBars = base.reduce((acc, section) => acc + section.length, 0);
if (!duration || totalBars === duration) return base;
const scaleFactor = duration / totalBars;
return base.map((section) => ({
...section,
length: Math.max(4, Math.round(section.length * scaleFactor))
}));
}
function craftSoundDesign(influences) {
const layers = [];
influences.forEach(({ entry }, index) => {
layers.push({
influence: entry.title,
focus: index === 0 ? "primary" : "support",
synthesis: entry.genre.match(/electronic|techno|synthwave/)
? "subtractives with layered modulation"
: entry.genre === "ambient"
? "granular textures with spectral diffusion"
: entry.genre === "jazz"
? "acoustic capture with ribbon coloration"
: "orchestral seating with natural room tails",
processing: entry.production.mix.slice(0, 2)
});
});
return layers;
}
function automateDynamics(influences, params) {
const automation = [];
const adjectives = {
uplifting: "expansive crescendo",
contemplative: "gentle swell",
peaceful: "weightless bloom",
energetic: "aggressive drive",
driving: "relentless lift"
};
const descriptor = adjectives[params.mood] || "expressive contour";
influences[0].entry.production.automation.forEach((step) => {
automation.push({
strategy: step,
intent: descriptor
});
});
if (params.duration && params.duration > 120) {
automation.push({
strategy: "Macro dynamics mapped to performance controller",
intent: "Maintain long-form interest"
});
}
return automation;
}
function createNarrative(influences, params) {
return {
concept: `${params.mood || influences[0].entry.mood} ${params.genre || influences[0].entry.genre} suite`,
storyline: [
"Initialize motif with sparse instrumentation",
"Introduce counter lines and rhythmic motion",
"Elevate density with harmonic expansion",
"Deliver apex with focused spotlight",
"Dissolve into tailored ambience"
],
influences: influences.map(({ entry, score }) => ({
title: entry.title,
genre: entry.genre,
mood: entry.mood,
weight: Number(score.toFixed(2))
}))
};
}
function generateMusicPlan(options = {}) {
try {
const corpus = loadCorpus();
const params = {
genre: options.genre || null,
mood: options.mood || null,
duration: options.duration || 120,
tempo: options.tempo || null,
key: options.key || null,
seedInstruments: options.instruments || []
};
const influences = chooseInfluences(params, corpus);
const tempo = blendTempos(influences, params);
const instruments = mergeInstruments(influences, params.seedInstruments);
const arrangement = deriveSections(influences, params.duration);
const soundDesign = craftSoundDesign(influences);
const automation = automateDynamics(influences, params);
const narrative = createNarrative(influences, params);
const key = params.key || influences[0].entry.key;
const scale = influences[0].entry.scale;
return {
ok: true,
metadata: {
genre: params.genre || influences[0].entry.genre,
mood: params.mood || influences[0].entry.mood,
tempo,
key,
scale,
duration: params.duration,
generatedAt: new Date().toISOString()
},
composition: {
arrangement,
instrumentation: instruments,
soundDesign,
automation,
narrative,
performance: {
expressive: influences[0].entry.performance.expressive,
spotlight: influences[0].entry.performance.spotlight
}
}
};
} catch (error) {
return {
ok: false,
error: error.message || String(error)
};
}
}
module.exports = {
loadCorpus,
generateMusicPlan
};