@@ -31,6 +31,8 @@ def _load(contents):
|
||||
policy = value['instruments'][part]
|
||||
if part == 'acoustic' and policy.get('first_attack') != 'bass_per_harmony':
|
||||
raise ValueError('acoustic patterns require bass at the first attack of each harmony')
|
||||
if part == 'acoustic' and policy.get('attack_assignment') != {'version': 1, 'mode': 'combined_except_eighth_pairs'}:
|
||||
raise ValueError('acoustic patterns require automatic eighth-pair assignment')
|
||||
groove = policy['groove']
|
||||
if any(type(groove[k]) is not int for k in ('cycle_patterns', 'slot_candidates', 'fill_spacing_measures')) or not 1 <= groove['cycle_patterns'] <= 4 or not 4 <= groove['slot_candidates'] <= 8 or groove['fill_spacing_measures'] < 8:
|
||||
raise ValueError('invalid bounded accompaniment groove policy')
|
||||
@@ -62,16 +64,15 @@ def _load(contents):
|
||||
if onset.denominator > 2 or duration.denominator > 2:
|
||||
raise ValueError('comping vocabulary uses a quarter/eighth grid')
|
||||
if part == 'acoustic':
|
||||
if row['layer'] == 'combined':
|
||||
if duration < 1 and duration != fractions.Fraction(1, 2):
|
||||
raise ValueError('combined acoustic attacks require quarter/eighth notes or sustains')
|
||||
elif row['layer'] not in ('bass', 'upper') or duration not in (fractions.Fraction(1, 2), 1):
|
||||
raise ValueError('acoustic short attacks require bass/upper quarter/eighth notes')
|
||||
if row['layer'] != 'acoustic':
|
||||
raise ValueError('acoustic pattern layers are assigned from the complete rhythm')
|
||||
elif row['layer'] != 'electric':
|
||||
raise ValueError('electric pattern must contain electric chord attacks')
|
||||
if row.get('anticipate') and row['layer'] not in ('upper', 'electric'):
|
||||
raise ValueError('only upper/electric chords can anticipate')
|
||||
lanes = ('bass', 'upper') if row['layer'] == 'combined' else (row['layer'],)
|
||||
if row.get('anticipate') and row['layer'] not in ('acoustic', 'electric'):
|
||||
raise ValueError('only acoustic/electric chords can anticipate')
|
||||
# Acoustic overlaps are checked after deterministic string-lane
|
||||
# assignment, including neighboring figures in the source form.
|
||||
lanes = () if part == 'acoustic' else (row['layer'],)
|
||||
if any(releases.get(lane, fractions.Fraction()) > onset for lane in lanes):
|
||||
raise ValueError('overlapping accompaniment attacks on the same strings')
|
||||
releases.update({lane: onset + duration for lane in lanes})
|
||||
|
||||
Reference in New Issue
Block a user