+12
-12
@@ -2,7 +2,7 @@ from __future__ import annotations
|
||||
|
||||
import re
|
||||
|
||||
from generator.model import NATURAL, alteration, parse_pitch_name, pitch_name, rational
|
||||
import generator.model
|
||||
|
||||
# Semantic degrees are independent of guitar voicing omissions.
|
||||
KINDS = {
|
||||
@@ -49,7 +49,7 @@ def degrees(harmony: dict) -> dict[int, int]:
|
||||
raise ValueError(f'unsupported harmony kind: {kind}')
|
||||
result = KINDS[kind].copy()
|
||||
for change in harmony.get('degrees', []):
|
||||
degree, alter, operation = change['value'], alteration(change['alter']), change['type']
|
||||
degree, alter, operation = change['value'], generator.model.alteration(change['alter']), change['type']
|
||||
if type(degree) is not int or degree < 1:
|
||||
raise ValueError('invalid harmony degree')
|
||||
if operation == 'subtract':
|
||||
@@ -79,10 +79,10 @@ def pitch_classes(harmony: dict) -> tuple[int, ...]:
|
||||
if harmony['kind'] == 'none':
|
||||
return ()
|
||||
root = harmony['root']
|
||||
root_pc = NATURAL[root['letter']] + alteration(root['alter'])
|
||||
root_pc = generator.model.NATURAL[root['letter']] + generator.model.alteration(root['alter'])
|
||||
values = [(root_pc + degree_semitones(d, a)) % 12 for d, a in degrees(harmony).items()]
|
||||
if bass := harmony.get('bass'):
|
||||
values.append((NATURAL[bass['letter']] + alteration(bass['alter'])) % 12)
|
||||
values.append((generator.model.NATURAL[bass['letter']] + generator.model.alteration(bass['alter'])) % 12)
|
||||
return tuple(dict.fromkeys(values))
|
||||
|
||||
def chord_suffix(harmony: dict) -> str:
|
||||
@@ -98,7 +98,7 @@ def chord_suffix(harmony: dict) -> str:
|
||||
return suffix
|
||||
suffix = SUFFIXES.get(kind, kind)
|
||||
for change in sorted(harmony.get('degrees', []), key=lambda change: change['value']):
|
||||
amount = alteration(change['alter'])
|
||||
amount = generator.model.alteration(change['alter'])
|
||||
sign = '#' * max(int(amount), 0) + 'b' * max(int(-amount), 0) if amount.denominator == 1 else f'({amount})'
|
||||
suffix += ('no' if change['type'] == 'subtract' else ('add' if change['type'] == 'add' and not sign else '') + sign) + str(change['value'])
|
||||
return suffix
|
||||
@@ -107,9 +107,9 @@ def symbol(harmony: dict) -> str:
|
||||
if harmony['kind'] == 'none':
|
||||
return 'N.C.'
|
||||
suffix = chord_suffix(harmony)
|
||||
result = pitch_name(harmony['root']) + suffix
|
||||
result = generator.model.pitch_name(harmony['root']) + suffix
|
||||
if bass := harmony.get('bass'):
|
||||
result += '/' + pitch_name(bass)
|
||||
result += '/' + generator.model.pitch_name(bass)
|
||||
return '(' + result + ')' if harmony.get('parenthesized') else result
|
||||
|
||||
def parse_symbol(text: str) -> dict:
|
||||
@@ -137,11 +137,11 @@ def parse_symbol(text: str) -> dict:
|
||||
operation = 'subtract' if operation == 'no' else 'alter' if degree in degrees(result) and operation != 'add' else 'add'
|
||||
result['degrees'].append({'value': degree, 'alter': accidental.count('#') - accidental.count('b'), 'type': operation})
|
||||
remainder = remainder[modifier.end():]
|
||||
result['root'] = parse_pitch_name(root)
|
||||
result['root'] = generator.model.parse_pitch_name(root)
|
||||
for change in result['degrees']:
|
||||
change['alter'] = rational(change['alter'])
|
||||
change['alter'] = generator.model.rational(change['alter'])
|
||||
if bass:
|
||||
result['bass'] = parse_pitch_name(bass)
|
||||
result['bass'] = generator.model.parse_pitch_name(bass)
|
||||
if parenthesized:
|
||||
result['parenthesized'] = True
|
||||
degrees(result)
|
||||
@@ -152,12 +152,12 @@ def normalize_text(harmony: dict, text: str) -> None:
|
||||
parenthesized = text.startswith('(') and text.endswith(')')
|
||||
content = text[1:-1] if parenthesized else text
|
||||
try:
|
||||
displayed = parse_symbol(pitch_name(harmony['root']) + content)
|
||||
displayed = parse_symbol(generator.model.pitch_name(harmony['root']) + content)
|
||||
except ValueError:
|
||||
displayed = parse_symbol(content)
|
||||
text_only = harmony['kind'] == 'other' and not harmony['degrees']
|
||||
if displayed['root'] != harmony['root']:
|
||||
if not text_only or harmony['root'] != parse_pitch_name('C'):
|
||||
if not text_only or harmony['root'] != generator.model.parse_pitch_name('C'):
|
||||
raise ValueError(f'contradictory harmony root in {text!r}')
|
||||
if 'bass' in displayed and 'bass' in harmony and displayed['bass'] != harmony['bass']:
|
||||
raise ValueError(f'contradictory harmony bass in {text!r}')
|
||||
|
||||
Reference in New Issue
Block a user