HoerspielPi
Purpose
('Hörspiel' is german for 'radioplay')
This thing is called HoerspielPi and you can see a video demonstrating what it does
here
(video to be uploaded yet)
I have not practised playing piano for quite a while, please excuse my
horrible touch in this video. But i hope you get the idea.
HoerspielPi is essentially a headless RaspberryPI 3, running Raspbian
and sooperlooper. Sooperlooper is a live looping sampler application,
it is open source and makes use of the JACK audio server.
HoerspielPi is not so much meant to make music (my piano skills are
really rusty at the moment) but rather to make a live radioplay one
day, where ambient atmosphere is built up by overdubbing loops.
I developed HoerspielPi because I did not want to by a dedicated
looper hardware for about 100Euro or more, maybe even an additional
midi controller. Instead everything is controlled by rarely used
ranges of the piano that I have. In addition to the keyboard, this
piano has only one turnknob I can use for MIDI. I use it for pan (or
rec_thresh, maybe).
Hardware
Raspberry Pi 3 B
a 8×8 matrix of red leds, with max7219 driver, connected to the Raspberry Pi via SPI
a button (broken out of an old PC), connected between Pin 5 and GND. This allows booting and shutting down the Pi properly.
a cheap USB soundcard. USB soundcards are said to allow only for moderate latency, but HoerspielPi is not really meant for making music anyway. This is why latency is not very important here, and I have not really tried to optimise for it. Instead, the soundcard being external makes the thing modular, in case I want to use the card otherwise.
a simple audio mixer, to feed mics or instruments into the soundcard which has just 1 line input *or* 1 microphone input.
an electronic piano, connected via USB-MIDI to the Pi.
Software
Raspbian
jack2
sooperlooper engine
http://essej.net/sooperlooper/ Sooperlooper is written with an engine separated from the
GUI. HoerspielPi only starts the engine, not slgui (the standard
GUI).
a sooperloooper
GUI python script (written by me), to display some sooperlooper states and values on the 8×8 led matrix. It communicates with the engine using OSC messages.
a mididings script, to split the midi note messages of the piano into 2 ranges, 'piano' and 'looper-control'.
The 'looper-control' range is everything above a certain note, 'c5' for me. The script transposes these notes to be next to 'c2' and sends them, actually to sooperlooper and the midi emulation script. This way, i can keep the sooperlooper bindings the same, no matter which octave is used for its midi control.
The 'piano' range is not transposed and just passed further, actually back into the piano. Since the piano is configured not to produce sounds for keypresses, but only for incoming midi, this makes the 'looper-control' range silent.
a python script to listen for a very long keypress (anywhere on the piano), of at least 10 seconds. When this is detected, it modifies the config file of the mididings script to do the keyboard splitting at precisely this note, and reboot. This way, the pressed key will become the „prev“, and the neighbouring ones be bind to the other commands, in order. Hence, this is not a full midi learning mechanism, but it allows to plug also a small midi keyboard to HoerspielPi, and use it.
an python script (written by me), to emulate certain midi messages
it emulates CC (control change): the value can be in-/decremented with piano key presses. The more velocity the note has, the more the control value changes.
it detects notes lasting for longer than 2 seconds. When this is detected, first a note_on msg will be sent again, and then secondly a note_on at *one octave higher*. The sooperlooper midi binding uses this to do 'pause', 'reverse' and 'undo_all' commands either for the selected loop (short keypress) or all loops (long keypress)
a python script to put an interrupt, to execute a command line when the button is pressed. This is used to shut down cleanly.
a script which displays simple splash animations on boot and shutdown. The shutdown runs neatly from the moment the button is pressed, to (almost) the moment the Pi is off. For the boot splash I could not find a way to display it really early and to make it stop (e.g. by systemd service conflict) when the dotmatrix is used by the sooperlooper client. So this has a fixed duration and actually prolongates the booting… but dont tell anyone (and hey, zynthian seems to do the same).
a python script which tries to find the correct soundcard and start jackd with reasonable parameters, to avoid xruns.
The whole thing is set up as a (crude, does not pass lintian cleanly,
but works for me) deb package, which will install/remove all the systemd
services, make a hoerspielpi the default target, give jackd the
appropriate dbus rights (by drop-in file), enable SPI, make some performance settings,
put a default midi binding, etc.
It will install required python packages using pip in the postinst script of the package.
This is not the way a package is supposed to do it, but I was not able to make it
work otherwise.
Python3 is used as much as possible, except for mididings, which I was not able to install for python3.
Usage
1. Install Rasbian or one of its minimal derivates on the SD of your Pi
2. copy the deb package to it and install it. This step needs a working internet connection.
3. connect a soundcard and a midi keyboard
4. reboot.
What the display shows
The 8×8 led matrix displays the selected loop as a number. The top line
shows a running pixel which is the current playback position in the selected loop.
The bottom line displays the record threshold, I just copied the log
function from the sooperlooper standard gui. The record threshold
changed in the same way for all loops, for simplicity, so this
displays the same value for all loops (unless you use slgui at the same time).
Single illuminated pixels in the leftmost column, at the left of the number, indicate thestate of commands, in this order (from top to bottom):
pause, play, mute, record, overdub, substitute, multiply, sync
About sync
There is only one key dedicated to sync at the moment. This key is
midi-wise bound to (many or all) of the sync-related settings of
sooperlooper. That is, by toggeling 'sync', you also toggle
'playback_sync', 'relative sync', quantize='loop' and 'round'. As I
am not experienced at all with live looping, this may change as I
discover how it works best for me.
ToDo
At the moment HoerspielPi lacks:
visualisation of many sooperlooper settings I considered irrelevant for me
other functionality than looping (what about some atmo recordings, or samples?)
There are still about 4*6=24 pixels unused…