This is a fork of laamaa's fantastic cross platform M8 tracker headless client or M8C for short and includes some minor modifications based on rasprague's fork. The modifications include adding two special button combinations for resetting the display and quitting the program before shutting down the Raspberry Pi.
M8C is a client for Dirtywave M8 headless mode. The original application should be cross-platform ready and can be built in Linux, Windows and Mac OS. However, this specific fork has been tested only on Raspberry Pi 4 Model B.
The main objective of this fork is to run M8C on a Raspberry Pi 4 with the best performance possible. Which means a stable setup with a good resolution and acceptable refresh rate, low audio latency and no sound artifacts such as random clicks and pops. After testing different approaches, I've settled for Blokas Patchbox OS and SDL2.
Below, you'll find the instructions to install Patchbox OS, configure your system and install M8C. In the end, M8C should start automatically on boot, connect your audio and MIDI devices and shutdown after quitting M8C.
If you have a Dirtywave M8 or if you're using M8 Headless, feel free to visit this website I created with a bunch of shortcuts, tips and tricks for the M8.
This project would not exist without Timothy Lamb's phenomenal invention, the Dirtywave M8 Tracker. Thank you for developing this fantastic product and for allowing the community to test and play it with the M8 Headless!
The M8C is also an essential part of this puzzle. Thank you very much laamaa for putting this together!
And finally, thank you to all the people on M8 Discord for all your support and rasprague for your button combination!
While this project may give you access to some sort of a handheld M8 with relatively low audio latency and reasonable stability, this should be regarded as a temporary device for testing or learning purposes only.
From my experience, no matter what you do, you will end up with some audio latency (even if minor) and eventual random crashes (either from overheating or from Alsa instability). The user experience will feel crippled when compared with what you would get with the actual M8 and there is no customer support for this project.
The Teensy 4.1, while very robust, may get damaged when handled by inexperienced people (like me) and you may need to spend money buying more than one. Furthermore, you may need to put a lot of time onto this project and those hours have a cost. Which means that this project could be more expensive than buying the actual M8 unless you already have everything you need and you know very well what you are doing.
IMPORTANT: If you gel with the tracker workflow and you like the M8, please support Timothy Lamb and Dirtywave by purchasing the actual product and/or subscribing to his Patreon. This project is not affiliated with Dirtywave.
Putting together a Raspberry Pi 4 with a screen, a Teensy board, a USB sound card, a game controller and, eventually, some sort of Power Bank or battery will always end up being a hot mess of cables.
This could be partially solved with a case such as a PiBoy or something similar or by 3D printing a custom case. However, this is a temporary device and I want to use most (if not all) of the parts in different audio projects. Thus, I opted to create something fun and easy to build and take apart.
I started thinking about different solutions, but Lego immediately became the obvious choice. I would be lying if I said that no Lego parts were hurt in this project. Afterall, it's not easy to hold the boards without screws.
Picture of headless M8 Tracker running in Raspberry Pi 4 Model B with 1 GB of RAM:
Another picture of the setup with headphones for scale:
And, lastly, a picture showing the different gear that can be connected:
Here's a quick demo video of this projetc:
-
A working Raspberry Pi 4 Model B. I'm using a discontinued 1GB model, so any RPi4 will do.
-
A Raspberry Pi Screen such as a Waveshare or equivalent. I'm using a cheap 3.5" LCD with HDMI.
-
A TeenTeensy 4.1 Board with the latest M8 Headless Firmware installed.
-
A USB Cable with 5-Pin Micro-B Plug to connect the Teensy to the Raspberry Pi. Must be a power and data cable, otherwise the Pi will not find the Teensy.
-
A USB audio interface. I got a really cheap USB sound card with a HS-100B chip. It's great because it handles 48K or 44.1KHz sampling rates and small buffer sizes. The only downside is the mono ADC, which means that I have stereo output, but only mono input.
-
A USB Game Controller. I'm using a Geeekpi set of controllers, but I wanted something really cheap so I could take it apart.
-
A power adapter for the Raspberry Pi or a Power Bank or something similar if you want a portable device. I'm using something like this because my Power Bank wasn't cutting it.
-
An ethernet cable because we will disconnect Wi-Fi to save battery and, hopefully, improve performance.
-
Lastly, if you want to put together something similar to what I've done, then you'll need lots of Lego. Preferably Lego Technics to keep everything cool and well ventilated.
-
Download and install balenaEtcher.
-
Download and unzip Patchbox OS.
-
Insert the SD card to your computer's SD card reader and launch balenaEtcher.
-
Click “Flash from File” and select the file you want to upload (e.g. 2022-05-17-Patchbox.img).
-
Click “Select Target”, choose your SD card and click “Flash”.
-
After flashing, safely remove the SD card, insert it into your Raspberry Pi and power it on.
-
Connect your computer to the same Network as Raspberry Pi.
-
Open a Terminal window and paste the following after boot is complete (password: blokaslabs):
ssh-keygen -R patchbox.local
ssh [email protected]
-
Follow the Setup Wizard instructions. Within the wizard, start by updating if required, then change your password, configure audio following these instructions, choose the boot environment ("Console Autologin"), disable Wi-Fi and, lastly, do not select any module (“None: Default Patchbox OS Environment”).
-
Once the setup if finished, open the config.txt file to edit the display settings, disable Bluetooth and WiFi and improve boot time:
sudo nano /boot/config.txt
hdmi_force_hotplug=1
hdmi_group=2
hdmi_mode=2
hdmi_cvt=480p 60 6 0 0 0
- If you have black borders around your display or if you cannot see the whole display, you may need to adjust “overscan”. In my case, I need to add the following so the left side of the display doesn’t go under the screen cover/protection:
overscan_left=16
overscan_right=-16
- Disable the on-board or internal (Broadcom) sound card, just add the following under “# Enable audio (loads snd_bcm2835)” (source):
dtparam=audio=off
- Disable HDMI audio, under “# Enable DRM VC4 V3D driver” (source):
dtoverlay=vc4-kms-v3d,noaudio
- Add the following under [all] (source). To enable these options back, just comment each line. Note that you’ll need an ethernet cable from here on:
dtoverlay=disable-bt
dtoverlay=disable-wifi
-
Save, exit and reboot the Raspberry Pi.
-
To improve boot time, go to raspi-config and disable “Wait for Network on Boot”, under “System Options” and “Network at Boot”:
sudo raspi-config
-
Still in raspi-config, set the locale to en_US.UTF-8.
-
Go to “Localisation Options”, then “Locale”, and select en_US.UTF-8 using the spacebar. Exit raspi-config and reboot:
sudo reboot
- Login again and finish setting the locale:
sudo update-locale LC_ALL="en_US.UTF-8"
sudo update-locale LANGUAGE="en_US"
sudo reboot
- Login again and check that your Raspberry Pi OS locale is properly set by typing the command locale and making sure it returns the following:
locale
LANG=en_US.UTF-8
LANGUAGE=en_US:en
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=en_US.UTF-8
- Disable pisound-ctl, pisound-btn, touchosc2midi services and opt-out of statistics program, which are not necessary:
sudo systemctl disable pisound-ctl
sudo systemctl disable pisound-btn
sudo systemctl disable touchosc2midi
sudo systemctl disable wifi-hotspot.service
sudo systemctl disable --now blokas-telemetry.target
- Login again, update, install required packages and install SLD2:
sudo apt update && sudo apt install -y git gcc make libsdl2-2.0-0 libsdl2-dev
sudo reboot
- Install other package needed to compile and install M8C:
sudo apt install -y autotools-dev autoconf libtool
- Download the source code for libserialport:
cd
git clone https://github.com/sigrokproject/libserialport.git
- After cloning, compile and install:
cd libserialport
./autogen.sh
./configure
make
sudo make install
- A couple more steps:
sudo ln -s /usr/local/lib/libserialport.so.0.1.0 /usr/lib/libserialport.so.0.1.0
sudo ln -s /usr/local/lib/libserialport.so.0 /usr/lib/libserialport.so.0
- And finally, run to finalise the packages installation and to ensure the library is found when building M8C:
sudo ldconfig
- At this stage, you can reboot before installing M8C:
cd
git clone https://github.com/RowdyVoyeur/m8c-rpi4.git
- Followed by, once it’s cloned:
cd m8c-rpi4
make
sudo make install
- Lastly, make shell scripts executable by everyone:
chmod a+x m8c*.sh
- To generate the config files in .local/share/m8c you need to run M8C once. Connect the Teensy 4.1 with the installed M8 Headless Firmware to the Raspberry Pi 4 using a USB data cable. Wait 10 seconds to ensure it is properly connected and run the following commands (use Ctrl+C or close the Terminal window to quit M8C):
cd m8c-rpi4
./m8c.sh
- Type the following to find if config.ini has been successfully generated (if config.ini isn't listed in this folder, repeat the step above):
cd .local/share/m8c
ls
-
Edit the config.ini file, so the [graphics] and [gamepad] sections look like this. Don't forget to change "fullscreen" and "disable_cursor" to "true".
-
Then, type the following to point the M8C to the gamecontrollerdb.txt, so it finds the game controller mapping:
cd ~/.local/share/m8c
ln -s ~/m8c-rpi4/gamecontrollerdb.txt .
-
On startup, M8C tries to load a SDL game controller database named gamecontrollerdb.txt from the same directory as the config file. Therefore, you need to check whether gamecontrollerdb.txt is inside .local/share/m8.
-
Assuming the gamecontrollerdb.txt is inside .local/share/m8, then you need to ensure that your game controller mapping is listed in this file. Just go to /m8c-rpi4 and edit gamecontrollerdb.txt and do one of the following:
-
Copy the full database from here and paste it onto gamecontrollerdb.txt. If your game controller is listed, then M8C should automagically recognize it;
-
If this does not work, then download SDL2 Gamepad Tool and follow the instructions to get your game controller mapping. Once you have the mapping, paste in under the “#Custom” line of gamecontrollerdb.txt.
-
amidiauto is a background process of Patchbox OS which takes care of setting up the MIDI routings automatically. You just need to configure it, so it recognizes and connects the MIDI devices. You can find an example here, but here's what I've done to automatically connect MC-101 and nanoKONTROL to M8:
-
Edit the amidiauto config file with the following command:
sudo nano /etc/amidiauto.conf
- And, in my case, here´s how it looks like:
[allow]
* <-> * # allows automatically connecting hardware and software ports
MC-101 <-> M8 # connects MC-101 and M8 in both directions
nanoKONTROL -> M8 # connects nanoKONTROL to M8
- Unless you already know the names of your devices, you'll need to find them by listing all the connected MIDI devices with:
amidi -l
-
Ths final step of my setup is to ensure the M8C starts on boot. To do this, I've used Cron (more information here and here):
-
Edit Cron as user, so it has permissions to run everything on boot:
sudo crontab -u patch -e
- Then, just add the following to the last line:
@reboot /home/pi/m8c-rpi4/m8c.sh
- Everything should be done now. You can safely shutdown Raspberry Pi.
-
Turn your Raspberry Pi on and M8C should start after boot. Provided that all audio and MIDI devices are connected and configured, the M8C script should automatically connect the audio in and out of M8C to the default sound card and amidiauto will connect all the MIDI devices.
-
You can use the following button combinations to reset the display or to quit the M8C script before automatically shutting down:
-
Reset display in case of graphic glitches: SELECT + OPTION + UP
-
Quit M8C and automatically shutdown Raspberry Pi: SELECT + OPTION + DOWN
-
If the M8C starts on boot, you can hear the M8 audio and record onto it, sync your connected MIDI devices and shutdown with the button combination, then you're good to go!
-
Well done, grab a cup of coffee, read the M8 User Manual and start saving for the actual thing ;)