Convenience functions for creating binary MIDI messages.
MIDI message functions
So that you don't have to remember all the MIDI message codes, this library has a large range of message generating functions. Some common types are below:
note_on/3note_off/3all_notes_off/1sound_off/1polyphonic_aftertouch/3channel_aftertouch/3control_change/3program_change/2pitch_bend/2pan/2volume/2
Various system messages are supported too, such as sysex/1.
Some functions have an optional high-resolution (14-bit) version. This is activated by providing the high_res: true option, e.g.: Midiex.Message.volume(16383, high_res: true). You can learn more about the resolution of MIDI messages below.
Notes
Functions that take notes as a parameter can accept a number, string or atom note representation. For example, middle-C can be represented as 60, "C4" or :C4.
Taking the note_on/1 function as an example, generating a "note on" MIDI message for middle-C <<144, 60, 127>> can be achieved in any of these ways:
Message.note_on(60)Message.note_on("C4")Message.note_on(:C4)
To get the MIDI number for a string or atom note representation, see note/1.
Example
alias Midiex.Message, as: M
# Connect to the synth, in this case the Arturia MicroFreak synth
synth = Midiex.ports("Arturia MicroFreak", :output) |> Midiex.open()
# Send the note on message, for D3
Midiex.send_msg(synth, M.note_on(:D3))
# Wait 1 second
:timer.sleep(1000)
# Send the note off message, for D3
Midiex.send_msg(synth, M.note_off(:D3))About MIDI messages
MIDI messages are in the format of:
status_byte + note_number (0-127) + velocity (0-127)
For example, taking the status byte for Note On which in HEX is 0x90, and the note Middle C which is 60 and a maximum key velocity of 127, the MIDI message in binary format is:
<<0x90, 60, 127>>
Resolution (bits)
Coarse resolution
This type of message format is sometimes called 'coarse' or 7-bit MIDI, as it takes a maximum of 128 values only (from 0 to 127).
High resolution
However, 'high resolution' or 14-bit MIDI messages are possible, giving a maximum of 16,384 values (from 0 to 16,383). When working with controllers such as mod wheels, it allows for finer and smoother changes.
To achieve this higher 14-bit resolution, the MIDI message combines two 7-bit values called:
- MSB (Most Significant Byte), which is used for 'coarser' values. This is the bit which has the greatest effect.
- LSB (Least Significant Byte), which is used for 'finer' values.
In Elixir, We can unpack a 14-bit value into it's MSB and LSB bits using binary pattern matching, e.g.:
<<msb::7, lsb::7>> = <<value::14>>
The MSB and LSB values are sent as two different messages. Below is what it would look like for a Mod wheel which uses two control change command messages (0x01 and 0x21) to send the MSB and LSB respectively
<<msb::7, lsb::7>> = <<mod_wheel_value::14>>
msb_binary = control_change(1, msb)
lsb_binary = control_change(0x21, lsb)
<<msb_binary::binary, lsb_binary::binary>>More information
https://www.midi.org/midi-articles/about-midi-part-3-midi-messages
Summary
Functions
Returns the MIDI numerical code for a note.
Channel voice messages
Channel change messages
Channel mode messages
System messages
Functions
Returns the MIDI numerical code for a note.
Takes either a string or atom representation of a note as the first parameter.
Example
# Return the code for middle-C (also known as C4)
Message.note(:C4)
Message.note("C4")
Message.note(:MiddleC)
Message.note("MiddleC")
# These all return: 60
# Return the code for A-sharp 3
Message.note(:As3)
Message.note("A#3")
# These both return: 58