/** * The generation models the studio offers, and which jobs each can do. * Both ACE-Steps edit audio directly. YuE2 plays scores: it covers a stretch * or builds a band from the melody and chords SheetSage2 reads out of it, but * cannot edit a stretch in place. Stem splitting is Demucs whatever is picked. */ export type Model='ace15'|'ace1'|'yue2'; export type Task='restyle'|'rewrite'|'band'|'extend'|'part'|'instrumental'|'song'|'cover'; export const MODELS:{id:Model;label:string;blurb:string}[]=[ {id:'ace15',label:'ACE-Step 1.5',blurb:'Newest. Writes bands and parts directly into your audio, and songs with lyrics.'}, {id:'yue2',label:'YuE2',blurb:'Plays the melody and chords it reads from your music, so the tune stays yours. Covers, bands and songs with vocals.'}, {id:'ace1',label:'ACE-Step 1',blurb:'The original engine. Bands follow a guide track built from your beat and chords.'}, ]; export const SUPPORTS:Record={ restyle:['ace15','ace1'],rewrite:['ace15','ace1'],band:['ace15','yue2','ace1'],extend:['ace15','ace1'], part:['ace15','ace1'],instrumental:['ace15','ace1'],song:['ace15','yue2'],cover:['yue2'], }; /** * The model a job starts on before the user picks one. Both YuE2 and ACE-Step * 1.5 write good bands under a kept vocal, with different strengths (see * TASK_NOTES), so the user chooses; YuE2 is simply first. */ export const PREFERRED:Partial>={band:'yue2',cover:'yue2'}; /** What each model is like at a particular job, where its general blurb is not enough to choose by. */ export const TASK_NOTES:Partial>>>={ band:{ yue2:'Reads your song’s chords and bars, then writes a fresh arrangement in your style and locks it to your timing. The biggest change of style; about 4 minutes for a whole song.', ace15:'Listens to the vocal itself and writes drums, bass, keys and guitar around it. Follows the singer’s feel closely; about 1.5 minutes for a whole song.', ace1:'The original engine: the band follows a guide track built from your beat and chords.', }, }; export const modelLabel=(model:Model)=>MODELS.find(m=>m.id===model)!.label; export function modelOf(value:unknown):Model{return value==='ace1'||value==='yue2'?value:'ace15';} /** The chosen model if it can do the task, otherwise the first one that can. */ export const modelFor=(task:Task,chosen:Model)=>SUPPORTS[task].includes(chosen)?chosen:SUPPORTS[task][0];