Features Help Download

Lomse Hacking Guide

2.2. The internal representation

2.2.1. Overview

The internal model is an abstract representation for an LDP document, containing all necessary information to derive any other representation when needed. It is not oriented to any particular use (rendering, play back, printing, music analysis, ...) but try to serve all them equally. In this way the document can serve to the purpose of any view: a view can either be a print out of a conventional music score; or it can be a textual representation in LDP or any other language; or it can be a play back oriented representation, such a table of MIDI events; or any other representation for any purpose.

When a particular use is intended, the corresponding optimised representation is derived from the internal model. For instance, from InternalModel the following purpose dependent representations are currently derived by Lomse:

  • For interchange with other applications: LDP source code.
  • For rendering: the GraphicModel class.
  • For score playback: the SoundEventsTable class.

The internal representation or internal model is, basically, a tree of objects, derived from abstract class ImoObj. All these objects have ‘Imo’ as class prefix and are sometimes named in this document as IMOs: Internal Model Objects.

The root of the internal model tree is an object of class ImoDocument and represents the content of a LDP tag ‘lenmusdoc’, that is, a whole LDP document. The internal model tree follows, basically, the same structure than the LDP document. As LDP language describes content in a tree fashion (as XML does), the internal model mimics the LDP structure. For instance, the following LDP document:

(lenmusdoc (vers 0.0)
    (content
        (score (vers 1.6)
            (instrument
                (musicData
                    (clef G)
                    (key A)
                    (n a4 q)
                    (n c5  q)
                )
            )
        )
    )
)

will render the following score:

http://lenmus.org/mws/content/lenmus/lomsedocs/hacking/_images/document-example.png

Figure. A simple LDP document containing just one trivial score.

Internally, it will be represented as the following tree:

                ImoDocument
                    |
                ImoContent
                    |
                 ImoScore
                    |
               ImoInstrument
                    |
               ImoMusicData
                    |
   +-------------+--+----------+---------+
   |             |             |         |
ImoClef   ImoKeySignature   ImoNote   ImoNote

Even auxiliary data transfer objects, used only during model construction, derive from ImoObj. This is for uniform treatment in LDP compiler, resulting in a simpler design and better type checking. But there is practically no cost in deriving from ImoObj and it provides some benefits.

2.2.2. Music scores issues

For documents containing only texts and images, such as HTML pages, a tree representation (i.e. the DOM) is normally good enough for processing. But for music scores there are two main issues to take into account.

  1. Music has two dimensions, the horizontal one, the melody, and the vertical one, the harmony. When considering how to represent music, it is necessary to take into account that depending on the task to perform, music events (notes and rests) will have to be traversed following the music vertical dimension (time) or following the horizontal dimension (one voice after the other). Therefore the internal representation should be addecuate to facilitate both traversing needs.
  2. Texts are just a sequence of characters. But music scores are not just a sequence of musical symbols, because some notations creates relationships between other musical symbols. For instance, slurs, ties, dynamics wedges and many other notations create relationships between many notes a rests, sometimes in different staves and systems. As a consequece, a music score is better modelled by a lattice than by a tree.

To take these two issues into account in a pragmatic way, for music scores I added some additional information to the internal model tree:

  1. For music scores, the tree structure representing the score content is complemented with an auxiliary representation, the ColStaffObjs object. It is oriented to traverse scores by voice and by time position. It is described in section The staff objects collection.

  2. For music scores, IMOs representing relationships between other IMOs (i.e. ImoTie) have to be linked to the objects that form part of the relationship. But these relation objects can not be modelled as tree nodes as that would transform the tree in a network. For instance, the following score with two tied notes:

    (score (vers 1.6)
        (instrument
            (musicData
                (clef G)
                (key C)
                (n a4 q (tie 1 start))
                (n a4 q (tie 1 stop))
            )
        )
    )

    would create the following invalid tree:

                     ImoScore
                        |
                   ImoInstrument
                        |
                   ImoMusicData
                        |
       +-------------+--+----------+--------+
       |             |             |        |
    ImoClef   ImoKeySignature   ImoNote  ImoNote
                                   \        /
                                    \      /
                                     ImoTie

    For this reason, the notation object itself, ImoTie in previous example, is not included as part of the tree, but stored in a special container class. This is described in detail in section Auxiliary objects: classes ImoAuxObj and ImoRelObj.

2.2.3. Internal model objects hierarchy

The base class for internal model objects is ImoObj. From it, a hierachy of derived classes is created.

At the root of this hierarchy, ImoObj specializes in three main types:

  1. Temporay Data Transfer Objects used during model building (ImoDto), but never part of the final tree. They have ‘Dto’ suffix.
  2. No renderizable objects containing just properties or relationships (ImoSimpleObj).
  3. Objects describing the content of the document (ImoContentObj). They are renderizable and have properties.

Content objects (ImoContentObj) can be subdivided into two main groups (although no base class for them has been created): components, representing atomic objects and containers, that is objects that have components.

Specific objects for music score are divided into two main categories: staff objects and auxiliary objects. Staff objects represent the ‘main’ content of the music (basically notes, rests, clefs, key signatures and time signatures), that is, those objects that must me rendered on a staff and that are are positiones by time (music ‘events).

All other notations are considered auxiliary objects. In turn, there are two main types of auxiliary objects: those modelling a simple musical notation (i.e. a fermata, an accent, an attacehd text) and those modelling a relationship between objects (i.e. a tie, and slur, a dynamics wedge).

  • Simple auxiliary objects require only a parent; for instance, in a fermata, the owner is a note, a rest or a barline. Therefore, simple auxiliary objects are modelled by a single ImoAuxObj object and can be stored as tree nodes.
  • On the contrary, relationship objects need to be linked to all the objects that are part of the relationship. For instance in a tie, the two tied notes. Relations can not be modelled explicitly as a node linked by two or more nodes, as this would transform the tree in a network. For this reason, RelObjs are objects that never will be tree nodes; instead, these objects will be stored in a special container node (ImoAttachments) and treated as data inside this node, not as child nodes of it.

The following picture shows current hierarchy of objects. Those marked with ‘(A)’ are abstract classes. In some cases the equivalence to HTML tags is marked:

ImoObj (A) (type, id)
  |
  +-- ImoDto (A) () Data Transfer Objects (Dto suffix).  Temporay use
  |     |           during model building, but never part of the final
  |     |           tree (the internal model)
  |     |
  |     +-- ImoFontStyleDto
  |     +-- ImoColorDto
  |     +-- ImoBeamDto
  |     +-- ImoSlurDto
  |     +-- ImoTieDto
  |     +-- ImoTupletDto
  |     +-- ImoBorderDto - not used!!!!
  |     +-- ImoPointDto - not used!!!!
  |     +-- ImoSizeDto - not used!!!!
  |
  |
  +-- ImoSimpleObj (A) () No renderizable
  |     |                 They just contains other objects or properties
  |     |
  |     |  ___________________________________________________________
  |     |  === Value Objects to encapsulate data ==
  |     |     Some of them are stored as nodes in the tree; others,
  |     |     as member variables in other objects. Nevertheless,.
  |     |     all defined as tree nodes for uniform treatment.
  |     |
  |     +-- ImoBezierInfo -- data (*) in SlurData, TieData, TieDto, SlurDto
  |     +-- (ImoFiguredBassInfo)
  |     +-- (ImoFigBassIntervalInfo)
  |     +-- ImoInstrGroup -- data in ImoInstrument(*)
  |     +-- ImoLineStyle -- data in ImoTextBox, ImoLine(*)
  |     +-- ImoMidiInfo -- data in ImoInstrument
  |     +-- ImoPageInfo -- data in ImoDocument, ImoScore
  |     +-- ImoStaffInfo -- data in ImoInstrument(list)
  |     +-- ImoSystemInfo -- data in ImoScore
  |     +-- ImoTextInfo (string, style) -- data in ImoScoreText
  |     |
  |     |       // Nodes in tree
  |     |
  |     +-- ImoOptionInfo - node in ImoOptions
  |     +-- ImoParamInfo - node in ImoDynamics
  |     +-- ImoStyle - not node, but element in ImoStyles (std::map)
  |     |
  |     |  ___________________________________________________________
  |     |  === Value objects to contain relation data for a node =====
  |     |
  |     +-- ImoRelDataObj (A)
  |     |     +-- ImoBeamData
  |     |     +-- ImoSlurData
  |     |     +-- ImoTieData
  |     |     +-- ImoTupletData
  |     |
  |     |  ___________________________________________________________
  |     |  === Container objects; no additional properties ===========
  |     |
  |     +-- ImoCollection (A) () A node. Branches are the stored objs
  |     |     |
  |     |     +-- ImoMusicData    <staffobj>
  |     |     +-- ImoOptions      <option>
  |     |     +-- ImoInstruments  <instrument>
  |     |     +-- ImoInstrGroups  <instrgroup>
  |     |     +-- ImoAttachments  <auxobj>
  |     |
  |     +-- ImoRelations  <relobj> [a list to store relobjs]
  |     |
  |     +-- ImoContainerObj (A) ()
  |           |
  |           +-- ImoInstrument (... , [musicData])
  |
  |
  +---ImoContentObj (A) (style, id, location, visible, [attachments])
        |
        +-- ImoBoxLevelObj (A)
        |     |       Abstract class for all box-level objects
        |     |
        |     +-- ImoScore
        |     |
        |     +-- ImoBoxContainer (A)
        |     |     |       A box-level container for box-level objects. All
        |     |     |       ImoBoxContainer objects (except ImoContent and
        |     |     |       ImoDynamic) have a ImoContent object as container.
        |     |     |
        |     |     +-- ImoDocument [html/body]
        |     |     +-- ImoContent [div] - a generic box-level container
        |     |     |     +-- ImoDynamic [object]
        |     |     |
        |     |     +-- ImoMultiColumn - a container subdivided in columns
        |     |     +-- (ImoTable) [table]
        |     |     +-- ImoList [ol, ul]
        |     |
        |     +-- ImoBoxContent (A)
        |           |        A box-level container for inline-level objs.
        |           |
        |           +-- ImoParagraph [p]
        |           +-- ImoHeading [h1, h2, h3, h4, h5]
        |           +-- ImoListItem [li]
        |
        |
        +-- ImoInlineObj (A)
        |     |       Inline-level objects
        |     |
        |     |
        |     +-- ImoBoxInline (A) (size, content) - an abstract
        |     |     |        inline-level box container.
        |     |     |
        |     |     +-- ImoInlineWrapper [] - A generic inline-box container
        |     |     +-- ImoLink [a] - Anchor
        |     |
        |     +-- ImoButton [button] - a button
        |     +-- ImoControl (control) - A user defined GUI obj.
        |     |     +-- ImoScorePlayer - A control for managing score playback
        |     |
        |     +-- ImoTextItem [] - a piece of text with the same style
        |     +-- ImoImage [img] - Inline image
        |
        |
        +-- ImoScoreObj (A) (color) content for scores
              |
              +-- ImoStaffObj (A) (timePos, numStaff)
              |     |
              |     +-- ImoBarline
              |     +-- ImoClef
              |     +-- ImoKeySignature
              |     +-- ImoMetronomeMark
              |     +-- ImoTimeSignature
              |     +-- ImoGoBackFwd
              |     +-- ImoSystemBreak
              |     +-- ImoSpacer
              |     +-- ImoNoteRest (A) (noteType, dots, voice)
              |           +-- ImoNote
              |           +-- ImoRest
              |
              +-- ImoAuxObj (A) () Can go attached to any score object
              |     +-- ImoFermata
              |     +-- ImoBlock (A)
              |     |     +--- ImoTextBox (anchor line, paragraphs)
              |     |
              |     +-- ImoScoreLine
              |     +-- ImoScoreText (text-info)
              |           +-- ImoScoreTitle (h-align)
              |         ( +-- ImoInstrNameAbbrev )
              |
              +-- ImoRelObj (A)  Relates two or more StaffObjs
                    +-- ImoTie
                    +-- ImoBeam
                    +-- ImoChord
                    +-- ImoSlur
                    +-- ImoTuplet