The hardest part

At least, for me. Now I have to code something that enables me to select banks and instruments on my synth module. I’ve settled for pyliblo to talk to ZynAddSubFX but I’m just no coder. My elbow now rests on “Learning Python” from O’Reilly, I started reading it like a year ago but never got past chapter 3 or something. Time to persist, I’ve been wanting to be able to code a little bit for years now.

As a note to self, and maybe it’s helpful for others too, what follows are some of the relevant OSC messages to change banks and instruments in ZynAddSubFX.

Changing banks can be done with /loadbank. pyliblo comes with an example script send_osc.py and loading a bank with send_osc.py works as follows:

send_osc.py 7777 /loadbank ,i 3

7777 is the port ZynAddSubFX runs on. The /loadbank message wants an integer (,i) and ,i 3 loads the fourth bank (Choir and Voice) as ZynAddSubFX starts counting from 0. Bear in mind that this will only load the bank, it won’t change the instrument that is loaded. To load an instrument from a loaded bank the following send_osc.py incantation does the trick:

send_osc.py 7777 /setprogram ,c $'\x03'

So /setprogram loads an instrument from an active bank. It takes a character (,c) as an argument because the program numbers are in hex. But hex are multiple characters so you have to add some escape sequences to make it work (and I lost it there so I could be completely wrong). The above command should load the fourth instrument from the Choir and Voice bank (Voice OOH) as that bank should have been loaded by the previous /loadbank message.

It is also possible to load instrument (.xiz) files. This can be done with the /load_xiz message:

send_osc.py 7777 /load_xiz 0 "/usr/share/zynaddsubfx/banks/Bass/0001-Bass 1.xiz"

This will load the Bass 1 instrument fom the Bass bank into part 1 (remember that ZynAddSubFX starts counting from 0). So to load the Bass 2 instrument into part 2 you’d do the following:

send_osc.py 7777 /load_xiz 1 "/usr/share/zynaddsubfx/banks/Bass/0002-Bass 2.xiz"

So now I have to incorporate this stuff into Python code that gets called when I press buttons on my LCD display. These are the mappings I’d like to accomplish:

  • Up: toggle next bank and display first instrument from that bank
  • Down: toggle previous bank and display first instrument from that bank
  • Left: toggle previous instrument and display instrument
  • Right: toggle next instrument and display instrument
  • Select: select displayed instrument

That shouldn’t be too hard right? Well, first hurdle, pyliblo can only send or dump OSC messages, it doesn’t seem to be able to handle return messages from the OSC server (ZynAddSubFX in this case). To be continued…

Edit: of course sending just messages with pyliblo won’t handle any return messages, you will need a receiving part. But maybe I should take a look at using MIDI with mididings for instance. Thanks Georg Mill for the tip!

The hardest part

Two steps further

For my little synth module project I created the following systemd unit file /etc/systemd/system/zynaddsubfx.service that starts up a ZynAddSubFX proces at boot time:

[Unit]
Description=ZynAddSubFX

[Service]
Type=forking
User=zynaddsubfx
Group=zynaddsubfx
ExecStart=/usr/local/bin/zynaddsubfx-mpk
ExecStop=/usr/bin/killall zynaddsubfx

[Install]
WantedBy=local-fs.target

/usr/local/bin/zynaddsubfx-mpk is a simple script that starts ZynAddSubFX and connects my Akai MPK:

#!/bin/bash

zynaddsubfx -r 48000 -b 64 -I alsa -O alsa -P 7777 -L /usr/share/zynaddsubfx/banks/SynthPiano/0040-BinaryPiano2.xiz &

while ! aconnect 'MPK mini' 'ZynAddSubFX'
do
  sleep 0.1
done

/usr/local/bin/zynpi.py

/usr/local/bin/zynpi.py in its turn is a small Python script that shows a message and a red LED on a 16×2 LCD display so that I know the synth module is ready to use:

#!/usr/bin/python
# Example using a character LCD plate.
import math
import time

import Adafruit_CharLCD as LCD

# Initialize the LCD using the pins
lcd = LCD.Adafruit_CharLCDPlate()

# Show some basic colors.
lcd.set_color(1.0, 0.0, 0.0)
lcd.clear()
lcd.message('Raspberry Pi 2\nZynAddSubFX')

The LCD is not an Adafruit one though but a cheaper version I found on Dealextreme. It works fine though with the Adafruit LCD Python library. Next step is to figure out if I can use the buttons on the LCD board to change banks and presets.

synth_module_lcd_startup
Raspberry Pi synth module with 16×2 LCD display
synth_module_test_setup
The synth module test environment
Two steps further

Working on a stable setup

Next step for the synth module project was to get the Raspberry Pi 2 to run in a stable manner. It seems like I’m getting close or that I’m already there. First I built a new RT kernel based on the 4.1.7 release of the RPi kernel. Therefore I had to checkout an older git commit because the RPi kernel is already at 4.1.8. The 4.1.7-rt8 patchset applied cleanly and the kernel booted right away:

pi@rpi-jessie:~$ uname -a
 Linux rpi-jessie 4.1.7-rt8-v7 #1 SMP PREEMPT RT Sun Sep 27 19:41:20 CEST 2015 armv7l GNU/Linux

After cleaning up my cmdline.txt it seems to run fine without any hiccups so far. My cmdline.txt now looks like this:

dwc_otg.lpm_enable=0 dwc_otg.speed=1 console=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 rootflags=data=writeback elevator=deadline rootwait

Setting USB speed to Full Speed (so USB1.1) by using dwc_otg.speed=1 is necessary otherwise the audio coming out of my USB DAC sounds distorted.

I’m starting ZynAddSubFX as follows:

zynaddsubfx -r 48000 -b 64 -I alsa -O alsa -P 7777 -L /usr/share/zynaddsubfx/banks/SynthPiano/0040-BinaryPiano2.xiz

With a buffer of 64 frames latency is very low and so far I haven’t run into instruments that cause a lot of xruns with this buffer size. Not even the multi-layered ones from Will Godfrey.

So I guess it’s time for the next step, creating a systemd startup unit so that ZynAddSubFX starts at boot. And it would be nice if USB MIDI devices would get connected automatically. And if you could see somehow which instrument is loaded, an LCD display would be great for this. Also I’d like to have the state of the synth saved, maybe by saving an .xmz file whenever there’s a state change or on regular intervals. And the synth module will need a housing or casing. Well, let’s get the software stuff down first.

Working on a stable setup

Building a synth module using a Raspberry Pi

Ever since I did an acid set with my brother in law at the now closed bar De Vinger I’ve been playing with the idea of creating some kind of synth module out of a Raspberry Pi. The Raspberry Pi 2 should be powerful enough to run a complex synth like ZynAddSubFX. When version  2.5.1 of that synth got released the idea resurfaced again since that version allows to remote control a running headless instance of ZynAddSubFX via OSC that is running on for instance a Raspberry Pi. I looked at this functionality before a few months ago but the developer was just starting to implement this feature so it wasn’t very usable yet.

zynaddsubfx-ext-guiBut with the release of ZynAddSubFX 2.5.1 the stabilitity of the zynaddsubfx-ext-gui utility has improved to such an extent that it’s a very usable tool. In the above screenshot you can see zynaddsubfx-ext-gui running on my notebook with Ubuntu 14.04 controlling a remote instance of ZynAddSubFX running on a Raspberry Pi.

So basically all the necessary building blocks for a synth module are there. Coupled with my battered Akai MPK Mini and a cheap PCM2704 USB DAC I started setting up a test setup.

For the OS on the Raspberry Pi 2 I chose Debian Jessie as I feel Raspbian isn’t getting you the most out of your Pi. It’s running a 4.1.6 kernel with the 4.1.5-rt5 RT patch set, which applied cleanly and seems to run so far:

pi@rpi-jessie:~$ uname -a
Linux rpi-jessie 4.1.6-rt0-v7 #1 SMP PREEMPT RT Sun Sep 13 21:01:19 CEST 2015 armv7l GNU/Linux

This isn’t a very clean solution of course so let’s hope a real 4.1.6 RT patch set will happen or maybe I could give the 4.1.6 PREEMPT kernel that rpi-update installed a try. I packaged a headless ZynAddSubFX for the RPi on my notebook using pbuilder with a Jessie armhf root and installed the package for Ubuntu 14.04 from the KXStudio repos. I slightly overclocked the RPi to 1000MHz and set the CPU scaling governor to performance. The filesystem is Ext4, mounted with noatime,nobarrier,data=writeback.

To get the USB audio interface and the USB MIDI keyboard into line I had to add the following line to my /etc/modprobe.d/alsa.conf file:

options snd-usb-audio index=0,1 vid=0x08bb,0x09e8 pid=0x2704,0x007c

This makes sure the DAC gets loaded as the first audio interface, so with index 0. Before adding this line the Akai would claim index 0 and since I’m using ZynAddSubFX with ALSA it couldn’t find an audio interface. But all is fine now:

pi@rpi-jessie:~$ cat /proc/asound/cards
 0 [DAC            ]: USB-Audio - USB Audio DAC
                      Burr-Brown from TI USB Audio DAC at usb-bcm2708_usb-1.3, full speed
 1 [mini           ]: USB-Audio - MPK mini
                      AKAI PROFESSIONAL,LP MPK mini at usb-bcm2708_usb-1.5, full speed

So no JACK as the audio back-end, the output is going directly to ALSA. I’ve decided to do it this way because I will only be running one single application that uses the audio interface so basically I don’t need JACK. And JACK tends to add a bit of overhead, you barely notice this on a PC system but on small systems like the Raspberry Pi JACK can consume a noticeable amount of resources. To make ZynAddSubFX use ALSA as the back-end I’m starting it with the -O alsa option:

zynaddsubfx -r 48000 -b 256 -I alsa -O alsa -P 7777

The -r option sets the sample rate, the -b option sets the buffer size, -I is for the MIDI input and the -P option sets the UDP port on which ZynAddSubFX starts listening for OSC messages. And now that’s the cool part. If you then start zynaddsubfx-ext-gui on another machine on the network and tell it to connect to this port it starts only the GUI and sends all changes to the GUI as OSC messages to the headless instance it is connected to:

zynaddsubfx-ext-gui osc.udp://10.42.0.83:7777

Next up is stabilizing this setup and testing with other kernels or kernel configs as the kernel I’ve cooked up now isn’t a viable long-term solution. And I’d like to add a physical MIDI in and maybe a display like described on the Samplerbox site. And the project needs a casing of course.

Building a synth module using a Raspberry Pi

Media units

media_units_editThe MK808 Android TV stick with a PCM2704 USB audio interface runs Debian Jessie with MPD and serves as our mediaplayer for audio files. It draws its power from the USB port of our cable modem so it’s always on. Most of the time Indie Pop Rocks is playing. It’s hooked up to the network via WiFi. We use MPDroid to control it.

The Raspberry Pi runs OpenELEC with Kodi. We use this for watching all kinds of video files that we stream from our NAS (an aging WD My Book Live that runs Debian Lenny) via an NFS share. It is connected to the network via ethernet.

The Chromecast is for watching Netflix. When we just got it we had some issues with connecting it to the network but after replacing our old router with an ASUS RT-AC68U it worked flawlessly.

The Technics SL-1210MK2 with Ortofon headshell and cartridge is for listening music on vinyl, you know those round black plastic units from the past with grooves in them. It doesn’t have any network connections and doesn’t run an OS. It does send electrical current to a NAD C 325BEE Stereo Integrated Amplifier with Dali Concept 2 speakers. Yeah, I’m a 2.0 guy.

The TV is an old pre Smart TV Samsung but as it still works we probably won’t replace it for the time being. It does have CEC so we can control the TV, RPi and Chromecast with a single remote.

Media units

Moved to WordPress

Took the plunge and migrated my blog to WordPress. Thanks to this PHP script it wasn’t that much work. Some issues with titles that contained the every odd character but other than that the migration went pretty smooth.

Hopefully this will revive my blogging spirit a bit. PivotX was sometimes pretty cumbersome to work with, I had to manually edit the HTML just a tad bit too often. And editing the HTML was quite tedious, it opened a new window with its own save button, not very fun to work with. Now I can simply toggle between Visual and Text. Other than that WordPress simply has more to offer, like plug-ins and themes that you can install on the fly. Being a big CMS has its drawbacks too of course. Installed Wordfence and Disable XML-RPC to keep out the bad guys. Hopefully it doesn’t get that bad that I have to resort to solutions like fail2ban. We’ll see.

Moved to WordPress

CarPC v1.0

As our collection of MP3 CD’s was wearing out I thought why not put a small embedded board with a big drive in our car? I dug up a Cubieboard2 that was gathering dust and started hacking. The goal:

  • Small system based on Debian Jessie
  • MPD to serve the audio files
  • Remote control via WiFi
  • Big drive
  • Acceptable boot time
  • Basic protection against file system corruption

Putting a bog standard Debian Jessie on the Cubieboard2 was quite straightforward with the help of the linux-sunxi.org wiki. The board booted with the standard kernel but unfortunately no sound. Luckily I had just received some ultra-cheap PCM2704 USB audio interfaces and these worked and sounded great too. WiFi worked out of the box but the rtl8192cu driver of the 3.16 kernel for the Realtek RTL8192CU chipset has the tendency to quickly go into suspension and as this driver doesn’t have any power management options I ended up with a hacky for loop in /etc/rc.local that pings all IP’s in the DHCP range. I quickly dropped this iffy set-up as it just didn’t work out that well and ended up using a DKMS based solution that made it possible to control power management of the WiFi dongle. Next hurdle was hostapd that stopped working with this alternative driver. But with the help of the hostapd-rtl871xdrv GitHub repo I managed to cook up a fully working hostapd Debian package.

Next up was the hard drive. I first tried a USB drive but the Cubieboard2 just couldn’t provide enough juice to power the drive properly together with the WiFi dongle. I also tried with my Raspberry Pi’s but those had the same issues. So I had to resort to a SATA drive. Of course I bought a 3.5″ drive first because those are cheaper. But you can’t power a 3.5″ drive with the SATA cable that comes with the Cubieboard2 and as I had a bit of a deadline I returned it for a 2.5″ drive and that works like a charm. I installed MPD, copied my music collection to the hard drive, fired up MPD and was greeted with a segmentation fault. Apparently the Jessie MPD package has issues with the sticker database file so I installed MPD from the backports repo and that version runs without any complaints so far.

For some basic protection against corruption by sudden power loss I created separate partitions for /home and /var on the SD card that are mounted rw with a couple of options to reduce corruption (sync,commit=1,data=journal) and / is mounted ro, just like the big hard drive with the audio files. /tmp is being mounted as tmpfs in RAM. Boot time is about 15 seconds and I’m OK with that. To remotely shut down the CarPC via WiFi I use a JuiceSSH homescreen shortcut of a connection that runs a simple shutdown -h now snippet.

After I had mounted everything in our car the thing wouldn’t boot though. Swapped the 1A USB car adapter for a 2.1A version and then the CarPC came up properly. Installed MPDroid on my Nexus 5 to control MPD via WiFi and so far, so good!

 

Cubieboard2 based CarPC

 

Addendum

Sometimes the CarPC became unreachable via WiFi. The culprit was that the DHCP service (udhcpd) didn’t always come up because it was sometimes started before hostapd. I fixed this by copying /var/run/systemd/generator.late/udhcpd.service to /etc/systemd/system/udhcpd-custom.service and adding hostapd.service to the After line and adding a Requires=hostapd.service line. I also added a [Install] stanza with the line WantedBy=multi-user.target. I then disabled udhcpd.service and enabled udhcpd-custom.service.

Addendum 2

Hostapd didn’t always start flawlessly either so I copied /var/run/systemd/generator.late/hostapd.service to /etc/systemd/system/hostapd-custom.service and added sys-subsystem-net-devices-wlan0.device to the After and Wants lines. Also added an [Install] stanza, disabled hostapd.service and enabled hostapd-custom.service.

CarPC v1.0

Raspberry Pi Revisited

When the Raspberry Pi 2 was released I certainly got curious. Would it be really better than it’s little brother? As soon as it got available in The Netherlands I bought it and sure this thing flies compared to the Raspberry Pi 1. The four cores and 1GB of memory are certainly an improvement. The biggest improvement though is the shift from ARMv6 to ARMv7. Now you can really run basically anything on it and thus I soon parted from Raspbian and I’m now running plain Debian Jessie armhf on the RPi.

So is everything fine and dandy with the RPi2? Well, no. It still uses the poor USB implementation and audio output. And it was quite a challenge to prepare it for its intended use: a musical instrument. To my great surprise a new version of the Wolfson Audio Card was available too for the new Raspberry Pi board layout so as soon as people reported they got it to work with the RPi2 I ordered one too.

 

http://community.emlid.com/t/raspberry-2-realtime-kernel-image/112/12

Cirrus Logic Audio Card for Raspberry Pi

One of the first steps to make the device suitable for use as a musical device was to build a real-time kernel for it. Building the kernel itself was quite easy as the RT patchset of the kernel being used at the moment by the Raspberry Foundation (3.18) applied cleanly and it also booted without issues. But after a few minutes the RPi2 would lock up without logging anything. Fortunately there were people on the same boat as me and with the help of the info and patches provided by the Emlid community I managed to get my RPi2 stable with a RT kernel.

Next step was to get the right software running so I dusted off my RPi repositories and added a Jessie armhf repo. With the help of fundamental the latest version of ZynAddSubFX now runs like charm with very acceptable latencies, when using not all too elaborate instrument patches Zyn is happy with an internal latency of 64/48000=1.3ms. I haven’t measured the total round-trip latency but it probably stays well below 10ms. LinuxSampler with the Salamander Grand Piano sample pack also performs a lot better than on the RPi1 and when using ALSA directly I barely get any underruns with a slightly higher buffer setting.

I’d love to get Guitarix running on the RPi2 with the Cirrus Logic Audio Card so that will be the next challenge.

Raspberry Pi Revisited

Packaging Python Stuff

While packaging Tuna I ran into an issue for which I couldn’t easily find a workaround on the ubiquitous search engine. Tuna depends on some unavailable Python applications so those had to be packaged too. After having successfully tested the packages locally with pbuilder I uploaded them to Launchpad and noticed that they failed to build. Apparently the Python installer setup.py wants to install in /usr/lib/python2.7/site-packages and while that worked fine locally with pbuilder, Launchpad had an issue with that:

Found files in /usr/lib/python2.7/site-packages (must be in dist-packages for python2.7).
debian/python-schedutils/usr/lib/python2.7/site-packages
debian/python-schedutils/usr/lib/python2.7/site-packages/schedutils.so
debian/python-schedutils/usr/lib/python2.7/site-packages/schedutils-0.4-py2.7.egg-info
dh_builddeb.pkgbinarymangler: dpkg-deb --build debian/python-schedutils .. returned exit code 1
make: *** [binary-arch] Error 1
dpkg-buildpackage: error: /usr/bin/fakeroot debian/rules binary-arch gave error exit status 2

Apparently the files had to be installed in /usr/lib/python2.7/dist-packages but how to instruct the installer to do so without having to resort to ugly hacks? As I couldn’t find any useful answers on the web I asked falkTX on #kxstudio. He said the setup.py installer has a flag to install to dist-packages instead of site-packages, --install-layout deb. So I added that to the debian/rules file and gave it another spin:

#!/usr/bin/make -f
# -*- makefile -*-
# Sample debian/rules that uses debhelper.
# This file was originally written by Joey Hess and Craig Small.
# As a special exception, when this file is copied by dh-make into a
# dh-make output file, you may use that output file without restriction.
# This special exception was added by Craig Small in version 0.37 of dh-make.

# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1

%:
        dh $@

override_dh_auto_build:
        python setup.py build

override_dh_auto_install:
        python setup.py install --skip-build --prefix /usr --root $(CURDIR) --install-layout deb

Now both pbuilder and Launchpad built the package without any issues.

Packaging Python Stuff