Saturday, August 22, 2020

Starting JACK automatically when a USB audio device is connected

I have a Raspberry Pi that I'm using headless for audio, and I wanted to automatically start jackd when I connected my USB audio device.

There are a lot of ways to try to do this - after a few false starts, I ended up with this method. It took me long enough to sort out the details that I figured I'd write up a little how-to.

This solution is composed of two parts: 1) set up jackd as a systemd service, and 2) use a udev rule to start the service when the sound card is connected.

First the service. Create a file called '/etc/systemd/system/jackd.service' with the following:

[Unit]
Description=JACK audio
After=network.target

[Service]
ExecStart=/usr/bin/jackd <your jack commandline arguments here>
WorkingDirectory=/usr/local/bin
StandardOutput=inherit
StandardError=inherit
Restart=always
User=root

[Install]
WantedBy=multi-user.target

Now (or at least after you reboot, or do 'sudo systemctl daemon-reload', you can start and stop jackd with 'sudo systemctl start jackd.service' and 'sudo systemctl stop jackd.service'. I'm running the service as root - if you want to use a different user, change the "User=" line.

We want this to happen automatically, though, so it is time to use udev - the system for managing Linux device events.

First, you need to know some information about your USB audio device. Plug it in, and run 'lsusb'. You should see something like this:

Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 003: ID 0582:01d6 Roland Corp.
Bus 001 Device 002: ID 2109:3431 VIA Labs, Inc. Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

Look for your sound card device in the list (mine is showing as "Roland Corp."), and note the two hex numbers after ID. They are the USB Vender and Product IDs for your device.

Create a file called something like '/etc/udev/rules.d/80-local.rules' with the following in it:

ACTION=="add", ATTR{idVendor}=="0582", ATTR{idProduct}=="01d6", TAG+="systemd", ENV{SYSTEMD_WANTS}="jackd.service"

Where the values for 'ATTR{idVendor}' and 'ATTR{idProduct}' are the Vendor and Product IDs you got from lsusb.

After your next reboot, or after running 'sudo udevadm control --reload', you new rule should be ready. When you plug in your sound card, the udev rule will fire and request your service, which will then start jackd.

Thursday, January 30, 2020

Using the Mod Devices guitar effects interface on Raspberry Pi 4


My last post was about getting my Boss GT-1 guitar effects floorboard to work in Linux. The reason I wanted to do this was to couple it with a Raspberry Pi to create a more configurable effect chain using LV2 plugins.

Once I had audio working, I installed Guitarix, an open-source guitar effects stack for Linux, and I was quickly off to the races. Guitarix works really well, but the interface is designed for desktop use - not ideal for my needs.

I had been aware of Mod Devices for a while, with their Mod Duo multi-effects hardware pedals built on top of Linux. They have added a slick, web-based pedalboard interface running on top of LV2 plugins. It is primarily designed for their hardware devices, but the project is open source.

The folks over at blokas.io have a project called MODEP, which provides a custom Raspberry Pi image for running the Mod Devices interface. Unfortunately, it currently does not work on Raspberry Pi 4, which is what I have.

So, I went straight to the Mod Devices GitHub and built it myself. It turned out to be pretty straightforward, and I was up and running after about a half an hour of tinkering. I'm going to try to outline what I did here in case anyone else wants to give it a try:

Get Jack running with audio capture and playback - there is plenty of information out there on this

Get the Mod software from GitHub:
  git clone --depth 1 https://github.com/moddevices/mod-host
  git clone --depth 1 https://github.com/moddevices/mod-ui
Install the tools you need to build the mod software. You'll need at least:
sudo apt-get install virtualenv python3-pip python3-dev git build-essential libasound2-dev libjack-jackd2-dev liblilv-dev libjpeg-dev zlib1g-dev
Build mod-host from the mod-host directory:
make
sudo make install
cd mod-ui
make
sudo make install
Make sure Jack is running, and start mod-host:
mod-host -n -p 5555 -f 5556
In another shell, build mod-ui from the mod-ui directory:
virtualenv modui-env
source modui-env/bin/activate
pip3 install -r requirements.txt
make -C utils
Run mod-ui from the mod-ui directory (you will also need to do "source modui-env/bin/activate" first if you did not just do it in the above build step):
export MOD_DEV_HOST=0
export MOD_DEV_ENVIRONMENT=1
export MOD_APP=1
export MOD_LIVE_ISO=1
python3 ./server.py
The mod-ui web server should now be running on port 8888. To access it, find out the IP address of your Raspberry Pi, and go to:
http://YOUR-PI-IP:8888/
You should see the Mod pedalboard interface. It should load whatever LV2 plugins you have in /usr/lib/lv2 with a generic look. In my case, I had Guitarix installed and all of its plugins were there and ready to be used.

The Mod folks have custom UI overlays for most popular plugins. You can grab them here:
git clone --depth 1 https://github.com/moddevices/mod-lv2-data
Look in the "plugins" and "plugins-fixed" sub-folders for your plugins. If you copy a plugin folder over your existing plugin in /usr/lib/lv2, you will install the custom UI for the plugin.

My Pi 4 has no trouble at all running a decently complex guitar effect stack, complete with multiple pedals and pre-amp and cabinet simulation, all at very low latency.

Saturday, January 25, 2020

Getting the Boss GT-1 effects processor to work in Linux




** NOTE: If you are just looking for my current solution, it is outlined here:



I recently picked up a Boss GT-1 guitar digital effects floorboard to use directly, and also to play with connecting it up to the Raspberry Pi.

A month later, I have everything working well. As is often the case with niche gear and Linux, though, it was a bumpy road to get there. I'm going to document the process here, in case it is helpful for anyone with a similar issue.

I booted up my Pi, connected the GT-1 via USB, ran lsusb to list the available USB devices, and there it was. Great - that was easy!

Next, I tried playing a .wav file with aplay. No go. No audio at all. Not so great.

Time to start scouring the internet. After a while, I came across this thread on linuxmusicians.com:

https://linuxmusicians.com/viewtopic.php?f=6&t=17180

It had a fix for another Boss device. It also turned out to work for Boss Katana Amplifiers, which have a software setup that is very similar to my GT-1 device.

I grabbed the kernel source code, applied the fix (with a tweak for my device), and soon I had working audio! Well, kind of working. I was getting pops and crackles every second or so - enough to make things unusable.

To understand this fix, and why it wasn't quite working requires a bit of explanation on how USB audio works. There are a number of methods that devices use to synchronize audio timing. The one used by the Boss GT-1 (and many similar devices) is called "implicit feedback". In simple terms, what this does is, on devices that have both a capture and playback that are controlled by the same clock, the capture source is used to determine the output data rate. Essentially, the host is in a USB feedback loop - outputting the same number of samples it receives - generally after doing some processing.

The fix that got my interface working basically disables the implicit feedback mechanism. This got audio moving through the system, but because there was no timing feedback it was slightly off - resulting in the pops and crackles I was experiencing.

A while later, I came across this post in the Line 6 forums about getting the Helix (another guitar processing device) working in Linux:

https://line6.com/support/topic/4426-line-6-with-linux/?tab=comments#comment-240302

The additional fix here was to hack the sample rate slightly to try to match the real timing of the device. I gave it a try, and it turned out that if I nudged the sample rate to 44105 (instead of 44100), my pops and crackles mostly went away - happening every few minutes instead of constantly.

This fix was obviously a hack, and not perfect, but it at least made my interface usable. The core problem still existed - the device should be operating using implicit feedback, but when this was enabled it didn't work at all.

I had posted about these issues on the alsa-devel mailing list, and a while later I got a helpful email suggesting that some Roland devices waited to send capture data until they had received some playback data. The kernel implicit feedback code, on the other hand, was waiting for some capture data before it send any playback data. The result was a standoff - with nothing getting sent either way.

Simply disabling the code that caused playback to wait on capture resulted in working audio with implicit feedback enabled, and a perfectly solid audio stream with no pops or crackles!

I outlined this fix on the alsa-devel mailing list here:

https://mailman.alsa-project.org/pipermail/alsa-devel/2020-January/161951.html

I hope to get a patch for this into the kernel eventually - right now I am doing some poking around to see if I can find out what other similar devices this fix might work for.