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)
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.