Training Model
This commit is contained in:
@@ -17,21 +17,18 @@ import generator.melody
|
||||
import generator.model
|
||||
import generator.musicxml
|
||||
import generator.parts
|
||||
import generator.rhythm
|
||||
import generator.scales.library
|
||||
import generator.scales.mapping
|
||||
import generator.scales.timeline
|
||||
import generator.score
|
||||
import generator.solo.arrangement
|
||||
import generator.solo.sequences
|
||||
|
||||
FINAL_SECTION_INDEX = 6
|
||||
|
||||
def arrange_document(document: dict, part_type: str, *, rhythms: generator.rhythm.Library, scales: generator.scales.library.Library | None = None) -> dict:
|
||||
"""Place the regular form; the song pipeline inserts solos after all heads exist."""
|
||||
document = generator.parts.prepare_document(document)
|
||||
plans = plan_arrangement(document, rhythms) if part_type != 'vocal' else {}
|
||||
return _arrange_document(document, part_type, plans, scales=scales)
|
||||
def arrange_document(document: dict, part_type: str) -> dict:
|
||||
"""Canonical source-only template; solos are inserted by production roles."""
|
||||
from generator import comping, vocabulary
|
||||
document=generator.parts.prepare_document(document)
|
||||
with vocabulary.using(vocabulary.load(),part_type+'_accompaniment'):
|
||||
backing=comping.Canonical(document,part_type,'canonical') if part_type!='vocal' else None
|
||||
return _arrange_document(document,part_type,accompaniment=backing)
|
||||
|
||||
def section_source(source: list[dict], section, next_section=None) -> list[dict]:
|
||||
result = copy.deepcopy(source)
|
||||
@@ -44,27 +41,13 @@ def section_source(source: list[dict], section, next_section=None) -> list[dict]
|
||||
generator.arrange.pickup.harmonies(destination, result[0])
|
||||
return result
|
||||
|
||||
def plan_arrangement(document: dict, rhythms: generator.rhythm.Library) -> dict[int, generator.accompaniment.Plan]:
|
||||
source = generator.score.source_staff(document)['measures']
|
||||
body = generator.score.body_start_measure_index(source)
|
||||
previous = generator.accompaniment.carried_chords(source)
|
||||
canonical = generator.accompaniment.plan_section(source[body:], rhythms, initial=previous[body], electric=True)
|
||||
result = {}
|
||||
for section in generator.arrange.form.full_arrangement_sections(source, 'acoustic'):
|
||||
start = section.source_measure_index - body
|
||||
end = start + section.measure_count
|
||||
result[section.section_index] = generator.accompaniment.Plan(canonical.acoustic_bass[start:end],
|
||||
canonical.acoustic_upper[start:end], canonical.electric[start:end])
|
||||
return result
|
||||
|
||||
def _arrange_document(document: dict, part_type: str, plans: dict[int, generator.accompaniment.Plan], *, scales: generator.scales.library.Library | None = None, reports: list[str] | None = None, source_name: str = '', owned=None, accompaniment=None) -> dict:
|
||||
def _arrange_document(document: dict, part_type: str, plans=None, *, owned=None, accompaniment=None) -> dict:
|
||||
if part_type not in generator.parts.PART_TYPES:
|
||||
raise ValueError(f'unknown arrangement part: {part_type}')
|
||||
staff = generator.score.source_staff(document)
|
||||
source = staff['measures']
|
||||
sections = generator.arrange.form.full_arrangement_sections(source, part_type)
|
||||
output, tuplets, octave_shifts, voicing_origins = [], [], [], []
|
||||
solos = []
|
||||
absolute = fractions.Fraction()
|
||||
source_starts = []
|
||||
source_time = fractions.Fraction()
|
||||
@@ -78,22 +61,16 @@ def _arrange_document(document: dict, part_type: str, plans: dict[int, generator
|
||||
segment = []
|
||||
for si in range(section.source_measure_index, section.source_measure_index + section.measure_count):
|
||||
m = section_measures[si]
|
||||
rhythm = None
|
||||
if role == 'accompaniment' and accompaniment is None:
|
||||
plan = plans[section.section_index]
|
||||
rhythm = (plan.acoustic_bass[len(segment)], plan.acoustic_upper[len(segment)]) if part_type == 'acoustic' else plan.electric[len(segment)]
|
||||
if role == 'accompaniment' and accompaniment is not None:
|
||||
result = accompaniment(m, previous[si], si)
|
||||
result['id'] = f'measure_{len(output) + len(segment) + 1}'
|
||||
result['section_label'] = section.label if not segment else ''
|
||||
else:
|
||||
result = generator.parts.build_measure(m, f'measure_{len(output) + len(segment) + 1}', role, part_type, previous[si], section.label if not segment else '', rhythm)
|
||||
result = generator.parts.build_measure(m, f'measure_{len(output) + len(segment) + 1}', role, part_type, previous[si], section.label if not segment else '')
|
||||
segment.append(result)
|
||||
if part_type == 'electric' and section.role in ('melody', 'accompaniment'):
|
||||
voicing_origins.append(generator.electric.MeasureOrigin(source_starts[si], section.role, result))
|
||||
segment_length = sum((generator.model.fraction(m['duration']) for m in segment), fractions.Fraction())
|
||||
if section.role == 'slash':
|
||||
solos.append(generator.scales.timeline.Solo(absolute, absolute + segment_length, section.label))
|
||||
if role in ('vocal', 'melody'):
|
||||
start = source_starts[section.source_measure_index]
|
||||
for shift in staff.get('octave_shifts', []):
|
||||
@@ -125,7 +102,7 @@ def _arrange_document(document: dict, part_type: str, plans: dict[int, generator
|
||||
generator.acoustic.prepare(result)
|
||||
generator.acoustic_voicing.place(result)
|
||||
generator.acoustic.combine(result)
|
||||
elif part_type == 'electric' and accompaniment is None and (owned is None or 'melody' in owned or 'accompaniment' in owned):
|
||||
elif part_type == 'electric' and (owned is None or 'melody' in owned):
|
||||
generator.melody.harmonize(result)
|
||||
generator.guitar.place_guitar(result)
|
||||
if generator.accompaniment.connect_continuations(result):
|
||||
@@ -134,15 +111,9 @@ def _arrange_document(document: dict, part_type: str, plans: dict[int, generator
|
||||
# the complete performance, including its lead-in and repeated choruses.
|
||||
for number, measure in enumerate(output, 1):
|
||||
measure['number'] = str(number)
|
||||
if part_type != 'vocal' and owned is None:
|
||||
generator.arrange.accompaniment.install(document, result, plans)
|
||||
generator.fretboard.validate_document(result)
|
||||
if scales and solos:
|
||||
report = generator.scales.mapping.annotate(result, solos, scales, source_name or document['metadata']['title'])
|
||||
if reports is not None:
|
||||
reports.append(report)
|
||||
return result
|
||||
|
||||
def generate_performance_scores(source_dir: pathlib.Path, output_dir: pathlib.Path, *, rhythms=None, scales=None, sequences=None, composition_jobs=2, cache_dir=None, progress=False, timings=None) -> int:
|
||||
def generate_performance_scores(source_dir: pathlib.Path, output_dir: pathlib.Path, *, composition_jobs=2, cache_dir=None, progress=False, timings=None) -> int:
|
||||
from generator.production import generate_tree
|
||||
return generate_tree(source_dir, output_dir, jobs=composition_jobs, cache_dir=cache_dir, progress=progress,timings=timings)
|
||||
|
||||
Reference in New Issue
Block a user