internal static ParsingResult TryParse(string input, out Note note) { note = null; if (string.IsNullOrWhiteSpace(input)) { return(ParsingResult.EmptyInputString); } var match = ParsingUtilities.Match(input, Patterns); if (match == null) { return(ParsingResult.NotMatched); } var noteNameGroup = match.Groups[NoteNameGroupName]; NoteName noteName; var noteNameParsingResult = NoteNameParser.TryParse(noteNameGroup.Value, out noteName); if (noteNameParsingResult.Status != ParsingStatus.Parsed) { return(noteNameParsingResult); } int octaveNumber; if (!ParsingUtilities.ParseInt(match, OctaveGroupName, Octave.Middle.Number, out octaveNumber)) { return(ParsingResult.Error(OctaveIsOutOfRange)); } if (!NoteUtilities.IsNoteValid(noteName, octaveNumber)) { return(ParsingResult.Error(NoteIsOutOfRange)); } note = Note.Get(noteName, octaveNumber); return(ParsingResult.Parsed); }
internal static ParsingResult TryParse(string input, out Chord chord) { chord = null; if (string.IsNullOrWhiteSpace(input)) return ParsingResult.EmptyInputString; var match = ParsingUtilities.Match(input, Patterns, ignoreCase: false); if (match == null) return ParsingResult.NotMatched; var rootNoteNameGroup = match.Groups[RootNoteNameGroupName]; NoteName rootNoteName; var rootNoteNameParsingResult = NoteNameParser.TryParse(rootNoteNameGroup.Value, out rootNoteName); if (rootNoteNameParsingResult.Status != ParsingStatus.Parsed) return rootNoteNameParsingResult; // NoteName? bassNoteName = null; var bassNoteNameGroup = match.Groups[BassNoteNameGroupName]; if (bassNoteNameGroup.Success) { NoteName actualBassNoteName; var bassNoteNameParsingResult = NoteNameParser.TryParse(bassNoteNameGroup.Value, out actualBassNoteName); if (bassNoteNameParsingResult.Status != ParsingStatus.Parsed) return bassNoteNameParsingResult; bassNoteName = actualBassNoteName; } var notesNames = ChordsNamesTable.GetChordNotesNames(rootNoteName, match.Groups[ChordCharacteristicsGroupName].Value, bassNoteName); if (!notesNames.Any()) return ParsingResult.Error(ChordCharacteristicIsUnknown); chord = new Chord(notesNames); return ParsingResult.Parsed; }
internal static ParsingResult TryParse(string input, out Chord chord) { chord = null; if (string.IsNullOrWhiteSpace(input)) { return(ParsingResult.EmptyInputString); } var match = ParsingUtilities.Match(input, Patterns, ignoreCase: false); if (match == null) { return(ParsingResult.NotMatched); } var rootNoteNameGroup = match.Groups[RootNoteNameGroupName]; NoteName rootNoteName; var rootNoteNameParsingResult = NoteNameParser.TryParse(rootNoteNameGroup.Value, out rootNoteName); if (rootNoteNameParsingResult.Status != ParsingStatus.Parsed) { return(rootNoteNameParsingResult); } if (match.Groups[ChordNameGroupName].Success) { return(TryParseChordName(match, rootNoteName, out chord)); } else if (match.Groups[ChordIntervalsGroupName].Success) { return(TryParseChordIntervals(match, rootNoteName, out chord)); } return(ParsingResult.Parsed); }
internal static ParsingResult TryParseChordName(Match match, NoteName rootNoteName, out Chord chord) { chord = null; // Quality?quality = null; var qualityGroup = match.Groups[ChordQualityGroupName]; if (qualityGroup.Success) { quality = GroupsQualities.FirstOrDefault(gq => match.Groups[gq.Key].Success).Value; } // var extensionIntervalNumber = -1; IntervalQuality?extensionIntervalQuality = null; var extensionGroup = match.Groups[ExtensionGroupName]; if (extensionGroup.Success && !string.IsNullOrWhiteSpace(extensionGroup.Value)) { if (match.Groups[ExtensionQualityGroupName].Success) { extensionIntervalQuality = GroupsExtensionQualities.FirstOrDefault(gq => match.Groups[gq.Key].Success).Value; } if (!ParsingUtilities.ParseInt(match, ExtensionNumberGroupName, -1, out extensionIntervalNumber) || extensionIntervalNumber < 5) { return(ParsingResult.Error(ExtensionNumberIsOutOfRange)); } } if (quality == Quality.HalfDiminished || quality == Quality.Dominant) { if (extensionIntervalNumber >= 0 && extensionIntervalNumber != 7) { return(ParsingResult.Error(HalfDiminishedOrDominantIsNotSeventh)); } if (extensionIntervalNumber < 0) { extensionIntervalNumber = 7; } } var extensionNotes = new List <NoteName>(); var extensionNumbers = new List <int>(); if (extensionIntervalNumber >= 0) { var extensionNotesDictionary = GetExtensionNotes(quality, rootNoteName, extensionIntervalNumber, extensionIntervalQuality); extensionNotes.AddRange(extensionNotesDictionary.Keys); extensionNumbers.AddRange(extensionNotesDictionary.Values); } if (quality == Quality.HalfDiminished) { quality = Quality.Diminished; } else if (quality == Quality.Dominant) { quality = Quality.Major; } if (quality == null) { quality = Quality.Major; } // var notes = new List <NoteName>(Chord.GetByTriad(rootNoteName, ChordQualities[quality.Value]).NotesNames); notes.AddRange(extensionNotes); extensionNumbers.InsertRange(0, new[] { 1, 3, 5 }); if (extensionIntervalNumber == 5) { notes.Clear(); notes.AddRange(new[] { rootNoteName, extensionNotes.First() }); extensionNumbers.Clear(); extensionNumbers.AddRange(new[] { 1, 5 }); } // var alteredToneGroup = match.Groups[AlteredToneGroupName]; if (alteredToneGroup.Success) { int alteredToneNumber; if (!ParsingUtilities.ParseInt(match, AlteredToneNumberGroupName, -1, out alteredToneNumber)) { return(ParsingResult.Error(AlteredToneNumberIsOutOfRange)); } var transposeBy = 0; var accidental = match.Groups[AlteredToneAccidentalGroupName].Value; switch (accidental) { case "#": case "+": transposeBy = 1; break; case "b": case "-": transposeBy = -1; break; } var maxExtensionNumber = extensionNumbers.Max(); if (maxExtensionNumber < alteredToneNumber) { var extensionNotesDictionary = GetExtensionNotes(quality, rootNoteName, alteredToneNumber, null) .Where(kv => kv.Value > maxExtensionNumber); notes.AddRange(extensionNotesDictionary.Select(kv => kv.Key)); extensionNumbers.AddRange(extensionNotesDictionary.Select(kv => kv.Value)); } var index = extensionNumbers.IndexOf(alteredToneNumber); if (index >= 0) { notes[index] = notes[index].Transpose(Interval.FromHalfSteps(transposeBy)); } } // var suspendedGroup = match.Groups[SuspendedGroupName]; if (suspendedGroup.Success) { int suspensionNumber; if (!ParsingUtilities.ParseInt(match, SuspendedNumberGroupName, -1, out suspensionNumber) || suspensionNumber != 2 && suspensionNumber != 4) { return(ParsingResult.Error(SuspensionNumberIsOutOfRange)); } var interval = suspensionNumber == 2 ? Interval.Get(IntervalQuality.Major, 2) : Interval.Get(IntervalQuality.Perfect, 4); notes[1] = rootNoteName.Transpose(interval); } // var addedToneGroup = match.Groups[AddedToneGroupName]; if (addedToneGroup.Success) { int addedToneNumber; if (!ParsingUtilities.ParseInt(match, AddedToneNumberGroupName, -1, out addedToneNumber)) { return(ParsingResult.Error(AddedToneNumberIsOutOfRange)); } var interval = Interval.IsPerfect(addedToneNumber) ? Interval.Get(IntervalQuality.Perfect, addedToneNumber) : Interval.Get(IntervalQuality.Major, addedToneNumber); notes.Add(rootNoteName.Transpose(interval)); } // var bassNoteNameGroup = match.Groups[BassNoteNameGroupName]; if (bassNoteNameGroup.Success) { NoteName bassNoteName; var bassNoteNameParsingResult = NoteNameParser.TryParse(bassNoteNameGroup.Value, out bassNoteName); if (bassNoteNameParsingResult.Status != ParsingStatus.Parsed) { return(bassNoteNameParsingResult); } notes.Insert(0, bassNoteName); } // chord = new Chord(notes); return(ParsingResult.Parsed); }
internal static ParsingResult TryParse(string input, out Scale scale) { scale = null; if (string.IsNullOrWhiteSpace(input)) { return(ParsingResult.EmptyInputString); } var match = ParsingUtilities.Match(input, Patterns); if (match == null) { return(ParsingResult.NotMatched); } var rootNoteNameGroup = match.Groups[RootNoteNameGroupName]; NoteName rootNoteName; var rootNoteNameParsingResult = NoteNameParser.TryParse(rootNoteNameGroup.Value, out rootNoteName); if (rootNoteNameParsingResult.Status != ParsingStatus.Parsed) { return(rootNoteNameParsingResult); } // IEnumerable <Interval> intervals = null; var intervalGroup = match.Groups[IntervalGroupName]; if (intervalGroup.Success) { var intervalsParsingResults = intervalGroup .Captures .OfType <Capture>() .Select(c => { Interval interval; var parsingResult = IntervalParser.TryParse(c.Value, out interval); return(new { Interval = interval, ParsingResult = parsingResult }); }) .ToArray(); var notParsedResult = intervalsParsingResults.FirstOrDefault(r => r.ParsingResult.Status != ParsingStatus.Parsed); if (notParsedResult != null) { return(notParsedResult.ParsingResult); } intervals = intervalsParsingResults.Select(r => r.Interval).ToArray(); } else { var intervalsMnemonicGroup = match.Groups[IntervalsMnemonicGroupName]; var intervalsName = intervalsMnemonicGroup.Value; intervals = ScaleIntervals.GetByName(intervalsName); } if (intervals == null) { return(ParsingResult.Error(ScaleIsUnknown)); } // scale = new Scale(intervals, rootNoteName); return(ParsingResult.Parsed); }