Tab Generation
ci / checks (push) Successful in 1h19m14s

This commit is contained in:
khodowany
2026-09-20 16:20:43 -05:00
parent 68ded4d8c8
commit cf7c0c010c
423 changed files with 1422 additions and 1332 deletions
+9 -14
View File
@@ -9,7 +9,8 @@ from pathlib import Path
import sys
import wave
from generator.model import TYPE_LENGTHS, fraction, pitch_number, rational
from generator.model import TYPE_LENGTHS, fraction, rational
from generator import pitch
SAMPLE_RATE = 48000
PROFILE = 'soft-struck-1'
@@ -18,21 +19,16 @@ MAX_EVENTS = 1000000
class PlaybackUnavailable(ValueError):
pass
def sounding_pitch(pitch: dict, state: dict, guitar: bool) -> Fraction:
if 'unpitched' in pitch:
def sounding_pitch(tone: dict, state: dict) -> Fraction:
if 'unpitched' in tone:
raise PlaybackUnavailable('unpitched notation has no generated-tone interpretation')
if guitar:
import generator.practice.guitar
value = generator.practice.guitar.sounding_pitch(pitch, state)
else:
transpose = state['transpose']
value = pitch_number(pitch) + transpose['chromatic'] + 12 * transpose['octave_change']
value = pitch.sounding_pitch(tone, state)
frequency = 440 * 2 ** (float(value - 69) / 12)
if not 20 <= frequency <= 18000:
raise PlaybackUnavailable(f'sounding pitch {value} is outside the generated-tone range (20-18000 Hz)')
return value
def compile_timeline(document: dict, *, guitar: bool = False) -> dict:
def compile_timeline(document: dict) -> dict:
events, notes, linked = [], {}, {}
absolute = Fraction()
for measure in document['staves'][0]['measures']:
@@ -108,7 +104,7 @@ def compile_timeline(document: dict, *, guitar: bool = False) -> dict:
length += sum((amount for time, amount in insertions.items() if onset < time < onset + fraction(pitch['duration'])), Fraction())
if length <= 0:
raise PlaybackUnavailable(f'{identifier}: grace timing consumes a chord tone')
value = sounding_pitch(pitch, state, guitar)
value = sounding_pitch(pitch, state)
if pitch.get('tie_from'):
previous = linked.get(pitch['tie_from'])
if previous is None or fraction(previous['onset']) + fraction(previous['duration']) != performed or fraction(previous['pitch']) != value:
@@ -132,7 +128,7 @@ def compile_timeline(document: dict, *, guitar: bool = False) -> dict:
amount = value
if tremolo['type'] == 'start' and attack % 2:
other = partner[0]['pitches'][note['pitches'].index(pitch)]
amount = sounding_pitch(other, partner[2], guitar)
amount = sounding_pitch(other, partner[2])
events.append({'id': f'{pitch["id"]}-{attack}', 'pitch': rational(amount), 'onset': rational(performed + cursor), 'duration': rational(min(step, length - cursor))})
cursor += step
attack += 1
@@ -181,8 +177,7 @@ def compile_tree(root: Path) -> None:
for path in sorted(root.rglob('*.json')):
document = json.loads(path.read_text(encoding='utf-8'))
try:
guitar = document['staves'][0].get('arrangement_part_type') in ('practice', 'acoustic', 'electric')
playback = compile_timeline(document, guitar=guitar)
playback = compile_timeline(document)
used = {}
for event in playback['events']:
event['end'] = rational(fraction(event['onset']) + fraction(event.pop('duration')))