DTD for mdml

DTD for mdml

The document type description

1 Dec 2002 Here is the document type description for mdml. The current up to date version is always included in the Melys package.

     This is version 1.4.0 of the MDML specification.

     Copyright (C) 1998, 1999 Steve Ratcliffe <steve@parabola.demon.co.uk>

     MDML is an XML representation of musical data for sequencers and
     similar programs.
     It concentrates on midi at present, but it is intended to add
     audio events as well.


        Add the midi tag for the midi version such as GM, GS, XG.

        The 'division' entity is deprecated.  Instead there is a ppq
        attribute to tempomap.

        The attibute 'program' is added to 'track'

        The 'cue' element corrected to 'cuepoint'.  This was an
        error in the DTD.  The word 'cue' has never been recognised.

        Name added to partref. Omitted in error.

        Some extra track attributes added.
        Comments added.

<!ENTITY % old.compat 'IGNORE'>
<!ENTITY % strict     'INCLUDE'>

<!-- Often a reference to a part can be used as well as a part -->
<!ENTITY % part.types "part | partref">

<!-- The events that go into the tempo map -->
<!ENTITY % events.tempo "tempo | timesignature | keysignature | smpteoffset">

<!-- All the non text midi events -->
<!ENTITY % events.music "note | control | pitch | keytouch | pressure | sysex
        | program | sequence">

<!-- All the text midi events -->
<!ENTITY % events.text "copyright | lyric | text | trackname
        | marker | instrument | cuepoint">

<!ENTITY % events.track "%events.music; | %events.text;">

<!-- There are some attributes that are valid on almost every
     element.  They are optional and default to the previous value
     if not given
<!ENTITY % att.common
    "t        CDATA        #IMPLIED
     channel  CDATA        #IMPLIED
     selected (yes|no)     #IMPLIED

<!ELEMENT mdml (head, tempomap, track*)>

<![ %old.compat; [
    The old dtd had a timebase element here which was really
    associated with the tempomap.  This is now an attribute of
    the tempomap.

    The old format will still be recognised for some time.
    version, format, timebase,
    title?, author?, comment?, midi?)>
<![ %strict; [
    version, format,
    title?, author?, comment?, midi?)>

<!ELEMENT tempomap (%events.tempo;)* >
<!ATTLIST tempomap
    ppq         CDATA       #REQUIRED

<!-- Track is the basic subdivision of the music description.  Tracks
     can be Midi or (in future revisions) audio, video etc.
     They consist solely of other parts that hold the actual music

     Some of the attributes that need explination:
        program  - this is an 32 bit integer value that represents
                   an instrument.  There can be different methods
                   of encoding the program number.  The default and
                   only current method is based on the bank select
                   messages of Midi: MSB<<14 + LSB<<7 + PROG.
        volume   - Initial volume for this track range: 0 to 65536
        pan      - Pan position: -32768 fully left to 32768 fully right.

     The following should be ignored on read and not set on write
     except for the following purposes.
        mute     - This track is muted by the user.
        solo     - This track is set to solo by the user.
        solomute - Indicates that this track is muted due to solo
                   on another track.
        sololast - Can be ignored, indicates that this was the last track
                   to be set to solo.
<!ELEMENT track (%part.types;)*>
<!ATTLIST track
    duration    CDATA       #IMPLIED
    name        CDATA       #IMPLIED
    program     CDATA       #IMPLIED
    volume      CDATA       #IMPLIED
    pan         CDATA       #IMPLIED
    mute        (yes|no)    #IMPLIED
    solo        (yes|no)    #IMPLIED
    solomute    (yes|no)    #IMPLIED
    sololast    (yes|no)    #IMPLIED

<!-- The 'part' element is used for spitting up tracks.
     The ability to nest parts had been removed from the dtd, but as the
     code already allows it, then this has now been returned.

<!ELEMENT part ((%events.track;)* | take+ | (%part.types;)+)>
<!ATTLIST part
    duration    CDATA       #IMPLIED
    name        CDATA       #IMPLIED
    id          CDATA       #IMPLIED
    Will include:

<!-- A reference to another part.  The 'ref' attribute must be present
     and is the id of another part.  It is not an error if the part
     does not exist, although a applications may want to warn of the
     case in certain situations

     Notyet: The 'partref' can itself have a name and be refered to by others.
     (Question: is this really a good idea?)
<!ELEMENT partref EMPTY>
<!ATTLIST partref
    name        CDATA       #IMPLIED
    ref         CDATA       #REQUIRED

<!-- A 'take' is one of a set of alternatives.  Within any
     one part there may be a sequence of take elements.  Only
     one of these is active at a time and this can be indicated
     with the 'selected' attribute.  If none have the selected
     attribute then the first one should be considered active.
<!ELEMENT take (%events.track;)*>
<!ATTLIST take
    duration    CDATA       #IMPLIED
    name        CDATA       #IMPLIED

<!-- Elements found within the header -->

<!ELEMENT version  EMPTY> <!-- the version of mdml -->
<!ATTLIST version
    major          CDATA     #REQUIRED
    minor          CDATA     #REQUIRED

    This is only relevent to files that were imported from the Midi
    format, and it is the original format of the file.
<!ELEMENT format   EMPTY>
<!ATTLIST format
    type          (0|1|2)    #REQUIRED

<!ELEMENT timebase EMPTY> <!-- midi divisions -->
<!ATTLIST timebase
    division    CDATA   #REQUIRED

<!ELEMENT title   (#PCDATA)>

<!ELEMENT author  (#PCDATA)>

<!ELEMENT comment (#PCDATA)>

<!ELEMENT midi            EMPTY>
<!ATTLIST midi
    type  (NONE | GM | GS | XG) #REQUIRED

<!-- The tempo map elements, these are all empty -->
<!ELEMENT tempo           EMPTY>
<!ATTLIST tempo
    bpm       CDATA    #REQUIRED

    This signature attribute is represented as 4/4 7/6 etc.
<!ELEMENT timesignature   EMPTY>
<!ATTLIST timesignature
    signature   CDATA     #REQUIRED
    clocks      CDATA     #REQUIRED
    n32PerQuarter CDATA   #REQUIRED

    The key attribute is represented as a number.  Positive numbers
    are keys that contain sharps and negative numbers keys
    that contain flats.  So 7 is C# and -1 is F.
<!ELEMENT keysignature    EMPTY>
<!ATTLIST keysignature
    key         CDATA          #REQUIRED
    mode        (minor|major)  'major'

<!-- The text based midi elements -->
<!ELEMENT copyright (#PCDATA)>
<!ATTLIST copyright
<!ELEMENT lyric     (#PCDATA)>
<!ATTLIST lyric
<!ELEMENT text      (#PCDATA)>
<!ATTLIST text
<!ELEMENT trackname (#PCDATA)>
<!ATTLIST trackname
<!ELEMENT marker    (#PCDATA)>
<!ATTLIST marker
<!ELEMENT instrument (#PCDATA)>
<!ATTLIST instrument
<!ELEMENT cuepoint       (#PCDATA)>
<!ATTLIST cuepoint

<!-- ENTITY % events.music "note | control | pitch | keytouch | pressure | sysex
        | program | sequence"

<!-- This represents a note.  The names are kept short to keep the
     file size down.  (mail steve@parabola.demon.co.uk if you have
     opinions on this or a better way to represent notes and control
       n  is the note as a string  eg E5 or F#6 midi note zero is C0
       v  the velocity 0-127
       len the length in timebase units
       off the velocity of the note off event if not zero.
<!ELEMENT note     EMPTY>
<!ATTLIST note
    n           CDATA      #REQUIRED
    v           CDATA      #REQUIRED
    len         CDATA      #REQUIRED
    off         CDATA      #IMPLIED

<!-- Midi controlers at present the numeric values are used so you need
     to look them to work out what they do.  It all depends on what midi
     standard you are using anyway.
        n    controler number if not present defaults to previous
        v    the value
<!ELEMENT control  EMPTY>
<!ATTLIST control
    n          CDATA       #REQUIRED
    v          CDATA       #REQUIRED

    The pitch bend wheel, in midi it goes from 0 to 0x3fff with 0x2000
    being the central point of no pitch bend.  We do a signed offset
    from that mid point.
       p="0"        no pitch bend
       p="-12"      bending down a bit
       p="32"       bending up a bit
<!ELEMENT pitch    EMPTY>
<!ATTLIST pitch
    p          CDATA       #REQUIRED

<!ELEMENT keytouch EMPTY>
<!ATTLIST keytouch
    n            CDATA     #REQUIRED
    v            CDATA     #REQUIRED

<!ELEMENT pressure EMPTY>
<!ATTLIST pressure
    v            CDATA     #REQUIRED

    The data for the system exclusive event is represented
    by pairs of hex digits as the content of this element.
    Eg: <sysex>f0 7e 7f 09 01 f7</sysex>
<!ELEMENT sysex    (#PCDATA)>
<!ATTLIST sysex

<!-- The program selects the instrument patch to use.  It is higher
     level than in midi.  Midi has two bank select controlers that
     select a bank of instruments and a program change command that
     selects a patch number of 0-127 within a bank.  Here we just
     have a single number that gets converted into the required commands
     as appropriate
<!ELEMENT program  EMPTY>
<!ATTLIST program
    program        CDATA     #REQUIRED

<!ELEMENT sequence EMPTY>
<!ELEMENT smpteoffset EMPTY>

Example usage

Mdml file

Here is a very small example of a mdml file.

<?xml version="1.0"?>
    <version major="1" minor="0"/>
    <format type="1"/>
    <timebase division="192"/>
    <tempo t="0" channel="0" bpm="120.0"/>
    <timesignature t="0" signature="4/4" clocks="24" n32PerQuarter="8"/>
    <keysignature t="0" key="0"/>
  <track duration="2000">
    <part duration="1300">
      <copyright>Steve Ratcliffe, 1998</copyright>
      <trackname t="0" channel="0">Background bells</trackname>
      <sysex t="0">f0 7e 7f 9 1 f7</sysex>
      <program t="0" channel="1" program="14"/>
      <control t="0" n="11" v="119"/>
      <note t="0" n="B4" v="89" len="668"/>
      <note t="200" n="E6" v="60" len="65"/>
      <pitch t="240" p="-23"/>
      <note t="400" n="D4" v="56" len="50"/>
      <note t="20" n="D4" v="56" len="50"/>
        <note t="20" n="D4" v="56" len="50"/>
        <note t="20" n="D4" v="56" len="50"/>
      <part duration="0">
      <!-- Not yet implemented in melys
        <take selected="yes">
          <note t="20" n="D4" v="56" len="50"/>
          <note t="22" n="D#4" v="58" len="50"/>