TuningXML, a new language for microtonal music – first draft

There are several file formats currently used for microtuning, which have been around for decades now. These are the scala format .scl and the VAZ Plus / AnaMark .tun format. Both of these are text files which are relatively easy to create using only a text editor, and are relatively easy to implement by any software developer who wants to support microtuning. A related Scala format is .kbm, which maps a .scl scale to MIDI notes.

So if these formats work fine and are being supported, why does the title of this post suggest a new format? Why fix what ain’t broken? I started this thread on the Tuning List beginning to address that question as the start of a dialog with the creators of the file formats cited above. I decided to go ahead and sketch out my idea of a new XML, which I am tentatively calling TuningXML (.tunxml extension?) and here I will outline what I have so far.

At this point I could provide an excruciatingly boring list of entities and attributes, but I’ll save that for later. Let’s start with some examples:

An example file here shows a 12ET scale, in “terse form”, using a minimum or required tags to do the job:

<!-- Default Scale Given in Cents, Terse Version -->

<Scale Units='Cents'>
     <Tone> 100 </Tone>
     <Tone> 200 </Tone>
     <Tone> 300 </Tone>
     <Tone> 400 </Tone>
     <Tone> 500 </Tone>
     <Tone> 600 </Tone>
     <Tone> 700 </Tone>
     <Tone> 800 </Tone>
     <Tone> 900 </Tone>
     <Tone> 1000 </Tone>
     <Tone> 1100 </Tone>
     <Tone> 1200 </Tone>
</Scale>

The same scale could be written including a tonic rather than an octave, as follows:

<!-- Default Scale Given in Cents, Terse Version -->

<Scale HasTonic='True' Format='Cents'>
     <Tone> 0 </Tone>
     <Tone> 100 </Tone>
     <Tone> 200 </Tone>
     <Tone> 300 </Tone>
     <Tone> 400 </Tone>
     <Tone> 500 </Tone>
     <Tone> 600 </Tone>
     <Tone> 700 </Tone>
     <Tone> 800 </Tone>
     <Tone> 900 </Tone>
     <Tone> 1000 </Tone>
     <Tone> 1100 </Tone>
</Scale>

Notice in the first example there is an attribute Units=’Cents’ and in the second it is Format=’Cents’; the idea is that these attributes are interchangeable, and I am allowing for many variations on names for different attributes; e.g. Units, Format, ToneUnits, and ToneFormat all mean the same thing. The Units or Format doesn’t have to be Cents; other formats are allowed (see below).

Here is a possible “verbose” version of the first version of the same scale, using a lot of optional tags:

<?xml version= "1.0"?>

<!-- Default Keyboard Scale Given in Cents, Verbose Version -->

<Scale Author='John Q. Public' Geography='United States'
     History='Known very early in Western history, used in
     inaccurate forms for lutes and other fixed pitch instruments
     since the 15th century, was advocated by some theorists but
     was almost always rejected by musicians because of its
     bad sounding thirds, but finally reached widespread adoption 
     in the late 19th century, although other fixed tunings 
     persisted well into the 20th century.' Description='Twelve 
     Tone Equal Temperament is a close approximation of 13-Tone 
     Pythagorean tuning where the a4 and d5 collapse into one 
     tone and the Pythagorean Comma of 23.4 cents is distributed 
     equally over 12 fifths, so that they are all about 2 cents 
     flat from their pure form 3/2.' IsEqual='True' 
     NonOctave='False' Period='2' Generator='2^(1/12)' 
     Type='Equal Division of the Octave' HasTonic='False' 
     TonicIsFixed='False' ToneFormat='Cents'>
     
     <!-- Tones below are defined as Intervals -->
     
     <Tone Index='0' Name='Minor Second' ID='m2' 
     Description='Also called HalfStep or Semitone, one cent
     more than 18/17 and 5 cents less than 17/16.'> 100 </Tone>
     
     <Tone Index='1' Name='Major Second' ID='M2'
     Description='Also called Wholestep or Whole Tone, 4 cents less
     then 9/8.'> 200 </Tone>
     
     <Tone Index='2' Name='Minor Third' ID='m3'
     Description='Not far from 19/16, this is a consonant sounding
     interval of 12ET.'> 300 </Tone>
     
     <Tone Index='3' Name='Major Third' ID='M3'
     Description='Close to the Pythagorean Ditone 81/64, this
     interval is the bane of 12ET, or its most audible feature,
     sometimes called "active thirds" because they cause rapid 
     beats.'> 400 </Tone>
     
     <Tone Index='4' Name='Perfect Fourth' ID='P4'
     Description='Two cents more than 4/3, the slow beating 
     is almost imperceptible in most cases.'> 500 </Tone>
     
     <Tone Index='5' Name='Tritone' ID='TT'
     Description='Known as "Diabolis en musicus", literally
     "The Devil In Music" this interval has a long history
     of being thought of as "defective", as it is in between
     the two most stable intervals after the Unison and the
     Octave, namely the Fourth and the Fifth. In 12ET it is
     either an Augmented Fourth or a Dimishied Fifth, though
     those intervals are not the same in the Pythagorean
     Intonation from which 12ET is derived.'> 600 </Tone>
     
     <Tone Index='6' Name='Perfect Fifth' ID='P5'
     Description='Two cents less than 3/2, the slow beating 
     is almost imperceptible in most cases.'> 700 </Tone>
     
     <Tone Index='7' Name='Minor Sixth' ID='m6'
     Description='The inversion of the Major Third, this
     interval does not beat as actively as its inversion, 
     so voicings using minor sixths usually sound more 
     consonant than those using Major Thirds. This interval
     has been determined by research to be the interval
     most commonly identified by musicians and non-musicians
     alike as the most expressive interval in music.'> 
     800 </Tone>
     
     <Tone Index='8' Name='Major Sixth' ID='M6'
     Description='The inversion of the Minor Third, this
     interval also usually has an "active" quality. For
     centuries it was recommended that composers avoid this 
     interval in vocal music, because it immediately invokes
     the problem of the Syntonic Comma and makes the tuning
     of the Major Second ambiguous (10/9 or 9/8 or in 
     between?) in a diatonic scale.'> 900 </Tone>
     
     <Tone Index='9' Name='Minor Seventh' ID='m7'
     Description='This is a highly controversial interval
     in Western harmonic theory, when it is included in
     addition to a third and fifth from a root, many
     theorists assert that the harmonic interval implied 
     is 7/4, which is a full 31 cents below the 12ET
     tone.'> 1000 </Tone>
     
     <Tone Index='10' Name='Major Seventh' ID='M7'
     Description='As the inversion of the Minor Second,
     This interval is also relatively close to a low
     harmonic interval, namely 17/9 minus one cent.'>
     1100 </Tone>
     
     <Tone Index='11' Name='Perfect Octave' ID='P8'
     Description='The octave, which has been indentified
     in virtually all cultures around the world as the
     interval of maximal similarity after the unison, but 
     the Octave is usually not tuned exactly as a doubling, 
     but for any number of reasons is rather usually tuned
     just a bit sharp.'> 1200 </Tone>
     
</Scale>

To map this scale to the keys of a MIDI keyboard (which is also the way a softsynth usually understands music data), I supply the NoteMap entity, which is based on Manuel Op de Coul’s .kbm format. First, a “super-terse” form:

<!-- Default Scale Note Mapping, Super-Terse Version -->

<NoteMap NoteCount='12' MapIndexZeroToNote='60'/>

… which could also be a bit more explicit, but still terse:

<!-- Default Scale Note Mapping, Terse Version -->

<NoteMap MapIndexZeroToNote='60'>
     <Map/>
     <Map/>
     <Map/>
     <Map/>
     <Map/>
     <Map/>
     <Map/>
     <Map/>
     <Map/>
     <Map/>
     <Map/>
     <Map/>
</NoteMap>

And here is a “verbose” version:

<!-- Default Scale Note Mapping, Verbose Version -->

<ReferenceTone Note='69' Frequency='440.0'/>

<NoteMap BottomNote='0' NoteSpan='12' Period='12' 
MapIndexZeroToNote='60' TopNote='127'>
     <Map Index='0' ToneIndex='0'/>
     <Map Index='1' ToneIndex='1'/>
     <Map Index='2' ToneIndex='2'/>
     <Map Index='3' ToneIndex='3'/>
     <Map Index='4' ToneIndex='4'/>
     <Map Index='5' ToneIndex='5'/>
     <Map Index='6' ToneIndex='6'/>
     <Map Index='7' ToneIndex='7'/>
     <Map Index='8' ToneIndex='8'/>
     <Map Index='9' ToneIndex='9'/>
     <Map Index='10' ToneIndex='10'/>
     <Map Index='11' ToneIndex='11'/>
</NoteMap>

So maybe you can see some the possibilities (and advantages, I hope) already. Now for the boring but necessary list of elements (tags) and attributes (parameters within tags), starting with a simple list of elements and attributes which are common to all elements: (descriptions follow below).

<ReferenceTone>
<Scale>
<Tone>
<NoteMap>
<Map>

     Attributes:     Name
                    ID
                    Description               
     Comment:     Common To All Elements
     Values:          any text
     Required:     no

And here are the elements with their additional attributes.

Element:      <ReferenceTone/>
Usage:           Define global reference frequency for all tones
Comment:     Can be overridden by ReferenceTone <Scale> attribute
Syntax:          <ReferenceTone attributes/>
Content:     empty
Default:     <ReferenceTone Note="69" Frequency="440.0"/>
Required:      no
Embedding:      forbidden
     
     Attribute:      Note
     Comment:     negative values or values > 127 are ignored
     Values:      numeric (0 ... 127)
     Default:     69
     Required:      no
     
     Attribute:      Hz or Hertz or Frequency or CPS 
                    or CyclesPerSecond
     Comment:     zero or negative values are replaced by default
     Values:      a positive number, integer or floating point, 
                    using comma or decimal point
     Default:     440.0
     Required:      no

     
Element:      <Scale> ... </Scale>
Usage:           Define global attributes for a group of pitches
Comment:     Based on the .scl and .tun file formats, by
               Manuel Op  de Coul and Mark Henning,
               respectively.
               http://www.xs4all.nl/~huygensf/scala/
               http://www.mark-henning.de/
Syntax:          <Scale attributes>content</Scale>
Content:     one or more <Tone> elements
Required:      no
Embedding:      forbidden

     Attributes: Author,
                    Geography,
                    History,
                    CreationDate or Date.
     Comment:     no impact on tuning; for database only
     Values:      any text
     Required:      no

     Attributes: IsNonOctave or NonOctave
     Comment:     no impact on tuning; for database only
     Values:      True or Yes, False or No
     Default:     False
     Required:      no

     Attributes: IsEqual or Equal
     Comment:     no impact on tuning; for database only
     Values:      True or Yes, False or No
     Default:     False
     Required:      no

     Attributes: Period
     Comment:     no impact on tuning; for database only
     Values:      same as <Tone> element content
     Default:     Empty
     Required:      no
     
     Attributes: Generator
     Comment:     no impact on tuning; for database only
     Values:      same as <Tone> element content
     Default:     Empty
     Required:      no

     Attributes: Class or Type
     Comment:     no impact on tuning; for database only
     Values:      any text
     Default:     Empty
     Required:      no

     Attribute:      HasTonic
     Comment:      Tells whether the scale contains the
                    tone 1/1 or not
     Values:      True or Yes, False or No
     Default:      False
     Required:     No
     
     Attribute:      TonicIsFixed
     Comment:      Tells whether the scale is giving fixed 
                    frequencies or not.
     Values:      True or Yes, False or No
     Default:      False
     Required:     No
     
     Attribute:      ToneFormat or Format or ToneUnits or Units
     Comment:      Gives a blanket for all tones in the scale, 
                    which can be overridden by individual tones.
     Values:      Hz or Hertz or Frequencies or Frequency or cps 
                    or CyclesPerSecond,
                    Cents or Cent,
                    FloatingPoint or Floating or Floats or Float or 
                    Decimals or Decimal,
                    Ratio or Slash or Interval or Colon
     Default:      Cents
     Required:     No
     

Element:      <Tone> ... </Tone>
Usage:           Define a tone of a scale
Syntax:          <Tone attributes>content</Tone>
Content:     numeric, allowing decimal-point(.) 
               comma-as-decimal-point(,) slash(/) colon(:)
Required:      no, but no tones results in no scale
Embedding:      allowed within <Scale> element
     
     Attribute:      Index
     Comment:      Tones can be given in the file in any order; 
                    this gives its ordinal position in the scale 
                    array. Not every tone has to be given. The 
                    highest index tells how many tones are in 
                    the scale. 
     Values:      integers
     Default:      If no index is provided, an index is given 
                    based on the location of the element within 
                    the <Scale> element.
     Required:     No     
     
     Attribute:      Format or Units
     Comment:      overrides ToneFormat or Format or ToneUnits 
                    or Units <Scale> attribute.
     Values:      Hz or Hertz or Frequencies or Frequency or cps 
                    or CyclesPerSecond,
                    Cents or Cent,
                    FloatingPoint or Floating or Floats or Float or 
                    Decimals or Decimal,
                    Ratio or Slash or Interval or Colon
     Default:      Cents
     Required:     No
     
     Attribute:      Note
     Comment:      maps the tone to a particular MIDI Note;
                    Can be overridden by <NoteMap> contents.
     Values:      numeric (0 ... 127)
     Default:      none
     Required:     No
     

Element:      <NoteMap> ... </NoteMap>
Usage:           Define how tones are mapped to MIDI Notes
               independent of the scale.
Comment:     Based on the Scala .kbm format by Manuel Op de Coul,
               http://www.xs4all.nl/~huygensf/scala/help.htm#mappings
Syntax:          <NoteMap attributes>content</NoteMap>
Content:     one or more <Map> elements
Required:      no
Embedding:      forbidden
     
     Attribute:      NoteCount
     Comment:      used for super-terse mapping when the contents 
                    are empty, this number of notes are mapped by
                    automatic indexing
     Values:      numeric (0 ... 127)
     Default:      none
     Required:     No
     
     Attribute:      BottomNote or Bottom or 
                    LowestNote or Lowest or
                    LowNote or Low or 
                    StartNote or Start or
                    FirstNote or First
     Comment:      the bottom MIDI note to be mapped
     Values:      numeric (0 ... 127)
     Default:      0
     Required:     No     

     Attribute:      Size or Span or NoteSpan
     Comment:      the pattern repeats after this many Notes
                    (greater than or equal to the number of tones
                    in the scale)
     Values:      numeric (0 ... 127)
     Default:      the number of embedded <Map> elements
     Required:     No
     
     Attribute:      PeriodNote or Period
     Comment:      the bottom MIDI note to be mapped
     Values:      numeric (0 ... 127)
     Default:      the number of embedded <Map> elements
     Required:     No
     
     Attribute:      TonicNote or Tonic or Do or Ut or
                    MapIndexZeroToNote or MapIndexZeroTo
     Comment:      <Map Index='0'> gets mapped to this MIDI Note.
     Values:      numeric (0 ... 127)
     Default:      0
     Required:     No
     
     Attribute:      TopNote or Top or
                    HighestNote or Highest or
                    EndNote or End or
                    LastNote or Last
     Comment:      the top MIDI note to be mapped
     Values:      numeric (0 ... 127)
     Default:      127
     Required:     No
     
Element:      <Map/>
Usage:           content of <NoteMap> referring to a Tone of a Scale.
Comment:     When left empty, the element is indexed and refers to
               a tone of its index.
Syntax:          <Map attributes/>
Content:     empty
Required:      No, but <NoteMap> should then use the NoteCount attribute
Embedding:      allowed within <NoteMap>
     
     Attribute:      Index 
     Comment:      Map elements can be given within a <NoteMap> 
                    in any order; the Index attribute gives an 
                    ordinal position in the NoteMap array. 
                    Not every Map has to be given. The 
                    highest index tells how many Tones of a
                    Scale are referred to by the NoteMap.
     Values:      numeric (0 ... n)
     Default:      0
     Required:     No
     
     Attribute:      Tone or ToneIndex 
     Comment:      the Index of a Tone of a Scale. If omitted,
                    the value is the same as the index of the 
                    Map element.
     Values:      numeric (0 ... n)
     Default:      0
     Required:     No
     

Well, that’s my first draft. Let me know what you think; if it seems obvious to you that I am making some mistakes and you would like to correct me, or if you have any suggestions or comments, please let me know. Please also note that comments cannot be posted on this blog, so I have copied this message as a forum post for discussion.

Thanks!

Comments are closed.