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