Table of Contents

Class MusicNotation

Namespace
Celeritas.Core
Assembly
Celeritas.dll

Parser for musical notation (scientific pitch notation) Supports: C4, D#5, Bb3, etc.

public static class MusicNotation
Inheritance
MusicNotation
Inherited Members

Fields

RestPitch

Special pitch value indicating a rest (silence).

public const int RestPitch = -1

Field Value

int

Remarks

This value is reserved across the library: a note event carrying it is silence, not a note. Analysis ignores it — it contributes no pitch class, no onset and no duration — and the MIDI and MusicXML writers leave a gap where it falls rather than writing a note. Transpose(NoteBuffer, int) leaves it alone for the same reason.

Methods

FormatDuration(Rational, bool, bool)

Format duration to string

public static string FormatDuration(Rational duration, bool useDot = true, bool useLetters = false)

Parameters

duration Rational

Duration as Rational

useDot bool

Enable dotted note notation (e.g., 3/8 -> "4.")

useLetters bool

Use letter notation (q, h, e, w) instead of numbers

Returns

string

Formatted duration string

FormatNoteSequence(ReadOnlySpan<NoteEvent>, bool, bool, bool)

Format note sequence to string with chord grouping

public static string FormatNoteSequence(ReadOnlySpan<NoteEvent> sequence, bool useDot = true, bool useLetters = false, bool groupChords = true)

Parameters

sequence ReadOnlySpan<NoteEvent>

Sequence of note events

useDot bool

Enable dotted note notation

useLetters bool

Use letter notation (q, h, e, w) instead of numbers

groupChords bool

Group simultaneous notes as chords [C4 E4 G4]/4

Returns

string

Formatted sequence (e.g., "C4/4 [E4 G4]/4 R/2" or "C4:q [E4 G4]:q R:h")

FormatWithDirectives(ReadOnlySpan<NoteEvent>, ReadOnlySpan<NotationDirective>, bool, bool, bool)

Format notes and directives together in timeline order.

public static string FormatWithDirectives(ReadOnlySpan<NoteEvent> notes, ReadOnlySpan<NotationDirective> directives, bool useDot = true, bool useLetters = false, bool groupChords = true)

Parameters

notes ReadOnlySpan<NoteEvent>
directives ReadOnlySpan<NotationDirective>
useDot bool
useLetters bool
groupChords bool

Returns

string

Remarks

The notes go through the same voice separation as FormatNoteSequence(ReadOnlySpan<NoteEvent>, bool, bool, bool). This walked them as one melodic line instead, and so carried the three faults that method was rewritten to lose: a gap between notes vanished, notes struck together but held for different lengths became a succession, and so did overlapping notes. Half of a small set of test passages came back as different music, and none of them had a directive in it.

A directive is not a sound, so the notation has nowhere to put one but inside a voice. They ride in the first, whose cursor is the timeline's, and read back at the same times. Where a directive's time falls inside a note, the note is written as tied pieces with the directive between them; inside a rest, as two rests. Written at the next note boundary instead, as they were, directives read back later than they were given — in 2297 of 3000 random passages at least one moved. A chord in that voice gives way to a directive inside it, since the notation ties notes and not chords: one of its notes stays there, cut and tied, and the others move to a voice of their own.

With no notes at all, the directives are still written at their times, carried by rests: written bare, as they were, every one of them read back at time zero.

Exceptions

ArgumentNullException

An element of directives is null.

Parse(string, bool)

Parse music notation into note events. Supports: notes, chords, rests, ties, time signatures, measures, polyphony. Examples: "C4/4 E4/4 G4/2", "[C4 E4 G4]/4", "C4/4~ C4/4", "4/4: C4/4 E4/4 | G4/2"

public static NoteEvent[] Parse(string input, bool validateMeasures = false)

Parameters

input string

Music notation string

validateMeasures bool

Validate measure durations against time signature

Returns

NoteEvent[]

Array of note events with timing information

Exceptions

ArgumentNullException

input is null.

ArgumentException

input is not valid notation: a syntax error, an unknown pitch or duration, or a pitch outside the MIDI range 0-127.

ParseDuration(string)

Parse duration string. Supports: any note value written as its denominator — 1 (whole), 2 (half), 4 (quarter), 8, 16, 32, 64, and the tuplet values like 3, 6 and 12 w/whole, h/half, q/quarter, e/eighth, s/16th, t/32nd Dotted: 4. (dotted quarter = 3/8), 2. (dotted half = 3/4)

public static Rational ParseDuration(string duration)

Parameters

duration string

Returns

Rational

Remarks

The bare number is the same vocabulary the notation grammar accepts after the slash, so everything FormatDuration(Rational, bool, bool) writes for a duration of the form 1/n reads back here. It used to stop at 32 and reject the rest: a 64th note was written "64" and then refused, and so was every tuplet value the grammar reads happily inside a note.

Exceptions

ArgumentNullException

duration is null.

ArgumentException

duration is not a note value — including the "3/8" form, which names a duration the notation writes as a dotted note ("4.") rather than as a fraction.

ParseFull(string, bool)

Parse music notation into a full result: notes plus directives (tempo, dynamics, sections, parts) and the leading time signature. Use this when you need more than the note events Parse(string, bool) returns.

public static ParseResult ParseFull(string input, bool validateMeasures = false)

Parameters

input string

Music notation string

validateMeasures bool

Validate measure durations against time signature

Returns

ParseResult

The parsed notes together with directives and the leading time signature. Errors is always empty — a parse error throws instead.

Exceptions

ArgumentNullException

input is null.

ArgumentException

input is not valid notation: a syntax error, an unknown pitch or duration, or a pitch outside the MIDI range 0-127.

ParseKey(string)

Parse key signature from various formats Supports: "C", "Cm", "C minor", "c", "C#", "C# major", "Db minor" The whole string must be consumed: a pitch class, then at most one mode token. No token means major; the word forms "min"/"minor" and "maj"/"major" are case-insensitive and may follow a single space. A lone 'm'/'M' must attach directly to the pitch and is case-significant, so "Em" is E minor and "EM" is E major (changed in 0.10.0). Trailing text is rejected — "Gm7", "dorian" and "Cat" are all invalid.

public static KeySignature ParseKey(string keyString)

Parameters

keyString string

Returns

KeySignature

Exceptions

ArgumentNullException

keyString is null.

ArgumentException

keyString is blank or is not a key signature.

ParseNote(string)

Parse scientific pitch notation to MIDI pitch number Examples: "C4" -> 60, "A4" -> 69, "C#5" -> 73, "Db3" -> 49

public static int ParseNote(string notation)

Parameters

notation string

Returns

int

ToNotation(int, bool)

Convert MIDI pitch number to scientific notation Examples: 60 -> "C4", 69 -> "A4", 73 -> "C#5"

public static string ToNotation(int midiPitch, bool preferSharps = true)

Parameters

midiPitch int
preferSharps bool

Returns

string

TryParseNote(ReadOnlySpan<char>, out int)

Try-parse scientific pitch notation to MIDI pitch number. Accepts: MIDI numbers (0-127), C4, D#5, Db3, Bb3, and Unicode accidentals (♯, ♭).

public static bool TryParseNote(ReadOnlySpan<char> notation, out int midi)

Parameters

notation ReadOnlySpan<char>
midi int

Returns

bool