Documentation
¶
Overview ¶
Package midi helps with reading and writing of MIDI messages.
A `Message` is a slice of bytes with some methods to get the data. Any complete midi message (i.e. without "running status") can be interpreted as a Message, by converting the type. The data can be retrieved with the corresponding Get* method.
// the raw bytes for a noteon message on channel 1 (2nd channel) for the key 60 with velocity of 120 var b = []byte{0x91, 0x3C, 0x78} // convert to Message type msg := midi.Message(b) var channel, key, velocity uint8 if msg.GetNoteOn(&channel, &key, &velocity) { fmt.Printf("got %s: channel: %v key: %v, velocity: %v\n", msg.Type(), channel, key, velocity) }
Received messages can be categorized by their type, e.g.
switch msg.Type() { case midi.NoteOnMsg, midi.NoteOffMsg: // do something case midi.ControlChangeMsg: // do some other thing default: if msg.Is(midi.RealTimeMsg) || msg.Is(midi.SysCommonMsg) || msg.Is(midi.SysExMsg) { // ignore } }
A new message is created by the corresponding function, e.g.
msg := midi.NoteOn(1, 60, 120) // channel, key, velocity fmt.Printf("% X\n", []byte(msg)) // prints 91 3C 78
Sending and retrieving of midi data is done via drivers. Most of the time, a single driver is sufficient. Therefor it is handy, that the drivers autoregister themself. This also makes it easy to exchange a driver if needed (see the example).
Different cross plattform implementations of the `Driver` interface can be found in the `drivers` subdirectory.
The `smf` subpackage helps with writing to and reading from `Simple MIDI Files` (SMF).
The `tools` subdirectory provides command line tools based on this library.
Example ¶
var eachMessage = func(msg Message, timestampms int32) { if msg.Is(RealTimeMsg) { // ignore realtime messages return } var channel, key, velocity, cc, val uint8 switch { // is better, than to use GetNoteOn (handles note on messages with velocity of 0 as expected) case msg.GetNoteStart(&channel, &key, &velocity): fmt.Printf("note started at %vms channel: %v key: %v velocity: %v\n", timestampms, channel, key, velocity) // is better, than to use GetNoteOff (handles note on messages with velocity of 0 as expected) case msg.GetNoteEnd(&channel, &key): fmt.Printf("note ended at %vms channel: %v key: %v\n", timestampms, channel, key) case msg.GetControlChange(&channel, &cc, &val): fmt.Printf("control change %v %q channel: %v value: %v at %vms\n", cc, ControlChangeName[cc], channel, val, timestampms) default: fmt.Printf("received %s at %vms\n", msg, timestampms) } } // always good to close the driver at the end defer CloseDriver() // allows you to get the ports when using "real" drivers like rtmididrv or portmididrv if len(os.Args) == 2 && os.Args[1] == "list" { fmt.Printf("MIDI IN Ports\n") for i, port := range InPorts() { fmt.Printf("no: %v %q\n", i, port) } fmt.Printf("\n\nMIDI OUT Ports\n") for i, port := range OutPorts() { fmt.Printf("no: %v %q\n", i, port) } fmt.Printf("\n\n") return } var out int = 0 // takes the first out port, for real, consider // var out = OutByName("my synth") // creates a sender function to the out port send, _ := SendTo(out) var in int = 0 // here we take first in port, for real, consider // var in = InByName("my midi keyboard") // listens to the in port and calls eachMessage for every message. // any running status bytes are converted and only complete messages are passed to the eachMessage. stop, _ := ListenTo(in, eachMessage) { // send some messages send(NoteOn(0, Db(4), 100)) time.Sleep(time.Millisecond * 30) send(NoteOff(0, Db(4))) send(Pitchbend(0, -12)) time.Sleep(time.Millisecond * 20) send(ProgramChange(1, 12)) send(ControlChange(2, FootPedalMSB, On)) } // stops listening stop()
Output: note started at 0ms channel: 0 key: 61 velocity: 100 note ended at 30ms channel: 0 key: 61 received PitchBend channel: 0 pitch: -12 (8180) at 30ms received ProgramChange channel: 1 program: 12 at 50ms control change 4 "Foot Pedal (MSB)" channel: 2 value: 127 at 50ms
Index ¶
- Constants
- Variables
- func A(oct int8) uint8
- func Ab(oct int8) uint8
- func AddTypeName(m Type, name string) bool
- func B(oct int8) uint8
- func Bb(oct int8) uint8
- func C(oct int8) uint8
- func CloseDriver()
- func CloseInPort(num int) error
- func CloseOutPort(num int) error
- func D(oct int8) uint8
- func Db(oct int8) uint8
- func E(oct int8) uint8
- func Eb(oct int8) uint8
- func F(oct int8) uint8
- func FindInPort(name string) int
- func FindOutPort(name string) int
- func G(oct int8) uint8
- func Gb(oct int8) uint8
- func InPorts() []string
- func ListenTo(portno int, recv func(msg Message, timestampms int32), opts ...Option) (stop func(), err error)
- func OutPorts() []string
- func SendTo(portno int) (func(msg Message) error, error)
- type Message
- func Activesense() Message
- func AfterTouch(channel, pressure uint8) Message
- func Continue() Message
- func ControlChange(channel, controller, value uint8) Message
- func MTC(m uint8) Message
- func NoteOff(channel, key uint8) Message
- func NoteOffVelocity(channel, key, velocity uint8) Message
- func NoteOn(channel, key, velocity uint8) Message
- func Pitchbend(channel uint8, value int16) Message
- func PolyAfterTouch(channel, key, pressure uint8) Message
- func ProgramChange(channel, program uint8) Message
- func ReadChannelMessage(status byte, arg1 byte, rd io.Reader) (m Message, err error)
- func Reset() Message
- func SPP(pointer uint16) Message
- func SongSelect(song uint8) Message
- func Start() Message
- func Stop() Message
- func SysEx(bt []byte) (m Message)
- func Tick() Message
- func TimingClock() Message
- func Tune() Message
- func (m Message) Bytes() []byte
- func (m Message) GetAfterTouch(channel, pressure *uint8) (is bool)
- func (m Message) GetChannel(channel *uint8) (is bool)
- func (m Message) GetControlChange(channel, controller, value *uint8) (is bool)
- func (m Message) GetMTC(quarterframe *uint8) (is bool)
- func (m Message) GetNoteEnd(channel, key *uint8) (is bool)
- func (m Message) GetNoteOff(channel, key, velocity *uint8) (is bool)
- func (m Message) GetNoteOn(channel, key, velocity *uint8) (is bool)
- func (m Message) GetNoteStart(channel, key, velocity *uint8) (is bool)
- func (m Message) GetPitchBend(channel *uint8, relative *int16, absolute *uint16) (is bool)
- func (m Message) GetPolyAfterTouch(channel, key, pressure *uint8) (is bool)
- func (m Message) GetProgramChange(channel, program *uint8) (is bool)
- func (m Message) GetSPP(spp *uint16) (is bool)
- func (m Message) GetSongSelect(song *uint8) (is bool)
- func (m Message) GetSysEx(bt *[]byte) bool
- func (m Message) Is(t Type) bool
- func (m Message) IsOneOf(checkers ...Type) bool
- func (m Message) IsPlayable() bool
- func (m Message) String() string
- func (m Message) Type() Type
- type Note
- type Option
- type Type
Examples ¶
Constants ¶
const ( Off uint8 = 0 // value meaning "off" On uint8 = 127 // value meaning "on" BankSelectMSB uint8 = 0 ModulationWheelMSB uint8 = 1 BreathControllerMSB uint8 = 2 FootPedalMSB uint8 = 4 PortamentoTimeMSB uint8 = 5 DataEntryMSB uint8 = 6 VolumeMSB uint8 = 7 BalanceMSB uint8 = 8 PanPositionMSB uint8 = 10 ExpressionMSB uint8 = 11 EffectControl1MSB uint8 = 12 EffectControl2MSB uint8 = 13 GeneralPurposeSlider1 uint8 = 16 GeneralPurposeSlider2 uint8 = 17 GeneralPurposeSlider3 uint8 = 18 GeneralPurposeSlider4 uint8 = 19 BankSelectLSB uint8 = 32 ModulationWheelLSB uint8 = 33 BreathControllerLSB uint8 = 34 FootPedalLSB uint8 = 36 PortamentoTimeLSB uint8 = 37 DataEntryLSB uint8 = 38 VolumeLSB uint8 = 39 BalanceLSB uint8 = 40 PanPositionLSB uint8 = 42 ExpressionLSB uint8 = 43 EffectControl1LSB uint8 = 44 EffectControl2LSB uint8 = 45 SoundVariation uint8 = 70 SoundTimbre uint8 = 71 SoundReleaseTime uint8 = 72 SoundAttackTime uint8 = 73 SoundBrightness uint8 = 74 SoundControl6 uint8 = 75 SoundControl7 uint8 = 76 SoundControl8 uint8 = 77 SoundControl9 uint8 = 78 SoundControl10 uint8 = 79 EffectsLevel uint8 = 91 TremuloLevel uint8 = 92 ChorusLevel uint8 = 93 CelesteLevel uint8 = 94 PhaserLevel uint8 = 95 DataButtonIncrement uint8 = 96 DataButtonDecrement uint8 = 97 NonRegisteredParameterLSB uint8 = 98 NonRegisteredParameterMSB uint8 = 99 RegisteredParameterLSB uint8 = 100 RegisteredParameterMSB uint8 = 101 AllSoundOff uint8 = 120 // send it with value of 0/Off AllControllersOff uint8 = 121 // send it with value of 0/Off AllNotesOff uint8 = 123 // send it with value of 0/Off OmniModeOff uint8 = 124 // send it with value of 0/Off OmniModeOn uint8 = 125 // send it with value of 0 MonoOperation uint8 = 126 PolyOperation uint8 = 127 // send it with value of 0 LocalKeyboardSwitch uint8 = 122 // send it with value of 127/On or 0/Off HoldPedalSwitch uint8 = 64 // send it with value of 127/On or 0/Off PortamentoSwitch uint8 = 65 // send it with value of 127/On or 0/Off SustenutoPedalSwitch uint8 = 66 // send it with value of 127/On or 0/Off SoftPedalSwitch uint8 = 67 // send it with value of 127/On or 0/Off LegatoPedalSwitch uint8 = 68 // send it with value of 127/On or 0/Off Hold2PedalSwitch uint8 = 69 // send it with value of 127/On or 0/Off GeneralPurposeButton1Switch uint8 = 80 // send it with value of 127/On or 0/Off GeneralPurposeButton2Switch uint8 = 81 // send it with value of 127/On or 0/Off GeneralPurposeButton3Switch uint8 = 82 // send it with value of 127/On or 0/Off GeneralPurposeButton4Switch uint8 = 83 // send it with value of 127/On or 0/Off )
const ( // PitchReset is the pitch bend value to reset the pitch wheel to zero PitchReset = 0 // PitchLowest is the lowest possible value of the pitch bending PitchLowest = -8192 // PitchHighest is the highest possible value of the pitch bending PitchHighest = 8191 )
Variables ¶
var ControlChangeName = map[uint8]string{
0: "Bank Select (MSB)",
1: "Modulation Wheel (MSB)",
2: "Breath controller (MSB)",
4: "Foot Pedal (MSB)",
5: "Portamento Time (MSB)",
6: "Data Entry (MSB)",
7: "Volume (MSB)",
8: "Balance (MSB)",
10: "Pan position (MSB)",
11: "Expression (MSB)",
12: "Effect Control 1 (MSB)",
13: "Effect Control 2 (MSB)",
16: "General Purpose Slider 1",
17: "General Purpose Slider 2",
18: "General Purpose Slider 3",
19: "General Purpose Slider 4",
32: "Bank Select (LSB)",
33: "Modulation Wheel (LSB)",
34: "Breath controller (LSB)",
36: "Foot Pedal (LSB)",
37: "Portamento Time (LSB)",
38: "Data Entry (LSB)",
39: "Volume (LSB)",
40: "Balance (LSB)",
42: "Pan position (LSB)",
43: "Expression (LSB)",
44: "Effect Control 1 (LSB)",
45: "Effect Control 2 (LSB)",
64: "Hold Pedal (on/off)",
65: "Portamento (on/off)",
66: "Sustenuto Pedal (on/off)",
67: "Soft Pedal (on/off)",
68: "Legato Pedal (on/off)",
69: "Hold 2 Pedal (on/off)",
70: "Sound Variation",
71: "Sound Timbre",
72: "Sound Release Time",
73: "Sound Attack Time",
74: "Sound Brightness",
75: "Sound Control 6",
76: "Sound Control 7",
77: "Sound Control 8",
78: "Sound Control 9",
79: "Sound Control 10",
80: "General Purpose Button 1 (on/off)",
81: "General Purpose Button 2 (on/off)",
82: "General Purpose Button 3 (on/off)",
83: "General Purpose Button 4 (on/off)",
91: "Effects Level",
92: "Tremulo Level",
93: "Chorus Level",
94: "Celeste Level",
95: "Phaser Level",
96: "Data Button increment",
97: "Data Button decrement",
98: "Non-registered Parameter (LSB)",
99: "Non-registered Parameter (MSB)",
100: "Registered Parameter (LSB)",
101: "Registered Parameter (MSB)",
120: "All Sound Off",
121: "All Controllers Off",
122: "Local Keyboard (on/off)",
123: "All Notes Off",
124: "Omni Mode Off",
125: "Omni Mode On",
126: "Mono Operation",
127: "Poly Operation",
}
stolen from http://midi.teragonaudio.com/tech/midispec.htm
var ErrListenStopped = drivers.ErrListenStopped
var ErrPortClosed = drivers.ErrPortClosed
Functions ¶
func AddTypeName ¶
AddTypeName adds names for new types that are not part of this package (e.g. meta types from the smf package). Don't use this function as a user, it is only internal to the library. Returns false, if the type already has been named, and true on success.
func FindInPort ¶
FindInPort returns the number of the midi in port with the given name It returns -1, if the port can't be found.
func FindOutPort ¶
FindOutPort returns the number of the midi out port with the given name It returns -1, if the port can't be found.
Types ¶
type Message ¶
type Message []byte
Message is a complete midi message (not including meta messages)
func AfterTouch ¶
AfterTouch returns an aftertouch message.
func ControlChange ¶
ControlChange returns a control change message.
func NoteOffVelocity ¶
NoteOffVelocity returns a note off message with velocity.
func Pitchbend ¶
Pitchbend returns a pitch bend message. If value is > 8191 (max), it will be set to 8191. If value is < -8192, it will be set to -8192. A value of 0 is considered as neutral position.
func PolyAfterTouch ¶
PolyAfterTouch returns a polyphonic aftertouch message.
func ProgramChange ¶
ProgramChange returns a program change message.
func ReadChannelMessage ¶
ReadChannelMessage reads a channel message for the given status byte from the given reader. Don't use this function as a user, it is only internal to the library.
func SysEx ¶
SysEx returns a system exclusive message. Only the inner bytes must be passed, the bytes that represent the start and end of a sysex message are added.
func (Message) GetAfterTouch ¶
GetAfterTouch returns true if (and only if) the message is a AfterTouchMsg. Then it also extracts the data to the given arguments.
func (Message) GetChannel ¶
GetChannel returns true if (and only if) the message is a ChannelMsg. Then it also extracts the channel to the given argument.
func (Message) GetControlChange ¶
GetControlChange returns true if (and only if) the message is a ControlChangeMsg. Then it also extracts the data to the given arguments.
func (Message) GetMTC ¶
GetMTC returns true if (and only if) the message is a MTCMsg. Then it also extracts the data to the given arguments.
func (Message) GetNoteEnd ¶
GetNoteEnd returns true if (and only if) the message is a NoteOnMsg with a velocity == 0 or a NoteOffMsg. Then it also extracts the data to the given arguments.
func (Message) GetNoteOff ¶
GetNoteOff returns true if (and only if) the message is a NoteOffMsg. Then it also extracts the data to the given arguments.
func (Message) GetNoteOn ¶
GetNoteOn returns true if (and only if) the message is a NoteOnMsg. Then it also extracts the data to the given arguments.
func (Message) GetNoteStart ¶
GetNoteStart returns true if (and only if) the message is a NoteOnMsg with a velocity > 0. Then it also extracts the data to the given arguments.
func (Message) GetPitchBend ¶
GetPitchBend returns true if (and only if) the message is a PitchBendMsg. Then it also extracts the data to the given arguments. Either relative or absolute may be nil, if not needed.
func (Message) GetPolyAfterTouch ¶
GetPolyAfterTouch returns true if (and only if) the message is a PolyAfterTouchMsg. Then it also extracts the data to the given arguments.
func (Message) GetProgramChange ¶
GetProgramChange returns true if (and only if) the message is a ProgramChangeMsg. Then it also extracts the data to the given arguments.
func (Message) GetSPP ¶
GetSPP returns true if (and only if) the message is a SPPMsg. Then it also extracts the spp to the given argument.
func (Message) GetSongSelect ¶
GetSongSelect returns true if (and only if) the message is a SongSelectMsg. Then it also extracts the song number to the given argument.
func (Message) GetSysEx ¶
GetSysEx returns true, if the message is a sysex message. Then it extracts the inner bytes to the given slice.
func (Message) IsPlayable ¶
IsPlayable returns, if the message can be send to an instrument.
type Note ¶
type Note uint8
type Option ¶
type Option func(*listeningOptions)
Option is an option for listening
func HandleError ¶
HandleError sets an error handler when receiving messages
func SysExBufferSize ¶
SysExBufferSize is an option to set the buffer size for sysex messages
func UseActiveSense ¶
func UseActiveSense() Option
UseActiveSense is an option to receive active sense messages
type Type ¶
type Type int8
Type is the type of a midi message
const ( // UnknownMsg is an invalid or unknown MIDI message UnknownMsg Type = 0 // RealTimeMsg is a MIDI realtime message. It can only be used over the wire. RealTimeMsg Type = -1 // SysCommonMsg is a MIDI system common message. It can only be used over the wire. SysCommonMsg Type = -2 // ChannelMsg is a MIDI channel message. It can be used in SMF and over the wire. ChannelMsg Type = -3 // SysExMsg is a MIDI system exclusive message. It can be used in SMF and over the wire. SysExMsg Type = -4 )
const ( // Tick is a MIDI tick realtime message (which is a RealTimeMsg). // There is no further data associated with messages of this type. TickMsg Type = 1 + iota // TimingClock is a MIDI timing clock realtime message (which is a RealTimeMsg). // There is no further data associated with messages of this type. TimingClockMsg // Start is a MIDI start realtime message (which is a RealTimeMsg). // There is no further data associated with messages of this type. StartMsg // Continue is a MIDI continue realtime message (which is a RealTimeMsg). // There is no further data associated with messages of this type. ContinueMsg // Stop is a MIDI stop realtime message (which is a RealTimeMsg). // There is no further data associated with messages of this type. StopMsg // ActiveSense is a MIDI active sense realtime message (which is a RealTimeMsg). // There is no further data associated with messages of this type. ActiveSenseMsg // Reset is a MIDI reset realtime message (which is a RealTimeMsg). // There is no further data associated with messages of this type. ResetMsg // NoteOn is a MIDI note on message (which is a ChannelMsg). // The channel of a concrete Message of this type can be retrieved via the Channel method of the Message. // The velocity of a concrete Message of this type can be retrieved via the Velocity method of the Message. // The key of a concrete Message of this type can be retrieved via the Key method of the Message. NoteOnMsg // NoteOff is a MIDI note off message (which is a ChannelMsg). // The channel of a concrete Message of this type can be retrieved via the Channel method of the Message. // The velocity of a concrete Message of this type can be retrieved via the Velocity method of the Message. // The key of a concrete Message of this type can be retrieved via the Key method of the Message. NoteOffMsg // ControlChange is a MIDI control change message (which is a ChannelMsg). // The channel of a concrete Message of this type can be retrieved via the Channel method of the Message. // The controller of a concrete Message of this type can be retrieved via the Controller method of the Message. // The change of a concrete Message of this type can be retrieved via the Change method of the Message. ControlChangeMsg // PitchBend is a MIDI pitch bend message (which is a ChannelMsg). // The channel of a concrete Message of this type can be retrieved via the Channel method of the Message. // The absolute and releative pitch of a concrete Message of this type can be retrieved via the Pitch method of the Message. PitchBendMsg // AfterTouch is a MIDI after touch message (which is a ChannelMsg). // The channel of a concrete Message of this type can be retrieved via the Channel method of the Message. // The pressure of a concrete Message of this type can be retrieved via the Pressure method of the Message. AfterTouchMsg // PolyAfterTouch is a polyphonic MIDI after touch message (which is a ChannelMsg). // The channel of a concrete Message of this type can be retrieved via the Channel method of the Message. // The key of a concrete Message of this type can be retrieved via the Key method of the Message. // The pressure of a concrete Message of this type can be retrieved via the Pressure method of the Message. PolyAfterTouchMsg // ProgramChange is a MIDI program change message (which is a ChannelMsg). // The channel of a concrete Message of this type can be retrieved via the Channel method of the Message. // The program number of a concrete Message of this type can be retrieved via the Program method of the Message. ProgramChangeMsg // MTC is a MIDI MTC system common message. // TODO add method to Message to get the quarter frame and document it. MTCMsg // SongSelect is a MIDI song select system common message. // TODO add method to Message to get the song number and document it. SongSelectMsg // SPP is a MIDI song position pointer (SPP) system common message. // TODO add method to Message to get the song position pointer and document it. SPPMsg // Tune is a MIDI tune request system common message. // There is no further data associated with messages of this type. TuneMsg )
Source Files
¶
Directories
¶
Path | Synopsis |
---|---|
midicatdrv
Package midicatdrv provides a Driver to connect via the program midicat (from the tools).
|
Package midicatdrv provides a Driver to connect via the program midicat (from the tools). |
portmididrv
Package portmididrv provides an Driver to connect via portmidi.
|
Package portmididrv provides an Driver to connect via portmidi. |
portmididrv/imported/portmidi
Package portmidi provides PortMidi bindings.
|
Package portmidi provides PortMidi bindings. |
rtmididrv
Package rtmididrv provides a Driver to connect via rtmidi.
|
Package rtmididrv provides a Driver to connect via rtmidi. |
testdrv
Package testdrv provides a Driver for testing.
|
Package testdrv provides a Driver for testing. |
webmididrv
Package webmididrv provides a Driver to connect to MIDI ports in the browser (via webmidi).
|
Package webmididrv provides a Driver to connect to MIDI ports in the browser (via webmidi). |
webmididrv/example
Module
|
|
example
|
|
listports
Module
|
|
logger
Module
|
|
simple
Module
|
|
smf0player
Module
|
|
smf0recorder
Module
|
|
smfplayer
Module
|
|
smfrecorder
Module
|
|
Package gm provides constants for instruments, drumkits and percussion keys based on the General MIDI standard.
|
Package gm provides constants for instruments, drumkits and percussion keys based on the General MIDI standard. |
internal
|
|
Package smf helps with reading and writing of Standard MIDI Files.
|
Package smf helps with reading and writing of Standard MIDI Files. |
Package sysex provides helpers when dealing with system exclusiv messages
|
Package sysex provides helpers when dealing with system exclusiv messages |
tools
|
|
midicat/cmd/midicat
Module
|
|
midispy
Module
|
|
midispy/cmd/midispy
Module
|
|
smflyrics
Module
|