Table of Contents

Class MusicXmlIo

Namespace
Celeritas.Core.Notation
Assembly
Celeritas.dll

Imports MusicXML into the engine's NoteBuffer / NoteEvent model.

This pass handles the common core of score-partwise: pitched notes (step/octave/alter), rests, chords (<chord/>), per-measure <divisions>, multiple measures, multiple parts (merged into one time line), <backup>/ <forward> cursor moves, and tie merging (a <tie> chain becomes one sustained note). Times are converted to the engine's whole-note units.

Multi-voice parts import correctly because voice timing rides on <backup>/ <forward>, and dynamics (<dynamics> marks and <sound dynamics>) set note velocity (and single-voice export writes velocity back as <sound dynamics>). Compressed .mxl archives are unwrapped and the score-timewise layout is transposed to partwise on import; grace notes are approximated as short notes at the following beat. Remaining boundaries: tuplet grouping metadata (<time-modification>) is ignored, though tuplet durations import exactly; and an <unpitched> note (a hit on a percussion staff) is not imported — it takes up its time and yields no note, since the engine holds pitches and a drum has none. Export bars the timeline into measures of the requested meter (4/4 unless one is given) and splits notes crossing a barline into tied segments.

Pitches are sounding pitches. A transposing instrument's part is written at written pitch and declares the difference in <attributes><transpose> (<chromatic> semitones plus <octave-change> octaves); import adds that offset to every note of the part from the point the element appears — per staff, when the element carries a number — so a B♭ clarinet's written D5 imports as the C5 it sounds. Export writes concert pitch and no <transpose>, since the buffer holds nothing else.

public static class MusicXmlIo
Inheritance
MusicXmlIo
Inherited Members

Remarks

Import used to ignore <transpose> and hand back the written pitch, so a clarinet part arrived a whole tone sharp and a horn part a fifth sharp, and every analysis downstream — key, chords, intervals against the other parts — read the wrong notes.

Methods

Export(NoteBuffer, Stream)

Writes a NoteBuffer as MusicXML (4/4) to a stream.

public static void Export(NoteBuffer buffer, Stream stream)

Parameters

buffer NoteBuffer
stream Stream

Exceptions

ArgumentNullException

buffer or stream is null.

ArgumentException

A note has a negative offset, which MusicXML cannot represent.

InvalidOperationException

The offsets and durations use denominators whose least common multiple overflows the 64-bit <divisions> value.

Export(NoteBuffer, Stream, TimeSignature)

Writes a NoteBuffer as MusicXML, barred into timeSignature, to a stream.

public static void Export(NoteBuffer buffer, Stream stream, TimeSignature timeSignature)

Parameters

buffer NoteBuffer
stream Stream
timeSignature TimeSignature

Exceptions

ArgumentNullException

buffer or stream is null.

ArgumentException

A note has a negative offset, which MusicXML cannot represent.

InvalidOperationException

The offsets and durations use denominators whose least common multiple overflows the 64-bit <divisions> value.

Export(NoteBuffer, string)

Writes a NoteBuffer as MusicXML (4/4) to path.

public static void Export(NoteBuffer buffer, string path)

Parameters

buffer NoteBuffer
path string

Exceptions

ArgumentNullException

buffer or path is null.

ArgumentException

A note has a negative offset, which MusicXML cannot represent.

InvalidOperationException

The offsets and durations use denominators whose least common multiple overflows the 64-bit <divisions> value.

Export(NoteBuffer, string, TimeSignature)

Writes a NoteBuffer as MusicXML, barred into timeSignature, to a file.

public static void Export(NoteBuffer buffer, string path, TimeSignature timeSignature)

Parameters

buffer NoteBuffer
path string
timeSignature TimeSignature

Exceptions

ArgumentNullException

buffer or path is null.

ArgumentException

A note has a negative offset, which MusicXML cannot represent.

InvalidOperationException

The offsets and durations use denominators whose least common multiple overflows the 64-bit <divisions> value.

Import(Stream)

Reads and imports MusicXML from a stream. Plain XML and compressed .mxl (a ZIP whose score is named by META-INF/container.xml) are both accepted, detected by content. Notes come back at sounding pitch: a part's <transpose> is applied on the way in. Unpitched (percussion) notes are not imported.

public static NoteBuffer Import(Stream stream)

Parameters

stream Stream

Returns

NoteBuffer

Remarks

An <unpitched> note — a hit on a percussion staff — is not imported: the engine holds pitches and a drum has none. It still takes up its time, so a pitched note after it in the same part stays on its beat, and the pitched parts of a score with a drum staff import as they would with that staff absent. Such a note used to be refused as having neither <pitch> nor <rest>, and a score with a drum part could not be imported at all.

Exceptions

ArgumentNullException

stream is null.

InvalidDataException

The document is not valid, importable MusicXML.

Import(string)

Reads and imports a MusicXML file from path. Notes come back at sounding pitch: a part's <transpose> is applied on the way in. Unpitched (percussion) notes are not imported.

public static NoteBuffer Import(string path)

Parameters

path string

Returns

NoteBuffer

Remarks

An <unpitched> note — a hit on a percussion staff — is not imported: the engine holds pitches and a drum has none. It still takes up its time, so a pitched note after it in the same part stays on its beat, and the pitched parts of a score with a drum staff import as they would with that staff absent. Such a note used to be refused as having neither <pitch> nor <rest>, and a score with a drum part could not be imported at all.

Exceptions

ArgumentNullException

path is null.

InvalidDataException

The document is not valid, importable MusicXML.

Parse(string)

Imports MusicXML held in a string. Notes come back at sounding pitch: a part's <transpose> is applied on the way in. Unpitched (percussion) notes are not imported.

public static NoteBuffer Parse(string xml)

Parameters

xml string

Returns

NoteBuffer

Remarks

An <unpitched> note — a hit on a percussion staff — is not imported: the engine holds pitches and a drum has none. It still takes up its time, so a pitched note after it in the same part stays on its beat, and the pitched parts of a score with a drum staff import as they would with that staff absent. Such a note used to be refused as having neither <pitch> nor <rest>, and a score with a drum part could not be imported at all.

Exceptions

ArgumentNullException

xml is null.

InvalidDataException

The document is not valid, importable MusicXML.

ToXml(NoteBuffer)

Serializes a NoteBuffer to a score-partwise MusicXML string, barred into 4/4 measures.

public static string ToXml(NoteBuffer buffer)

Parameters

buffer NoteBuffer

Returns

string

Remarks

Notes at the same onset and duration are written as a chord; gaps become rests; overlapping notes are split into separate voices (via <backup>). The timeline is divided into measures of the given meter, notes crossing a barline are split and tied, and pitches are spelled with sharps — so import → export → import round-trips.

Dynamics are deliberately exported for single-voice output only (a per-voice dynamic has no clean MusicXML representation in this writer), and a chord is written with its first note's velocity — chords are assumed dynamically uniform.

Exceptions

ArgumentNullException

buffer is null.

ArgumentException

A note has a negative offset, which MusicXML cannot represent.

InvalidOperationException

The offsets and durations use denominators whose least common multiple overflows the 64-bit <divisions> value.

ToXml(NoteBuffer, TimeSignature)

Serializes a NoteBuffer to a score-partwise MusicXML string, barred into 4/4 measures.

public static string ToXml(NoteBuffer buffer, TimeSignature timeSignature)

Parameters

buffer NoteBuffer

The notes to serialize.

timeSignature TimeSignature

The meter to bar the notes into.

Returns

string

Remarks

Notes at the same onset and duration are written as a chord; gaps become rests; overlapping notes are split into separate voices (via <backup>). The timeline is divided into measures of the given meter, notes crossing a barline are split and tied, and pitches are spelled with sharps — so import → export → import round-trips.

Dynamics are deliberately exported for single-voice output only (a per-voice dynamic has no clean MusicXML representation in this writer), and a chord is written with its first note's velocity — chords are assumed dynamically uniform.

Exceptions

ArgumentNullException

buffer is null.

ArgumentException

A note has a negative offset, which MusicXML cannot represent.

InvalidOperationException

The offsets and durations use denominators whose least common multiple overflows the 64-bit <divisions> value.

InvalidOperationException

The offsets and durations use denominators whose least common multiple overflows the 64-bit <divisions> value.