PortMidi.jl
This is mostly a fun project I did in the last few days to play music with Julia and to learn how to use BinaryBuilder.jl (thanks @giordano for all the corrections of my beginner mistakes).
PortMidi.jl is a mostly autogenerated wrapper of PortMidi/portmidi: portmidi is a cross-platform MIDI input/output library (github.com), allowing us to play music instruments (and other devices) via MIDI on Linux, macOS and Windows.
The underlying C library itself is very portable but hence also minimal. It can:
- Open and close existing MIDI devices
 - (Create new virtual MIDI devices on some platforms)
 - Send and receive MIDI messages in real-time
 - A few things regarding synchronization and timing for real-time applications
 
I could imagine that it could be useful in JuliaMusic @Datseris? Or maybe it could help to play music with MusicTheory.jl @dpsanders?
EDIT: That was fast, it is now part of JuliaMusic ![]()
Example for generating music
On a computer with some MIDI instrument listening, one can essentially do something like:
using PortMidi, MusicTheory
using MusicTheory.PitchNames
id = 1  # change according to setup
Pm_Initialize()
stream = Ref{Ptr{PortMidi.PortMidiStream}}(C_NULL)
Pm_OpenOutput(stream, id, C_NULL, 0, C_NULL, C_NULL, 0)
# 3. Send MIDI messages to play notes  (0x90: Note ON, 0x80: Note OFF)
function play_note(stream, note, velocity, duration)
    Pm_WriteShort(stream[], 0, Pm_Message(0x90, semitone(note), velocity)) 
    sleep(duration)
    Pm_WriteShort(stream[], 0, Pm_Message(0x80, semitone(note), velocity))
end
# 4. play a melody
@sync begin
    for (base, type) in zip([C[4], G[4], A[4], F[4]], [Major, Major, Minor, Major])
        for rep in 1:3
            @async play_note(stream, base, 100, 0.3)
            @async play_note(stream, base + Interval(3, type), 100, 0.25, 0.05)
            @async play_note(stream, base + Interval(5, Major), 100, 0.28, 0.02)
            sleep(0.4)
        end
        sleep(0.4)
    end
end
# 4. Close device
Pm_Close(stream[])
Here is a small and not very musical melody ‘Random Melody’ generated with this script example script.
Setup for actually hearing sound
On Windows, one might want to use loopMIDI to create a virtual MIDI device and then some VSTs in a DAW or VCV Rack to generate some sound from the incoming MIDI. (It’s off-topic, but feel free to PM me if you need advice for the setup.)
Next?
I didn’t add much to the generated wrapper yet, since I am only interested in playing music and that is simple enough.
- The main question I need to answer is: Will people use it, and if, should extra functionallity go into a separate package or directly to PortMidi.jl?
 
Any suggestions are very welcome.
PS: My dream, in another package, is to do something like Extempore docs (extemporelang.github.io) but with pure Julia. No idea yet how to manage the hot-loading of new coding while playing music ![]()