+12
-12
@@ -1,4 +1,5 @@
|
||||
"""Learned inference and explicit authored reuse have different contracts."""
|
||||
import generator.composition
|
||||
import copy
|
||||
import dataclasses
|
||||
import json
|
||||
@@ -8,7 +9,6 @@ import tempfile
|
||||
import unittest
|
||||
import unittest.mock
|
||||
|
||||
import generator.production
|
||||
import generator.parts
|
||||
import generator.musicxml
|
||||
import generator.model
|
||||
@@ -21,7 +21,7 @@ import generator.solo.learned
|
||||
import generator.solo.composer
|
||||
import generator.solo.decoder
|
||||
import generator.solo.harmonic
|
||||
import generator.solo.analysis
|
||||
import generator.source
|
||||
import tests.score_events
|
||||
import tests.solo_fixtures
|
||||
import tests.test_musicxml
|
||||
@@ -53,9 +53,9 @@ class TrainingAndRepertoire(unittest.TestCase):
|
||||
with self.subTest(pair=entry['id']):
|
||||
part = 'acoustic' if entry['slot'] == 1 else 'electric'
|
||||
doc = generator.parts.prepare_document(generator.musicxml.load_musicxml(ROOT / 'data/training' / entry['source']))
|
||||
source = generator.production.SourceAnalysis.read(doc)
|
||||
source = generator.source.SourceAnalysis.read(doc)
|
||||
with unittest.mock.patch('generator.solo.composer.compose', side_effect=AssertionError('authored pair must not be predicted')):
|
||||
result = generator.production.generate_role(source, part + '_solo', ROOT / 'data')
|
||||
result = generator.composition.generate_role(source, part + '_solo', ROOT / 'data')
|
||||
measures = result['document']['staves'][0]['measures']
|
||||
first = next(i for i, m in enumerate(measures) if m.get('section_label') == part.capitalize() + ' Solo')
|
||||
last = next((i for i in range(first + 1, len(measures)) if measures[i].get('section_label')), len(measures))
|
||||
@@ -82,13 +82,13 @@ class TrainingAndRepertoire(unittest.TestCase):
|
||||
def test_lookup_uses_source_music_and_slot_not_title_or_path(self):
|
||||
entry = json.loads((ROOT / 'data/training/manifest.json').read_text())['examples'][0]
|
||||
doc = generator.parts.prepare_document(generator.musicxml.load_musicxml(ROOT / 'data/training' / entry['source']))
|
||||
source = generator.production.SourceAnalysis.read(doc)
|
||||
source = generator.source.SourceAnalysis.read(doc)
|
||||
part = 'acoustic' if entry['slot'] == 1 else 'electric'
|
||||
self.assertIsNotNone(generator.solo.authored.lookup(source, part, ROOT / 'data'))
|
||||
doc['metadata'].update(title='Renamed standard', composer='Display only')
|
||||
self.assertEqual(source, generator.production.SourceAnalysis.read(doc))
|
||||
self.assertEqual(source, generator.source.SourceAnalysis.read(doc))
|
||||
doc['staves'][0]['measures'][0]['voices'][0]['notes'][0]['pitches'][0]['octave'] += 1
|
||||
self.assertIsNone(generator.solo.authored.lookup(generator.production.SourceAnalysis.read(doc), part, ROOT / 'data'))
|
||||
self.assertIsNone(generator.solo.authored.lookup(generator.source.SourceAnalysis.read(doc), part, ROOT / 'data'))
|
||||
def test_adding_a_new_pair_requires_no_code_or_existing_song_names(self):
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
root = pathlib.Path(directory)
|
||||
@@ -102,7 +102,7 @@ class TrainingAndRepertoire(unittest.TestCase):
|
||||
examples, _ = generator.train.load_examples(manifest)
|
||||
self.assertEqual(len(examples), 1)
|
||||
doc = generator.parts.prepare_document(generator.musicxml.load_musicxml(root / 'data/songs' / source.name))
|
||||
context = generator.production.SourceAnalysis.read(doc)
|
||||
context = generator.source.SourceAnalysis.read(doc)
|
||||
self.assertIsNotNone(generator.solo.authored.lookup(context, 'acoustic', root / 'data'))
|
||||
self.assertIsNone(generator.solo.authored.lookup(context, 'electric', root / 'data'))
|
||||
self.assertEqual(solo.read_bytes(), (manifest.parent / solo.name).read_bytes())
|
||||
@@ -130,7 +130,7 @@ class LearnedInference(unittest.TestCase):
|
||||
generator.solo.learned.Model.load('/missing-model-file')
|
||||
def test_decoder_runs_without_training_files_and_is_deterministic(self):
|
||||
source = tests.solo_fixtures.song(count=1, chords=('C7',))
|
||||
a = generator.solo.analysis.analyze(source)
|
||||
a = generator.source.analyze(source)
|
||||
predictor = generator.solo.learned.Model.load(ROOT / 'data/models/solo.json')
|
||||
with generator.vocabulary.using(generator.vocabulary.load(), 'acoustic_solo', {'attempts': 2}):
|
||||
original = pathlib.Path.open
|
||||
@@ -146,7 +146,7 @@ class LearnedInference(unittest.TestCase):
|
||||
self.assertEqual(first.diagnostics['construction'], 'learned_joint_events')
|
||||
def test_event_score_does_not_depend_on_action_grouping(self):
|
||||
source = tests.solo_fixtures.song(count=1, chords=('C7',))
|
||||
a = generator.solo.analysis.analyze(source)
|
||||
a = generator.source.analyze(source)
|
||||
h = generator.solo.harmonic.Harmony(generator.harmonic_time.read(source['staves'][0]))
|
||||
predictor = generator.solo.learned.Model.load(ROOT / 'data/models/solo.json')
|
||||
engine = generator.solo.decoder.Decoder(a, h, predictor, 'acoustic', fractions.Fraction(), fractions.Fraction(4))
|
||||
@@ -157,7 +157,7 @@ class LearnedInference(unittest.TestCase):
|
||||
self.assertEqual(combined, split)
|
||||
def test_source_features_include_actual_melodic_intervals(self):
|
||||
source = tests.solo_fixtures.song(count=1, chords=('C7',))
|
||||
a = generator.solo.analysis.analyze(source)
|
||||
a = generator.source.analyze(source)
|
||||
changed = dataclasses.replace(a, melody=tuple(dataclasses.replace(n, pitch=dataclasses.replace(n.pitch, octave=n.pitch.octave + (i == 1))) for i, n in enumerate(a.melody)))
|
||||
self.assertNotEqual(generator.solo.learned.source_feature(a, fractions.Fraction(1)), generator.solo.learned.source_feature(changed, fractions.Fraction(1)))
|
||||
def test_generated_long_nonchord_notes_still_need_support(self):
|
||||
@@ -167,7 +167,7 @@ class LearnedInference(unittest.TestCase):
|
||||
self.assertTrue(h.evaluate((tests.solo_fixtures.note(0, fractions.Fraction(1, 2), 'g'), tests.solo_fixtures.note(fractions.Fraction(1, 2), 1, 'f'), tests.solo_fixtures.note(1, 2, 'e'))).valid)
|
||||
def test_held_chord_member_can_become_a_supported_color(self):
|
||||
source = tests.solo_fixtures.song(count=2, chords=('C', 'Dm'))
|
||||
a = generator.solo.analysis.analyze(source)
|
||||
a = generator.source.analyze(source)
|
||||
h = generator.solo.harmonic.Harmony(tests.solo_fixtures.choices(('C', 'Dm')))
|
||||
engine = generator.solo.decoder.Decoder(a, h, generator.solo.learned.Model.load(ROOT / 'data/models/solo.json'), 'acoustic', fractions.Fraction(), fractions.Fraction(8))
|
||||
n = engine.note(fractions.Fraction(3), fractions.Fraction(6), 64) # E: C's third becomes D minor's ninth.
|
||||
|
||||
Reference in New Issue
Block a user