This is another in the series of Vertically Adaptive Tuning of Herzliebster, with some fixes made to the tuning optimization to search harder for just tunings that meet the criteria I set down. The last one, #17, included some wolf chords. These were caused by conflicts between different intervals in a chord. I check all six intervals between the four notes of each chord. I’d start with note 0 to note 1, then 0 to 2, 0-3, then 1-2, 1-3, finally 2-3. Doing the checks in that order guaranteed that notes 2 and 3 were subject to change by a later comparison interval. That wasn’t going to work, so I made some changes to ensure that a change would only take place if it was for the improved the score of the entire chord, not just one interval at the expense of another.
I’ve had much better results if I try different voicing of chords. For example, I was struggling to find code that would produce good results for the MIDI F# major chord: [66, 64, 61, 46], which is note names: [‘F♯’ ‘E♮’ ‘C♯’ ‘A♯’]. It’s just a revoiced F# major scale, but I could not find a set of intervals where all six resulted in consonant chords. I the four notes two at a time, and that means six choices, which sometimes conflict. But when I run four different voicings through, it finds the best ones every time. The Numpy function roll takes a four-note array and moves it over by 0,1,2,3 places, creating four different chords. There must be some bug in my code, because after I do that, it works great.
for inx in np.arange(4):
result = find_intervals(np.roll(chord_in_1200,inx), range = range)
score = score_chord_cents(result)
if score < best_score:
best_choice = result
best_score = score
Next step is to start the horizonal optimizations.