|
| 1 | +namespace ZMidi.DataTypes |
| 2 | + |
| 3 | +type midiportnumber = byte |
| 4 | +type word8 = byte |
| 5 | +type word16 = uint16 |
| 6 | +type word32 = uint32 |
| 7 | +type bits7 = byte |
| 8 | +type midichannel = byte |
| 9 | +type [<Struct>] DeltaTime(value: int32) = |
| 10 | + member x.Value = value |
| 11 | + |
| 12 | +type [<Struct>] word14(value: word16) = |
| 13 | + member x.Value = value |
| 14 | + |
| 15 | + |
| 16 | +/// The file format - in a MIDI file this is a big-endian |
| 17 | +/// word16 with 0,1 or 2 being the only valid values. |
| 18 | +type MidiFormat = |
| 19 | +/// Format 0 file - single multi-channel track. |
| 20 | +| MidiFormat0 |
| 21 | +/// Format 1 file - 1 or more tracks, played simultaneously. |
| 22 | +| MidiFormat1 |
| 23 | +/// Format 2 file - 1 or more independent tracks. |
| 24 | +| MidiFormat2 |
| 25 | +type MidiTimeDivision = |
| 26 | + | FPS of frame: word16 |
| 27 | + | TicksPerBeat of ticks: word16 |
| 28 | + |
| 29 | +type MidiHeader = { |
| 30 | + format: MidiFormat |
| 31 | + trackCount: word16 |
| 32 | + timeDivision: MidiTimeDivision |
| 33 | +} |
| 34 | + |
| 35 | +/// Running Status. |
| 36 | +/// |
| 37 | +/// MIDI allows a compact representation of voice events where |
| 38 | +/// consecutive events (same event, same channel) only need to |
| 39 | +/// include the first event-channel byte - subsequent events |
| 40 | +/// only send payload until the next event or channel change. |
| 41 | +/// |
| 42 | +/// Including @MidiRunningStatus@ in the data representation is |
| 43 | +/// important for ZMidi as an aim is to allow round-tripping |
| 44 | +/// of exisiting MIDI files. However it makes MIDI generation |
| 45 | +/// more complicated (there is more scope to generate bad |
| 46 | +/// output) - if you are only generating MIDI it is wise to always |
| 47 | +/// set @MidiRunningStatus@ to @OFF@. |
| 48 | +[<RequireQualifiedAccess>] |
| 49 | +type MidiRunningStatus = ON | OFF |
| 50 | +type TagByte = word8 |
| 51 | +type MidiDataOther = TagByte |
| 52 | +type MidiEvent = |
| 53 | + | MidiEventOther of MidiDataOther |
| 54 | + | VoiceEvent of MidiRunningStatus * MidiVoiceEvent |
| 55 | + | SysExEvent of MidiSysExEvent |
| 56 | + | SysCommonEvent of MidiSysCommonEvent |
| 57 | + | SysRealtimeEvent of MidiSysRealtimeEvent |
| 58 | + | MetaEvent of MidiMetaEvent |
| 59 | + |
| 60 | +and MidiVoiceEvent = |
| 61 | + /// Note off. |
| 62 | + /// |
| 63 | + /// > 80 to 8F (0 to F is channel number) * note * velocity |
| 64 | + /// |
| 65 | + /// Turn off a sounding note. |
| 66 | + | NoteOff of status: bits7 * note: bits7 * velocity: bits7 |
| 67 | + |
| 68 | + /// Note on. |
| 69 | + /// |
| 70 | + /// > 90 to 9F (0 to F is channel number) * note * velocity |
| 71 | + /// |
| 72 | + /// Start playing a note. |
| 73 | + | NoteOn of status: bits7 * note: bits7 * velocity: bits7 |
| 74 | + |
| 75 | + /// Polyphonic key pressure. |
| 76 | + /// |
| 77 | + /// > A0 to AF (0 to F is channel number) * note * pressure_value |
| 78 | + /// |
| 79 | + /// Change of pressure applied to the synthesizer key. |
| 80 | + | NoteAfterTouch of status: bits7 * note: bits7 * pressure: bits7 |
| 81 | + |
| 82 | + /// Set a controller. |
| 83 | + /// |
| 84 | + /// > B0 to BF (0 to F is channel number) * controller_number * value |
| 85 | + /// |
| 86 | + /// Controller change, e.g. by a footswitch. |
| 87 | + | Controller of status: bits7 * controller: bits7 * value: bits7 |
| 88 | + |
| 89 | + /// Set the program. |
| 90 | + /// |
| 91 | + /// > C0 to CF (0 to F is channel number) * program_number |
| 92 | + /// |
| 93 | + /// Change the instrument |
| 94 | + /// playing on the specified channel. For playback on |
| 95 | + /// computers (rather than synthesizers) the program numbers |
| 96 | + /// will correspond to the /General MIDI/ instrument numbers. |
| 97 | + | ProgramChange of status: bits7 * programNumber: bits7 |
| 98 | + |
| 99 | + /// Channel pressure. |
| 100 | + /// |
| 101 | + /// > D0 to DF (0 to F is channel number) * pressure_value |
| 102 | + /// |
| 103 | + | ChannelAfterTouch of status: bits7 * pressure: bits7 |
| 104 | + |
| 105 | + /// Pitch bend |
| 106 | + /// |
| 107 | + /// > E0 to EF (0 to F is channel number) * value |
| 108 | + /// |
| 109 | + /// Change the pitch of a sounding note. Often used to |
| 110 | + /// approximate microtonal tunings. |
| 111 | + /// |
| 112 | + /// NOTE - as of v0.9.0 the value is interpreted. |
| 113 | + /// This is a Word14 value, the range is (0..16383). |
| 114 | + | PitchBend of status: bits7 * bend: word14 |
| 115 | + |
| 116 | + |
| 117 | +and MidiTextType = |
| 118 | + | GenericText |
| 119 | + | CopyrightNotice |
| 120 | + | SequenceName |
| 121 | + | InstrumentName |
| 122 | + | Lyrics |
| 123 | + | Marker |
| 124 | + | CuePoint |
| 125 | + |
| 126 | + |
| 127 | +/// Sequential messages with delta time 0 are played simultaneously. |
| 128 | +and MidiMessage = { |
| 129 | + timestamp: DeltaTime |
| 130 | + event: MidiEvent |
| 131 | +} |
| 132 | + |
| 133 | +and MidiTrack = MidiMessage array |
| 134 | + |
| 135 | +and MidiFile = { |
| 136 | + header : MidiHeader |
| 137 | + tracks : MidiTrack array |
| 138 | + } |
| 139 | + |
| 140 | +and MidiSysExEvent = |
| 141 | + /// Single SysEx event. |
| 142 | + /// |
| 143 | + /// > F0 * length * data |
| 144 | + /// |
| 145 | + /// An uninterpreted sys-ex event. |
| 146 | + | SysExSingle of byte array |
| 147 | + |
| 148 | + /// SysEx sent as (non-standard) multiple continuation |
| 149 | + /// packets. |
| 150 | + /// |
| 151 | + /// > F0 * length * packet1 ... [SysExContPacket] |
| 152 | + /// |
| 153 | + | SysExCont of byte array * MidiSysExContPacket array |
| 154 | + |
| 155 | + /// Escape sequence of one-or-more SysEx events. |
| 156 | + /// |
| 157 | + /// > F7 * length * data |
| 158 | + /// |
| 159 | + | SysExEscape of byte array |
| 160 | + |
| 161 | +/// Continuation packet for a (non-standard) multi-part SysEx |
| 162 | +/// event. |
| 163 | +/// |
| 164 | +/// Apprently this format is use by Casio. |
| 165 | +and MidiSysExContPacket = MidiSysExContPacket of DeltaTime * byte array |
| 166 | + |
| 167 | + |
| 168 | + |
| 169 | +and MidiMetaEvent = |
| 170 | + |
| 171 | + /// Text / copywright etc. |
| 172 | + /// |
| 173 | + /// > FF * text_type * contents |
| 174 | + /// |
| 175 | + /// Free text field (e.g. copyright statement). The contents |
| 176 | + /// can notionally be any length. |
| 177 | + /// |
| 178 | + | TextEvent of MidiTextType * string |
| 179 | + |
| 180 | + /// Sequence Number |
| 181 | + /// |
| 182 | + /// > FF 00 02 * value |
| 183 | + /// |
| 184 | + /// Format 1 files - only track 1 should have a sequence |
| 185 | + /// number. |
| 186 | + /// |
| 187 | + /// Format 2 files - a sequence number should identify each |
| 188 | + /// track. |
| 189 | + /// |
| 190 | + /// The sequence number event should occur at the start of a |
| 191 | + /// track, before any non-zero time events. |
| 192 | + /// |
| 193 | + | SequenceNumber of word16 |
| 194 | + |
| 195 | + /// Channel prefix |
| 196 | + /// |
| 197 | + /// > FF 20 01 * channel |
| 198 | + /// |
| 199 | + /// Relay all meta and sys-ex events to the given channel. |
| 200 | + /// |
| 201 | + | ChannelPrefix of midichannel |
| 202 | + |
| 203 | + /// Midi port |
| 204 | + /// |
| 205 | + /// > FF 21 01 * port |
| 206 | + /// |
| 207 | + /// Midi port number - used to workaround 16 channel limit... |
| 208 | + /// |
| 209 | + | MidiPort of midiportnumber |
| 210 | + |
| 211 | + /// End-of-track event. |
| 212 | + /// |
| 213 | + /// > FF 2F 00 |
| 214 | + /// |
| 215 | + | EndOfTrack |
| 216 | + |
| 217 | + /// Set tempo |
| 218 | + /// |
| 219 | + /// > FF 51 03 * microseconds_per_quarter_note |
| 220 | + /// |
| 221 | + | SetTempo of word32 |
| 222 | + |
| 223 | + /// SMPTE offest |
| 224 | + /// |
| 225 | + /// > FF 54 05 * hour * minute * second * frac * subfrac |
| 226 | + /// |
| 227 | + /// The SMPTE time when a track should start. This event |
| 228 | + /// should occur at the start of a track, before any non-zero |
| 229 | + /// time events. |
| 230 | + /// |
| 231 | + | SMPTEOffset of word8 * word8 * word8 * word8 * word8 |
| 232 | + |
| 233 | + /// Time signature |
| 234 | + /// |
| 235 | + /// > FF 58 04 * numerator * denominator * metro * num_32nd_notes |
| 236 | + /// |
| 237 | + | TimeSignature of word8 * word8 * word8 * word8 |
| 238 | + |
| 239 | + /// Key signature |
| 240 | + /// |
| 241 | + /// > FF 59 02 * key_type * scale_type |
| 242 | + /// |
| 243 | + /// @key_type@ is the number of sharps (postive numbers) or |
| 244 | + /// flats (negative numbers), e.g. (-1) is 1 flat. |
| 245 | + /// |
| 246 | + /// @scale_type@ indicates major or minor. |
| 247 | + /// |
| 248 | + | KeySignature of int8 * MidiScaleType |
| 249 | + |
| 250 | + /// SSME |
| 251 | + /// |
| 252 | + /// > FF 7F * length * data |
| 253 | + /// |
| 254 | + /// Sequencer specific meta-event - uninterpreted. |
| 255 | + /// |
| 256 | + | SSME of byte array |
| 257 | + /// Unrecognized Meta Event |
| 258 | + /// |
| 259 | + /// > FF * type * length * data |
| 260 | + /// |
| 261 | + | MetaOther of otherType: word8 * byte array |
| 262 | + |
| 263 | + |
| 264 | +/// System common event. |
| 265 | +/// |
| 266 | +/// Common information for all channels in a system. |
| 267 | +/// |
| 268 | +/// These events may not be pertinent to MIDI files generated on a |
| 269 | +/// computer (as opposed to MIDI generated by a synthesizer or |
| 270 | +/// sequencer). |
| 271 | +/// |
| 272 | +and MidiSysCommonEvent = |
| 273 | + /// Time code quarter frame. |
| 274 | + /// |
| 275 | + /// > F1 * payload |
| 276 | + /// |
| 277 | + /// Note the payload is really a byte split into two 4-bit |
| 278 | + /// values, however here it is uninterpreted. |
| 279 | + /// |
| 280 | + | QuarterFrame of word8 |
| 281 | + |
| 282 | + /// Song position pointer. |
| 283 | + /// |
| 284 | + /// > F2 * lsb * msb |
| 285 | + /// |
| 286 | + | SongPosPointer of word8 * word8 |
| 287 | + |
| 288 | + /// Song number. |
| 289 | + /// |
| 290 | + /// > F3 * song_number |
| 291 | + /// |
| 292 | + /// Song number should be in the range 0..127. |
| 293 | + /// |
| 294 | + | SongSelect of word8 |
| 295 | + |
| 296 | + /// Undefined system common event. |
| 297 | + /// |
| 298 | + /// > F4 |
| 299 | + /// |
| 300 | + | UndefinedF4 |
| 301 | + |
| 302 | + /// Undefined system common event. |
| 303 | + /// |
| 304 | + /// > F5 |
| 305 | + /// |
| 306 | + | UndefinedF5 |
| 307 | + |
| 308 | + /// Tune request. |
| 309 | + /// |
| 310 | + /// > F6 |
| 311 | + /// |
| 312 | + /// Tune request message for analogue synthesizers. |
| 313 | + /// |
| 314 | + | TuneRequest |
| 315 | + |
| 316 | + /// End-of-system-exclusive message. |
| 317 | + /// |
| 318 | + /// > F7 |
| 319 | + /// |
| 320 | + | EOX |
| 321 | + |
| 322 | +/// System real-time event. |
| 323 | +/// |
| 324 | +/// These events may not be pertinent to MIDI files generated on a |
| 325 | +/// computer (as opposed to MIDI generated by a synthesizer or |
| 326 | +/// sequencer). |
| 327 | +and MidiSysRealtimeEvent = |
| 328 | + /// Timing signal. |
| 329 | + /// |
| 330 | + /// > F8 |
| 331 | + /// |
| 332 | + | TimingClock |
| 333 | + |
| 334 | + /// Undefined real time event. |
| 335 | + /// |
| 336 | + /// > F9 |
| 337 | + /// |
| 338 | + /// |
| 339 | + | UndefinedF9 |
| 340 | + |
| 341 | + |
| 342 | + /// Start playing a sequence. |
| 343 | + /// |
| 344 | + /// > FA |
| 345 | + /// |
| 346 | + | StartSequence |
| 347 | + |
| 348 | + |
| 349 | + /// Continue playing a stopped sequence. |
| 350 | + /// |
| 351 | + /// > FB |
| 352 | + /// |
| 353 | + | ContinueSequence |
| 354 | + |
| 355 | + |
| 356 | + /// Stop playing a sequence. |
| 357 | + /// |
| 358 | + /// > FC |
| 359 | + /// |
| 360 | + | StopSequence |
| 361 | + |
| 362 | + |
| 363 | + /// Undefined real time event. |
| 364 | + /// |
| 365 | + /// > FD |
| 366 | + /// |
| 367 | + /// |
| 368 | + | UndefinedFD |
| 369 | + |
| 370 | + /// Active sensing |
| 371 | + /// |
| 372 | + /// > FE |
| 373 | + /// |
| 374 | + /// Synchronization pulse... |
| 375 | + /// |
| 376 | + | ActiveSensing |
| 377 | + |
| 378 | + |
| 379 | + /// Reset to power-up status. |
| 380 | + /// |
| 381 | + /// > FF |
| 382 | + /// |
| 383 | + | SystemReset |
| 384 | + |
| 385 | + |
| 386 | + |
| 387 | +and [<RequireQualifiedAccess>] MidiScaleType = Major | Minor | OtherScale of word8 |
0 commit comments