public IntervalPattern( IntervalQuality quality, IntervalQuantity quantity = IntervalQuantity.Unison) { this.quantity = quantity; this.semitones = GetSemitones(); this.quality = quality; }
/// <summary> /// Gets an instance of the <see cref="Interval"/> by the specified interval quality and number. /// </summary> /// <param name="intervalQuality">Interval quality.</param> /// <param name="intervalNumber">Interval number.</param> /// <returns>An instance of the <see cref="Interval"/> which represents <paramref name="intervalNumber"/> /// along with <paramref name="intervalQuality"/>.</returns> /// <exception cref="InvalidEnumArgumentException"><paramref name="intervalQuality"/> specified an /// invalid value.</exception> /// <exception cref="ArgumentOutOfRangeException"><paramref name="intervalNumber"/> is less than 1.</exception> /// <exception cref="ArgumentException"><paramref name="intervalQuality"/> is not applicable to /// <paramref name="intervalNumber"/>.</exception> public static Interval Get(IntervalQuality intervalQuality, int intervalNumber) { ThrowIfArgument.IsInvalidEnumValue(nameof(intervalQuality), intervalQuality); ThrowIfArgument.IsLessThan(nameof(intervalNumber), intervalNumber, 1, "Interval number is less than 1."); if (!IsQualityApplicable(intervalQuality, intervalNumber)) { throw new ArgumentException($"{intervalQuality} quality is not applicable to interval number of {intervalNumber}.", nameof(intervalQuality)); } var maxIntervalNumber = 8; if (intervalQuality == IntervalQuality.Minor || intervalQuality == IntervalQuality.Major || intervalQuality == IntervalQuality.Augmented) { maxIntervalNumber = 7; } var result = intervalNumber > maxIntervalNumber ? ((intervalNumber - 1) / 7) * Octave.OctaveSize : 0; var additionalNumber = intervalNumber; if (intervalNumber > maxIntervalNumber) { additionalNumber = ((intervalNumber - 1) % 7) + 1; } var halfTones = IntervalsHalfTones[intervalQuality]; result += halfTones[additionalNumber]; return(FromHalfSteps(result)); }
public IntervalMatch CanBeCalled(IntervalQuality quality, int size) { int targetSemitones = GetSemitonesInInterval(quality, size); int thisIntervalSemitones = Math.Abs(note1 - note2); if (targetSemitones == thisIntervalSemitones) { return(IntervalMatch.ExactMatch); } // not an exact match; reduce both intervals to less than an octave targetSemitones = targetSemitones % 12; thisIntervalSemitones = thisIntervalSemitones % 12; if (targetSemitones == thisIntervalSemitones) { return(IntervalMatch.UninvertedMatch); } // still not a match; invert one of the intervals as a last try thisIntervalSemitones = 12 - thisIntervalSemitones; if (targetSemitones == thisIntervalSemitones) { return(IntervalMatch.InvertedMatch); } return(IntervalMatch.NoMatch); }
public void Test_GetByInterval(Interval interval, IntervalQuality intervalQuality, Key inputKey, Alteration inputAlteration, Key expectedKey, Alteration expectedAlteration) { var result = _noteService.GetByInterval(new Note(inputKey, inputAlteration), interval, intervalQuality); Assert.That(result.Key, Is.EqualTo(expectedKey)); Assert.That(result.Alteration, Is.EqualTo(expectedAlteration)); }
public Interval Diminish() { IntervalQuality quality = _quality; sbyte multiplicity = _multiplicity; if (quality == IntervalQuality.Augmented) { multiplicity--; if (multiplicity == 0) { quality = Number.IsPerfect() ? IntervalQuality.Perfect : IntervalQuality.Major; } } else if (quality == IntervalQuality.Perfect || quality == IntervalQuality.Minor) { multiplicity++; quality = IntervalQuality.Diminished; } else if (quality == IntervalQuality.Major) { quality = IntervalQuality.Minor; } else { multiplicity++; } return(new Interval(_absoluteNumber, quality, multiplicity)); }
public void Parse_QualityNumber(string input, IntervalQuality expectedIntervalQuality, int expectedIntervalNumber) { var parsedInterval = Interval.Parse(input); var expectedInterval = Interval.Get(expectedIntervalQuality, expectedIntervalNumber); Assert.AreEqual(expectedInterval, parsedInterval, "Parsed interval is invalid."); }
/// <summary> /// Initializes a new instance of the <see cref="IntervalDefinition"/> with the specified /// interval number and quality. /// </summary> /// <param name="number">Interval number.</param> /// <param name="quality">Interval quality.</param> /// <exception cref="ArgumentOutOfRangeException"><paramref name="number"/> is less than 1.</exception> /// <exception cref="InvalidEnumArgumentException"><paramref name="quality"/> specified an invalid value.</exception> public IntervalDefinition(int number, IntervalQuality quality) { ThrowIfArgument.IsLessThan(nameof(number), number, 1, "Interval number is less than 1."); ThrowIfArgument.IsInvalidEnumValue(nameof(quality), quality); Number = number; Quality = quality; }
private static int QualitySize(IntervalQuality quality, int number) { switch ((Math.Abs(number) - 1) % 7 + 1) { case 1: case 4: case 5: switch (quality) { case IntervalQuality.Diminished: return(-1); case IntervalQuality.Minor: throw new InvalidEnumArgumentException("Invalid quality for interval. Quality: " + quality + " Interval: " + number); case IntervalQuality.Perfect: return(0); case IntervalQuality.Major: throw new InvalidEnumArgumentException("Invalid quality for interval. Quality: " + quality + " Interval: " + number); case IntervalQuality.Augmented: return(1); default: throw new Exception("Should not be possible"); } case 2: case 3: case 6: case 7: switch (quality) { case IntervalQuality.Diminished: return(-2); case IntervalQuality.Minor: return(-1); case IntervalQuality.Perfect: throw new InvalidEnumArgumentException("Invalid quality for interval. Quality: " + quality + " Interval: " + number); case IntervalQuality.Major: return(0); case IntervalQuality.Augmented: return(1); default: throw new Exception("Should not be possible"); } default: throw new Exception("Should not be possible"); } }
public Note GetByInterval(Note startNote, Interval interval, IntervalQuality intervalQuality) { var targetKey = _keyService.GetByInterval(startNote.Key, interval); var halfStepCountBetweenStartNoteAndTargetKey = (_keyService.GetHalfStepCountBetweenTwoKey(startNote.Key, targetKey) - (int)startNote.Alteration); var targetHalfStepCount = GetHalfStepCountFromInterval(interval, intervalQuality); var neededAlterationHalfStepCount = targetHalfStepCount - halfStepCountBetweenStartNoteAndTargetKey; var alteration = (Alteration)(neededAlterationHalfStepCount); return(new Note(targetKey, alteration)); }
/// <remarks>interval number is zero based, thus a second interval has a number of 1</remarks> public Interval(int number, IntervalQuality quality) { if (!Interval.IsValid(number, quality)) { throw new ArgumentException("Number and quality mismatch"); } this.Number = number; this.Quality = quality; }
public static int GetSemitonesInInterval(IntervalQuality quality, int size) { int zeroBasedSize = size - 1; int octaveOffset = (zeroBasedSize / 7) * 12; int baseInterval = zeroBasedSize % 7; int baseIntervalSize = intervalTable[baseInterval, (int)quality]; if (baseIntervalSize == -9) { throw new InvalidIntervalException(); } return(octaveOffset + baseIntervalSize); }
/// <remarks>interval number is zero based, thus a second interval has a number of 1</remarks> public static bool IsValid(int number, IntervalQuality quality) { if (number < 0) { throw new ArgumentOutOfRangeException(nameof(number)); } var normalizedNumber = number % 7; if (normalizedNumber == 0 || normalizedNumber == 3 || normalizedNumber == 4) { return(quality != IntervalQuality.Major && quality != IntervalQuality.Minor); } else { return(quality != IntervalQuality.Perfect); } }
public Interval(int absoluteNumber, IntervalQuality quality, sbyte multiplicity = 0) { var number = GetNumber(absoluteNumber); if (number.IsPerfect()) { if (quality == IntervalQuality.Minor || quality == IntervalQuality.Major) { throw new ArgumentException(null, nameof(quality)); } } else { if (quality == IntervalQuality.Perfect) { throw new ArgumentException(null, nameof(quality)); } } if (quality < IntervalQuality.Diminished || quality > IntervalQuality.Augmented) { throw new ArgumentOutOfRangeException(nameof(quality)); } if (quality == IntervalQuality.Diminished || quality == IntervalQuality.Augmented) { if (multiplicity <= 0) { throw new ArgumentOutOfRangeException(nameof(multiplicity)); } } else { if (multiplicity != 0) { throw new ArgumentOutOfRangeException(nameof(multiplicity)); } } _absoluteNumber = absoluteNumber; _quality = quality; _multiplicity = multiplicity; }
public Interval(int number, IntervalQuality quality) { Direction = number >= 0; Number = number; Quality = quality; noteNumQualitySize = QualitySize(quality, number); HalfTones = 0; number = Math.Abs(number); while (number > 7) { HalfTones += 12; number -= 7; } HalfTones += INTERVAL_LENGTHS[number - 1]; HalfTones += noteNumQualitySize; if (!Direction) { HalfTones *= -1; } }
private static int GetSemitones(IntervalNumber number, IntervalQuality quality, sbyte multiplicity) { int semitones = s_numberToSemitones[number - IntervalNumber.Unison]; if (quality == IntervalQuality.Minor || quality == IntervalQuality.Diminished && !number.IsPerfect()) { semitones--; } if (multiplicity > 0) { if (quality == IntervalQuality.Augmented) { semitones += multiplicity; } else { semitones -= multiplicity; } } return(semitones); }
private static string QualityToString(IntervalQuality quality) { switch (quality) { case IntervalQuality.Diminished: return("d"); case IntervalQuality.Minor: return("m"); case IntervalQuality.Perfect: return("P"); case IntervalQuality.Major: return("M"); case IntervalQuality.Augmented: return("A"); default: throw new Exception("Should not be possible."); } }
/// <summary> /// Gets a value indicating whether quality is applicable to the specified interval number (1 and greater) or not. /// </summary> /// <param name="intervalQuality">Interval quality to check whether it's applicable to /// <paramref name="intervalNumber"/> or not.</param> /// <param name="intervalNumber">Interval number to check whether <paramref name="intervalQuality"/> is /// applicable to it or not.</param> /// <returns>true if <paramref name="intervalQuality"/> is applicable to <paramref name="intervalNumber"/>; /// otherwise, false.</returns> /// <exception cref="InvalidEnumArgumentException"><paramref name="intervalQuality"/> specified an /// invalid value.</exception> /// <exception cref="ArgumentOutOfRangeException"><paramref name="intervalNumber"/> is less than 1.</exception> public static bool IsQualityApplicable(IntervalQuality intervalQuality, int intervalNumber) { ThrowIfArgument.IsInvalidEnumValue(nameof(intervalQuality), intervalQuality); ThrowIfArgument.IsLessThan(nameof(intervalNumber), intervalNumber, 1, "Interval number is less than 1."); switch (intervalQuality) { case IntervalQuality.Perfect: return(IsPerfect(intervalNumber)); case IntervalQuality.Minor: case IntervalQuality.Major: return(!IsPerfect(intervalNumber)); case IntervalQuality.Diminished: return(intervalNumber >= 2); case IntervalQuality.Augmented: return(true); } return(false); }
internal IntervalTableItem(int chromaticDegree, int scaleDegree, IntervalQuality intervalType) { ChromaticDegree = chromaticDegree; ScaleDegree = scaleDegree; IntervalQuality = intervalType; }
public Interval(IntervalNumber number, IntervalQuality quality, sbyte multiplicity = 0) : this(IntervalNumber.Unison <= number && number <= IntervalNumber.Octave ? number - IntervalNumber.Unison : throw new ArgumentOutOfRangeException(nameof(number)), quality, multiplicity) { }
public static string GetSign(this IntervalQuality quality, int multiciplity = 0) { return(new string(s_qualitySigns[quality - IntervalQuality.Diminished], Math.Max(multiciplity, 1))); }
private int GetHalfStepCountFromInterval(Interval interval, IntervalQuality intervalQuality) { switch (interval) { case Interval.Second: switch (intervalQuality) { case IntervalQuality.Major: return(2); case IntervalQuality.Minor: return(1); case IntervalQuality.Augmented: return(3); case IntervalQuality.Diminished: return(0); case IntervalQuality.Perfect: throw new NotExistingIntervalException($"Interval {interval} {intervalQuality} does not exist"); default: throw new ArgumentOutOfRangeException(nameof(intervalQuality), intervalQuality, null); } case Interval.Third: switch (intervalQuality) { case IntervalQuality.Major: return(4); case IntervalQuality.Minor: return(3); case IntervalQuality.Augmented: return(5); case IntervalQuality.Diminished: return(2); case IntervalQuality.Perfect: throw new NotExistingIntervalException($"Interval {interval} {intervalQuality} does not exist"); default: throw new ArgumentOutOfRangeException(nameof(intervalQuality), intervalQuality, null); } case Interval.Fourth: switch (intervalQuality) { case IntervalQuality.Perfect: return(5); case IntervalQuality.Augmented: return(6); case IntervalQuality.Diminished: return(4); case IntervalQuality.Major: case IntervalQuality.Minor: throw new NotExistingIntervalException($"Interval {interval} {intervalQuality} does not exist"); default: throw new ArgumentOutOfRangeException(nameof(intervalQuality), intervalQuality, null); } case Interval.Fifth: switch (intervalQuality) { case IntervalQuality.Perfect: return(7); case IntervalQuality.Augmented: return(8); case IntervalQuality.Diminished: return(6); case IntervalQuality.Major: case IntervalQuality.Minor: throw new NotExistingIntervalException($"Interval {interval} {intervalQuality} does not exist"); default: throw new ArgumentOutOfRangeException(nameof(intervalQuality), intervalQuality, null); } case Interval.Sixth: switch (intervalQuality) { case IntervalQuality.Major: return(9); case IntervalQuality.Minor: return(8); case IntervalQuality.Augmented: return(10); case IntervalQuality.Diminished: return(7); case IntervalQuality.Perfect: throw new NotExistingIntervalException($"Interval {interval} {intervalQuality} does not exist"); default: throw new ArgumentOutOfRangeException(nameof(intervalQuality), intervalQuality, null); } case Interval.Seventh: switch (intervalQuality) { case IntervalQuality.Major: return(11); case IntervalQuality.Minor: return(10); case IntervalQuality.Augmented: return(12); case IntervalQuality.Diminished: return(9); case IntervalQuality.Perfect: throw new NotExistingIntervalException($"Interval {interval} {intervalQuality} does not exist"); default: throw new ArgumentOutOfRangeException(nameof(intervalQuality), intervalQuality, null); } default: throw new ArgumentOutOfRangeException(nameof(interval), interval, null); } }
public static Interval GetC4BasedInterval(IntervalQuality quality, IntervalQuantity quantity) { var C4 = new Pitch(new Step(StepLetter.C)); switch (quantity) { case IntervalQuantity.Unison: if (quality == IntervalQuality.Perfect) return new Interval(C4, C4); else throw new ArgumentException(string.Format(exceptionFormatString, quantity, quality)); break; case IntervalQuantity.Second: if (quality == IntervalQuality.Minor) return new Interval(C4, new Pitch(new Step(StepLetter.D), accidental: Accidentals.Flat)); if (quality == IntervalQuality.Major) return new Interval(C4, new Pitch(new Step(StepLetter.D))); if (quality == IntervalQuality.Augmented) return new Interval(C4, new Pitch(new Step(StepLetter.D), accidental: Accidentals.Sharp)); if (quality == IntervalQuality.Diminished) return new Interval(C4, new Pitch(new Step(StepLetter.D), accidental: Accidentals.DoubleFlat)); else throw new ArgumentException(string.Format(exceptionFormatString, quantity, quality)); break; case IntervalQuantity.Third: if (quality == IntervalQuality.Minor) return new Interval(C4, new Pitch(new Step(StepLetter.E), accidental: Accidentals.Flat)); if (quality == IntervalQuality.Major) return new Interval(C4, new Pitch(new Step(StepLetter.E))); if (quality == IntervalQuality.Augmented) return new Interval(C4, new Pitch(new Step(StepLetter.E), accidental: Accidentals.Sharp)); if (quality == IntervalQuality.Diminished) return new Interval(C4, new Pitch(new Step(StepLetter.E), accidental: Accidentals.DoubleFlat)); else throw new ArgumentException(string.Format(exceptionFormatString, quantity, quality)); break; case IntervalQuantity.Fourth: if (quality == IntervalQuality.Perfect) return new Interval(C4, new Pitch(new Step(StepLetter.F))); if (quality == IntervalQuality.Augmented) return new Interval(C4, new Pitch(new Step(StepLetter.F), accidental: Accidentals.Sharp)); if (quality == IntervalQuality.Diminished) return new Interval(C4, new Pitch(new Step(StepLetter.F), accidental: Accidentals.Flat)); else throw new ArgumentException(string.Format(exceptionFormatString, quantity, quality)); break; case IntervalQuantity.Fifth: if (quality == IntervalQuality.Perfect) return new Interval(C4, new Pitch(new Step(StepLetter.G))); if (quality == IntervalQuality.Augmented) return new Interval(C4, new Pitch(new Step(StepLetter.G), accidental: Accidentals.Sharp)); if (quality == IntervalQuality.Diminished) return new Interval(C4, new Pitch(new Step(StepLetter.G), accidental: Accidentals.Flat)); else throw new ArgumentException(string.Format(exceptionFormatString, quantity, quality)); break; case IntervalQuantity.Sixth: if (quality == IntervalQuality.Minor) return new Interval(C4, new Pitch(new Step(StepLetter.A), accidental: Accidentals.Flat)); if (quality == IntervalQuality.Major) return new Interval(C4, new Pitch(new Step(StepLetter.A))); if (quality == IntervalQuality.Augmented) return new Interval(C4, new Pitch(new Step(StepLetter.A), accidental: Accidentals.Sharp)); if (quality == IntervalQuality.Diminished) return new Interval(C4, new Pitch(new Step(StepLetter.A), accidental: Accidentals.DoubleFlat)); else throw new ArgumentException(string.Format(exceptionFormatString, quantity, quality)); break; case IntervalQuantity.Seventh: if (quality == IntervalQuality.Minor) return new Interval(C4, new Pitch(new Step(StepLetter.B), accidental: Accidentals.Flat)); if (quality == IntervalQuality.Major) return new Interval(C4, new Pitch(new Step(StepLetter.B))); if (quality == IntervalQuality.Augmented) return new Interval(C4, new Pitch(new Step(StepLetter.A), accidental: Accidentals.Sharp)); if (quality == IntervalQuality.Diminished) return new Interval(C4, new Pitch(new Step(StepLetter.A), accidental: Accidentals.DoubleFlat)); else throw new ArgumentException(string.Format(exceptionFormatString, quantity, quality)); break; case IntervalQuantity.Octave: var tempInterval = GetC4BasedInterval(quality, IntervalQuantity.Unison); if (quality == IntervalQuality.Perfect) return new Interval(tempInterval.Root, tempInterval.Top.TransposeOctaves(1)); if (quality == IntervalQuality.Augmented) return new Interval(C4, new Pitch(new Step(StepLetter.A), accidental: Accidentals.Sharp)); if (quality == IntervalQuality.Diminished) return new Interval(C4, new Pitch(new Step(StepLetter.A), accidental: Accidentals.DoubleFlat)); else throw new ArgumentException(string.Format(exceptionFormatString, quantity, quality)); break; case IntervalQuantity.Ninth: break; case IntervalQuantity.Tenth: break; case IntervalQuantity.Eleventh: break; case IntervalQuantity.Twelfth: break; case IntervalQuantity.Thirteenth: break; case IntervalQuantity.Fourteenth: break; case IntervalQuantity.Fifteenth: break; default: break; } return default(Interval); }