Save
This commit is contained in:
+17
-4
@@ -43,7 +43,7 @@ class SourceAnalysis:
|
||||
staff.update(id='source', name='Source')
|
||||
melodic = analysis.analyze(prepared)
|
||||
content = {'melody': [(str(n.start), str(n.end), dataclasses.asdict(n.pitch)) for n in melodic.melody],
|
||||
'measures': [{k: m.get(k) for k in ('duration', 'meter', 'key', 'harmonies', 'tempos', 'section_label', 'implicit')} for m in staff['measures']]}
|
||||
'measures': [{k: m.get(k) for k in ('duration', 'time_signature', 'key', 'harmonies', 'tempos', 'section_label', 'implicit')} for m in staff['measures']]}
|
||||
# Fraction/string spelling is canonical and never includes filesystem IDs.
|
||||
key = hashlib.sha256(json.dumps(content, sort_keys=True, default=str).encode()).hexdigest()
|
||||
return cls(json.dumps(prepared, sort_keys=True), key)
|
||||
@@ -148,6 +148,18 @@ def _fill(notes, length, prefix, voice='voice_arranged'):
|
||||
|
||||
|
||||
def generate_role(source, role, data_dir, settings=None, cache_dir=None):
|
||||
from generator.input_audit import composition
|
||||
started=time.monotonic()
|
||||
with composition(data_dir,role,cache_dir) as reads:
|
||||
result=_generate_role(source,role,data_dir,settings,cache_dir)
|
||||
# Observed reads are diagnostics, never cache identity or musical seeds.
|
||||
result['trace']={**result['trace'],'input_boundary':'data, generator code, Python runtime, own role cache'}
|
||||
result['observed_reads']=sorted(reads)
|
||||
result['seconds']=time.monotonic()-started
|
||||
return result
|
||||
|
||||
|
||||
def _generate_role(source, role, data_dir, settings=None, cache_dir=None):
|
||||
if role not in ROLES: raise ValueError('Unknown generation role: '+role)
|
||||
data_dir=Path(data_dir); resources=vocabulary.load(data_dir/'composition')
|
||||
settings=settings or {}
|
||||
@@ -190,7 +202,7 @@ def generate_role(source, role, data_dir, settings=None, cache_dir=None):
|
||||
output=notation.measures(result['staves'][0]['measures'][first:first+count],solo.notes(),'solo_'+part)
|
||||
notation.replace_region(result,first,output);annotate(result,solo,offset)
|
||||
details=report.structure(solo)
|
||||
solo_report=report.describe(solo,scale_library,first,offset)
|
||||
solo_report=report.describe(solo,scale_library,first,offset,detail=details)
|
||||
elif role.endswith('_accompaniment'):
|
||||
canonical=comping.Canonical(document,part,seed)
|
||||
result=generate._arrange_document(document,part,{},owned={'accompaniment'},accompaniment=canonical)
|
||||
@@ -251,7 +263,7 @@ def _job(request):
|
||||
return generate_role(source,role,directory,settings,cache)
|
||||
|
||||
|
||||
def generate_tree(source_dir, output_dir, *, jobs=2, cache_dir=None, progress=False):
|
||||
def generate_tree(source_dir, output_dir, *, jobs=2, cache_dir=None, progress=False, timings=None):
|
||||
if type(jobs) is not int or not 1<=jobs<=16:
|
||||
raise ValueError('composition workers must be between 1 and 16')
|
||||
source_dir,output_dir=Path(source_dir),Path(output_dir)
|
||||
@@ -263,6 +275,7 @@ def generate_tree(source_dir, output_dir, *, jobs=2, cache_dir=None, progress=Fa
|
||||
results={p:{} for p in sources}
|
||||
def accept(path,role,value):
|
||||
results[path][role]=value
|
||||
if timings is not None:timings.append({'source':str(path),'role':role,'seconds':value['seconds'],'cache_hit':value['cache_hit'],'observed_reads':value.get('observed_reads',[])})
|
||||
if progress:print(f'Composition: {path.stem}/{role}: '+('cached' if value['cache_hit'] else f'{value["seconds"]:.1f}s'),flush=True)
|
||||
if jobs==1:
|
||||
for path,role,args in requests:
|
||||
@@ -283,6 +296,6 @@ def generate_tree(source_dir, output_dir, *, jobs=2, cache_dir=None, progress=Fa
|
||||
analysis_dir=output_dir.parent/'analysis';analysis_dir.mkdir(parents=True,exist_ok=True)
|
||||
(analysis_dir/(score.slugify(path.stem)+'.txt')).write_text('\n'.join(results[path][r]['report'] for r in ROLES))
|
||||
# Not a score file: diagnostics are deliberately outside the songs schema.
|
||||
stable={role:{k:v for k,v in value.items() if k not in ('seconds','cache_hit')} for role,value in results[path].items()}
|
||||
stable={role:{k:v for k,v in value.items() if k not in ('seconds','cache_hit','observed_reads')} for role,value in results[path].items()}
|
||||
(analysis_dir/(score.slugify(path.stem)+'.roles')).write_text(json.dumps(stable,sort_keys=True,indent=2))
|
||||
return len(sources)*3
|
||||
|
||||
Reference in New Issue
Block a user