Fix: Correctly parse slurs and triplets preceding grace notes#1137
Open
leedale30 wants to merge 1 commit intopaulrosen:mainfrom
Open
Fix: Correctly parse slurs and triplets preceding grace notes#1137leedale30 wants to merge 1 commit intopaulrosen:mainfrom
leedale30 wants to merge 1 commit intopaulrosen:mainfrom
Conversation
Author
|
hey Paul, so its 5am here in China and i couldnt sleep so i decided to run those tests you asked for :D Checked the nested slurs and the ones with notes in between, seems to work grait. Heres the ABC file i used: Click to see full XML output<?xml version='1.0' encoding='utf-8'?>
<?xml-model href="https://www.w3.org/2021/06/musicxml40/musicxml.xsd" type="application/xml" schematypens="http://www.w3.org/2001/XMLSchema"?>
<score-partwise>
<work>
<work-title>Paul Rosen Slur Tests</work-title>
</work>
<identification>
<creator type="composer">leedale30</creator>
<encoding>
<encoder>abc2xml version 239</encoder>
<encoding-date>2026-01-20</encoding-date>
</encoding>
</identification>
<part-list>
<score-part id="P1">
<part-name />
</score-part>
<score-part id="P2">
<part-name />
</score-part>
</part-list>
<part id="P1">
<measure number="1">
<attributes>
<divisions>120</divisions>
<key>
<fifths>1</fifths>
<mode>major</mode>
</key>
<time>
<beats>4</beats>
<beat-type>4</beat-type>
</time>
</attributes>
<note>
<pitch>
<step>G</step>
<octave>4</octave>
</pitch>
<duration>60</duration>
<voice>1</voice>
<type>eighth</type>
<beam number="1">begin</beam>
</note>
<note>
<pitch>
<step>A</step>
<octave>4</octave>
</pitch>
<duration>60</duration>
<voice>1</voice>
<type>eighth</type>
<beam number="1">continue</beam>
</note>
<note>
<pitch>
<step>G</step>
<octave>4</octave>
</pitch>
<duration>60</duration>
<voice>1</voice>
<type>eighth</type>
<beam number="1">end</beam>
</note>
<note>
<grace />
<pitch>
<step>B</step>
<octave>4</octave>
</pitch>
<voice>1</voice>
<type>eighth</type>
<notations>
<slur number="1" type="start" />
</notations>
</note>
<note>
<grace />
<pitch>
<step>C</step>
<octave>5</octave>
</pitch>
<voice>1</voice>
<type>eighth</type>
</note>
<note>
<grace />
<pitch>
<step>B</step>
<octave>4</octave>
</pitch>
<voice>1</voice>
<type>eighth</type>
</note>
<note>
<pitch>
<step>G</step>
<octave>4</octave>
</pitch>
<duration>60</duration>
<voice>1</voice>
<type>eighth</type>
<notations>
<slur number="1" type="stop" />
</notations>
</note>
<note>
<pitch>
<step>A</step>
<octave>4</octave>
</pitch>
<duration>60</duration>
<voice>1</voice>
<type>eighth</type>
<beam number="1">begin</beam>
</note>
<note>
<pitch>
<step>B</step>
<octave>4</octave>
</pitch>
<duration>60</duration>
<voice>1</voice>
<type>eighth</type>
<beam number="1">end</beam>
</note>
<note>
<pitch>
<step>C</step>
<octave>5</octave>
</pitch>
<duration>60</duration>
<voice>1</voice>
<type>eighth</type>
<beam number="1">begin</beam>
</note>
<note>
<pitch>
<step>D</step>
<octave>5</octave>
</pitch>
<duration>60</duration>
<voice>1</voice>
<type>eighth</type>
<beam number="1">end</beam>
</note>
</measure>
<measure number="2">
<note>
<pitch>
<step>C</step>
<octave>4</octave>
</pitch>
<duration>60</duration>
<voice>1</voice>
<type>eighth</type>
<beam number="1">begin</beam>
<notations>
<slur number="1" type="start" />
</notations>
</note>
<note>
<pitch>
<step>D</step>
<octave>4</octave>
</pitch>
<duration>60</duration>
<voice>1</voice>
<type>eighth</type>
<beam number="1">end</beam>
<notations>
<slur number="1" type="stop" />
<slur number="1" type="start" />
</notations>
</note>
<note>
<pitch>
<step>E</step>
<octave>4</octave>
</pitch>
<duration>60</duration>
<voice>1</voice>
<type>eighth</type>
<notations>
<slur number="1" type="stop" />
</notations>
</note>
<note>
<pitch>
<step>F</step>
<alter>1</alter>
<octave>4</octave>
</pitch>
<duration>60</duration>
<voice>1</voice>
<type>eighth</type>
</note>
<note>
<pitch>
<step>G</step>
<octave>4</octave>
</pitch>
<duration>240</duration>
<voice>1</voice>
<type>half</type>
</note>
</measure>
<measure number="3">
<note>
<pitch>
<step>C</step>
<octave>4</octave>
</pitch>
<duration>60</duration>
<voice>1</voice>
<type>eighth</type>
<beam number="1">begin</beam>
<notations>
<slur number="1" type="start" />
</notations>
</note>
<note>
<pitch>
<step>G</step>
<octave>5</octave>
</pitch>
<duration>60</duration>
<voice>1</voice>
<type>eighth</type>
<beam number="1">continue</beam>
</note>
<note>
<pitch>
<step>G</step>
<octave>5</octave>
</pitch>
<duration>60</duration>
<voice>1</voice>
<type>eighth</type>
<beam number="1">continue</beam>
</note>
<note>
<pitch>
<step>G</step>
<octave>5</octave>
</pitch>
<duration>60</duration>
<voice>1</voice>
<type>eighth</type>
<beam number="1">continue</beam>
</note>
<note>
<pitch>
<step>D</step>
<octave>4</octave>
</pitch>
<duration>60</duration>
<voice>1</voice>
<type>eighth</type>
<beam number="1">continue</beam>
<notations>
<slur number="1" type="stop" />
<slur number="1" type="start" />
</notations>
</note>
<note>
<pitch>
<step>G</step>
<octave>5</octave>
</pitch>
<duration>60</duration>
<voice>1</voice>
<type>eighth</type>
<beam number="1">continue</beam>
</note>
<note>
<pitch>
<step>G</step>
<octave>5</octave>
</pitch>
<duration>60</duration>
<voice>1</voice>
<type>eighth</type>
<beam number="1">continue</beam>
</note>
<note>
<pitch>
<step>G</step>
<octave>5</octave>
</pitch>
<duration>60</duration>
<voice>1</voice>
<type>eighth</type>
<beam number="1">end</beam>
<notations>
<slur number="1" type="stop" />
</notations>
</note>
</measure>
<measure number="4">
<note>
<pitch>
<step>C</step>
<octave>4</octave>
</pitch>
<duration>60</duration>
<voice>1</voice>
<type>eighth</type>
<beam number="1">begin</beam>
<notations>
<slur number="1" type="start" />
</notations>
</note>
<note>
<grace />
<pitch>
<step>G</step>
<octave>5</octave>
</pitch>
<voice>1</voice>
<type>eighth</type>
<notations>
<slur number="2" type="start" />
</notations>
</note>
<note>
<pitch>
<step>D</step>
<octave>4</octave>
</pitch>
<duration>60</duration>
<voice>1</voice>
<type>eighth</type>
<beam number="1">continue</beam>
<notations>
<slur number="2" type="stop" />
</notations>
</note>
<note>
<pitch>
<step>E</step>
<octave>4</octave>
</pitch>
<duration>60</duration>
<voice>1</voice>
<type>eighth</type>
<beam number="1">end</beam>
<notations>
<slur number="1" type="stop" />
</notations>
</note>
<note>
<pitch>
<step>F</step>
<alter>1</alter>
<octave>4</octave>
</pitch>
<duration>60</duration>
<voice>1</voice>
<type>eighth</type>
</note>
<note>
<pitch>
<step>G</step>
<octave>4</octave>
</pitch>
<duration>240</duration>
<voice>1</voice>
<type>half</type>
</note>
</measure>
</part>
<part id="P2">
<measure number="1">
<attributes>
<divisions>120</divisions>
<key>
<fifths>1</fifths>
<mode>major</mode>
</key>
<time>
<beats>4</beats>
<beat-type>4</beat-type>
</time>
</attributes>
<note>
<grace />
<pitch>
<step>G</step>
<octave>5</octave>
</pitch>
<voice>1</voice>
<type>eighth</type>
<notations>
<slur number="1" type="start" />
</notations>
</note>
<note>
<pitch>
<step>A</step>
<octave>4</octave>
</pitch>
<duration>60</duration>
<voice>1</voice>
<type>eighth</type>
<notations>
<slur number="1" type="stop" />
</notations>
</note>
<note>
<pitch>
<step>B</step>
<octave>4</octave>
</pitch>
<duration>60</duration>
<voice>1</voice>
<type>eighth</type>
</note>
<note>
<pitch>
<step>C</step>
<octave>5</octave>
</pitch>
<duration>60</duration>
<voice>1</voice>
<type>eighth</type>
</note>
<note>
<pitch>
<step>D</step>
<octave>5</octave>
</pitch>
<duration>60</duration>
<voice>1</voice>
<type>eighth</type>
</note>
<note>
<pitch>
<step>E</step>
<octave>5</octave>
</pitch>
<duration>240</duration>
<voice>1</voice>
<type>half</type>
</note>
</measure>
<measure number="2">
<note>
<pitch>
<step>A</step>
<octave>4</octave>
</pitch>
<duration>60</duration>
<voice>1</voice>
<type>eighth</type>
<beam number="1">begin</beam>
<notations>
<slur number="1" type="start" />
</notations>
</note>
<note>
<grace />
<pitch>
<step>G</step>
<octave>5</octave>
</pitch>
<voice>1</voice>
<type>eighth</type>
<notations>
<slur number="2" type="start" />
</notations>
</note>
<note>
<pitch>
<step>B</step>
<octave>4</octave>
</pitch>
<duration>60</duration>
<voice>1</voice>
<type>eighth</type>
<beam number="1">continue</beam>
<notations>
<slur number="2" type="stop" />
</notations>
</note>
<note>
<pitch>
<step>C</step>
<octave>5</octave>
</pitch>
<duration>60</duration>
<voice>1</voice>
<type>eighth</type>
<beam number="1">end</beam>
<notations>
<slur number="1" type="stop" />
</notations>
</note>
<note>
<pitch>
<step>D</step>
<octave>5</octave>
</pitch>
<duration>60</duration>
<voice>1</voice>
<type>eighth</type>
</note>
<note>
<pitch>
<step>E</step>
<octave>5</octave>
</pitch>
<duration>240</duration>
<voice>1</voice>
<type>half</type>
</note>
</measure>
<measure number="3">
<note>
<pitch>
<step>G</step>
<octave>4</octave>
</pitch>
<duration>60</duration>
<voice>1</voice>
<type>eighth</type>
<beam number="1">begin</beam>
</note>
<note>
<pitch>
<step>A</step>
<octave>4</octave>
</pitch>
<duration>60</duration>
<voice>1</voice>
<type>eighth</type>
<beam number="1">continue</beam>
</note>
<note>
<pitch>
<step>G</step>
<octave>4</octave>
</pitch>
<duration>60</duration>
<voice>1</voice>
<type>eighth</type>
<beam number="1">end</beam>
</note>
<note>
<grace />
<pitch>
<step>B</step>
<octave>4</octave>
</pitch>
<voice>1</voice>
<type>eighth</type>
<notations>
<slur number="1" type="start" />
</notations>
</note>
<note>
<grace />
<pitch>
<step>C</step>
<octave>5</octave>
</pitch>
<voice>1</voice>
<type>eighth</type>
</note>
<note>
<grace />
<pitch>
<step>B</step>
<octave>4</octave>
</pitch>
<voice>1</voice>
<type>eighth</type>
</note>
<note>
<pitch>
<step>G</step>
<octave>4</octave>
</pitch>
<duration>60</duration>
<voice>1</voice>
<type>eighth</type>
<notations>
<slur number="1" type="stop" />
</notations>
</note>
<note>
<pitch>
<step>A</step>
<octave>4</octave>
</pitch>
<duration>60</duration>
<voice>1</voice>
<type>eighth</type>
<beam number="1">begin</beam>
</note>
<note>
<pitch>
<step>B</step>
<octave>4</octave>
</pitch>
<duration>60</duration>
<voice>1</voice>
<type>eighth</type>
<beam number="1">end</beam>
</note>
<note>
<pitch>
<step>C</step>
<octave>5</octave>
</pitch>
<duration>60</duration>
<voice>1</voice>
<type>eighth</type>
<beam number="1">begin</beam>
</note>
<note>
<pitch>
<step>D</step>
<octave>5</octave>
</pitch>
<duration>60</duration>
<voice>1</voice>
<type>eighth</type>
<beam number="1">end</beam>
</note>
</measure>
<measure number="4">
<note>
<pitch>
<step>A</step>
<octave>4</octave>
</pitch>
<duration>240</duration>
<voice>1</voice>
<type>half</type>
</note>
<note>
<pitch>
<step>A</step>
<octave>4</octave>
</pitch>
<duration>240</duration>
<voice>1</voice>
<type>half</type>
</note>
</measure>
</part>
</score-partwise>Seems like the logic holds up! I also verified with a local rendering that the visual output matches. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

This PR addresses the issue where slurs (and triplets) are incorrectly parsed when they immediately precede a grace note block (e.g.,
({BcB}G)).Root Cause
In
MusicParser.prototype.parseMusic, the "prefix gathering" loop (which collects chords, accents, and grace notes) would exit if it encountered a(character becauseletter_to_open_slurs_and_tripletswas called after this loop. When a slur start(precedes a grace note block{...}, the loop would see the(and break, preventingletter_to_gracefrom being called.Fix
Integrated the gathering of open slurs and triplets directly into the prefix gathering loop. Specifically:
letter_to_open_slurs_and_tripletswithin the loop, afterletter_to_gracereturns 0.letter_to_open_slurs_and_tripletsthat followed the loop.This ensures slurs and triplets are correctly associated with the following note/chord even if grace notes are interspersed.
Fixes #1136 (if applicable) or relates to the reported slur parsing issue.