Design & implementation
There are only a few documents regarding MuseScore internals, except of course the code and its comments.
Element classes hierarchy
Click on the image to download as PDF
Elements and score objects model
Click on the image to download as PDF.
A score is represented by a Score
object in memory. A Score
object can have a parent Score
if the score is an Excerpt
. An Excerpt
object is used to represent a part in part extraction. A Score also maintain a list of Excerpt
s if it has parts.
In a Score
, notes are stored in a list of Measure objects. Measure inherits from MeasureBase together with the frames. A Measure represents a measure across all the staves of a system, it's a "vertical column" of music. The Score
also stores the tempo change list (TempoMap
) and the time signature change list TimeSigMap
. A Score
object is complex, and has several states variables for layout, audio rendering. It also stores score metadata, style etc...
Layer
s in a Score
object are a way to hide or show some Element
according to the selected layer. A Score
stores a list of Layer
s.
Layout
Element positions
The screen position of a visible element is computed from three values:
AP |
Anchor position of element. This is usually the position of the parent element. |
LO |
Layout Offset, computed in the layout engine. MuseScore calculates it as the normal position of the element |
UO |
User Offset, created by dragging an element by the user |
The display position is computed as:Display Position = AP + LO + UO
The saved position in a MuseScore file is computed as:Saved Position = LO + UO
On read the saved position is written to the UserOffset (UO
). The LayoutOffset (LO
) is set to zero. On the first call of layout()
the values for UO
and LO
are reconstructed. The condition LO==0
is used to determine the first call to layout()
.
After first Layout the values are computed as (RP
= read position from file)
void Element::adjustReadPos() { if (RP != 0) { UO = RP – newLO; RP = 0; } }
As a consequence, if you are writing an import filter and want to override the automatic placement of elements on import, set Element->_readPos. After layout MuseScore will compute a proper userOffset out of it.
Older MuseScore versions (<= 0.9.6) do only save the UO value. If loaded with a different MuseScore version than created, the position of certain elements may differ, as the layout algorithm (and the LO
value) may have changed. This is avoided with the above scheme.
Caveats: adjustReadPos()
has to be applied after the first complete layout of an element. This also means that a second layout()
call should not change any element position. The layout has to be done in one pass.
Playback and synthesizers
msynth is a wrapper for Fluid and Zerberus.
Fluid is a SF2/SF3 soundfont synthesizer. The SF3 format is not a standard and use by MuseScore only. It's exactly like SF2 except the samples are encoded in OGG instead of WAV.
Zerberus is a SFZ synthesizer. It's mainly tested with the salamander piano SFZ. Any work to add support for more opcode is welcome.