Cleanup
This commit is contained in:
@@ -37,58 +37,3 @@ def annotate(document, solo, offset):
|
||||
else:
|
||||
spans.append({'id': f'{solo.part}_scale_{len(spans) + 1}', 'start': generator.model.rational(offset + choice.span.start), 'end': generator.model.rational(offset + choice.span.end), 'label': label, 'matched': True})
|
||||
document['staves'][0]['scale_spans'] = spans
|
||||
|
||||
def apply(source, parts, *, rhythms, scales, sequences, solos=None, revise=True, contexts=None, references=(), stage='elaborated', enclosures_enabled=True):
|
||||
"""Compose once per song, replacing only already-placed solo section windows."""
|
||||
if references:
|
||||
raise ValueError('Audition references are not production composition inputs')
|
||||
from generator.arrange import generate
|
||||
analysis = generator.solo.analysis.analyze(source)
|
||||
sections = regions(source)
|
||||
source_measures = generator.score.source_staff(source)['measures']
|
||||
reports = []
|
||||
requests = {}
|
||||
for section_index, part in ((3, 'acoustic'), (4, 'electric')):
|
||||
first, count, offset, length = sections[section_index]
|
||||
form = generator.arrange.form.full_arrangement_sections(source_measures, part)
|
||||
section = form[section_index]
|
||||
effective = generate.section_source(source_measures, section, form[section_index+1])
|
||||
initial = generator.accompaniment.carried_chords(effective)[section.source_measure_index]
|
||||
template = copy.deepcopy(effective[section.source_measure_index:section.source_measure_index+count])
|
||||
cutoff = length
|
||||
if part == 'electric' and generator.score.body_start_measure_index(source_measures):
|
||||
pickup = source_measures[0]
|
||||
sounding = [generator.model.fraction(n['onset']) for n in generator.score.measure_notes(pickup) if n['pitches']]
|
||||
if sounding:
|
||||
cutoff -= generator.model.fraction(pickup['duration']) - min(sounding)
|
||||
requests[part] = (template, cutoff, initial)
|
||||
selected = generator.solo.composer.compose_pair(analysis, requests, scales=scales, sequences=sequences, rhythms=rhythms, contexts=contexts, stage=stage,enclosures_enabled=enclosures_enabled)
|
||||
for solo, section_index, other in zip(selected, (3, 4), ('electric', 'acoustic')):
|
||||
part = solo.part
|
||||
first, count, offset, length = sections[section_index]
|
||||
template, cutoff, initial = requests[part]
|
||||
if solos is not None:
|
||||
solos.append(solo)
|
||||
foreground = generator.solo.notation.measures(template, solo.notes(), 'solo_' + part)
|
||||
generator.solo.notation.replace_region(parts[part], first, foreground)
|
||||
annotate(parts[part], solo, offset)
|
||||
# The other instrument already contains its canonical accompaniment.
|
||||
# Installing a solo must never rewrite the learned supporting part.
|
||||
# Canonical supporting notes must remain compatible throughout every
|
||||
# overlapped mapped span, independent of the foreground realization.
|
||||
elapsed = fractions.Fraction()
|
||||
for measure in parts[other]['staves'][0]['measures'][first:first+count]:
|
||||
for event in generator.score.measure_notes(measure):
|
||||
start = elapsed + generator.model.fraction(event['onset'])
|
||||
end = min(cutoff, start + generator.model.fraction(event['duration']))
|
||||
if start >= end: continue
|
||||
allowed = generator.solo.types.permitted(solo.choices,start,end)
|
||||
if any(int(generator.model.pitch_number(p)) % 12 not in allowed for p in event['pitches']):
|
||||
raise ValueError(f'{other} accompaniment, measure {measure["number"]}: canonical voicing outside solo map')
|
||||
elapsed += generator.model.fraction(measure['duration'])
|
||||
solo.diagnostics['canonical_accompaniment'] = generator.arrange.accompaniment.audit(source, parts)
|
||||
reports.append(generator.solo.report.describe(solo, scales, first, offset))
|
||||
for document in parts.values():
|
||||
generator.model.validate_document(document)
|
||||
generator.fretboard.validate_document(document)
|
||||
return '\n'.join(reports)
|
||||
|
||||
Reference in New Issue
Block a user