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); }