Refine melodic threshold to continuous scoring
- Use continuous scoring instead of binary pass/fail - Below min: score = (cents / min)^2 - Above max: score = ((1200 - cents) / (1200 - max))^2 - Use product across voices to penalize worst offenders
This commit is contained in:
parent
1926930c3d
commit
1eb95ffad7
35
src/graph.py
35
src/graph.py
|
|
@ -274,23 +274,36 @@ class PathFinder:
|
|||
}
|
||||
|
||||
def _factor_melodic_threshold(self, edge_data: dict, config: dict) -> float:
|
||||
"""Returns 1.0 if all voice movements are within melodic threshold, 0.0 otherwise."""
|
||||
# Check weight - if 0, return 1.0 (neutral)
|
||||
if config.get("weight_melodic", 1) == 0:
|
||||
return 1.0
|
||||
"""Returns continuous score based on melodic threshold.
|
||||
|
||||
- cents == 0: score = 1.0 (no movement is always ideal)
|
||||
- Below min (0 < cents < min): score = (cents / min)^2
|
||||
- Within range (min <= cents <= max): score = 1.0
|
||||
- Above max (cents > max): score = ((1200 - cents) / (1200 - max))^2
|
||||
|
||||
Returns product of all voice scores.
|
||||
"""
|
||||
melodic_min = config.get("melodic_threshold_min", 0)
|
||||
melodic_max = config.get("melodic_threshold_max", float("inf"))
|
||||
|
||||
cent_diffs = edge_data.get("cent_diffs", [])
|
||||
|
||||
if melodic_min is not None or melodic_max is not None:
|
||||
for cents in cent_diffs:
|
||||
if melodic_min is not None and cents < melodic_min:
|
||||
return 0.0
|
||||
if melodic_max is not None and cents > melodic_max:
|
||||
return 0.0
|
||||
return 1.0
|
||||
if not cent_diffs:
|
||||
return 1.0
|
||||
|
||||
product = 1.0
|
||||
for cents in cent_diffs:
|
||||
if cents == 0:
|
||||
score = 1.0
|
||||
elif cents < melodic_min:
|
||||
score = (cents / melodic_min) ** 2
|
||||
elif cents > melodic_max:
|
||||
score = ((1200 - cents) / (1200 - melodic_max)) ** 2
|
||||
else:
|
||||
score = 1.0
|
||||
product *= score
|
||||
|
||||
return product
|
||||
|
||||
def _factor_direct_tuning(self, edge_data: dict, config: dict) -> float:
|
||||
"""Returns 1.0 if directly tunable (or disabled), 0.0 otherwise."""
|
||||
|
|
|
|||
Loading…
Reference in a new issue