+17
-18
@@ -2,38 +2,37 @@ from __future__ import annotations
|
||||
|
||||
import copy
|
||||
|
||||
from generator import harmony
|
||||
from generator.model import LETTERS, NATURAL, alteration, fraction, key_from_fifths, key_label, pitch_number, rational
|
||||
import generator.harmony
|
||||
import generator.model
|
||||
|
||||
def shift_pitch(pitch: dict, steps: int, semitones: int) -> dict:
|
||||
output = copy.deepcopy(pitch)
|
||||
if 'unpitched' in pitch:
|
||||
return output
|
||||
original_octave = pitch.get('octave', 4)
|
||||
diatonic = original_octave * 7 + LETTERS.index(pitch['letter']) + steps
|
||||
diatonic = original_octave * 7 + generator.model.LETTERS.index(pitch['letter']) + steps
|
||||
octave, index = divmod(diatonic, 7)
|
||||
output['letter'] = LETTERS[index]
|
||||
output['letter'] = generator.model.LETTERS[index]
|
||||
output['octave'] = octave
|
||||
output['alter'] = rational(pitch_number({**pitch, 'octave': original_octave}) + semitones - (12 * (octave + 1) + NATURAL[output['letter']]))
|
||||
output['alter'] = generator.model.rational(generator.model.pitch_number({**pitch, 'octave': original_octave}) + semitones - (12 * (octave + 1) + generator.model.NATURAL[output['letter']]))
|
||||
if 'octave' not in pitch:
|
||||
output.pop('octave')
|
||||
if 'accidental_display' in output:
|
||||
from generator.model import accidental_name
|
||||
output['accidental_display']['name'] = accidental_name(alteration(output['alter']))
|
||||
output['accidental_display']['name'] = generator.model.accidental_name(generator.model.alteration(output['alter']))
|
||||
return output
|
||||
|
||||
def shift_key(key: dict, steps: int, semitones: int) -> dict:
|
||||
tonic = shift_pitch(key['tonic'], steps, semitones) if key.get('tonic') else None
|
||||
alterations = [0] * 7
|
||||
for index, letter in enumerate(LETTERS):
|
||||
for index, letter in enumerate(generator.model.LETTERS):
|
||||
p = shift_pitch({'letter': letter, 'alter': key['alterations'][index]}, steps, semitones)
|
||||
alterations[LETTERS.index(p['letter'])] = p['alter']
|
||||
alterations[generator.model.LETTERS.index(p['letter'])] = p['alter']
|
||||
result = {**copy.deepcopy(key), 'tonic': tonic, 'alterations': alterations}
|
||||
if 'steps' in key:
|
||||
result['steps'] = [shift_pitch(step, steps, semitones) for step in key['steps']]
|
||||
if not key.get('custom') and tonic:
|
||||
for fifths in range(-14, 15):
|
||||
candidate = key_from_fifths(fifths, key['mode'])
|
||||
candidate = generator.model.key_from_fifths(fifths, key['mode'])
|
||||
if candidate['tonic'] == tonic and candidate['alterations'] == alterations:
|
||||
result['fifths'] = fifths
|
||||
break
|
||||
@@ -41,7 +40,7 @@ def shift_key(key: dict, steps: int, semitones: int) -> dict:
|
||||
result['custom'] = True
|
||||
if 'cancel' in key:
|
||||
# A cancellation references the old signature, not a count of naturals.
|
||||
canceled = shift_key(key_from_fifths(key['cancel']), steps, semitones)
|
||||
canceled = shift_key(generator.model.key_from_fifths(key['cancel']), steps, semitones)
|
||||
if canceled.get('custom'):
|
||||
raise ValueError('transposed key cancellation cannot be represented by fifths')
|
||||
result['cancel'] = canceled['fifths']
|
||||
@@ -59,7 +58,7 @@ def concert_document(document: dict, *, octave_transposing: bool = False) -> dic
|
||||
def interval(onset):
|
||||
state = dict(initial)
|
||||
for change in changes:
|
||||
if fraction(change['onset']) <= onset:
|
||||
if generator.model.fraction(change['onset']) <= onset:
|
||||
state.update({key: change[key] for key in initial if key in change})
|
||||
transpose, clef = state['transpose'], state['clef']
|
||||
steps = transpose['diatonic'] + 7 * transpose['octave_change']
|
||||
@@ -69,17 +68,17 @@ def concert_document(document: dict, *, octave_transposing: bool = False) -> dic
|
||||
return steps, semitones
|
||||
|
||||
measure['key'] = shift_key(measure['key'], *interval(0))
|
||||
measure['key_signature'] = key_label(measure['key'])
|
||||
measure['key_signature'] = generator.model.key_label(measure['key'])
|
||||
for n in (n for v in measure['voices'] for n in v['notes']):
|
||||
n['pitches'] = [shift_pitch(p, *interval(fraction(n['onset']))) for p in n['pitches']]
|
||||
n['pitches'] = [shift_pitch(p, *interval(generator.model.fraction(n['onset']))) for p in n['pitches']]
|
||||
for h in measure['harmonies']:
|
||||
for field in ('root', 'bass'):
|
||||
if field in h:
|
||||
h[field] = shift_pitch(h[field], *interval(fraction(h['onset'])))
|
||||
h['symbol'] = harmony.symbol(h)
|
||||
h[field] = shift_pitch(h[field], *interval(generator.model.fraction(h['onset'])))
|
||||
h['symbol'] = generator.harmony.symbol(h)
|
||||
for change in measure.get('attributes', []):
|
||||
if 'key' in change:
|
||||
change['key'] = shift_key(change['key'], *interval(fraction(change['onset'])))
|
||||
change['key'] = shift_key(change['key'], *interval(generator.model.fraction(change['onset'])))
|
||||
if 'transpose' in change:
|
||||
change['transpose'] = copy.deepcopy(zero)
|
||||
measure['transpose'] = copy.deepcopy(zero)
|
||||
@@ -92,4 +91,4 @@ def sounding_pitch(pitch: dict, state: dict):
|
||||
if 'unpitched' in pitch:
|
||||
raise ValueError('unpitched notes have no fretted or generated-tone interpretation')
|
||||
transpose = state['transpose']
|
||||
return pitch_number(pitch) + transpose['chromatic'] + 12 * transpose['octave_change']
|
||||
return generator.model.pitch_number(pitch) + transpose['chromatic'] + 12 * transpose['octave_change']
|
||||
|
||||
Reference in New Issue
Block a user