Skip to content
No description, website, or topics provided.
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.

Winterbloom SmolMIDI

This is a CircuitPython helper library for communicating over MIDI. This library is intentionally minimal and low-level. It's just enough to make using the PortIn bearable. If you are looking for a high-level, beginner-friendly MIDI library please look at Adafruit CircuitPython MIDI.

It's also experimental at this point. While I've verified it works for my boards, my controllers, and my DAWs, I haven't been able to test it broadly enough to feel confident it'll work with other setups. If you use it and run into issues, please file a bug and let me know!


Create a MidiIn instance using a PortIn instance:

import usb_midi
import winterbloom_smolmidi as smolmidi

midi_in = smolmidi.MidiIn(usb_midi.ports[0])

Then use receive to receive messages. You can use the message type constants at the top of the library file to determine what sort of MIDI message you received:

while True:
    msg = midi_in.receive()
    if not msg:

    if msg.type == midi.NOTE_ON:
        channel =
        note =[0]
        velocity =[1]
        print('Note On, Channel: {}, Note: {}, Velocity: {}'.format(
            channel, note, velocity))
    elif msg.type == midi.NOTE_OFF:
        note =[0]
        velocity =[1]
        print('Note Off, Channel: {}, Note: {}, Velocity: {}'.format(
            channel, note, velocity))
    elif msg.type == midi.SYSTEM_RESET:
        print('System reset')

System exclusive messages

This library has basic support for system exclusive messages. To get a system exclusive message you must check for the SYSEX message and then call receive_sysex to get the data for the payload. If you don't call receive_sysex the payload will be discarded on the next call to receive. receive_sysex requires you to pass the maximum number of bytes to read from the payload. Any remaining bytes will be discarded.

while True:
    msg = midi_in.receive()
    if not msg:

    if msg.type == midi.SYSEX:
        sysex_payload, truncated = midi_in.receive_sysex(128)
        print('Got sysex of length {}, Truncated: {}'.format(
            len(sysex_payload, 128)))

In the future, I may add the ability to read the sysex messages in chunks if that's something folks desire.

No MidiOut?

The built-in PortOut is more than usable enough at a low-level. For example, you can use the constants defined here to send a Note On message:

port_out = usb_midi.ports[0]
port_out.write(bytearray([smolmidi.NOTE_ON, 0x64, 0x42]))

So at this point I don't feel like it needs an additional library to wrap it, but, if you have ideas I'd love to hear them. :)


Install this library by copying to your device's lib folder.

License and contributing

This is available under the MIT License. I welcome contributors, please read the Code of Conduct first. :)

You can’t perform that action at this time.