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. Changes 991123: Add the midi tag for the midi version such as GM, GS, XG. 991002: 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. 991005: Name added to partref. Omitted in error. 991019: 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. --> <!ELEMENT head (COPYRIGHT?, version, format, timebase, title?, author?, comment?, midi?)> ]]> <![ %strict; [ <!ELEMENT head (COPYRIGHT?, 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 events. 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 %att.common; 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 %att.common; duration CDATA #IMPLIED name CDATA #IMPLIED id CDATA #IMPLIED ><!-- Will include: transpose velocity.offset etc. --> <!-- 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 %att.common; 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 %att.common; duration CDATA #IMPLIED name CDATA #IMPLIED > <!-- Elements found within the header --> <!ELEMENT COPYRIGHT (#PCDATA)> <!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 %att.common; bpm CDATA #REQUIRED > <!-- This signature attribute is represented as 4/4 7/6 etc. --> <!ELEMENT timesignature EMPTY> <!ATTLIST timesignature %att.common; 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 %att.common; key CDATA #REQUIRED mode (minor|major) 'major' > <!-- The text based midi elements --> <!ELEMENT copyright (#PCDATA)> <!ATTLIST copyright %att.common;> <!ELEMENT lyric (#PCDATA)> <!ATTLIST lyric %att.common;> <!ELEMENT text (#PCDATA)> <!ATTLIST text %att.common;> <!ELEMENT trackname (#PCDATA)> <!ATTLIST trackname %att.common;> <!ELEMENT marker (#PCDATA)> <!ATTLIST marker %att.common;> <!ELEMENT instrument (#PCDATA)> <!ATTLIST instrument %att.common;> <!ELEMENT cuepoint (#PCDATA)> <!ATTLIST cuepoint %att.common;> <!-- 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 messages) 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 %att.common; 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 %att.common; 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 %att.common; p CDATA #REQUIRED > <!ELEMENT keytouch EMPTY> <!ATTLIST keytouch %att.common; n CDATA #REQUIRED v CDATA #REQUIRED > <!ELEMENT pressure EMPTY> <!ATTLIST pressure %att.common; 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 %att.common; > <!-- 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 %att.common; 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"?> <mdml> <head> <version major="1" minor="0"/> <format type="1"/> <timebase division="192"/> </head> <tempomap> <tempo t="0" channel="0" bpm="120.0"/> <timesignature t="0" signature="4/4" clocks="24" n32PerQuarter="8"/> <keysignature t="0" key="0"/> </tempomap> <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"/> <lyric>Word..</lyric> <pitch t="240" p="-23"/> <note t="400" n="D4" v="56" len="50"/> </part> </track> <track> <part> <note t="20" n="D4" v="56" len="50"/> </part> <part> <part> <note t="20" n="D4" v="56" len="50"/> </part> <part> <note t="20" n="D4" v="56" len="50"/> </part> <part duration="0"> <!-- Not yet implemented in melys <take selected="yes"> <note t="20" n="D4" v="56" len="50"/> </take> <take> <note t="22" n="D#4" v="58" len="50"/> </take> --> </part> </part> </track> </mdml>