void ParseLength(out Length length, out int dots) { float noteDuration = ParserUtil.lengthDurations[unitNoteLength]; noteDuration *= ReadDurationModifier(); if (!ParserUtil.ParseDuration(noteDuration, out length, out dots)) { throw new ParseException($"Invalid Note duration at {lineNum}, {index}"); } }
float ReadDurationModifier() { // length modifier will be either '/*' or '\d*/N' ReadUntil((char c) => { return(!char.IsDigit(c) && c != '/'); }, out string lengthMod); try { return(ParserUtil.ParseDurationModifierString(lengthMod)); } catch (FormatException) { throw new ParseException($"Unable to parse length modifier at {lineNum}, {index}"); } }
void UpdateBrokenRhythm() { if (brokenRhythm == BrokenRhythm.None) { return; } if (voice.items.Count < 2) { throw new ParseException($"Unable to apply broken rhythm to item near {lineNum}, {index}"); } var itemA = voice.items[voice.items.Count - 2] as Duration; var itemB = voice.items[voice.items.Count - 1] as Duration; if (itemA == null || itemB == null) { throw new ParseException($"Unable to apply broken rhythm to item near {lineNum}, {index}"); } Duration halfItem, dotItem; if (brokenRhythm == BrokenRhythm.DotHalf) { dotItem = itemA; halfItem = itemB; } else { dotItem = itemB; halfItem = itemA; } dotItem.dotCount = brokenRhythmCount; var duration = ParserUtil.lengthDurations[halfItem.length] * (1.0f / (1 << brokenRhythmCount)); ParserUtil.ParseDuration(duration, out Length l, out int dots); halfItem.length = l; halfItem.dotCount = dots; brokenRhythm = BrokenRhythm.None; }
void ParseChord() { EnsureVoice(); CheckForLineBreak(); index += 1; var notes = new List <Note>(); float noteDurationModifier = 1.0f; do { if (SkipWhiteSpace()) { throw new ParseException($"Unterminated chord at {lineNum}, {index}"); } if (!Elements.IsStartOfNoteStream(currentLine[index])) { throw new ParseException($"Invalid character in chord at {lineNum}, {index}"); } notes.Add(ReadBaseNote()); //only the duration modifier for the first chord will have impact on its overall duration float durationModifier = ReadDurationModifier(); if (notes.Count == 1) { noteDurationModifier = durationModifier; } if (index == currentLine.Length) { throw new ParseException($"Unterminated chord at {lineNum}, {index}"); } } while (currentLine[index] != ']'); index += 1; if (notes.Count == 0) { throw new ParseException($"Encountered empty chord at {lineNum}, {index}"); } var chord = Chord.FromNotes(notes); float chordDurationModifier = ReadDurationModifier(); // spec states that length modifiers inside the chord are multiplied by outside float noteDuration = ParserUtil.lengthDurations[unitNoteLength] * (noteDurationModifier * chordDurationModifier); if (!ParserUtil.ParseDuration(noteDuration, out Length chordLength, out int dotCount)) { throw new ParseException($"Invalid Note duration at {lineNum}, {index}"); } chord.length = chordLength; chord.dotCount = dotCount; UpdateBeam(chord); voice.items.Add(chord); SetDecorationsForItem(chord); }