+15
-12
@@ -6,20 +6,21 @@ policy. Unknown song/role pairs go to the learned composer.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
import dataclasses
|
||||
import fractions
|
||||
import hashlib
|
||||
import json
|
||||
import pathlib
|
||||
import fractions
|
||||
|
||||
import generator.harmonic_time
|
||||
import generator.musicxml
|
||||
import generator.parts
|
||||
import generator.training_io
|
||||
import generator.harmonic_time
|
||||
import generator.solo.analysis
|
||||
import generator.solo.types
|
||||
import generator.solo.harmonic
|
||||
import generator.solo.placement
|
||||
import generator.solo.profiles
|
||||
import generator.solo.harmonic
|
||||
import generator.production
|
||||
import generator.solo.types
|
||||
import generator.source
|
||||
import generator.training_io
|
||||
import generator.vocabulary
|
||||
|
||||
def sounding(evidence, offset=fractions.Fraction()):
|
||||
result = []
|
||||
@@ -32,9 +33,10 @@ def sounding(evidence, offset=fractions.Fraction()):
|
||||
result.append(generator.solo.types.Note(fractions.Fraction(event['start']) - offset, fractions.Fraction(event['end']) - offset, pitch, role='authored', event_id=f'authored_{i}'))
|
||||
return tuple(result)
|
||||
|
||||
def validate_evidence(document, evidence):
|
||||
def validate_evidence(document, evidence, *, composition=None):
|
||||
"""Training uses the same source-form harmonic context as solo playback."""
|
||||
h = generator.solo.harmonic.Harmony(generator.harmonic_time.solo_source(document['staves'][0]))
|
||||
composition = composition or generator.vocabulary.current()
|
||||
h = generator.solo.harmonic.Harmony(generator.harmonic_time.solo_source(document['staves'][0]), composition=composition)
|
||||
checked = h.evaluate(sounding(evidence), complete=True)
|
||||
if not checked.valid:
|
||||
raise ValueError('Unsupported harmonic relationship in authored solo: ' + checked.error)
|
||||
@@ -56,7 +58,7 @@ def lookup(source, role, data_dir):
|
||||
if not path.is_relative_to((root / 'songs').resolve()):
|
||||
raise ValueError('Registered sources must be in data/songs')
|
||||
doc = generator.parts.prepare_document(generator.musicxml.load_musicxml(path))
|
||||
if generator.production.SourceAnalysis.read(doc).musical_key == source.musical_key:
|
||||
if generator.source.SourceAnalysis.read(doc).musical_key == source.musical_key:
|
||||
target = (manifest.parent / entry['solo']).resolve()
|
||||
if not target.is_relative_to(manifest.parent.resolve()):
|
||||
raise ValueError('Registered solo must be inside data/training')
|
||||
@@ -67,7 +69,8 @@ def lookup(source, role, data_dir):
|
||||
raise ValueError('Multiple authored solos registered for the same source music and role')
|
||||
return matches[0] if matches else None
|
||||
|
||||
def realize(entry, source_analysis, measures, part, start, end, initial=None):
|
||||
def realize(entry, source_analysis, measures, part, start, end, initial=None, *, composition=None):
|
||||
composition = composition or generator.vocabulary.current()
|
||||
evidence = generator.training_io.read(entry['path'], part, pitch_convention=entry['pitch_convention'])
|
||||
if evidence['discrepancies']:
|
||||
raise ValueError(entry['id'] + ': invalid authored timing/ties: ' + str(evidence['discrepancies']))
|
||||
@@ -86,7 +89,7 @@ def realize(entry, source_analysis, measures, part, start, end, initial=None):
|
||||
if placed is None:
|
||||
raise ValueError(entry['id'] + ': no legal complete guitar placement')
|
||||
spans = tuple(dataclasses.replace(s, start=s.start + start, end=s.end + start) for s in generator.harmonic_time.read({'measures': measures}, initial=initial))
|
||||
checked = generator.solo.harmonic.Harmony(spans).evaluate(placed[1], complete=True)
|
||||
checked = generator.solo.harmonic.Harmony(spans, composition=composition).evaluate(placed[1], complete=True)
|
||||
if not checked.valid:
|
||||
raise ValueError(entry['id'] + ': ' + checked.error)
|
||||
phrase = generator.solo.types.Phrase('authored', start, end, placed[1], 'authored', 'authored', 'handoff', theme=entry['id'], expressions=checked.contracts)
|
||||
|
||||
Reference in New Issue
Block a user