Rhythm Patterns

This commit is contained in:
khodowany
2026-10-06 23:55:58 -05:00
parent d2f493c17b
commit 23b606e47f
11 changed files with 673 additions and 109 deletions
+5 -4
View File
@@ -258,7 +258,7 @@ def _generate_role(source, role, data_dir, settings=None, cache_dir=None):
elif role.endswith('_accompaniment'):
canonical = generator.comping.Canonical(document, part, seed)
result = generator.arrange.generate._arrange_document(document, part, {}, owned={'accompaniment'}, accompaniment=canonical)
details = {'canonical_comping': canonical.report, 'accompaniment_rhythm': canonical.rhythm_report, 'rhythm_source': choice_source}
details = {'canonical_comping': canonical.report, 'accompaniment_rhythm': canonical.rhythm_report, 'groove_cycles': canonical.groove_report, 'rhythm_source': choice_source}
else:
result = generator.arrange.generate._arrange_document(document, part, {}, owned={'vocal' if part == 'vocal' else 'melody'})
allowed = tuple((a, b) for a, b, r in windows(document, part) if r == role)
@@ -367,7 +367,8 @@ def generate_tree(source_dir, output_dir, *, jobs=2, cache_dir=None, progress=Fa
raise ValueError(f'{path.name}/{role}: {error}') from error
for path, (original, source) in sources.items():
assembled = assemble(source, results[path])
reuse = generator.arrange.accompaniment.audit(original, assembled)
generator.arrange.accompaniment.audit(original, assembled)
reuse = generator.arrange.accompaniment.audit(original, {role: value['document'] for role, value in results[path].items()}, role_documents=True)
for part, document in assembled.items():
document['metadata'] = copy.deepcopy(original['metadata'])
document['metadata']['song_id'] = generator.score.slugify(path.stem)
@@ -377,7 +378,7 @@ def generate_tree(source_dir, output_dir, *, jobs=2, cache_dir=None, progress=Fa
(analysis_dir / (generator.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', 'composition_timings', 'cache_hit', 'observed_reads')} for role, value in results[path].items()}
for part, audit in reuse.items():
stable[part + '_accompaniment']['details']['reuse_audit'] = audit
for role, audit in reuse.items():
stable[role]['details']['reuse_audit'] = audit
(analysis_dir / (generator.score.slugify(path.stem) + '.roles')).write_text(json.dumps(stable, sort_keys=True, indent=2))
return len(sources) * 3