// find where to place a ratio on the scale private int FindNextBestCandidate(List <IntervalRatio> toPlace, out int stepIdx) { stepIdx = -1; int ratioIdx = -1; double bestPlacediff = double.PositiveInfinity; for (int i = 0; i < toPlace.Count; i++) { IntervalRatio ratio = toPlace[i]; // place ratio between smaller and greater entries int idxStart = 0; int idxEnd = 0; FindValidRange(ratio, out idxStart, out idxEnd); for (int j = idxStart; j <= idxEnd; j++) { var checkStep = scaleSteps[j]; if (checkStep.Ratio == null) { double diff = Math.Abs(ratio.Cents - checkStep.Cents); if (diff < bestPlacediff) { ratioIdx = i; stepIdx = j; bestPlacediff = diff; } } } } return(ratioIdx); }
private void FindValidRange(IntervalRatio ratio, out int idxStart, out int idxEnd) { idxStart = 1; // we dont place anything on step 0, it is the root, no interval idxEnd = scaleSteps.Length - 1; // start at last placed ratio entry smaller than ratio for (int i = scaleSteps.Length - 1; i >= 0; i--) { if (scaleSteps[i].Ratio != null && scaleSteps[i].Ratio.Cents < ratio.Cents) { idxStart = i; break; } } // end at 1st placed ratio entry greater than ratio for (int i = 0; i < scaleSteps.Length; i++) { if (scaleSteps[i].Ratio != null && scaleSteps[i].Ratio.Cents > ratio.Cents) { idxEnd = i; break; } } }
public void PlaceRatios() { List <IntervalRatio> toPlace = new List <IntervalRatio>(refIntervalRatios); // always place C on 1st entry, idx = 0 scaleSteps[0].Ratio = new IntervalRatio(1, 1, "P1", "C"); while (toPlace.Count > 0) { // find next best candidate int stepIdx = -1; int ratioIdx = FindNextBestCandidate(toPlace, out stepIdx); if (stepIdx < 0) { break; } // place it IntervalRatio ratio = toPlace[ratioIdx]; ScaleStep scaleStep = scaleSteps[stepIdx]; toPlace.RemoveAt(ratioIdx); scaleStep.Ratio = ratio; //## debug //Console.WriteLine("placing ratio {0} {1:F2} @ {2} {3:F2}", ratio, ratio.Cents, stepIdx, scaleStep.Cents); } }