This commit is contained in:
khodowany
2026-10-02 00:35:31 -05:00
parent f2f371b951
commit a0bd19b3ba
25 changed files with 1421 additions and 586 deletions
+14 -4
View File
@@ -93,14 +93,24 @@ def identifying_features(notes, source):
def feature_error(feature, notes):
by_id = {n.event_id: n for n in notes}
actual = [by_id.get(identity) for identity in feature.events]
if not all(actual):
if not actual or not all(actual):
return 1.0
first = actual[0].start
rhythm = tuple((n.start - first, n.end - n.start) for n in actual)
movement = tuple(b.pitch.number() - a.pitch.number() for a, b in zip(actual, actual[1:]))
timing = sum(a != b for a, b in zip(rhythm, feature.rhythm)) / max(1, len(rhythm))
contour = sum(((a > 0) - (a < 0)) != ((b > 0) - (b < 0)) or abs(a - b) > 2 for a, b in zip(movement, feature.intervals)) / max(1, len(movement))
return (timing + contour) / 2
errors = []
if 'rhythm' in feature.preserves:
errors.append(1.0 if len(rhythm) != len(feature.rhythm) else sum(a != b for a,b in zip(rhythm,feature.rhythm))/max(1,len(rhythm)))
if 'intervals' in feature.preserves or 'contour' in feature.preserves:
if len(movement) != len(feature.intervals) or not movement and feature.intervals:
errors.append(1.0)
else:
errors.append(sum(((a>0)-(a<0)) != ((b>0)-(b<0)) or 'intervals' in feature.preserves and abs(a-b)>2 for a,b in zip(movement,feature.intervals))/max(1,len(movement)))
if 'exact_intervals' in feature.preserves:
errors.append(float(movement != feature.intervals))
if 'pitches' in feature.preserves:
errors.append(float(tuple(n.pitch.number() for n in actual) != feature.pitches))
return max(errors,default=0.0)
def relationship(notes, reference):
"""One joint relationship cost: timed movement, not absolute-pitch copying."""