audio-cpp's picture
Publish Audio Model Architecture Atlas
f4cd8a9 verified
Raw History Blame Contribute Delete
14.1 kB
const db = window.ARCHITECTURE;
const $ = id => document.getElementById(id);
const esc = value => String(value ?? '').replace(/[&<>"']/g, c => ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c]));
const icon = name => `<img src="assets/icons/${name}.svg" alt="">`;
const byId = new Map(db.models.map(m=>[m.id,m]));
const roleNames = {ar:'Autoregressive backbone',flow:'Generation architecture',encoder:'Encoder',codec:'Codec / vocoder',head:'Prediction',dsp:'Frontend / DSP',io:'Input / output'};
const state = {mode:'shared',selected:new Set(['higgs_audio_tts','soprano_tts','miotts']),model:'higgs_audio_tts',compare:null,component:'ar-qwen3',node:null,routes:{},blocks:[],zoom:1};
let overview=null, graphResult=null;
const route = model => model.routes[state.routes[model.id] || 0];
const technology = model => [...new Set(model.routes.flatMap(r=>r.nodes.filter(n=>n.component).map(n=>db.components[n.component].name)))];
const visible = () => {
const q=$('search').value.toLowerCase();
return db.models.filter(m=>(!$('task').value||m.task===$('task').value)&&[m.name,m.family,...m.variants,...technology(m)].join(' ').toLowerCase().includes(q)).sort((a,b)=>a.name.localeCompare(b.name));
};
$('count').textContent=db.models.length;
$('coverage').textContent=`Run ${db.models.length} models locally with audio.cpp`;
$('snapshot').textContent=`Spec snapshot ${db.revision.slice(0,8)}`;
$('task').innerHTML='<option value="">All tasks</option>'+db.tasks.map(t=>`<option value="${t.id}">${esc(t.name)}</option>`).join('');
$('task').value='';
function focusComponent(id,node=null){state.component=id;state.node=node;state.blocks=[];}
function selectedNode(){
if(state.mode==='shared')return null;
const comparison=state.node?.startsWith('compare:')&&state.compare;
const model=byId.get(comparison?state.compare:state.model);
return state.node?route(model).nodes.find(n=>n.id===(comparison?state.node.slice(8):state.node)):route(model).nodes.find(n=>n.component===state.component);
}
function firstComponent(model){return route(model).nodes.find(n=>n.component&&db.components[n.component].role==='ar')?.component||route(model).nodes.find(n=>n.component)?.component;}
function openModel(id){
if(state.mode==='shared')overview={component:state.component,blocks:[...state.blocks],zoom:state.zoom,scroll:[$('graph').scrollLeft,$('graph').scrollTop]};
state.mode='model';state.model=id;state.compare=null;focusComponent(firstComponent(byId.get(id)));state.zoom=1;
render();fit();$('title').focus({preventScroll:true});
}
function back(){
state.mode='shared';state.compare=null;
if(overview){state.component=overview.component;state.blocks=[...overview.blocks];state.zoom=overview.zoom;}
render();if(overview){[$('graph').scrollLeft,$('graph').scrollTop]=overview.scroll;}
}
function toggle(id){state.selected.has(id)?state.selected.delete(id):state.selected.add(id);render();fit();}
function library(){
$('models').innerHTML=visible().map(m=>{
const active=state.mode==='shared'?state.selected.has(m.id):state.model===m.id;
return `<div class="model-row"><button class="model ${active?'active':''}" aria-pressed="${active}" data-model="${m.id}"><span class="model-name">${esc(m.name)}</span><small>${esc(technology(m).join(' · '))}</small></button><button class="open-model" data-open="${m.id}" aria-label="Open ${esc(m.name)} pipeline" title="Open ${esc(m.name)} pipeline">${icon('arrow-up-right')}</button></div>`;
}).join('')||'<p class="empty">No matching models</p>';
$('models').querySelectorAll('[data-model]').forEach(b=>b.onclick=()=>state.mode==='shared'?toggle(b.dataset.model):openModel(b.dataset.model));
$('models').querySelectorAll('[data-open]').forEach(b=>b.onclick=()=>openModel(b.dataset.open));
}
function graphNode(n,prefix=''){
const c=n.component?db.components[n.component]:null;
return {id:prefix+n.id,label:c?.name||n.label,role:c?.role||n.kind||'input',component:n.component,optional:n.optional,description:n.detail||c?.summary||n.label,action:c?'component':null};
}
function modelGraph(model,prefix=''){
const r=route(model);
return {nodes:r.nodes.map(n=>graphNode(n,prefix)),edges:r.edges.map(e=>({...e,from:prefix+e.from,to:prefix+e.to}))};
}
function sharedGraph(){
const filtered=visible();
const chosen=$('scope-filter').value==='selected'?filtered.filter(m=>state.selected.has(m.id)):filtered;
const nodes=new Map(),edges=new Map();
for(const model of chosen){
const r=route(model),mapped=new Map();
for(const n of r.nodes){
if(!n.component)continue;
const c=db.components[n.component];
if(!$('frontends').checked&&['dsp','io'].includes(c.role))continue;
const repeat=r.nodes.filter(other=>other.component===n.component).length>1;
const key=n.component+(repeat?'@'+n.id:'');
mapped.set(n.id,key);
if(!nodes.has(key))nodes.set(key,{...graphNode(n),id:key,models:new Set()});
nodes.get(key).models.add(model.id);
}
// Collapse omitted input / DSP nodes without inventing conditioning edges.
function successors(id,visited=new Set()){
if(visited.has(id))return [];
visited.add(id);
return r.edges.filter(e=>e.from===id).flatMap(e=>mapped.has(e.to)?[mapped.get(e.to)]:successors(e.to,new Set(visited)));
}
for(const [id,key] of mapped){
const next=successors(id);
const targets=next.length?next:['model:'+model.id];
for(const target of targets){const ekey=key+'|'+target;if(!edges.has(ekey))edges.set(ekey,{from:key,to:target,models:new Set()});edges.get(ekey).models.add(model.id);}
}
nodes.set('model:'+model.id,{id:'model:'+model.id,label:model.name,role:'model',action:'toggle',model:model.id,models:new Set([model.id]),pressed:state.selected.has(model.id)});
}
const focused=chosen.some(m=>state.selected.has(m.id));
const dim=ids=>focused&&![...ids].some(id=>state.selected.has(id));
return {nodes:[...nodes.values()].map(n=>({...n,dim:dim(n.models)})),edges:[...edges.values()].map(e=>({...e,dim:dim(e.models),highlight:!dim(e.models)}))};
}
function graph(){
let data;
if(state.mode==='shared')data=sharedGraph();
else{
data=modelGraph(byId.get(state.model));
if(state.compare){const other=modelGraph(byId.get(state.compare),'compare:');data.nodes.push(...other.nodes);data.edges.push(...other.edges);}
}
if(!data.nodes.length){$('graph').innerHTML='<p class="empty">No models selected in this filter.</p>';graphResult=null;return;}
graphResult=AtlasGraph.render($('graph'),data.nodes,data.edges,{active:state.mode==='shared'?state.component:state.node||selectedNode()?.id,onNode:n=>{
if(n.action==='toggle'){toggle(n.model);return;}
focusComponent(n.component,state.mode==='model'?n.id:null);
if(state.mode==='shared'){
const users=visible().filter(m=>route(m).nodes.some(n=>n.component===state.component));
const all=users.every(m=>state.selected.has(m.id));users.forEach(m=>all?state.selected.delete(m.id):state.selected.add(m.id));
}
render();
}});
sizeGraph();
}
function sizeGraph(){if(graphResult){graphResult.svg.style.width=graphResult.width*state.zoom+'px';graphResult.svg.style.height=graphResult.height*state.zoom+'px';}$('zoom-level').textContent=Math.round(state.zoom*100)+'%';}
function fit(){if(graphResult){state.zoom=Math.min(1,($('graph').clientWidth-8)/graphResult.width,($('graph').clientHeight-8)/graphResult.height);sizeGraph();}}
function setZoom(value){state.zoom=Math.max(.15,Math.min(2.5,value));sizeGraph();}
function links(urls){return urls.map((url,i)=>`<a href="${esc(url)}" target="_blank" rel="noopener noreferrer">${i===0?'Architecture source':'Reference '+(i+1)} ↗</a>`).join('');}
function inspect(){
const c=db.components[state.component];
if(!c){$('component-title').textContent='Select a component';return;}
const [ink,fill]=AtlasGraph.colors[c.role]||AtlasGraph.colors.dsp;
$('component-title').textContent=c.name;$('component-role').textContent=roleNames[c.role]||c.role;$('component-role').style.cssText=`color:${ink};background:${fill}`;
$('component-description').textContent=c.summary;
const instance=selectedNode()?.detail;
$('instance-description').hidden=!instance;$('instance-description').textContent=instance||'';
$('evidence').innerHTML=links(c.sources||[]);
const stack=c.diagram?[c.diagram,...state.blocks]:[];
$('block-nav').innerHTML=stack.slice(0,-1).map((id,i)=>`<button data-depth="${i}">${esc(db.diagrams[id].title)}</button>`).join('');
$('block-nav').querySelectorAll('button').forEach(b=>b.onclick=()=>{state.blocks=state.blocks.slice(0,Number(b.dataset.depth));inspect();});
if(!stack.length){$('scope').textContent='Block diagram not yet curated';$('blocks').replaceChildren();$('block-caption').textContent='';return;}
const diagram=db.diagrams[stack.at(-1)];
$('scope').textContent=diagram.title;$('block-caption').textContent=diagram.scope;
AtlasGraph.render($('blocks'),diagram.blocks.map(n=>({...n,role:n.kind||c.role,action:n.expand?'expand':null,sublabel:n.expand?'EXPAND BLOCK':'',actionLabel:n.expand?'Expand '+n.label:n.label})),diagram.edges.map(([from,to])=>({from,to})),{compact:true,residuals:diagram.residuals,onNode:n=>{state.blocks.push(n.expand);inspect();}});
}
function peers(){
const c=db.components[state.component];$('relation-name').textContent=c?'/ '+c.name:'';
const related=db.models.filter(m=>(state.mode==='shared'||m.id!==state.model)&&m.routes.some(r=>r.nodes.some(n=>n.component===state.component)));
$('peers').innerHTML=related.map(m=>`<button data-peer="${m.id}" title="${state.mode==='shared'?'Open pipeline':'Compare pipeline'}">${esc(m.name)} ${state.mode==='shared'?'↗':'↔'}</button>`).join('')||'<p class="empty">No other family uses this component in the current registry.</p>';
$('peers').querySelectorAll('button').forEach(b=>b.onclick=()=>{if(state.mode==='shared')openModel(b.dataset.peer);else{state.compare=b.dataset.peer;focusComponent(state.component);render();fit();}});
}
function heading(){
const model=byId.get(state.model),shared=state.mode==='shared';
$('breadcrumb').hidden=shared;$('breadcrumb-model').textContent=model.name;
$('view-label').textContent=shared?'ARCHITECTURE EXPLORER':'MODEL DETAIL';
$('title').textContent=shared?'Shared building blocks':state.compare?model.name+' + '+byId.get(state.compare).name:model.name;
$('title').tabIndex=-1;
$('family').hidden=shared;$('family').textContent=model.family+(state.compare?' / '+byId.get(state.compare).family:'');
$('variants').hidden=shared;$('variants').innerHTML=model.variants.map(v=>`<span>${esc(v)}</span>`).join('');
$('subtitle').textContent=shared?`${state.selected.size} selected · ${visible().length} matching models`:db.tasks.find(t=>t.id===model.task).name;
$('clear').hidden=shared?!state.selected.size:!state.compare;$('clear').textContent=shared?'Clear selection':'Clear comparison';
$('model-info').hidden=shared;$('summary').textContent=model.summary;
$('detail-status').textContent=model.detailStatus;
$('inputs').innerHTML=(route(model).inputs||model.inputs).map(i=>`<span>${esc(i.type.toUpperCase())} · ${esc(i.label)}<em>${i.required?'required':'optional'}</em></span>`).join('');
$('model-links').innerHTML=links(model.sources.slice(0,2))+`<a href="https://github.com/0xShug0/audio.cpp/blob/${db.revision}/${esc(model.usageDoc)}" target="_blank" rel="noopener noreferrer">audio.cpp usage ↗</a>`;
$('graph-label').textContent=shared?'SHARED ARCHITECTURE':state.compare?'PIPELINE COMPARISON':'MODEL PIPELINE';
$('scope-filter').hidden=!shared;$('frontend-control').hidden=!shared;
$('variant-wrap').hidden=shared||model.routes.length<2;
$('variant').innerHTML=model.routes.map((r,i)=>`<option value="${i}">${esc(r.name)}</option>`).join('');$('variant').value=state.routes[model.id]||0;
$('packages').hidden=shared||!model.packages.length;
$('package-list').innerHTML=model.packages.map(p=>`<div>${esc(p.display_name)}<br><code>${esc(p.id)}</code></div>`).join('');
}
function render(){heading();library();graph();inspect();peers();}
$('search').oninput=()=>{render();fit();};$('task').onchange=()=>{render();fit();};$('scope-filter').onchange=()=>{graph();fit();};$('frontends').onchange=()=>{graph();fit();};
$('variant').onchange=()=>{state.routes[state.model]=Number($('variant').value);focusComponent(firstComponent(byId.get(state.model)));render();fit();};
$('back').onclick=back;$('clear').onclick=()=>{if(state.mode==='shared')state.selected.clear();else{state.compare=null;focusComponent(firstComponent(byId.get(state.model)));}render();fit();};
$('zoom-in').onclick=()=>setZoom(state.zoom*1.2);$('zoom-out').onclick=()=>setZoom(state.zoom/1.2);$('fit').onclick=fit;
$('export').onclick=()=>{
if(!graphResult){$('status').textContent='No graph to export.';return;}
const svg=graphResult.svg.cloneNode(true);svg.removeAttribute('style');
const style=document.createElementNS('http://www.w3.org/2000/svg','style');style.textContent='text{font-family:"Noto Sans",sans-serif}.dim{opacity:.2}';svg.prepend(style);
const url=URL.createObjectURL(new Blob([new XMLSerializer().serializeToString(svg)],{type:'image/svg+xml'}));
const a=document.createElement('a');a.href=url;a.download=state.mode==='shared'?'shared-architecture.svg':state.model+'-pipeline.svg';a.click();setTimeout(()=>URL.revokeObjectURL(url),1000);
};
document.querySelector('.brand').onclick=e=>{e.preventDefault();if(state.mode==='model')back();};
const inspector=document.querySelector('.inspector');
$('expand-detail').onclick=()=>{
if($('detail-dialog').open){$('detail-dialog').close();return;}
$('detail-dialog').append(inspector);
$('expand-detail').innerHTML=icon('x');
$('expand-detail').title='Close component detail';
$('expand-detail').setAttribute('aria-label','Close component detail');
$('detail-dialog').showModal();
};
$('detail-dialog').onclose=()=>{
document.querySelector('.workspace').append(inspector);
$('expand-detail').innerHTML=icon('maximize');
$('expand-detail').title='Expand component detail';
$('expand-detail').setAttribute('aria-label','Expand component detail');
$('expand-detail').focus({preventScroll:true});
};
window.addEventListener('resize',fit);
document.fonts.ready.then(()=>{render();fit();});