- C 79.8%
- Makefile 16.2%
- Shell 4%
| .gitignore | ||
| CHANGELOG.md | ||
| crosscompile.container | ||
| LICENSE | ||
| Makefile | ||
| midipipe.1.md | ||
| midipipe.c | ||
| README.md | ||
| twistertop.sh | ||
midipipe - MIDI from stdin and to stdout
midipipe(1) is a Linux program that accepts MIDI events in a plain text format
on stdin, and sends them to a MIDI device or client using the ALSA sequencer
API, and vice versa.
echo 'ch 1 note_on 60 127' | midipipe | grep 'ch 2 cc'
It keeps a persistent client, so while you can send a single message like in
this example, you can also continuously stream messages in or out, which is
where midipipe shines.
Use it in your shell scripts, or really anywhere where you don't have a proper MIDI API available, but you are able to shell out and write to/from a sub-process. It also makes a great "MIDI monitor", to see exactly the messages a device or program is emitting.
Events are always sent in (or near) real time, midipipe does not handle
timestamps.
Installation
There are per-built binaries available on the releases page, or build it from source (see below).
Design and Usage
midipipe - MIDI message to and from plain text pipe
OPTIONS:
-i, --input <dev> Connect device for input
-o, --output <dev> Connect device for output
-d, --device <dev> Connect device for input and output
-c, --client <name> Name of the ALSA client, default 'midipipe'
-v, --version Print version information and exit
-l, --list List devices
-h, --help Show this output
midipipe uses the ALSA Sequencer API, not the more low-level ALSA Rawmidi
API. With Rawmidi, only one process can access a device at the same time. With
Sequencer, you get a "client" with an input and output port, which can be
connected to multiple devices, or routed to other clients. Sequencer also plays
nicely with modern Pipewire setups, allowing you to freely interconnect
ALSA/Jack/Pulseaudio/Pipewire applications.
midipipe can setup connections for you when it starts (see
--input/--output/--device), or you can set them up yourself through
aconnect, once or the patch bay application of your choice.
--list, -l— List devices--input, -i— Specify an input device (a devicemidipipewill read from)--output, -o— Specify an output device (a devicemidipipewill write to)--device, -d— Combination of-iand-o, connect to the same device for input and output
Devices can be specified with ALSA address numbers, e.g. midipipe -d 28:0, or
by name. A partial prefix of the name is enough. So to connect to 28:0 - Midi Fighter Twister MIDI 1, any of the following work:
midipipe -d 28:0
midipipe -d 'Midi Fighter Twister MIDI 1'
midipipe -d 'Midi Fighter'
midipipe -d 'Midi F'
MIDI Message Format
MIDI messages are represented as line-based text, each line representing a single MIDI message of a given type on a given channel. Channel numbers are 1-indexed (1-16).
| Message Type | Text Format | Notes |
|---|---|---|
| Note On | ch <1-16> note_on <note> |
Velocity = 127 |
| Note On | ch <1-16> note_on <note> <velocity> |
|
| Note Off | ch <1-16> note_off <note> |
|
| Controller | ch <1-16> cc <param> <value> |
|
| Program Change | ch <1-16> pgm <value> |
|
| Channel Pressure | ch <1-16> pressure <value> |
|
| Key Pressure | ch <1-16> keypress <note> <value> |
|
| Pitch Bend | ch <1-16> bend <0-16383> |
Values for <note>, <value>, <velocity>, <param> are in the 0-127 range.
Building
To build the midipipe binary
make
To cross-compile multiple architectures (requires podman):
make cross-build
To build the man page (requires pandoc)
make man
Installation
sudo make install
To uninstall
sudo make uninstall
These will honor $PREFIX and/or $DESTDIR.
Examples
The included twistertop.sh is a shell script that you can pipe into midipipe:
./twistertop.sh | midipipe -d '...', and which will use the LEDs on a MIDI
Fighter Twister controller to show current CPU load.
Shell tips
In bash you can use coproc to get a subprocess with file descriptors you can
read from or write to:
#!/bin/bash
coproc MIDI { ./midipipe "$@"; }
# Write to midipipe
echo "ch 1 note_on 60" >&"${MIDI[1]}"
sleep 0.5
echo "ch 1 note_on 62" >&"${MIDI[1]}"
sleep 0.5
echo "ch 1 note_on 64" >&"${MIDI[1]}"
# Read from midipipe
while true; do
read -u "${MIDI[0]}" _ chan type p1 p2
echo "Midi says: channel $chan, message $type, $p1, $p2"
done
Dependencies
- ALSA development libraries (
libasound2-devon Ubuntu/Debian) - Standard C library development tools
- pandoc for the man page
- podman for cross compilation
License
© Copyright Arne Brasseur 2026. Licensed under the EUPL, see LICENSE.