Fix: Midi pcsetNearest not taking octave displacement into account #468
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
I noticed a small bug with the pcsetNearest function in the Midi package. The issue is with the following code:
The problem here is that in certain situations
ch + i
could be greater than 11, orch - i
could be lower than 0. For an extreme example that demonstrates the issue, consider mapping the chromatic scale to a pcset of just a C and F# (i.e. 100000100000).With the old algorithm, this would give the following output:
However, this is clearly wrong. The B natural (midi 47) is closer to a C than an F#, but is marked as being closest to the F#. This is because
ch + i
will be greater than 12 for any value ofi > 0
, but the pcset only includes chromas between 0 and 11. This causes subtler issues with more real-world examples. For example, consider mapping the chromatic scale to the nearest C minor pentatonic scale. The B natural will be marked as being nearest to the Bb (rather than C). While B natural is equidistant from Bb and C, the algorithm usually prefers the higher pitch in equidistant scenarios.To fix this, I have modified the pcsetNearest algorithm to take into account octave displacement. I have also modified the tests, and added a few demonstrating the issue to take this into account. I think it might also make sense to add a boolean flag to the function
preferHigherPitchWhenEquidistant
, but I'll leave that for a separate PR.