Training Model
This commit is contained in:
+1
-44
@@ -15,7 +15,7 @@ ACTIVE = contextvars.ContextVar('composition_vocabulary', default=None)
|
||||
def load(root=ROOT):
|
||||
# Content, not just the directory, keys memoization. Long-lived individual
|
||||
# role builds must observe edited production data without restarting Python.
|
||||
names = ('roles', 'solo', 'harmony', 'lead_ins', 'rhythms')
|
||||
names = ('roles', 'harmony', 'lead_ins', 'accompaniment')
|
||||
return _load(tuple((name, (Path(root)/(name+'.json')).read_text()) for name in names))
|
||||
|
||||
@functools.lru_cache(maxsize=16)
|
||||
@@ -29,12 +29,6 @@ def _load(contents):
|
||||
if len({v['id'] for v in entries}) != len(entries):
|
||||
raise ValueError(f'{name}: duplicate vocabulary ID')
|
||||
result[name] = value
|
||||
cells=result['rhythms']['cells']+result['solo']['cells']
|
||||
if len({c['id'] for c in cells})!=len(cells):raise ValueError('Duplicate rhythm identity')
|
||||
rules=result['solo']
|
||||
if any(type(rules['search'][k]) is not int or rules['search'][k]<=0 for k in ('histories','alternatives')):raise ValueError('Invalid deterministic search budget')
|
||||
for group in rules['groups']:
|
||||
if not group['values'] or any(F(v.removeprefix('r:'))<=0 for v in group['values']):raise ValueError('Invalid rhythm group')
|
||||
return result
|
||||
|
||||
@functools.lru_cache(maxsize=1)
|
||||
@@ -62,40 +56,3 @@ def using(resources, name, settings=None):
|
||||
|
||||
def fingerprint(value):
|
||||
return hashlib.sha256(json.dumps(value, sort_keys=True, separators=(',', ':')).encode()).hexdigest()
|
||||
|
||||
@dataclasses.dataclass(frozen=True)
|
||||
class RhythmCell:
|
||||
id: str
|
||||
pattern: tuple
|
||||
duration: F
|
||||
purpose: str
|
||||
difficulty: str | None = None
|
||||
subdivision: str = 'binary'
|
||||
entry: str = 'attack'
|
||||
exit: str = 'continue'
|
||||
|
||||
|
||||
def rhythm_cells(tempo, purpose=None):
|
||||
limits = data('roles')['difficulty']
|
||||
for cell in (*data('rhythms')['cells'],*data('solo')['cells']):
|
||||
if purpose is not None and cell['purpose'] != purpose:
|
||||
continue
|
||||
difficulty = cell.get('difficulty')
|
||||
if difficulty and tempo > limits[difficulty + '_max_bpm']:
|
||||
continue
|
||||
cursor, notes = F(), []
|
||||
for value in cell['values']:
|
||||
rest = value.startswith('r:')
|
||||
duration = F(value[2:] if rest else value)
|
||||
if duration <= 0:
|
||||
raise ValueError(cell['id'] + ': nonpositive rhythm duration')
|
||||
if not rest:
|
||||
notes.append((cursor, cursor + duration))
|
||||
cursor += duration
|
||||
if difficulty and len(notes) > limits['burst_attacks']:
|
||||
continue
|
||||
from generator.solo import groups
|
||||
realized=groups.describe(tuple(notes),source=cell['id'])
|
||||
family=cell.get('subdivision','binary')
|
||||
if family=='triplet' and not any(g.family=='triplet' for g in realized):raise ValueError(cell['id']+': missing complete tuplet group')
|
||||
yield RhythmCell(cell['id'],tuple(notes),cursor,cell['purpose'],difficulty,family,cell.get('entry','attack'),cell.get('exit','continue'))
|
||||
|
||||
Reference in New Issue
Block a user