Skip to content

Conversation

@pacebes
Copy link
Contributor

@pacebes pacebes commented Nov 4, 2025

Resolves: #22671

  • This PR is able to deal with nested tuplets when importing nested tuplets in MusicXML
  • It has been tested with the following Score: musescore-22671-test.zip
  • I signed the CLA
  • The title of the PR describes the problem it addresses
  • Each commit's message describes its purpose and effects, and references the issue it resolves
  • If changes are extensive, there is a sequence of easily reviewable commits
  • The code in the PR follows the coding rules
  • There are no unnecessary changes
  • The code compiles and runs on my machine, preferably after each commit individually
  • I created a unit test or vtest to verify the changes I made (if applicable)

@pacebes pacebes force-pushed the 22671-SupportForNestedTupletsInMusicXML branch from 8120cea to 5e433bc Compare November 4, 2025 22:13
@pacebes pacebes force-pushed the 22671-SupportForNestedTupletsInMusicXML branch from 5e433bc to a58af61 Compare November 5, 2025 15:41
@cbjeukendrup cbjeukendrup moved this to Needs Review in MuseScore Studio 4.7 Nov 6, 2025
Implicit tuplets are now supported but not nested implicit tuplets
@pacebes pacebes force-pushed the 22671-SupportForNestedTupletsInMusicXML branch from a58af61 to ca8186a Compare November 9, 2025 06:32
@pacebes
Copy link
Contributor Author

pacebes commented Nov 9, 2025

Hi @cbjeukendrup

I'm a bit stuck with a scenario and I would appreciate some help from someone with more experience in these matters.
I have a version (the last PR) that works with several nested tuplets scenarios included in previously xml file and most of the regression tests.

I have a problem with the second measure of testTuplets5.xml file (red and blue notes):
image

XML:

    <measure number="2">
      <note>
        <pitch>
          <step>G</step>
          <octave>4</octave>
          </pitch>
        <duration>1</duration>
        <voice>1</voice>
        <type>quarter</type>
        <dot/>
        <time-modification>
          <actual-notes>3</actual-notes>
          <normal-notes>2</normal-notes>
          </time-modification>
        <stem>up</stem>
        <notations>
          <tuplet type="start" bracket="no"/>
          </notations>
        </note>
      <note>
        <pitch>
          <step>G</step>
          <octave>4</octave>
          </pitch>
        <duration>1</duration>
        <voice>1</voice>
        <type>quarter</type>
        <dot/>
        <time-modification>
          <actual-notes>3</actual-notes>
          <normal-notes>2</normal-notes>
          </time-modification>
        <stem>up</stem>
        <notations>
          <tuplet type="start" bracket="no"/>
          </notations>
        </note>

As I see it the first note (red one) creates a new tuplet :

      <note>
        <pitch>
          <step>G</step>
          <octave>4</octave>
          </pitch>
        <duration>1</duration>
        <voice>1</voice>
        <type>quarter</type>
        <dot/>
        <time-modification>
          <actual-notes>3</actual-notes>
          <normal-notes>2</normal-notes>
          </time-modification>
        <stem>up</stem>
        <notations>
          <tuplet type="start" bracket="no"/>
          </notations>
        </note>

... but then the second (blue one) note begins

      <note>
        <pitch>
          <step>G</step>
          <octave>4</octave>
          </pitch>
        <duration>1</duration>
        <voice>1</voice>
        <type>quarter</type>
        <dot/>
        <time-modification>
          <actual-notes>3</actual-notes>
          <normal-notes>2</normal-notes>
          </time-modification>
        <stem>up</stem>
        <notations>
          <tuplet type="start" bracket="no"/>
          </notations>
        </note>

The second note (blue one) declares that a new tuplet must be created. This is the scenario I have problems with:

  • Prior to this PR (as no nested tuplets are supported) the solution is to stop the previous tuplet and create a new one
  • Now (with this PR) we try to support nested tuplets. Therefore the code see a new "tuplet start" and decides to create a new nested tuplet because there is no way (at least I haven't been able to find one) to determine that the previous tuplet (red one) is full now.

I would appreciate if some one could provide some support because I don't know how to deal with it.

@pacebes pacebes force-pushed the 22671-SupportForNestedTupletsInMusicXML branch 4 times, most recently from 582c558 to 0651878 Compare November 9, 2025 10:42
This PR still has an scenario to deal with (testTuplets5.xml). A thread has been opened within this PR to determine how to deal with it
@pacebes pacebes force-pushed the 22671-SupportForNestedTupletsInMusicXML branch from 0651878 to 404dbab Compare November 9, 2025 11:51
@pacebes
Copy link
Contributor Author

pacebes commented Nov 10, 2025

Sorry to bother @cbjeukendrup

testTuplets5.xml is only test failing now. I don't' know if you are yet to analyze the prior comment or you think I am not right about the comment and there is a way to deal with this regression test

@cbjeukendrup
Copy link
Member

Sorry, I will attempt to look into this within the next days. Or maybe @miiizen can help

@cbjeukendrup cbjeukendrup requested a review from miiizen November 11, 2025 14:38
@miiizen
Copy link
Contributor

miiizen commented Nov 12, 2025

I'm fairly sure we have enough information to tell that this tuplet is full. The note has a duration of 1. Because divisions is also 1, this means the note's length is 1 quarter note. However, the type and dot tags tell us to display a dotted quarter, giving us a ratio of 3:2.

We can then compare the ratio between these two values to the time-modification tag. This is also 3:2, suggesting we have a full tuplet.

Let me know if that helps!

@pacebes
Copy link
Contributor Author

pacebes commented Nov 12, 2025

I'm fairly sure we have enough information to tell that this tuplet is full. The note has a duration of 1. Because divisions is also 1, this means the note's length is 1 quarter note. However, the type and dot tags tell us to display a dotted quarter, giving us a ratio of 3:2.

We can then compare the ratio between these two values to the time-modification tag. This is also 3:2, suggesting we have a full tuplet.

Let me know if that helps!

Thanks. I'll review it in the coming days

@pacebes
Copy link
Contributor Author

pacebes commented Nov 13, 2025

I'm fairly sure we have enough information to tell that this tuplet is full. The note has a duration of 1. Because divisions is also 1, this means the note's length is 1 quarter note. However, the type and dot tags tell us to display a dotted quarter, giving us a ratio of 3:2.

We can then compare the ratio between these two values to the time-modification tag. This is also 3:2, suggesting we have a full tuplet.

Let me know if that helps!

Hi @miiizen. I would appreciate additional clarification to avoid further mistakes because I am missing something.
Previous example (where divisions = 1):

Tuplet (3/2):

  • Duration-1 + Divisions-1 => Real duration= 1/4
  • Type: Quarter (1/4) + dotted => 3/8
  • Ratio: (3/8)/ (1/4) => (3:2)

So, ratio of 3:2 and time-modification tag 3:2 => complete. OK

So if we get some other examples such as testTuplets2.xml with

<divisions>3</divisions>

and a tuplet defined as:

      <note>
        <pitch>
          <step>G</step>
          <octave>4</octave>
          </pitch>
        <duration>2</duration>
        <voice>1</voice>
        <type>quarter</type>
        <time-modification>
          <actual-notes>3</actual-notes>
          <normal-notes>2</normal-notes>
          </time-modification>
        <stem>up</stem>
        </note>
      <note>
        <pitch>
          <step>G</step>
          <octave>4</octave>
          </pitch>
        <duration>1</duration>
        <voice>1</voice>
        <type>eighth</type>
        <time-modification>
          <actual-notes>3</actual-notes>
          <normal-notes>2</normal-notes>
          </time-modification>
        <stem>up</stem>
        </note>

First part of the tuplet (3/2):

  • Duration-2 + Divisions-3 => Real duration= 1/6
  • Type: Quarter (1/4)
  • Ratio: (1/4)/ (1/6) => (3/2)

Second part of the tuplet (3/2):

  • Duration-1 + Divisions-3 => Real duration= 1/12
  • Type: Eighth (1/8)
  • Ratio: (1/8/ (1/12) => (3/2)

I always the same ratio in the first part of the tuplet and it's not complete. I am missing something and I would appreciate additional help, please.

@pacebes
Copy link
Contributor Author

pacebes commented Nov 17, 2025

I'm fairly sure we have enough information to tell that this tuplet is full. The note has a duration of 1. Because divisions is also 1, this means the note's length is 1 quarter note. However, the type and dot tags tell us to display a dotted quarter, giving us a ratio of 3:2.
We can then compare the ratio between these two values to the time-modification tag. This is also 3:2, suggesting we have a full tuplet.
Let me know if that helps!

Hi @miiizen. I would appreciate additional clarification to avoid further mistakes because I am missing something. Previous example (where divisions = 1):

Tuplet (3/2):

* Duration-1 + Divisions-1 => Real duration= 1/4

* Type: Quarter (1/4) + dotted => 3/8

* Ratio: (3/8)/ (1/4) => (3:2)

So, ratio of 3:2 and time-modification tag 3:2 => complete. OK

So if we get some other examples such as testTuplets2.xml with

<divisions>3</divisions>

and a tuplet defined as:

      <note>
        <pitch>
          <step>G</step>
          <octave>4</octave>
          </pitch>
        <duration>2</duration>
        <voice>1</voice>
        <type>quarter</type>
        <time-modification>
          <actual-notes>3</actual-notes>
          <normal-notes>2</normal-notes>
          </time-modification>
        <stem>up</stem>
        </note>
      <note>
        <pitch>
          <step>G</step>
          <octave>4</octave>
          </pitch>
        <duration>1</duration>
        <voice>1</voice>
        <type>eighth</type>
        <time-modification>
          <actual-notes>3</actual-notes>
          <normal-notes>2</normal-notes>
          </time-modification>
        <stem>up</stem>
        </note>

First part of the tuplet (3/2):

* Duration-2 + Divisions-3 => Real duration= 1/6

* Type: Quarter (1/4)

* Ratio: (1/4)/ (1/6) => (3/2)

Second part of the tuplet (3/2):

* Duration-1 + Divisions-3 => Real duration= 1/12

* Type: Eighth (1/8)

* Ratio: (1/8/ (1/12) => (3/2)

I always the same ratio in the first part of the tuplet and it's not complete. I am missing something and I would appreciate additional help, please.

What I try to explain here is that, INMO, every note within a triplet has the same ratio (between type and real duration) as the tuplet. Therefore it can't be used to determine when a Triplet ends (At least I haven't been able to). I would appreciate any additional comments or explanations, please

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Needs Review

Development

Successfully merging this pull request may close these issues.

Add support for nested tuplets in MusicXML

3 participants