// Returns per-row errors public static string[] GetErrors(Tempered[] ts, Subgroup subgroup) { if (ts == null) { return(null); } string[] errors = new string[ts.Length]; Rational[] indep = new Rational[ts.Length]; // independent intervals int indepSize = 0; for (int i = 0; i < ts.Length; ++i) { Rational r = ts[i].rational; string error = null; if (r.IsDefault()) { error = "Invalid rational"; } else if (r.Equals(Rational.One)) { error = "1/1 can't be tempered"; } else if (!subgroup.IsInRange(r)) { error = "Out of JI range"; } else { if (indepSize > 0) { var m = new Vectors.Matrix(indep, -1, indepSize, makeDiagonal: true); var coords = m.FindRationalCoordinates(r); if (coords != null) { error = ""; for (int j = 0; j < coords.Length; ++j) { if (coords[j].sign != 0) { error += String.Format(" * {0}^{1}", indep[j].FormatFraction(), coords[j].FormatFraction()); } } if (error.Length != 0) { error = "Dependend: " + error.Substring(2); } } } indep[indepSize++] = r; } errors[i] = error; } return(errors); }
public void SetTemperament(Tempered[] tempered, Subgroup subgroup) { // skip invalid tempered intervals Tempered[] ts = Validate(tempered, subgroup); if (ts == null || ts.Length == 0) { // unset temperament _matrix = null; _pureCents = null; _deltaCents = null; _measuredCents = null; return; } // Fill cents arrays and temperament matrix. // We add the subgroup items to be able to solve each narrow prime of the basis. Rational[] subgroupItems = subgroup.GetItems(); int matrixSize = ts.Length + subgroupItems.Length; Rational[] rs = new Rational[matrixSize]; _pureCents = new float[matrixSize]; _deltaCents = new float[matrixSize]; _measuredCents = new float[matrixSize]; for (int i = 0; i < ts.Length; ++i) // tempered intervals { Rational r = ts[i].rational; rs[i] = r; float cents = (float)r.ToCents(); _pureCents [i] = cents; _deltaCents[i] = ts[i].cents - cents; } for (int i = 0; i < subgroupItems.Length; ++i) // subgroup intervals { int j = ts.Length + i; Rational r = subgroupItems[i]; rs[j] = r; float cents = (float)r.ToCents(); _pureCents [j] = cents; _deltaCents[j] = 0f; } _matrix = new Matrix(rs, makeDiagonal: true); // UpdateMeasuredCents(); }
// Filters out invalid and dependent vectors public static Tempered[] Validate(Tempered[] ts, Subgroup subgroup) { if (ts == null) { return(null); } var result = new List <Tempered>(); Rational[] indep = new Rational[ts.Length]; // independent intervals int indepSize = 0; for (int i = 0; i < ts.Length; ++i) { Rational r = ts[i].rational; if (r.IsDefault()) { continue; } // skip if out of subgroup if (!subgroup.IsInRange(r)) { continue; } // skip if dependend if (indepSize > 0) { var m = new Matrix(indep, -1, indepSize, makeDiagonal: true); if (m.FindCoordinates(r) != null) { continue; } } indep[indepSize++] = r; // result.Add(ts[i]); } return(result.Count == 0 ? null : result.ToArray()); }