The document type description

2 Apr 2017: 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>


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>



Copyright © Steve Ratcliffe 2008-2017.