I was asking myself if I can use a headless Raspberry PI Zero together with a MIDI keyboard as simple Synthesizer which sends the sound via A2DP to a Bluetooth Speaker. So technically speaking I wanted to set up my PI as a2dp source.

Installation

Initially I tried to do the setup with Pulseaudio. However it seems that there are plenty of issues with this option, so I decided to use ALSA instead and removed Pulseaudio again! I also added the fluidsynth synthesizer in order that I have a MIDI output device available:

sudo apt remove pulseaudio pulseaudio-module-bluetooth
sudo apt install bluealsa fluidsynth

We add the user pi to the bluetooth user group so that he can execute bluetoothctl w/o sudo:

sudo usermod -a -G bluetooth pi

Services

We need to extend the bluealsa to support a2dp

sudo nano /lib/systemd/system/bluealsa.service

We change the ExecStart command:

ExecStart=/usr/bin/bluealsa -p a2dp-sink -p a2dp-source

We also might need to disable the sap plugin in the bluetooth service. (check with systemctl status bluetooth if you get any errors):

sudo nano /lib/systemd/system/bluetooth.service

We change the ExecStart command:

ExecStart=/usr/lib/bluetooth/bluetoothd --noplugin=sap

After restarting, the following services should be working properly:

systemctl status bluealsa
● bluealsa.service - BluezALSA proxy
   Loaded: loaded (/lib/systemd/system/bluealsa.service; static; vendor preset: enabled)
   Active: active (running) since Tue 2020-10-06 19:06:18 BST; 16s ago
 Main PID: 393 (bluealsa)
   CGroup: /system.slice/bluealsa.service
           └─393 /usr/bin/bluealsa -p a2dp-sink -p a2dp-source


systemctl status bluetooth
● bluetooth.service - Bluetooth service
   Loaded: loaded (/lib/systemd/system/bluetooth.service; enabled; vendor preset: enabled)
   Active: active (running) since Tue 2020-10-06 19:59:18 BST; 6s ago
     Docs: man:bluetoothd(8)
 Main PID: 528 (bluetoothd)
   Status: "Running"
   CGroup: /system.slice/bluetooth.service
           └─528 /usr/lib/bluetooth/bluetoothd --noplugin=sap

Now we can try to connect to the bluetooth sink (e.g. Bluetooth Speaker) using the bluetoothctl command. If the user is not part of the bluetooth group you will need to use sudo.

bluetoothctl
Agent registered

scan on
[CHG] Controller B8:27:EB:D2:72:43 Discovering: yes
[CHG] Device 24:6F:28:AF:54:76 RSSI: -70
scan off

pair 24:6F:28:AF:54:76
...
trust 24:6F:28:AF:54:76
Changing 24:6F:28:AF:54:76 trust succeeded

connect 24:6F:28:AF:54:76
[CHG] Device 24:6F:28:AF:54:76 Connected: yes
Connection successful
[CHG] Device 24:6F:28:AF:54:76 ServicesResolved: yes

Configuration

In order for the output to work we need to have the following content in the .asoundrc configuration file:

pcm.btspeaker {
  type plug
  slave.pcm {
    type bluealsa
    device "24:6F:28:AF:54:76"
    profile "a2dp"
  }

  hint {
    show on
    description "RadioPlayer"
  }
}

pcm.!default pcm.btspeaker

The last line is defining the default output, which points to the btspeaker.

We can test the speaker by playing a wav file

aplay -D btspeaker test.wav

Since we also have defined the default, the following should work as well:

aplay test.wav

The Synthesizer

FluidSynth is a real-time software synthesizer based on the SoundFont 2 specifications.
We should now also be able to play a midi file using fluidsynth. First we play the test.mid MIDI file using the FluidR3_GM.sf2 soundfont file:

fluidsynth -a alsa  /usr/share/sounds/sf2/FluidR3_GM.sf2 test.mid

Finally we are ready to start fluidsynth w/o any file input:

fluidsynth -a alsa  /usr/share/sounds/sf2/FluidR3_GM.sf2 --server

Connecting to the MIDI keyboard

The aconnect command provides a list of MIDI devices:

aconnect -i -o
client 0: 'System' [type=kernel]
    0 'Timer           '
    1 'Announce        '
client 14: 'Midi Through' [type=kernel]
    0 'Midi Through Port-0'
client 20: 'Q61' [type=kernel,card=1]
    0 'Q61 MIDI 1      '
client 128: 'FLUID Synth (1271)' [type=user,pid=1271]
    0 'Synth input port (1271:0)'

We want to connect the Q61 Keyboard to the fluidsynth MIDI input:

aconnect 20:0 128:0

Now the MIDI keyboard has been connected to the synthesizer and if we use the keyboard, the selected MIDI instrument is played to the Bluetooth speaker…

Summary

There are quite a few steps to have this scenario working. Unfortunately the lag between a keypress and the related sound on the speaker is a round 1 sec which is too much to be useful as a music instrument.

The PI Zero as a sound device however still might be a good solution if you use it e.g. as file based music player – where the lag is not disturbing or if you replace the Bluetooth output with some additional hardware:

  • A sound HAT (15 – 20 USD) or
  • a I2S Sound Module (5 – 10 USD) or
  • USB based Sound Card (1-10 USD)
Categories: Machine Sound

1 Comment

Florent · 3. November 2020 at 22:25

A2DP source on config on Raspberry Pi Zero W is a nightmare for many people. Thank you for this straightforward article! My PiZero W is finally reconnecting smoothly to my bluetooth speaker at reboot.

Leave a Reply

Avatar placeholder

Your email address will not be published. Required fields are marked *