Crate midi_msg

Source
Expand description

This is a library for serializing and deserializing MIDI (byte) streams.

§Creating MIDI byte sequences

MidiMsg is the starting point for all MIDI messages. All MidiMsgs can be serialized into a valid MIDI sequence. You can create a MidiMsg and turn it into a Vec<u8> like so:

use midi_msg::*;

MidiMsg::ChannelVoice {
    channel: Channel::Ch1,
    msg: ChannelVoiceMsg::NoteOn {
        note: 60,
        velocity: 127
    }
}
.to_midi();

§Deserializing MIDI byte sequences

Likewise, byte sequences can be deserialized into MidiMsgs with MidiMsg::from_midi:

use midi_msg::*;

// These are two MIDI 'note on' messages:
let midi_bytes: Vec<u8> = vec![
   0x93, 0x66, 0x70, // First msg
   0x93, 0x55, 0x60, // Second msg
];

let (msg, len) = MidiMsg::from_midi(&midi_bytes).expect("Not an error");

assert_eq!(len, 3);
assert_eq!(msg, MidiMsg::ChannelVoice {
    channel: Channel::Ch4,
    msg: ChannelVoiceMsg::NoteOn {
        note: 0x66,
        velocity: 0x70
    }
});

Where then len returned is the number of bytes used when a MidiMsg has been deserialized.

Similarly, MidiMsg::from_midi_with_context can be used to track the state associated with a MIDI stream, which is necessary to deserialize certain messages:

use midi_msg::*;

let mut ctx = ReceiverContext::new();

// This is a three-byte MIDI 'note on' message followed by a two-byte "running status"
// 'note on' message, which inherits its first ("status") byte from the last `ChannelModeMsg`:
let midi_bytes: Vec<u8> = vec![
   0x93, 0x66, 0x70, // First msg
   0x55, 0x60, // Running status msg
];

let (_msg1, len1) =
    MidiMsg::from_midi_with_context(&midi_bytes, &mut ctx).expect("Not an error");
let (msg2, len2) =
    MidiMsg::from_midi_with_context(&midi_bytes[len1..], &mut ctx).expect("Not an error");

assert_eq!(len2, 2);
assert_eq!(msg2, MidiMsg::ChannelVoice {
    channel: Channel::Ch4,
    msg: ChannelVoiceMsg::NoteOn {
        note: 0x55,
        velocity: 0x60
    }
});

The previous message would not have been deserializable without the context:

use midi_msg::*;

let midi_bytes: Vec<u8> = vec![
   0x93, 0x66, 0x70, // First msg
   0x55, 0x60, // Running status msg
];

let (_msg1, len1) = MidiMsg::from_midi(&midi_bytes).expect("Not an error");
MidiMsg::from_midi(&midi_bytes[len1..]).unwrap();

§Midi files

We can work with Standard Midi Files (SMF) in much the same way. The MidiFile struct represents this data type and it can be serialized into a Vec<u8> and deserialized from a Vec<u8>. It holds a header and a list of tracks. Regular Track::Midi tracks contains a list of MidiMsg events along with the “delta time” that separates subsequent ones. The definition of the delta time is given by the division field in the Header.

Convenience functions are provided for constructing a MidiFile based on a series of events and absolute beat or frame timings. For example, the following creates a MidiFile with a single track containing a single note.

use midi_msg::*;

let mut file = MidiFile::default();
// Add a track, updating the header with the number of tracks:
file.add_track(Track::default());
// Add a note on message at beat 0:
file.extend_track(0, MidiMsg::ChannelVoice {
    channel: Channel::Ch1,
    msg: ChannelVoiceMsg::NoteOn {
        note: 60,
        velocity: 127
    }
}, 0.0);
// Add a note off message at beat 1:
file.extend_track(0, MidiMsg::ChannelVoice {
    channel: Channel::Ch1,
    msg: ChannelVoiceMsg::NoteOff {
        note: 60,
        velocity: 0
    }
}, 1.0);
// Add an end of track message at beat 4,
// which is the only required (by the spec) message in a track:
file.extend_track(0, MidiMsg::Meta { msg: Meta::EndOfTrack }, 4.0);

// Now we can serialize the track to a Vec<u8>:
let midi_bytes = file.to_midi();
// And we can deserialize it back to a MidiFile:
let file2 = MidiFile::from_midi(&midi_bytes).unwrap();
assert_eq!(file, file2);

§Notes

See the readme for a list of the MIDI Manufacturer Association documents that are referenced throughout these docs.

Deserialization of most of UniversalRealTimeMsg and UniversalNonRealTimeMsg has not yet been implemented.

Structs§

ChannelBitMap
The set of channels to apply this tuning message to. Used by ScaleTuning1Byte and ScaleTuning2Byte.
ChannelIter
An iterator over the variants of Self
ControlChangeControllerDestination
Allows for the selection of the destination of a control change message. Used by UniversalRealTimeMsg::GlobalParameterControl.
ControllerDestination
Allows for the selection of the destination of a channel pressure/poly key pressure message. Used by UniversalRealTimeMsg.
FileTimeSignature
A time signature occurring in a Standard Midi File.
GMPercussionMapIter
An iterator over the variants of Self
GMSoundSetIter
An iterator over the variants of Self
GlobalParameter
An id:value pair that must line up with the GlobalParameterControl that it is placed in.
GlobalParameterControl
Global Parameter Control, to control parameters on a device that affect all sound. E.g. a global reverb. Used by UniversalRealTimeMsg::GlobalParameterControl.
Header
The header chunk of a Standard Midi File
HighResTimeCode
Like TimeCode but includes fractional_frames. Used in TimeCodeCueingSetupMsg and the SMF Meta event.
IdentityReply
A response to UniversalNonRealTimeMsg::IdentityRequest, meant to indicate the type of device that this message is sent from. Used by UniversalNonRealTimeMsg::IdentityReply.
KeyBasedInstrumentControl
Intended to act like Control Change messages, but targeted at an individual key. For e.g. Drum sounds that have configurable attack/release/decay per key. Used by UniversalRealTimeMsg::KeyBasedInstrumentControl.
KeyBasedTuningDump
Set the tunings of all 128 notes. Used by UniversalNonRealTimeMsg.
KeySignature
A key signature occurring in a Standard Midi File.
ManufacturerID
Two 7-bit “bytes”, used to identify the manufacturer for SystemExclusiveMsg::Commercial messages. See the published list of IDs.
MidiFile
A Standard Midi File (SMF)
MidiFileParseError
Errors that can occur when parsing a MidiFile
ReceiverContext
Passed to MidiMsg::from_midi_with_context to allow for the capture and use of captured context while reading from a MIDI stream.
ScaleTuning1Byte
Set the tuning of all octaves for a set of channels. Used by UniversalNonRealTimeMsg and UniversalRealTimeMsg.
ScaleTuning2Byte
Set the high-res tuning of all octaves for a set of channels. Used by UniversalNonRealTimeMsg and UniversalRealTimeMsg.
ScaleTuningDump1Byte
Set the tuning of all octaves for a tuning program/bank. Used by UniversalNonRealTimeMsg.
ScaleTuningDump2Byte
Set the high-res tuning of all octaves for a tuning program/bank. Used by UniversalNonRealTimeMsg.
Signature
A time signature. Used by TimeSignature.
SoundFileMap
How to map a DLS or SF2 file for MIDI reference. Used by SelectMap.
StandardTimeCode
Like TimeCode but uses subframes to optionally include status flags, and fractional frames. Also may be negative. Used in MachineControlCommandMsg.
StandardUserBits
Like UserBits but allows for the embedding of a “secondary time code”.
TimeCode
Used to synchronize device positions, by SystemCommonMsg::TimeCodeQuarterFrameX as well as UniversalRealTimeMsg::TimeCodeFull.
TimeCodeStatus
Used by StandardTimeCode.
TimeSignature
Used to communicate a new time signature to the receiver. Used by UniversalRealTimeMsg.
TrackEvent
An event occurring in a track in a Standard Midi File
Tuning
Used to represent a tuning by TuningNoteChange and KeyBasedTuningDump.
TuningNoteChange
Change the tunings of one or more notes, either real-time or not. Used by UniversalNonRealTimeMsg and UniversalRealTimeMsg.
UserBits
32 bits defined by SMPTE for “special functions”. Used in UniversalRealTimeMsg::TimeCodeUserBits. See the SMTPE time code standard.
WAVMap
How to map a WAV file for MIDI reference. Used by SelectMap.

Enums§

BarMarker
Indicates that the next MIDI clock message is the first clock of a new measure. Which bar is optionally indicated by this message. Used by UniversalRealTimeMsg::BarMarker.
BeatValue
The note value of a beat, used by Signature.
Channel
The MIDI channel, 1-16. Used by MidiMsg and elsewhere.
ChannelModeMsg
Channel-level messages that should alter the mode of the receiver. Used in MidiMsg.
ChannelVoiceMsg
Channel-level messages that act on a voice. For instance, turning notes on off, or modifying sounding notes. Used in MidiMsg.
ChorusType
The type of chorus, used by GlobalParameterControl::chorus.
ControlChange
Used by ChannelVoiceMsg::ControlChange to modify sounds. Each control targets a particular ControlNumber, the meaning of which is given by convention.
ControlNumber
An enum that defines the MIDI numbers associated with Control Changes.
ControlledParameter
The parameters that can be controlled by ControllerDestination or ControlChangeControllerDestination.
DeviceID
The device ID being addressed, either a number between 0-126 or AllCall (all devices). Used by SystemExclusiveMsg::UniversalNonRealTime and SystemExclusiveMsg::UniversalRealTime.
Division
The division of a Standard Midi File, which specifies the meaning of the delta times in the file
ExtendedLoopType
The type of loop being described by a SampleDumpMsg.
ExtendedSampleDumpMsg
The extended sample dump messages described in CA-019, used to allow for longer, named samples. Used by UniversalNonRealTimeMsg::SampleDump.
FileDumpMsg
Used to transmit general file data. Used by UniversalNonRealTimeMsg.
FileReferenceMsg
The set of messages used for accessing files on a shared file system or network so they can be used to play sounds without transferring the file contents. Used by UniversalNonRealTimeMsg::FileReference.
FileReferenceType
The file type of a given file, as used by FileReferenceMsg.
FileType
A four-character file type used by FileDumpMsg.
GMPercussionMap
The General MIDI percussion sound to play for a given note number when targeting Channel 10.
GMSoundSet
The instrument that should be played when applying a ChannelVoiceMsg::ProgramChange.
GeneralMidi
Used to turn General MIDI level 1 or 2 on, or turn them off.
InformationField
A MIDI Machine Control Information Field, which functions something like an address
LoopNumber
What loop a SampleDumpMsg or ExtendedSampleDumpMsg is referring to.
LoopType
The type of loop being described by a SampleDumpMsg.
MachineControlCommandMsg
A MIDI Machine Control Command. Used by UniversalRealTimeMsg::MachineControlCommand.
MachineControlResponseMsg
A MIDI Machine Control Response> Used by UniversalRealTimeMsg::MachineControlResponse.
Meta
A meta event in a Standard Midi File
MidiMsg
The primary interface of this library. Used to encode MIDI messages.
Parameter
Used by ControlChange::Parameter. “Entry” Parameters can be used to set the given parameters: they will first select that parameter, then send a ControlChange::DataEntry with the given value.
ParseError
Returned when MidiMsg::from_midi and similar where not successful.
PolyMode
Used by ChannelModeMsg::PolyMode.
ReverbType
The type of reverb, used by GlobalParameterControl::reverb.
SMFFormat
The format of a Standard Midi File
SampleDumpMsg
Used to request and transmit sampler data. Used by UniversalNonRealTimeMsg::SampleDump.
SelectMap
How to map a file for MIDI reference. Used by FileReferenceMsg::SelectContents.
ShowControlMsg
A MIDI Show Control command. Used by UniversalRealTimeMsg::ShowControl.
SlotPath
The “slot” of the device being referred to by GlobalParameterControl. Values other than Unregistered come from the General MIDI 2 spec.
SubFrames
Used by StandardTimeCode.
SystemCommonMsg
A fairly limited set of messages, generally for device synchronization. Used in MidiMsg.
SystemExclusiveMsg
The bulk of the MIDI spec lives here, in “Universal System Exclusive” messages. Also used for manufacturer-specific messages. Used in MidiMsg.
SystemRealTimeMsg
A fairly limited set of messages used for device synchronization. Used in MidiMsg.
TimeCodeCueingMsg
Realtime Time Code Cueing. Used by UniversalRealTimeMsg::TimeCodeCueing.
TimeCodeCueingSetupMsg
Non-realtime Time Code Cueing. Used by UniversalNonRealTimeMsg::TimeCodeCueingSetup.
TimeCodeType
Indicates the frame rate of the given TimeCode.
Track
A track in a Standard Midi File
UniversalNonRealTimeMsg
A diverse range of messages for non-real-time applications. Used by SystemExclusiveMsg::UniversalNonRealTime.
UniversalRealTimeMsg
A diverse range of messages for real-time applications. Used by SystemExclusiveMsg::UniversalRealTime.

Functions§

freq_to_midi_note_cents
Given a frequency in Hertz, returns (midi_note_number, additional cents from semitone)
freq_to_midi_note_float
Given a frequency in Hertz, returns a floating point midi note number with 1.0 = 100 cents
midi_note_cents_to_freq
Given a midi note number and additional cents, return the frequency
midi_note_float_to_freq
Given a floating point midi note number, return the frequency in Hertz
next_message
Find the index of the next message in a MIDI byte sequence. This is useful for being able to skip over messages, which may be necessary when a message is unable to be deserialized.