Calculate accurate time value from tick count in a plugin?

• Dec 29, 2020 - 05:36

I am developing tools that help automate aspects of my workflow, which comprises arrangement in MuseScore and recording in other programs (currently Audition) with the MuseScore recording as a backing track. I am quite new to MuseScore plugin development, but a decently experienced programmer. In any case, this automation would ideally include creating markers at each rehearsal marking, but as Audition lacks a sufficient notion of tempo/measures for this job, that requires calculating a time for each rehearsal marking (note that many if not most pieces involve tempo changes, and I'd like the system to be robust in that respect).

Currently my thought process for how to do this (as of yet unimplemented) is to iterate through each Segment (https://musescore.github.io/MuseScore_PluginAPI_Docs/plugins/html/class… - linked in case I'm misunderstanding) and get the rehearsal marks from there. Then, I can get tick values for each rehearsal mark, which leaves only the conversion from tick to time. I googled around to see if this had been tackled before, but found only this (https://musescore.org/en/node/84886), which I can only assume is for either the 1.x/2.x interface or some form of internal development, as I can find no reference to it.

Unfortunately, all of this still leaves that conversion from tick to time. My only thought for how to do this is to walk the score with a Cursor (perhaps with some advance mode like these [https://musescore.github.io/MuseScore_PluginAPI_Docs/plugins/html/names…] that only advances to tempo changes?) and manually calculate the time-wise distance using ticks, the division setting, and that scraped tempo information.

However, this seems incredibly convoluted, so my question (and apologies for the bad forum practice, as this is somewhat of a "how-do-I-do-this" question) is if there's any better way to do this conversion? Or perhaps some way to avoid it entirely? MuseScore clearly calculates these things internally, such as in the play panel, so I'm hoping I've missed some easy solution.

Thanks in advance for any help!


Comments

I don't believe this information is currently available in any decent form to the plugin API. Doing it yourself will indeed mean duplicating a lot things already done internally.

A tick is the notation-based position of an element. It does not account for repeats, jumps, breath marks, section breaks or any other pauses. Nor does it account for tempo changes and time stretches (such as from a fermate).

Internally, there is a process that "unwinds" the score (processes all repeats/jumps), which results in uticks and creates a "tempomap" from it, where all tempo changes and pause events are collected. Combining uticks with the tempomap is what leads to the time information.

I realize that none of this offers an actual solution to your problem, but it might help you in understanding the code and what would be possibly involved in handling such a thing from within a plugin.

It may partially help to make use of time property of Cursor, so it should be possible to convert tick value to time with something like this:

cursor.rewindToTick(tick);
var time = cursor.time;

There is however no way to specify which repeat you are currently on so I guess that would return only time values from the first repeat of the corresponding section. But if a score has no repeats this should work, and if it has it still may make it easier to get the needed information.

In reply to by mirabilos

Looking at this with the object explorer, it’s not useful at all any more once a single repeat or jump is in the score. cursor.time literally goes linearly through the chordrests and maps their ticks to time using the tempo until then, so the time after the first repeat or jump is already off.

I think one has to implement all of RepeatList::unwind() in QML to get at this information then…

In reply to by Jojo-Schmitz

Yeah, @jeetee said so and that the scores list should make it possible for the plugin to find the unrolled score.

Some more challenges exist, but they’re probably doable, and thanks to you mentioning I should put startCmd/endCmd around my code, I can probably even do tmp changes to the score and undo them later. I will have to experiment…

Do you still have an unanswered question? Please log in first to post your question.