Midi Description of a scale's pattern as it ascends through an octave. This class describes the general behavior of a scale as it ascends from a tonic up to the next tonic. It is described in terms of semitones relative to the tonic; to apply it to a particular tonic, pass one of these to the constructor of . Constructs a scale pattern. The name of the scale pattern. The ascending pattern of the scale. See the property for a detailed description and requirements. This parameter is copied. name or ascent is null. ascent is invalid. ToString returns the pattern name. The pattern's name, such as "Major" or "Melodic Minor (ascending)". Equality operator does value equality. Inequality operator does value inequality. Value equality. Hash code. Returns true if ascent is valid. The name of the scale being described. The ascent of the scale. The ascent is expressed as a series of integers, each giving a semitone distance above the tonic. It must have at least two elements, start at zero (the tonic), be monotonically increasing, and stay below 12 (the next tonic above). The number of elements in the ascent tells us how many notes-per-octave in the scale. For example, a heptatonic scale will always have seven elements in the ascent. A scale based on a pattern and a tonic note. For our purposes, a scale is defined by a tonic and then the pattern that it uses to ascend up to the next tonic. The tonic is described with a because it is not specific to any one octave. The ascending pattern is provided by the class. This class comes with a collection of predefined patterns, such as and . Constructs a scale from its tonic and its pattern. The tonic note. The scale pattern. tonic or pattern is null. Returns true if pitch is in this scale. The pitch to test. True if pitch is in this scale. Returns the scale degree of the given pitch in this scale. The pitch to test. The scale degree of pitch in this scale, where 1 is the tonic. Returns -1 if pitch is not in this scale. Pattern for Major scales. Pattern for Natural Minor scales. Pattern for Harmonic Minor scales. Pattern for Melodic Minor scale as it ascends. Pattern for Melodic Minor scale as it descends. Pattern for Chromatic scales. Array of all the built-in scale patterns. ToString returns the scale's human-readable name. The scale's name, such as "G# Major" or "Eb Melodic Minor (ascending)". Equality operator does value equality because Scale is immutable. Inequality operator does value inequality because Chord is immutable. Value equality. Hash code. Builds a scale. The tonic. The scale pattern. Must have 12 elements, and is filled with the 0-indexed scale position (or -1) for each position in the octave. Must have pattern.Ascent.Length elements, and is filled with the notes for each scale degree. Filled with the total number of accidentals in the built scale. The tonic of this scale. The pattern of this scale. The sequence of notes in this scale. This sequence begins at the tonic and ascends, stopping before the next tonic. Base class for all MIDI messages. Protected constructor. The timestamp for this message. Sends this message immediately. Returns a copy of this message, shifted in time by the specified amount. Milliseconds since the music started. Base class for messages relevant to a specific device. Protected constructor. The device from which this message originated, or for which it is destined. Base class for messages relevant to a specific device channel. Protected constructor. Channel. Base class for messages relevant to a specific note. Protected constructor. The pitch for this note message. Velocity, 0..127. Note On message. Constructs a Note On message. The device associated with this message. Channel, 0..15, 10 reserved for percussion. The pitch for this note message. Velocity, 0..127. The timestamp for this message. Sends this message immediately. Returns a copy of this message, shifted in time by the specified amount. Percussion message. A percussion message is simply shorthand for sending a Note On message to Channel10 with a percussion-specific note. This message can be sent to an OutputDevice but will be received by an InputDevice as a NoteOn message. Constructs a Percussion message. The device associated with this message. Percussion. Velocity, 0..127. The timestamp for this message. Sends this message immediately. Returns a copy of this message, shifted in time by the specified amount. Percussion. Velocity, 0..127. Note Off message. Constructs a Note Off message. The device associated with this message. Channel, 0..15, 10 reserved for percussion. The pitch for this note message. Velocity, 0..127. The timestamp for this message. Sends this message immediately. Returns a copy of this message, shifted in time by the specified amount. A Note On message which schedules its own Note Off message when played. Constructs a Note On/Off message. The device associated with this message. Channel, 0..15, 10 reserved for percussion. The pitch for this note message. Velocity, 0..127. The timestamp for this message. The clock that should schedule the off message. Time delay between on message and off messasge. Sends this message immediately. Returns a copy of this message, shifted in time by the specified amount. The clock used to schedule the follow-up message. Time delay between the Note On and the Note Off. Control change message. Construts a Control Change message. The device associated with this message. Channel, 0..15, 10 reserved for percussion. Control, 0..119 Value, 0..127. The timestamp for this message. Sends this message immediately. Returns a copy of this message, shifted in time by the specified amount. The control for this message. Value, 0..127. Pitch Bend message. Constructs a Pitch Bend message. The device associated with this message. Channel, 0..15, 10 reserved for percussion. Pitch bend value, 0..16383, 8192 is centered. The timestamp for this message. Sends this message immediately. Returns a copy of this message, shifted in time by the specified amount. Pitch bend value, 0..16383, 8192 is centered. Program Change message. Constructs a Program Change message. The device associated with this message. Channel. Instrument. The timestamp for this message. Sends this message immediately. Returns a copy of this message, shifted in time by the specified amount. Instrument. Pseudo-MIDI message used to arrange for a callback at a certain time. This message can be scheduled with Clock.Schedule just like any other message. When its time comes and it gets "sent", it invokes the callback provided in the constructor. The idea is that you can embed callback points into the music you've scheduled, so that (if the clock gets to that point in the music) your code has an opportunity for some additional processing. The callback is invoked on the MidiOutputDevice's worker thread. Constructs a Callback message. The callback to invoke when this message is "sent". The timestamp for this message. Sends this message immediately, ignoring the beatTime. Returns a copy of this message, shifted in time by the specified amount. The callback to invoke when this message is "sent". Delegate called when a CallbackMessage is sent. The time at which this event was scheduled. Additional messages which should be scheduled as a result of this callback, or null. Common base class for input and output devices. This base class exists mainly so that input and output devices can both go into the same kinds of MidiMessages. Protected constructor. The name of this device. The name of this device. Exception thrown when an operation on a MIDI device cannot be satisfied. Constructs exception with a specific error message. Description of a chord's pattern starting at the root note. This class describes the ascending sequence of notes included in a chord, starting with the root note. It is described in terms of semitones relative to root and letters relative to the root. To apply it to particular tonic, pass one of these to the constructor of . Constructs a chord pattern. The name of the chord pattern. The abbreviation for the chord. See the property for details. Array encoding the notes in the chord. See the property for details. Array encoding the sequence of letters in the chord. Must be the same length as ascent. See the property for details. ascent or letterOffsets is invalid, or they have different lengths. an argument is null. ToString returns the pattern name. The pattern's name, such as "Major" or "Minor". Equality operator does value equality. Inequality operator does value inequality. Value equality. Hash code. Returns true if sequence has at least two elements, starts at zero, and is monotonically increasing. The name of the chord pattern. Abbreviation for this chord pattern. This is the string used in the abbreviated name for a chord, placed immediately after the tonic and before the slashed inversion (if there is one). For example, for minor chords the abbreviation is "m", as in "Am". The ascending note sequence of the chord, in semitones-above-the-root. This sequence starts at zero (for the root) and is monotonically increasing, each element representing a pitch in semitones above the root. The sequence of letters in the chord. This array describes what sequence of letters appears in this chord. Each element is a "letter offset", a positive integer that tell you how many letters to move up from the root for that note. It must start at zero, representing the letter for the root note. A chord. A chord is defined by its root note, the sequence of semitones, the sequence of letters, and the inversion. The root note is described with a because we want to be able to talk about the chord independent of any one octave. The pattern of semitones and letters is given by the nested class. The inversion is an integer indicating how many rotations the pattern has undergone. This class comes with a collection of predefined chord patterns, such as and . Constructs a chord from its root note, pattern, and inversion. The root note of the chord. The chord pattern. The inversion, in [0..N-1] where N is the number of notes in pattern. pattern is null. inversion is out of range. Constructs a chord from a string. The name to parse. This is the same format as the Name property: a letter in ['A'..'G'], an optional series of accidentals (#'s or b's), then an optional inversion specified as a '/' followed by another note name. If the inversion is present it must be one of the notes in the chord. name is null. cannot parse a chord from name. Returns a list of chords which match the set of input pitches. Notes being analyzed. A (possibly empty) list of chords. Returns true if this chord contains the specified pitch. The pitch to test. True if this chord contains the pitch. Pattern for Major chords. Pattern for Minor chords. Pattern for Seventh chords. Pattern for Augmented chords. Pattern for Diminished chords. Array of all the built-in chord patterns. ToString returns the chord name. The chord's name. Equality operator does value equality because Chord is immutable. Inequality operator does value inequality because Chord is immutable. Value equality. Hash code. Fills dest with a rotated version of source. The source array. The dest array, which must have the same length and underlying type as source. The number of elements to rotate to the left by. The name of this chord. The root note of this chord. The bass note of this chord. The pattern of this chord. The inversion of this chord. The sequence of notes in this chord. General MIDI instrument, used in Program Change messages. The MIDI protocol defines a Program Change message, which can be used to switch a device among "presets". The General MIDI specification further standardizes those presets into the specific instruments in this enum. General-MIDI-compliant devices will have these particular instruments; non-GM devices may have other instruments. MIDI instruments are one-indexed in the spec, but they're zero-indexed in code, so we have them zero-indexed here. This enum has extension methods, such as and , defined in . General MIDI instrument 0 ("Acoustic Grand Piano"). General MIDI instrument 1 ("Bright Acoustic Piano"). General MIDI instrument 2 ("Electric Grand Piano"). General MIDI instrument 3 ("Honky Tonk Piano"). General MIDI instrument 4 ("Electric Piano 1"). General MIDI instrument 5 ("Electric Piano 2"). General MIDI instrument 6 ("Harpsichord"). General MIDI instrument 7 ("Clavinet"). General MIDI instrument 8 ("Celesta"). General MIDI instrument 9 ("Glockenspiel"). General MIDI instrument 10 ("Music Box"). General MIDI instrument 11 ("Vibraphone"). General MIDI instrument 12 ("Marimba"). General MIDI instrument 13 ("Xylophone"). General MIDI instrument 14 ("Tubular Bells"). General MIDI instrument 15 ("Dulcimer"). General MIDI instrument 16 ("Drawbar Organ"). General MIDI instrument 17 ("Percussive Organ"). General MIDI instrument 18 ("Rock Organ"). General MIDI instrument 19 ("Church Organ"). General MIDI instrument 20 ("Reed Organ"). General MIDI instrument 21 ("Accordion"). General MIDI instrument 22 ("Harmonica"). General MIDI instrument 23 ("Tango Accordion"). General MIDI instrument 24 ("Acoustic Guitar (nylon)"). General MIDI instrument 25 ("Acoustic Guitar (steel)"). General MIDI instrument 26 ("Electric Guitar (jazz)"). General MIDI instrument 27 ("Electric Guitar (clean)"). General MIDI instrument 28 ("Electric Guitar (muted)"). General MIDI instrument 29 ("Overdriven Guitar"). General MIDI instrument 30 ("Distortion Guitar"). General MIDI instrument 31 ("Guitar Harmonics"). General MIDI instrument 32 ("Acoustic Bass"). General MIDI instrument 33 ("Electric Bass (finger)"). General MIDI instrument 34 ("Electric Bass (pick)"). General MIDI instrument 35 ("Fretless Bass"). General MIDI instrument 36 ("Slap Bass 1"). General MIDI instrument 37 ("Slap Bass 2"). General MIDI instrument 38 ("Synth Bass 1"). General MIDI instrument 39("Synth Bass 2"). General MIDI instrument 40 ("Violin"). General MIDI instrument 41 ("Viola"). General MIDI instrument 42 ("Cello"). General MIDI instrument 43 ("Contrabass"). General MIDI instrument 44 ("Tremolo Strings"). General MIDI instrument 45 ("Pizzicato Strings"). General MIDI instrument 46 ("Orchestral Harp"). General MIDI instrument 47 ("Timpani"). General MIDI instrument 48 ("String Ensemble 1"). General MIDI instrument 49 ("String Ensemble 2"). General MIDI instrument 50 ("Synth Strings 1"). General MIDI instrument 51 ("Synth Strings 2"). General MIDI instrument 52 ("Choir Aahs"). General MIDI instrument 53 ("Voice oohs"). General MIDI instrument 54 ("Synth Voice"). General MIDI instrument 55 ("Orchestra Hit"). General MIDI instrument 56 ("Trumpet"). General MIDI instrument 57 ("Trombone"). General MIDI instrument 58 ("Tuba"). General MIDI instrument 59 ("Muted Trumpet"). General MIDI instrument 60 ("French Horn"). General MIDI instrument 61 ("Brass Section"). General MIDI instrument 62 ("Synth Brass 1"). General MIDI instrument 63 ("Synth Brass 2"). General MIDI instrument 64 ("Soprano Sax"). General MIDI instrument 65 ("Alto Sax"). General MIDI instrument 66 ("Tenor Sax"). General MIDI instrument 67 ("Baritone Sax"). General MIDI instrument 68 ("Oboe"). General MIDI instrument 69 ("English Horn"). General MIDI instrument 70 ("Bassoon"). General MIDI instrument 71 ("Clarinet"). General MIDI instrument 72 ("Piccolo"). General MIDI instrument 73 ("Flute"). General MIDI instrument 74 ("Recorder"). General MIDI instrument 75 ("PanFlute"). General MIDI instrument 76 ("Blown Bottle"). General MIDI instrument 77 ("Shakuhachi"). General MIDI instrument 78 ("Whistle"). General MIDI instrument 79 ("Ocarina"). General MIDI instrument 80 ("Lead 1 (square)"). General MIDI instrument 81 ("Lead 2 (sawtooth)"). General MIDI instrument 82 ("Lead 3 (calliope)"). General MIDI instrument 83 ("Lead 4 (chiff)"). General MIDI instrument 84 ("Lead 5 (charang)"). General MIDI instrument 85 ("Lead 6 (voice)"). General MIDI instrument 86 ("Lead 7 (fifths)"). General MIDI instrument 87 ("Lead 8 (bass + lead)"). General MIDI instrument 88 ("Pad 1 (new age)"). General MIDI instrument 89 ("Pad 2 (warm)"). General MIDI instrument 90 ("Pad 3 (polysynth)"). General MIDI instrument 91 ("Pad 4 (choir)"). General MIDI instrument 92 ("Pad 5 (bowed)"). General MIDI instrument 93 ("Pad 6 (metallic)"). General MIDI instrument 94 ("Pad 7 (halo)"). General MIDI instrument 95 ("Pad 8 (sweep)"). General MIDI instrument 96 ("FX 1 (rain)"). General MIDI instrument 97 ("FX 2 (soundtrack)"). General MIDI instrument 98 ("FX 3 (crystal)"). General MIDI instrument 99 ("FX 4 (atmosphere)"). General MIDI instrument 100 ("FX 5 (brightness)"). General MIDI instrument 101 ("FX 6 (goblins)"). General MIDI instrument 102 ("FX 7 (echoes)"). General MIDI instrument 103 ("FX 8 (sci-fi)"). General MIDI instrument 104 ("Sitar"). General MIDI instrument 105 ("Banjo"). General MIDI instrument 106 ("Shamisen"). General MIDI instrument 107 ("Koto"). General MIDI instrument 108 ("Kalimba"). General MIDI instrument 109 ("Bagpipe"). General MIDI instrument 110 ("Fiddle"). General MIDI instrument 111 ("Shanai"). General MIDI instrument 112 ("Tinkle Bell"). General MIDI instrument 113 (Agogo""). General MIDI instrument 114 ("Steel Drums"). General MIDI instrument 115 ("Woodblock"). General MIDI instrument 116 ("Taiko Drum"). General MIDI instrument 117 ("Melodic Tom"). General MIDI instrument 118 ("Synth Drum"). General MIDI instrument 119 ("Reverse Cymbal"). General MIDI instrument 120 ("Guitar Fret Noise"). General MIDI instrument 121 ("Breath Noise"). General MIDI instrument 122 ("Seashore"). General MIDI instrument 123 ("Bird Tweet"). General MIDI instrument 124 ("Telephone Ring"). General MIDI instrument 125 ("Helicopter"). General MIDI instrument 126 ("Applause"). General MIDI instrument 127 ("Gunshot"). Extension methods for the Instrument enum. Returns true if the specified instrument is valid. The instrument to test. Throws an exception if instrument is not valid. The instrument to validate. The instrument is out-of-range. General Midi instrument names, used by GetInstrumentName(). Returns the human-readable name of a MIDI instrument. The instrument. The instrument is out-of-range. Utility functions for encoding and decoding short messages. Returns true if the given short message describes a Note On message. The dwParam1 arg passed to MidiInProc. The dwParam2 arg passed to MidiInProc. Decodes a Note On short message. The dwParam1 arg passed to MidiInProc. The dwParam2 arg passed to MidiInProc. Filled in with the channel. Filled in with the pitch. Filled in with the velocity, 0.127 Filled in with the timestamp in microseconds since midiInStart(). Encodes a Note On short message. The channel. The pitch. The velocity 0..127. A value that can be passed to midiOutShortMsg. pitch is not in MIDI range. Returns true if the given short message describes a Note Off message. The dwParam1 arg passed to MidiInProc. The dwParam2 arg passed to MidiInProc. Decodes a Note Off short message. The dwParam1 arg passed to MidiInProc. The dwParam2 arg passed to MidiInProc. Filled in with the channel. Filled in with the pitch. Filled in with the velocity, 0.127 Filled in with the timestamp in microseconds since midiInStart(). Encodes a Note Off short message. The channel. The pitch. The velocity 0..127. A value that can be passed to midiOutShortMsg. Returns true if the given short message describes a Control Change message. The dwParam1 arg passed to MidiInProc. The dwParam2 arg passed to MidiInProc. Decodes a Control Change short message. The dwParam1 arg passed to MidiInProc. The dwParam2 arg passed to MidiInProc. Filled in with the channel. Filled in with the control. Filled in with the value, 0-127. Filled in with the timestamp in microseconds since midiInStart(). Encodes a Control Change short message. The channel. The control. The new value 0..127. A value that can be passed to midiOutShortMsg. Returns true if the given short message a Program Change message. The dwParam1 arg passed to MidiInProc. The dwParam2 arg passed to MidiInProc. Decodes a Program Change short message. The dwParam1 arg passed to MidiInProc. The dwParam2 arg passed to MidiInProc. Filled in with the channel, 0-15. Filled in with the instrument, 0-127 Filled in with the timestamp in microseconds since midiInStart(). Encodes a Program Change short message. The channel. The instrument. A value that can be passed to midiOutShortMsg. Returns true if the given MidiInProc params describe a Pitch Bend message. The dwParam1 arg passed to MidiInProc. The dwParam2 arg passed to MidiInProc. Decodes a Pitch Bend message based on MidiInProc params. The dwParam1 arg passed to MidiInProc. The dwParam2 arg passed to MidiInProc. Filled in with the channel, 0-15. Filled in with the pitch bend value, 0..16383, 8192 is centered. Filled in with the timestamp in microseconds since midiInStart(). Encodes a Pitch Bend short message. The channel. The pitch bend value, 0..16383, 8192 is centered. A value that can be passed to midiOutShortMsg. Pitches supported by MIDI. MIDI defines 127 distinct pitches, in semitone intervals, ranging from C five octaves below middle C, up to G five octaves above middle C. This covers several octaves above and below the range of a normal 88-key piano. These 127 pitches are the only ones directly expressible in MIDI. Precise variations in frequency can be achieved with Pitch Bend messages, though Pitch Bend messages apply to the whole channel at once. In this enum, pitches are given C Major note names (eg "F", "GSharp") followed by the octave number. Octaves use standard piano terminology: Middle C is in octave 4. (Note that this is different from "MIDI octaves", which have Middle C in octave 0.) This enum has extension methods, such as and , defined in . C in octave -1. C# in octave -1. D in octave -1. D# in octave -1. E in octave -1. F in octave -1. F# in octave -1. G in octave -1. G# in octave -1. A in octave -1. A# in octave -1. B in octave -1. C in octave 0. C# in octave 0. D in octave 0. D# in octave 0. E in octave 0. F in octave 0. F# in octave 0. G in octave 0. G# in octave 0. A in octave 0. A# in octave 0, usually the lowest key on an 88-key keyboard. B in octave 0. C in octave 1. C# in octave 1. D in octave 1. D# in octave 1. E in octave 1. F in octave 1. F# in octave 1. G in octave 1. G# in octave 1. A in octave 1. A# in octave 1. B in octave 1. C in octave 2. C# in octave 2. D in octave 2. D# in octave 2. E in octave 2. F in octave 2. F# in octave 2. G in octave 2. G# in octave 2. A in octave 2. A# in octave 2. B in octave 2. C in octave 3. C# in octave 3. D in octave 3. D# in octave 3. E in octave 3. F in octave 3. F# in octave 3. G in octave 3. G# in octave 3. A in octave 3. A# in octave 3. B in octave 3. C in octave 4, also known as Middle C. C# in octave 4. D in octave 4. D# in octave 4. E in octave 4. F in octave 4. F# in octave 4. G in octave 4. G# in octave 4. A in octave 4. A# in octave 4. B in octave 4. C in octave 5. C# in octave 5. D in octave 5. D# in octave 5. E in octave 5. F in octave 5. F# in octave 5. G in octave 5. G# in octave 5. A in octave 5. A# in octave 5. B in octave 5. C in octave 6. C# in octave 6. D in octave 6. D# in octave 6. E in octave 6. F in octave 6. F# in octave 6. G in octave 6. G# in octave 6. A in octave 6. A# in octave 6. B in octave 6. C in octave 7. C# in octave 7. D in octave 7. D# in octave 7. E in octave 7. F in octave 7. F# in octave 7. G in octave 7. G# in octave 7. A in octave 7. A# in octave 7. B in octave 7. C in octave 8, usually the highest key on an 88-key keyboard. C# in octave 8. D in octave 8. D# in octave 8. E in octave 8. F in octave 8. F# in octave 8. G in octave 8. G# in octave 8. A in octave 8. A# in octave 8. B in octave 8. C in octave 9. C# in octave 9. D in octave 9. D# in octave 9. E in octave 9. F in octave 9. F# in octave 9. G in octave 9. Extension methods for the Pitch enum. Returns true if pitch is in the MIDI range [1..127]. The pitch to test. True if the pitch is in [0..127]. Returns the octave containing this pitch. The pitch. The octave, where octaves begin at each C, and Middle C is the first pitch in octave 4. Returns the position of this pitch in its octave. The pitch. The pitch's position in its octave, where octaves start at each C, so C's position is 0, C#'s position is 1, etc. Maps PositionInOctave() to a Note preferring sharps. Maps PositionInOctave() to a Note preferring flats. Returns the simplest note that resolves to this pitch, preferring sharps where needed. The pitch. The simplest note for that pitch. If that pitch is a "white key", the note is simply a letter with no accidentals (and is the same as ). Otherwise the note has a sharp. Returns the simplest note that resolves to this pitch, preferring flats where needed. The pitch. The simplest note for that pitch. If that pitch is a "white key", the note is simply a letter with no accidentals (and is the same as ). Otherwise the note has a flat. Returns the note that would name this pitch if it used the given letter. The pitch being named. The letter to use in the name, in ['A'..'G']. The note for pitch with letter. The result may have a large number of accidentals if pitch is not easily named by letter. letter is out of range. A time-sorted queue of MIDI messages. Messages can be added in any order, and can be popped off in timestamp order. Constructs an empty message queue. Adds a message to the queue. The message to add to the queue. The message must have a valid timestamp (not MidiMessage.Now), but other than that there is no restriction on the timestamp. For example, it is legal to add a message with a timestamp earlier than some other message which was previously removed from the queue. Such a message would become the new "earliest" message, and so would be be the first message returned by PopEarliest(). Discards all messages in the queue. Removes and returns the message(s) in the queue that have the earliest timestamp. True if the queue is empty. The timestamp of the earliest messsage(s) in the queue. Throws an exception if the queue is empty. General MIDI percussion note. In General MIDI, notes played on make the following percussion sounds, regardless of any Program Change messages on that channel. This enum is used with OutputDevice.SendPercussion and . Equivalently, when cast to it can be used with OutputDevice.SendNoteOn and on . This enum has extension methods, such as and , defined in . General MIDI percussion 35 ("Bass Drum 2"). General MIDI percussion 36 ("Bass Drum 1"). General MIDI percussion 37 ("Side Stick"). General MIDI percussion 38 ("Snare Drum 1"). General MIDI percussion 39 ("Hand Clap"). General MIDI percussion 40 ("Snare Drum 2"). General MIDI percussion 41 ("Low Tom 2"). General MIDI percussion 42 ("Closed Hi-hat"). General MIDI percussion 43 ("Low Tom 1"). General MIDI percussion 44 ("Pedal Hi-hat"). General MIDI percussion 45 ("Mid Tom 2"). General MIDI percussion 46 ("Open Hi-hat"). General MIDI percussion 47 ("Mid Tom 1"). General MIDI percussion 48 ("High Tom 2"). General MIDI percussion 49 ("Crash Cymbal 1"). General MIDI percussion 50 ("High Tom 1"). General MIDI percussion 51 ("Ride Cymbal 1"). General MIDI percussion 52 ("Chinese Cymbal"). General MIDI percussion 53 ("Ride Bell"). General MIDI percussion 54 ("Tambourine"). General MIDI percussion 55 ("Splash Cymbal"). General MIDI percussion 56 ("Cowbell"). General MIDI percussion 57 ("Crash Cymbal 2"). General MIDI percussion 58 ("Vibra Slap"). General MIDI percussion 59 ("Ride Cymbal 2"). General MIDI percussion 60 ("High Bongo"). General MIDI percussion 61 ("Low Bongo"). General MIDI percussion 62 ("Mute High Conga"). General MIDI percussion 63 ("Open High Conga"). General MIDI percussion 64 ("Low Conga"). General MIDI percussion 65 ("High Timbale"). General MIDI percussion 66 ("Low Timbale"). General MIDI percussion 67 ("High Agogo"). General MIDI percussion 68 ("Low Agogo"). General MIDI percussion 69 ("Cabasa"). General MIDI percussion 70 ("Maracas"). General MIDI percussion 71 ("Short Whistle"). General MIDI percussion 72 ("Long Whistle"). General MIDI percussion 73 ("Short Guiro"). General MIDI percussion 74 ("Long Guiro"). General MIDI percussion 75 ("Claves"). General MIDI percussion 76 ("High Wood Block"). General MIDI percussion 77 ("Low Wood Block"). General MIDI percussion 78 ("Mute Cuica"). General MIDI percussion 79 ("Open Cuica"). General MIDI percussion 80 ("Mute Triangle"). General MIDI percussion 81 ("Open Triangle"). Extension methods for the Percussion enum. Be sure to "using midi" if you want to use these as extension methods. Returns true if the specified percussion is valid. The percussion to test. Throws an exception if percussion is not valid. The percussion to validate. The percussion is out-of-range. Returns the human-readable name of a MIDI percussion. The percussion. A letter and accidental, which together form an octave-independent note. This class lets you define a note by combining a letters A-G with accidentals (sharps and flats). Examples of notes are D, B#, and Gbb. This is the conventional way to refer to notes in an octave independent way. Each note unambiguously identifies a pitch (modulo octave), but each pitch has potentially many notes. For example, the notes F, E#, D###, and Gbb all resolve to the same pitch, though the last two names are unlikely to be used in practice. Double-flat accidental value. Flat accidental value. Natural accidental value. Sharp accidental value. Double-sharp accidental value. Constructs a note from a letter. The letter, which must be in ['A'..'G']. letter is out of range. Constructs a note from a string. The name to parse. Must begin with a letter in ['A'..'G'], then optionally be followed by a series of '#' (sharps) or a series of 'b' (flats). name is null. name cannot be parsed. Constructs a note name from a letter and accidental. The letter, which must be in ['A'..'G']. The accidental. Zero means natural, positive values are sharp by that many semitones, and negative values are flat by that many semitones. Likely values are (0), (1), (2), (-1), and (-2). letter is out of range. ToString returns the note name. The note name with '#' for sharp and 'b' for flat. For example, "G", "A#", "Cb", "Fbb". Parses a Note from s, starting at position pos. The string to parse from. The position to start at. On success, advances pos to after the end of the note. The note. A note cannot be parsed. This function must find a valid letter at s[pos], and then optionally a sequence of '#' (sharps) or 'b' (flats). It finds as many of the accidental as it can and then stops at the first character that can't be part of the accidental. Returns true if this note name is enharmonic with otherNote. Another note. True if the names can refer to the same pitch. Returns the pitch for this note in the specified octave. The octave, where octaves begin at each C and Middle C is the first note in octave 4. The pitch with this name in the specified octave. Returns the pitch for this note that is at or above nearPitch. The pitch from which the search is based. The pitch for this note at or above nearPitch. Returns the pitch for this note that is at or below nearPitch. The pitch from which the search is based. The pitch for this note at or below nearPitch. Returns the number of semitones it takes to move up to the next otherNote. The other note. The number of semitones. Returns the number of semitones it takes to move down to the next otherNote. The other note. The number of semitones. Equality operator does value comparison. Inequality operator does value comparison. Value equality for Note. Hash code. Table mapping (letter-'A') to the Note in octave -1, used to compute positionInOctave. The letter for this note name, in ['A'..'G']. The accidental for this note name. Zero means natural, positive values are sharp by that many semitones, and negative values are flat by that many semitones. Likely values are (0), (1), (2), (-1), and (-2). This note's position in the octave, where octaves start at each C. A MIDI output device. Each instance of this class describes a MIDI output device installed on the system. You cannot create your own instances, but instead must go through the property to find which devices are available. You may wish to examine the property of each one and present the user with a choice of which device to use. Open an output device with and close it with . While it is open, you may send MIDI messages with functions such as , and . All notes may be silenced on the device by calling . Note that the above methods send their messages immediately. If you wish to arrange for a message to be sent at a specific future time, you'll need to instantiate some subclass of (eg ) and then pass it to Clock.Schedule. Opens this output device. The device is already open. The device cannot be opened. Closes this output device. The device is not open. The device cannot be closed. Silences all notes on this output device. The device is not open. The message cannot be sent. Sends a Note On message to this MIDI output device. The channel. The pitch. The velocity 0..127. channel, pitch, or velocity is out-of-range. The device is not open. The message cannot be sent. Sends a Note Off message to this MIDI output device. The channel. The pitch. The velocity 0..127. channel, note, or velocity is out-of-range. The device is not open. The message cannot be sent. Sends a Note On message to Channel10 of this MIDI output device. The percussion. The velocity 0..127. This is simply shorthand for a Note On message on Channel10 with a percussion-specific note, so there is no corresponding message to receive from an input device. percussion or velocity is out-of-range. The device is not open. The message cannot be sent. Sends a Control Change message to this MIDI output device. The channel. The control. The new value 0..127. channel, control, or value is out-of-range. The device is not open. The message cannot be sent. Sends a Pitch Bend message to this MIDI output device. The channel. The pitch bend value, 0..16383, 8192 is centered. channel or value is out-of-range. The device is not open. The message cannot be sent. Sends a Program Change message to this MIDI output device. The channel. The instrument. channel or instrument is out-of-range. The device is not open. The message cannot be sent. A Program Change message is used to switch among instrument settings, generally instrument voices. An instrument conforming to General Midi 1 will have the instruments described in the enum; other instruments may have different instrument sets. Makes sure rc is MidiWin32Wrapper.MMSYSERR_NOERROR. If not, throws an exception with an appropriate error message. Throws a MidiDeviceException if this device is not open. Throws a MidiDeviceException if this device is open. Private Constructor, only called by the getter for the InstalledDevices property. Position of this device in the list of all devices. Win32 Struct with device metadata Private method for constructing the array of MidiOutputDevices by calling the Win32 api. List of devices installed on this system. True if this device is open. MIDI Control, used in Control Change messages. In MIDI, Control Change messages are used to influence various auxiliary "controls" on a device, such as knobs, levers, and pedals. Controls are specified with integers in [0..127]. This enum provides an incomplete list of controls, because most controls are too obscure to document effetively here. Even for the ones listed here, the details of how the value is interpreted are arcane. Please see the MIDI spec for details. The most commonly used control is SustainPedal, which is considered off when < 64, on when > 64. This enum has extension methods, such as and , defined in . General MIDI Control--See MIDI spec for details. General MIDI Control--See MIDI spec for details. General MIDI Control--See MIDI spec for details. General MIDI Control--See MIDI spec for details. General MIDI Control--See MIDI spec for details. General MIDI Control--See MIDI spec for details. General MIDI Control--See MIDI spec for details. General MIDI Control--See MIDI spec for details. General MIDI Control--See MIDI spec for details. General MIDI Control--See MIDI spec for details. General MIDI Control--See MIDI spec for details. General MIDI Control--See MIDI spec for details. General MIDI Control--See MIDI spec for details. General MIDI Control--See MIDI spec for details. General MIDI Control--See MIDI spec for details. General MIDI Control--See MIDI spec for details. General MIDI Control--See MIDI spec for details. General MIDI Control--See MIDI spec for details. Extension methods for the Control enum. Be sure to "using midi" if you want to use these as extension methods. Returns true if the specified control is valid. The Control to test. Throws an exception if control is not valid. The control to validate. The control is out-of-range. Table of control names. Returns the human-readable name of a MIDI control. The control. The control is out-of-range. C# wrappers for the Win32 MIDI API. Because .NET does not provide MIDI support itself, in C# we must use P/Invoke to wrap the Win32 API. That API consists of the MMSystem.h C header and the winmm.dll library. The API is described in detail here: http://msdn.microsoft.com/en-us/library/ms712733(VS.85).aspx. The P/Invoke interop mechanism is described here: http://msdn.microsoft.com/en-us/library/aa288468(VS.71).aspx. This file covers the subset of the MIDI protocol needed to manage input and output devices and send and receive Note On/Off, Control Change, Pitch Bend and Program Change messages. Other portions of the MIDI protocol (such as sysex events) are supported in the Win32 API but are not wrapped here. Some of the C functions are not typesafe when wrapped, so those wrappers are made private and typesafe variants are provided. Max length of a manufacturer name in the Win32 API. Returns the number of MIDI output devices on this system. Win32 docs: http://msdn.microsoft.com/en-us/library/ms711627(VS.85).aspx Fills in the capabilities struct for a specific output device. NOTE: This is adapted from the original Win32 function in order to make it typesafe. Win32 docs: http://msdn.microsoft.com/en-us/library/ms711621(VS.85).aspx Opens a MIDI output device. NOTE: This is adapted from the original Win32 function in order to make it typesafe. Win32 docs: http://msdn.microsoft.com/en-us/library/ms711632(VS.85).aspx Turns off all notes and sustains on a MIDI output device. Win32 docs: http://msdn.microsoft.com/en-us/library/dd798479(VS.85).aspx Closes a MIDI output device. Win32 docs: http://msdn.microsoft.com/en-us/library/ms711620(VS.85).aspx Sends a short MIDI message (anything but sysex or stream). Win32 docs: http://msdn.microsoft.com/en-us/library/ms711640(VS.85).aspx Gets the error text for a return code related to an output device. NOTE: This is adapted from the original Win32 function in order to make it typesafe. Win32 docs: http://msdn.microsoft.com/en-us/library/ms711622(VS.85).aspx Returns the number of MIDI input devices on this system. Win32 docs: http://msdn.microsoft.com/en-us/library/ms711608(VS.85).aspx Fills in the capabilities struct for a specific input device. NOTE: This is adapted from the original Win32 function in order to make it typesafe. Win32 docs: http://msdn.microsoft.com/en-us/library/ms711604(VS.85).aspx Opens a MIDI input device. NOTE: This is adapted from the original Win32 function in order to make it typesafe. Win32 docs: http://msdn.microsoft.com/en-us/library/ms711610(VS.85).aspx Starts input on a MIDI input device. Win32 docs: http://msdn.microsoft.com/en-us/library/ms711614(VS.85).aspx Stops input on a MIDI input device. Win32 docs: http://msdn.microsoft.com/en-us/library/ms711615(VS.85).aspx Resets input on a MIDI input device. Win32 docs: http://msdn.microsoft.com/en-us/library/ms711613(VS.85).aspx Closes a MIDI input device. Win32 docs: http://msdn.microsoft.com/en-us/library/ms711602(VS.85).aspx Gets the error text for a return code related to an input device. NOTE: This is adapted from the original Win32 function in order to make it typesafe. Win32 docs: http://msdn.microsoft.com/en-us/library/ms711605(VS.85).aspx Status type returned from most functions in the Win32 API. Flags passed to midiInOpen() and midiOutOpen(). Values for wTechnology field of MIDIOUTCAPS structure. Flags for dwSupport field of MIDIOUTCAPS structure. "Midi Out Messages", passed to wMsg param of MidiOutProc. "Midi In Messages", passed to wMsg param of MidiInProc. Win32 handle for a MIDI output device. Win32 handle for a MIDI input device. Struct representing the capabilities of an output device. Win32 docs: http://msdn.microsoft.com/en-us/library/ms711619(VS.85).aspx Struct representing the capabilities of an input device. Win32 docs: http://msdn.microsoft.com/en-us/library/ms711596(VS.85).aspx Callback invoked when a MIDI output device is opened, closed, or finished with a buffer. Win32 docs: http://msdn.microsoft.com/en-us/library/ms711637(VS.85).aspx Callback invoked when a MIDI event is received from an input device. Win32 docs: http://msdn.microsoft.com/en-us/library/ms711612(VS.85).aspx Interval measuring the relationship between pitches. This enum is simply for making interval operations more explicit. When adding to or subtracting from the enum, one can either use ints... Pitch p = Pitch.C4 + 5; ...or use the Interval enum, cast to int... Pitch p = Pitch.C4 + (int)Interval.PerfectFourth; These two examples are equivalent. The benefit of the latter is simply that it makes the intention more explicit. This enum has extension methods, such as , defined in . Unison interval, 0 semitones Semitone interval, 1 semitone Whole Tone interval, 2 semitones Minor Third interval, 3 semitones Major Third interval, 4 semitones Perfect Fourth interval, 5 semitones Tritone interval, 6 semitones Perfect Fifth interval, 7 semitones Minor Sixth interval, 8 semitones Major Sixth interval, 9 semitones Minor seventh interval, 10 semitones Major Seventh interval, 11 semitones Octave interval, 12 semitones Extension methods for the Interval enum. Table of interval names. Returns the human-readable name of an interval. The interval. The human-readable name. If the interval is less than an octave, it gives the standard term (eg, "Major third"). If the interval is more than an octave, it gives the number of semitones in the interval. A MIDI input device. Each instance of this class describes a MIDI input device installed on the system. You cannot create your own instances, but instead must go through the property to find which devices are available. You may wish to examine the property of each one and present the user with a choice of which device(s) to use. Open an input device with and close it with . While it is open, you may arrange to start receiving messages with and then stop receiving them with . An input device can only receive messages when it is both open and started. Incoming messages are routed to the corresponding events, such as and . The event handlers are invoked on a background thread which is started in and stopped in . As each message is received, it is assigned a timestamp in one of two ways. If is called with a , then each message is assigned a time by querying the clock's property. If is called with null, then each message is assigned a time based on the number of seconds since was called. Removes all event handlers from the input events on this device. Opens this input device. The device is already open. The device cannot be opened. Note that Open() establishes a connection to the device, but no messages will be received until is called. Closes this input device. The device is not open or is still receiving. The device cannot be closed. Starts this input device receiving messages. If non-null, the clock's property will be used to assign a timestamp to each incoming message. If null, timestamps will be in seconds since StartReceiving() was called. The device is not open or is already receiving. The device cannot start receiving. This method launches a background thread to listen for input events, and as events are received, the event handlers are invoked on that background thread. Event handlers should be written to work from a background thread. (For example, if they want to update the GUI, they may need to BeginInvoke to arrange for GUI updates to happen on the correct thread.) The background thread which is created by this method is joined (shut down) in . Stops this input device from receiving messages. This method waits for all in-progress input event handlers to finish, and then joins (shuts down) the background thread that was created in . Thus, when this function returns you can be sure that no more event handlers will be invoked. It is illegal to call this method from an input event handler (ie, from the background thread), and doing so throws an exception. If an event handler really needs to call this method, consider using BeginInvoke to schedule it on another thread. The device is not open; is not receiving; or called from within an event handler (ie, from the background thread). The device cannot start receiving. Makes sure rc is MidiWin32Wrapper.MMSYSERR_NOERROR. If not, throws an exception with an appropriate error message. Throws a MidiDeviceException if this device is not open. Throws a MidiDeviceException if this device is open. Throws a MidiDeviceException if this device is not receiving. Throws a MidiDeviceException if this device is receiving. Private Constructor, only called by the getter for the InstalledDevices property. Position of this device in the list of all devices. Win32 Struct with device metadata Private method for constructing the array of MidiInputDevices by calling the Win32 api. The input callback for midiOutOpen. Thread-local, set to true when called by an input handler, false in all other threads. Event called when an input device receives a Note On message. Event called when an input device receives a Note Off message. Event called when an input device receives a Control Change message. Event called when an input device receives a Program Change message. Event called when an input device receives a Pitch Bend message. List of input devices installed on this system. True if this device has been successfully opened. True if this device is receiving messages. Delegate called when an input device receives a Note On message. Delegate called when an input device receives a Note Off message. Delegate called when an input device receives a Control Change message. Delegate called when an input device receives a Program Change message. Delegate called when an input device receives a Pitch Bend message. A MIDI Channel. Each MIDI device has 16 independent channels. Channels are named starting at 1, but are encoded programmatically starting at 0. All of the channels are general-purpose except for Channel10, which is the dedicated percussion channel. Any notes sent to that channel will play percussion notes, regardless of any Program Change messages sent on that channel. This enum has extension methods, such as and , defined in . MIDI Channel 1. MIDI Channel 2. MIDI Channel 3. MIDI Channel 4. MIDI Channel 5. MIDI Channel 6. MIDI Channel 7. MIDI Channel 8. MIDI Channel 9. MIDI Channel 10, the dedicated percussion channel. MIDI Channel 11. MIDI Channel 12. MIDI Channel 13. MIDI Channel 14. MIDI Channel 15. MIDI Channel 16. Extension methods for the Channel enum. Returns true if the specified channel is valid. The channel to test. Throws an exception if channel is not valid. The channel to validate. The channel is out-of-range. Table of channel names. Returns the human-readable name of a MIDI channel. The channel. The channel is out-of-range. A clock for scheduling MIDI messages in a rate-adjustable, pausable timeline. Clock is used for scheduling MIDI messages. Though you can always send messages synchronously with the various .Send* methods, doing so requires your code to be "ready" at the precise moment each message needs to be sent. In most cases, and especially in interactive programs, it's more convenient to describe messages that will be sent at specified points in the future, and then rely on a scheduler to make it happen. Clock is such a scheduler.

Basic usage

In the simplest case, Clock can be used to schedule a sequence of messages which is known in its entirety ahead of time. For example, this code snippet schedules two notes to play one after the other: Clock clock(120); // beatsPerMinute=120 OutputDevice outputDevice = ...; clock.Schedule(new NoteOnMessage(outputDevice, Channel.Channel1, Note.E4, 80, 0)); clock.Schedule(new NoteOffMessage(outputDevice, Channel.Channel1, Note.E4, 80, 1)); clock.Schedule(new NoteOnMessage(outputDevice, Channel.Channel1, Note.D4, 80, 1)); clock.Schedule(new NoteOffMessage(outputDevice, Channel.Channel1, Note.D4, 80, 2)); At this point, four messages have been scheduled, but they haven't been sent because the clock has not started. We can start the clock with , pause it with , and reset it with . We can change the beats-per-minute at any time, even as the sequence is playing. And the playing happens in a background thread, so your client code can focus on arranging the notes and controlling the clock. You can even schedule new notes as the clock is playing. Generally you should schedule messages for times in the future; scheduling a message with a time in the past simply causes it to play immediately, which is probably not what you wanted.

NoteOnOffMessage and Self-Propagating Messages

In the above example, we wanted to play two notes but had to schedule four messages. This case is so common that we provide a convenience class, , which encapsulates a Note On message and its corresponding Note Off message in a single unit. We could rewrite the above example as follows: Clock clock(120); // beatsPerMinute=120 OutputDevice outputDevice = ...; clock.Schedule(new NoteOnOffMessage(outputDevice, Channel.Channel1, Note.E4, 80, 0, 1)); clock.Schedule(new NoteOnOffMessage(outputDevice, Channel.Channel1, Note.D4, 80, 1, 1)); This works because each NoteOnOffMessage, when it is actually sent, does two things: it sends the Note On message to the output device, and also schedules the correponding Note Off message for the appropriate time in the future. This is an example of a self-propagating message: a message which, when triggered, schedules additional events for the future. You can design your own self-propagating messages by subclassing from . For example, you could make a self-propagating MetronomeMessage which keeps a steady beat by always scheduling the next MetronomeMessage when it plays the current beat. However, subclassing can be tedious, and it is usually preferable to use to call-out to your own code instead.
Constructs a midi clock with a given beats-per-minute. The initial beats-per-minute, which can be changed later. When constructed, the clock is not running, and so will return zero. Call when you are ready for the clock to start progressing (and scheduled messages to actually trigger). beatsPerMinute is non-positive Starts or resumes the clock. This method causes the clock to start progressing at the rate given in the property. It may only be called when the clock is not yet rnuning. If this is the first time Start is called, the clock starts at time zero and progresses from there. If the clock was previously started, stopped, and not reset, then Start effectively "unpauses" the clock, picking up at the left-off time, and resuming scheduling of any as-yet-unsent messages. This method creates a new thread which runs in the background and sends messages at the appropriate times. All Message.SendNow methods and s will be called in that thread. The scheduler thread is joined (shut down) in . Clock is already running. Stops the clock (but does not reset its time or discard pending events). This method stops the progression of the clock. It may only be called when the clock is running. Any scheduled but as-yet-unsent messages remain in the queue. A consecutive call to can re-start the progress of the clock, or can discard pending messages and reset the clock to zero. This method waits for any in-progress messages to be processed and joins (shuts down) the scheduler thread before returning, so when it returns you can be sure that no more messages will be sent or callbacks invoked. It is illegal to call Stop from the scheduler thread (ie, from any Message.SendNow method or . If a callback really needs to stop the clock, consider using BeginInvoke to arrange for it to happen in another thread. Clock is not running or Stop was invoked from the scheduler thread. Resets the clock to zero and discards pending messages. This method resets the clock to zero and discards any scheduled but as-yet-unsent messages. It may only be called when the clock is not running. Clock is running. Schedules a single message based on its beatTime. The message to schedule. This method schedules a message to be sent at the time indicated in the message's property. It may be called at any time, whether the clock is running or not. The message will not be sent until the clock progresses to the specified time. (If the clock is never started, or is paused before that time and not re-started, then the message will never be sent.) If a message is scheduled for a time that has already passed, then the scheduler will send the message at the first opportunity. Schedules a collection of messages, applying an optional time delta to the scheduled beatTime. The message to send The delta to apply (or zero). Returns the number of milliseconds from now until the specified beat time. The beat time. The positive number of milliseconds, or 0 if beatTime is in the past. Worker thread function. Thread-local, set to true in the scheduler thread, false in all other threads. This clock's current time in beats. Normally, this method polls the clock's current time, and thus changes from moment to moment as long as the clock is running. However, when called from the scheduler thread (that is, from a Message.SendNow method or a ), it returns the precise time at which the message was scheduled. For example, suppose a callback was scheduled for time T, and the scheduler managed to call that callback at time T+delta. In the callback, Time will return T for the duration of the callback. In any other thread, Time would return approximately T+delta. Beats per minute property. Setting this property changes the rate at which the clock progresses. If the clock is currently running, the new rate is effectively immediately. Returns true if this clock is currently running.