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 MidiMsg
s
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 MidiMsg
s 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§
- The set of channels to apply this tuning message to. Used by
ScaleTuning1Byte
andScaleTuning2Byte
. - An iterator over the variants of Self
- Allows for the selection of the destination of a control change message. Used by
UniversalRealTimeMsg::GlobalParameterControl
. - Allows for the selection of the destination of a channel pressure/poly key pressure message. Used by
UniversalRealTimeMsg
. - A time signature occurring in a Standard Midi File.
- An iterator over the variants of Self
- An iterator over the variants of Self
- Global Parameter Control, to control parameters on a device that affect all sound. E.g. a global reverb. Used by
UniversalRealTimeMsg::GlobalParameterControl
. - The header chunk of a Standard Midi File
- Like
TimeCode
but includesfractional_frames
. Used inTimeCodeCueingSetupMsg
and the SMFMeta
event. - A response to
UniversalNonRealTimeMsg::IdentityRequest
, meant to indicate the type of device that this message is sent from. Used byUniversalNonRealTimeMsg::IdentityReply
. - 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
. - Set the tunings of all 128 notes. Used by
UniversalNonRealTimeMsg
. - A key signature occurring in a Standard Midi File.
- Two 7-bit “bytes”, used to identify the manufacturer for
SystemExclusiveMsg::Commercial
messages. See the published list of IDs. - A Standard Midi File (SMF)
- Errors that can occur when parsing a
MidiFile
- Passed to
MidiMsg::from_midi_with_context
to allow for the capture and use of captured context while reading from a MIDI stream. - Set the tuning of all octaves for a set of channels. Used by
UniversalNonRealTimeMsg
andUniversalRealTimeMsg
. - Set the high-res tuning of all octaves for a set of channels. Used by
UniversalNonRealTimeMsg
andUniversalRealTimeMsg
. - Set the tuning of all octaves for a tuning program/bank. Used by
UniversalNonRealTimeMsg
. - Set the high-res tuning of all octaves for a tuning program/bank. Used by
UniversalNonRealTimeMsg
. - A time signature. Used by
TimeSignature
. - Like
TimeCode
but usessubframes
to optionally include status flags, and fractional frames. Also may be negative. Used inMachineControlCommandMsg
. - Like
UserBits
but allows for the embedding of a “secondary time code”. - Used to synchronize device positions, by
SystemCommonMsg::TimeCodeQuarterFrameX
as well asUniversalRealTimeMsg::TimeCodeFull
. - Used by
StandardTimeCode
. - Used to communicate a new time signature to the receiver. Used by
UniversalRealTimeMsg
. - An event occurring in a track in a Standard Midi File
- Used to represent a tuning by
TuningNoteChange
andKeyBasedTuningDump
. - Change the tunings of one or more notes, either real-time or not. Used by
UniversalNonRealTimeMsg
andUniversalRealTimeMsg
. - 32 bits defined by SMPTE for “special functions”. Used in
UniversalRealTimeMsg::TimeCodeUserBits
. See the SMTPE time code standard. - How to map a
WAV
file for MIDI reference. Used bySelectMap
.
Enums§
- 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
. - The note value of a beat, used by
Signature
. - The MIDI channel, 1-16. Used by
MidiMsg
and elsewhere. - Channel-level messages that should alter the mode of the receiver. Used in
MidiMsg
. - Channel-level messages that act on a voice. For instance, turning notes on off, or modifying sounding notes. Used in
MidiMsg
. - The type of chorus, used by
GlobalParameterControl::chorus
. - Used by
ChannelVoiceMsg::ControlChange
to modify sounds. Each control targets a particularControlNumber
, the meaning of which is given by convention. - An enum that defines the MIDI numbers associated with Control Changes.
- The parameters that can be controlled by
ControllerDestination
orControlChangeControllerDestination
. - The device ID being addressed, either a number between 0-126 or
AllCall
(all devices). Used bySystemExclusiveMsg::UniversalNonRealTime
andSystemExclusiveMsg::UniversalRealTime
. - The division of a Standard Midi File, which specifies the meaning of the delta times in the file
- The type of loop being described by a
SampleDumpMsg
. - The extended sample dump messages described in CA-019, used to allow for longer, named samples. Used by
UniversalNonRealTimeMsg::SampleDump
. - Used to transmit general file data. Used by
UniversalNonRealTimeMsg
. - 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
. - The file type of a given file, as used by
FileReferenceMsg
. - A four-character file type used by
FileDumpMsg
. - The General MIDI percussion sound to play for a given note number when targeting Channel 10.
- The instrument that should be played when applying a
ChannelVoiceMsg::ProgramChange
. - Used to turn General MIDI level 1 or 2 on, or turn them off.
- A MIDI Machine Control Information Field, which functions something like an address
- What loop a
SampleDumpMsg
orExtendedSampleDumpMsg
is referring to. - The type of loop being described by a
SampleDumpMsg
. - A MIDI Machine Control Command. Used by
UniversalRealTimeMsg::MachineControlCommand
. - A MIDI Machine Control Response> Used by
UniversalRealTimeMsg::MachineControlResponse
. - A meta event in a Standard Midi File
- The primary interface of this library. Used to encode MIDI messages.
- Used by
ControlChange::Parameter
. “Entry” Parameters can be used to set the given parameters: they will first select that parameter, then send aControlChange::DataEntry
with the given value. - Returned when
MidiMsg::from_midi
and similar where not successful. - Used by
ChannelModeMsg::PolyMode
. - The type of reverb, used by
GlobalParameterControl::reverb
. - The format of a Standard Midi File
- Used to request and transmit sampler data. Used by
UniversalNonRealTimeMsg::SampleDump
. - How to map a file for MIDI reference. Used by
FileReferenceMsg::SelectContents
. - A MIDI Show Control command. Used by
UniversalRealTimeMsg::ShowControl
. - The “slot” of the device being referred to by
GlobalParameterControl
. Values other thanUnregistered
come from the General MIDI 2 spec. - Used by
StandardTimeCode
. - A fairly limited set of messages, generally for device synchronization. Used in
MidiMsg
. - The bulk of the MIDI spec lives here, in “Universal System Exclusive” messages. Also used for manufacturer-specific messages. Used in
MidiMsg
. - A fairly limited set of messages used for device synchronization. Used in
MidiMsg
. - Realtime Time Code Cueing. Used by
UniversalRealTimeMsg::TimeCodeCueing
. - Non-realtime Time Code Cueing. Used by
UniversalNonRealTimeMsg::TimeCodeCueingSetup
. - Indicates the frame rate of the given
TimeCode
. - A track in a Standard Midi File
- A diverse range of messages for non-real-time applications. Used by
SystemExclusiveMsg::UniversalNonRealTime
. - A diverse range of messages for real-time applications. Used by
SystemExclusiveMsg::UniversalRealTime
.
Functions§
- Given a frequency in Hertz, returns (midi_note_number, additional cents from semitone)
- Given a frequency in Hertz, returns a floating point midi note number with 1.0 = 100 cents
- Given a midi note number and additional cents, return the frequency
- Given a floating point midi note number, return the frequency in Hertz
- 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.