No, not a Bluetooth related post again! Rather surprisingly, the old posts about Bluetooth on the Raspberry Pi still generate a fair amount of traffic on this site. Not too long ago there was a query on that topic but in relation to the Orange Pi Zero Plus 2. I could not provide a definitive answer as I do not have that board. On the other hand, I do have an Orange Pi PC 2 (OPiPC2 for short) which shares the same Allwinner H5 SOC. Unlike the Zero, the PC 2 does not have built-in wireless connectivity. However, an old Wi-Fi-USB dongle and the cheapest Bluetooth-USB dongle found from the traditional Chinese sellers were recognized by the system. That was close enough to investigate Bluetooth on an H5 Orange Pi running the latest version of Armbian Bionic
(kernel version 5.4.14). Of course, what is reported below may not apply to a Zero Plus 2 which relies on an AP612 chip for Wi-Fi and Bluetooth.
Table of Contents
- Sound ALSA
- Playing Sound
- Recording Sound
- Bluetooth
- Compiling BlueALSA
- Sending an Audio Stream to Bluetooth Speakers
- Playing an Audio Stream from a Bluetooth Device
- BlueALSA
systemd
Service File
- References
As before, I want to stream audio using Bluetooth as a transport mechanism. The obvious first step is to make sure that audio works on the OPiPC2. In other words, the OPiPC2 must have audio capabilities, functionning sound card device drivers must be installed and ALSA (Advanced Linux Sound Architecture) which provides an application programming interface for the sound cards must be running. ALSA is part of the Linux kernel and all the rest is in place at least with the latest version of Armbian Bionic
.
I connected a powered pair of speakers to the 3.5 mm jack, enabled the analogue output and tested it following the SUNXI Audio Codec instructions. That means first creating a system wide ALSA configuration file asound.conf
in the /etc/
directory. The nano
editor is fine for this, but any text editor such as vim
could be used.
opipc@orangepipc2:~$ nano /etc/asound.conf
Here is the content added to the file.
pcm.!default {
type hw
card 1
device 0
}
ctl.!default {
type hw
card 1
}
Again, this is explained in the SUNXI Wiki as well as the next step on testing that the audio output is directed to the 3.5 mm jack.
opipc@orangepipc2:~$ speaker-test -twav -c2 -l4
speaker-test 1.1.3
Playback device is default
Stream parameters are 48000Hz, S16_LE, 2 channels
WAV file(s)
Rate set to 48000Hz (requested 48000Hz)
Buffer size range from 128 to 131072
Period size range from 64 to 16384
Using max buffer size 131072
Periods = 4
was set period_size = 16384
was set buffer_size = 131072
0 - Front Left
1 - Front Right
Time per period = 0.390926
0 - Front Left
1 - Front Right
Time per period = 3.070523
0 - Front Left
1 - Front Right
Time per period = 3.071815
0 - Front Left
1 - Front Right
It's hard to show sound on a Web page, but take my word for it, "Front Left Front Right" was repeated four times. The speaker-test
options used are:
- -twav: test using a WAV file ("Front Left, "Front Right" ...).
- -c2: test 2 channels (front left and right speakers)
- -l4: repeat the test 4 times (loop count)
If the sound is not heard, omit the -l4
option and the utility will repeat "Front Left Front Right" until interrupted with CtrlC. Then open another session and start alsamixer
.
opipc@orangepipc2:~$
alsamixer
┌────────────────────────────── AlsaMixer v1.1.3 ──────────────────────────────┐
│ Card: H3 Audio Codec F1: Help │
│ Chip: F2: System information │
│ View: F3:[Playback] F4: Capture F5: All F6: Select sound card │
│ Item: Line Out [dB gain: -6.00] Esc: Exit │
│ │
│ ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐ │
│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │ │ │ │ │ │ │▒▒│ │
│ │ │ │▒▒│ │ │ │ │ │ │ │ │ │▒▒│ →
│ │ │ │▒▒│ │ │ │ │ │ │ │ │ │▒▒│ →
│ │ │ │▒▒│ │ │ │▒▒│ │ │ │▒▒│ │▒▒│ →
│ │ │ │▒▒│ │ │ │▒▒│ │ │ │▒▒│ │▒▒│ →
│ │▒▒│ │▒▒│ │▒▒│ │▒▒│ │▒▒│ │▒▒│ │▒▒│ →
│ │▒▒│ │▒▒│ │▒▒│ │▒▒│ │▒▒│ │▒▒│ │▒▒│ →
│ │▒▒│ │▒▒│ │▒▒│ │▒▒│ │▒▒│ │▒▒│ │▒▒│ →
│ │▒▒│ │▒▒│ │▒▒│ │▒▒│ │▒▒│ │▒▒│ │▒▒│ │
│ │▒▒│ │▒▒│ │▒▒│ │▒▒│ │▒▒│ │▒▒│ │▒▒│ │
│ ├──┤ ├──┤ Stereo ├──┤ └──┘ ├──┤ └──┘ ├──┤ │
│ │MM│ │OO│ │MM│ │MM│ │OO│ │
│ └──┘ └──┘ └──┘ └──┘ └──┘ │
│ 43 79 43 64 43 64 95 │
│ Line In <Line Out>Line Out Mic1 Mic1 Boo Mic2 Mic2 Boo DAC │
└──────────────────────────────────────────────────────────────────────────────┘
If there's a need, press the F3 to select Playback
devices only. The output volume of the speakers is determined by mixer controls: Line Out
and DAC
which apparently stands for Power Amplifier Digital Analog Converter
. The level of the latter was 100 on my system (although it says 95 above), and that of the former was about 79, if memory serves. Use the right and left cursor keys to select a control, and the up or down cursor key to set a value. The second Line Out
(full name: Line Out Source
) can be used to select between Stereo
output or a very thin Mono Differential
output.
Playing a WAV sound file is just as straightforward, if there's one on hand.
opipc@orangepipc2:~$ opipc@orangepipc2:~$ aplay sound/sound-off.wav
Playing WAVE 'sound/sound-off.wav' : Signed 16 bit Little Endian, Rate 44100 Hz, Stereo
There are two hardware devices capable of playing sound on the OPiPC.
opipc@orangepipc2:~$ aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: Codec [H3 Audio Codec], device 0: CDC PCM Codec-0 [CDC PCM Codec-0]
Subdevices: 1/1
Subdevice #0: subdevice #0
card 1: allwinnerhdmi [allwinner-hdmi], device 0: 1c22800.i2s-i2s-hifi i2s-hifi-0 [1c22800.i2s-i2s-hifi i2s-hifi-0]
Subdevices: 1/1
Subdevice #0: subdevice #0
The first (index 0) sends analogue audio through the 3.5 mm jack. As can be guessed from what precedes, a DAC transforms the pulse-code modulation (PCM) data stored in the WAV file into an analogue signal. The second device sends sound to the HDMI connector, presumably using an IIS (Inter-IC Sound) serial bus which sends the PCM audio data straight through. Apparently both are default playback devices.
opipc@orangepipc2:~$ aplay -L | grep default
default:CARD=Codec
sysdefault:CARD=Codec
default:CARD=allwinnerhdmi
sysdefault:CARD=allwinnerhdmi
Is selection of the output device automatic as on a Raspberry Pi? I could not find an ALSA configuration file. Usually it is named asound.conf
and it is stored in the /etc
directory.
I tried recording sound with the on-board microphone.
opipc@orangepipc2:~$ arecord -i -f S16 -r 22050 test.wav
Recording WAVE 'test.wav' : Signed 16 bit Little Endian, Rate 22050 Hz, Mono
arecord: pcm_read:2103: read error: Input/output error
There is an easy fix. In the other session, select the capture controls by pressing the F4 key.
┌────────────────────────────── AlsaMixer v1.1.3 ──────────────────────────────┐
│ Card: H3 Audio Codec F1: Help │
│ Chip: F2: System information │
│ View: F3: Playback F4:[Capture] F5: All F6: Select sound card │
│ Item: Line In [Off, Off] Esc: Exit │
│ │
│ ┌──┐ ┌──┐ ┌──┐ │
│ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │
│ │▒▒│ │▒▒│ │ │ │
│ │▒▒│ │▒▒│ │ │ │
│ │▒▒│ │▒▒│ │▒▒│ │
│ │▒▒│ │▒▒│ │▒▒│ │
│ │▒▒│ │▒▒│ │▒▒│ │
│ │▒▒│ │▒▒│ │▒▒│ │
│ │▒▒│ │▒▒│ │▒▒│ │
│ └──┘ └──┘ └──┘ │
│ ------- ------- ------- ------- ------- │
│ 64 64 43 │
│ <Line In > Mic1 Mic1 Boo Mic2 Mic2 Boo Mixer Mixer Re ADC Gain │
│ │
└──────────────────────────────────────────────────────────────────────────────┘
Notice how there is no visible control for the actual sound devices. That makes sense for Mic2
because there is only one on-board microphone on the OPiPC2 even though the H5 has two microphone inputs. Select the Mic1
control with the left or right cursor key and press the SPACE bar. The microphone will be turned on and this is indicated with L R / CAPTURE
above Mic1
. The recording level is adjusted with the Mic1 Boost
and the ADC Gain
mixer controls. Thank you to kutysam in the Armbian Forum for those instructions.
Of course, aplay
can be used to playback the recording to make sure it worked.
opipc@orangepipc2:~$ aplay test.wav
Playing WAVE 'test.wav' : Signed 16 bit Little Endian, Rate 22050 Hz, Mono
The Record from mic page on the ALSA wiki has instructions on how to control the capture device using the command line utility amixer
instead of alsamixer
. First list the available controls.
pipc@orangepipc2:~$ amixer scontrols
Simple mixer control 'Line In',0
Simple mixer control 'Line Out',0
Simple mixer control 'Line Out Source',0
Simple mixer control 'Mic1',0
Simple mixer control 'Mic1 Boost',0
Simple mixer control 'Mic2',0
Simple mixer control 'Mic2 Boost',0
Simple mixer control 'Mixer',0
Simple mixer control 'Mixer Reversed',0
Simple mixer control 'ADC Gain',0
Simple mixer control 'DAC',0
Simple mixer control 'DAC Reversed',0
It is possible to get the status of microphone 1, and then to enable capture using it. The recording level is set with the Mic1 Boost
and ADC Gain
controls.
opipc@orangepipc2:~$ amixer sget Mic1
Simple mixer control 'Mic1',0
Capabilities: pvolume pvolume-joined pswitch cswitch
Playback channels: Front Left - Front Right
Capture channels: Front Left - Front Right
Limits: Playback 0 - 7
Front Left: Playback 0 [0%] [-4.50dB] [off] Capture [off]
Front Right: Playback 0 [0%] [-4.50dB] [off] Capture [off]
pipc@orangepipc2:~$ amixer sset Mic1 Capture cap
Simple mixer control 'Mic1',0
Capabilities: pvolume pvolume-joined pswitch cswitch
Playback channels: Front Left - Front Right
Capture channels: Front Left - Front Right
Limits: Playback 0 - 7
Front Left: Playback 3 [43%] [0.00dB] [off] Capture [on]
Front Right: Playback 3 [43%] [0.00dB] [off] Capture [on]
opipc@orangepipc2:~$ amixer sset 'Mic1 Boost' 80%
Simple mixer control 'Mic1 Boost',0
Capabilities: volume volume-joined
Playback channels: Mono
Capture channels: Mono
Limits: 0 - 7
Mono: 6 [86%] [39.00dB]
To turn off capture is just as easy.
opipc@orangepipc2:~$ amixer sset Mic1 Capture nocap
Simple mixer control 'Mic1',0
Capabilities: pvolume pvolume-joined pswitch cswitch
Playback channels: Front Left - Front Right
Capture channels: Front Left - Front Right
Limits: Playback 0 - 7
Front Left: Playback 0 [0%] [-4.50dB] [off] Capture [off]
Front Right: Playback 0 [0%] [-4.50dB] [off] Capture [off]
As stated in the introduction, the good news was that the Bluetooth dongle was recognized by Armbian. The Bluetooth (BT for short from now on) was not installed.
opipc@orangepipc2:~$ lsusb
...
Bus 008 Device 002: ID 0a12:0001 Cambridge Silicon Radio, Ltd Bluetooth Dongle (HCI mode)
...
opipc@orangepipc2:~$ bluetoothctl
Command 'bluetoothctl' not found, but can be installed with:
sudo apt install bluez
As suggested, it was a simple matter to install BT.
opipc@orangepipc2:~$ sudo apt install bluez
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following NEW packages will be installed:
bluez
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 772 kB of archives.
After this operation, 4,277 kB of additional disk space will be used.
...
Processing triggers for systemd (237-3ubuntu10.38)
opipc@orangepipc2:~$ sudo systemctl status blue*
● bluetooth.target - Bluetooth
Loaded: loaded (/lib/systemd/system/bluetooth.target; static; vendor preset: enabled)
Active: active since Wed 2020-02-12 19:12:21 AST; 2 weeks 0 days ago
Docs: man:systemd.special(7)
Feb 12 19:12:21 orangepipc2 systemd[1]: Reached target Bluetooth.
● bluetooth.service - Bluetooth service
Loaded: loaded (/lib/systemd/system/bluetooth.service; enabled; vendor preset: enabled)
Active: active (running) since Wed 2020-02-26 22:52:17 AST; 2min 12s ago
Docs: man:bluetoothd(8)
Main PID: 2996 (bluetoothd)
Status: "Running"
Tasks: 1 (limit: 1021)
CGroup: /system.slice/bluetooth.service
└─2996 /usr/lib/bluetooth/bluetoothd
Feb 26 22:52:17 orangepipc2 systemd[1]: Starting Bluetooth service...
Feb 26 22:52:17 orangepipc2 bluetoothd[2996]: Bluetooth daemon 5.48
Feb 26 22:52:17 orangepipc2 systemd[1]: Started Bluetooth service.
Feb 26 22:52:17 orangepipc2 bluetoothd[2996]: Starting SDP server
Feb 26 22:52:17 orangepipc2 bluetoothd[2996]: Bluetooth management interface 1.14 initialized
From experience, it's best to add the default user to the bluetooth
group to avoid having to use sudo
when running the bluetootctl
.
The session has to be closed and reopened to actually updated the group membership.
opipc@orangepipc2:~$
cat /etc/group | grep bluetooth
bluetooth:x:114:
opipc@orangepipc2:~$
groups
opipc tty disk dialout sudo audio video plugdev games users systemd-journal input netdev ssh
opipc@orangepipc2:~$
sudo adduser opipc bluetooth
Adding user `opipc' to group `bluetooth' ...
Adding user opipc to group bluetooth
Done.
opipc@orangepipc2:~$
exit
logout
Connection to orangepipc2.local closed.
@hp:~$ ssh opipc@orangepipc2.local
michel@hp:~$ ssh opipc@orangepipc2.local
opipc@orangepipc2.local's password: xxxxxxxx
...
Now is a good time to check that the bluetooth
service started automatically during the boot process.
opipc@orangepipc2:~$ sudo systemctl status blue*
● bluetooth.service - Bluetooth service
Loaded: loaded (/lib/systemd/system/bluetooth.service; enabled; vendor preset
Active: active (running) since Wed 2020-02-12 02:17:27 UTC; 1min 2s ago
Docs: man:bluetoothd(8)
Main PID: 1773 (bluetoothd)
Status: "Running"
Tasks: 1 (limit: 1021)
CGroup: /system.slice/bluetooth.service
└─1773 /usr/lib/bluetooth/bluetoothd
Feb 26 22:54:35 orangepipc2 systemd[1]: Starting Bluetooth service...
Feb 26 22:54:35 orangepipc2 bluetoothd[1773]: Bluetooth daemon 5.48
Feb 26 22:54:35 orangepipc2 systemd[1]: Started Bluetooth service.
Feb 26 22:54:35 orangepipc2 bluetoothd[1773]: Starting SDP server
Feb 26 22:54:35 orangepipc2 bluetoothd[1773]: Bluetooth management interface 1.1
● bluetooth.target - Bluetooth
Loaded: loaded (/lib/systemd/system/bluetooth.target; static; vendor preset:
Active: active since Wed 2020-02-26 22:54:35 UTC; 4min 48s ago
Docs: man:systemd.special(7)
Feb 12 02:13:41 orangepipc2 systemd[1]: Reached target Bluetooth.
It was not possible to connect with a BT speaker although it was possible to pair with it.
opipc@orangepipc2:~$ bluetoothctl
[NEW] Controller 00:1A:7D:DA:71:13 orangepipc2 [default]
Agent registered
[bluetooth]# scan on
Discovery started
[CHG] Controller 00:1A:7D:DA:71:13 Discovering: yes
[NEW] Device 30:21:5C:30:F1:C4 AUDIOPOD2
[bluetooth]# pair 30:21:5C:30:F1:C4
Attempting to pair with 30:21:5C:30:F1:C4
[CHG] Device 30:21:5C:30:F1:C4 Connected: yes
[CHG] Device 30:21:5C:30:F1:C4 UUIDs: 00001108-0000-1000-8000-00805f9b34fb
[CHG] Device 30:21:5C:30:F1:C4 UUIDs: 0000110b-0000-1000-8000-00805f9b34fb
[CHG] Device 30:21:5C:30:F1:C4 UUIDs: 0000110c-0000-1000-8000-00805f9b34fb
[CHG] Device 30:21:5C:30:F1:C4 UUIDs: 0000110e-0000-1000-8000-00805f9b34fb
[CHG] Device 30:21:5C:30:F1:C4 UUIDs: 0000111e-0000-1000-8000-00805f9b34fb
[CHG] Device 30:21:5C:30:F1:C4 ServicesResolved: yes
[CHG] Device 30:21:5C:30:F1:C4 Paired: yes
Pairing successful
[CHG] Device 30:21:5C:30:F1:C4 ServicesResolved: no
[CHG] Device 30:21:5C:30:F1:C4 Connected: no
[bluetooth]# connect 30:21:5C:30:F1:C4
Attempting to connect to 30:21:5C:30:F1:C4
Failed to connect: org.bluez.Error.Failed
[bluetooth]# scan off
Discovery stopped
[CHG] Controller 00:1A:7D:DA:71:13 Discovering: no
[CHG] Device 30:21:5C:30:F1:C4 RSSI is nil
[bluetooth]# quit
Agent unregistered
[DEL] Controller 00:1A:7D:DA:71:13 orangepipc2 [default]
Not unexpectedly, BlueALSA was not installed. It gets worse, bluealsa
is not available in the repository.
opipc@orangepipc2:~$ sudo apt-cache policy bluealsa
N: Unable to locate package bluealsa
opipc@orangepipc2:~$
It will have to be built from source.
The first steps consist in installing build prerequisites and then the required libraries.
opipc@orangepipc2:~$ sudo apt install libtool -y
Reading package lists... Done
..
The following NEW packages will be installed:
file libmagic-mgc libmagic1 libtool
0 upgraded, 4 newly installed, 0 to remove and 0 not upgraded.
Need to get 462 kB of archives.
After this operation, 6,538 kB of additional disk space will be used.
opipc@orangepipc2:~$ sudo apt install libasound2-dev libbluetooth-dev libglib2.0-dev libsbc-dev libdbus-1-dev -y
Reading package lists... Done
...
The following NEW packages will be installed:
libasound2-dev libbluetooth-dev libdbus-1-dev libglib2.0-bin libglib2.0-data libglib2.0-dev libglib2.0-dev-bin libpcre16-3 libpcre3-dev
libpcre32-3 libpcrecpp0v5 libsbc-dev libsbc1 pkg-config python3-distutils python3-lib2to3 zlib1g-dev
0 upgraded, 17 newly installed, 0 to remove and 0 not upgraded.
Need to get 3,087 kB of archives.
After this operation, 19.2 MB of additional disk space will be used.
...
Processing triggers for libc-bin (2.27-3ubuntu1) ...
Get the archived source for BlueALSA from GitHub and extract it.
opipc@opipc2:~$ wget https://github.com/Arkq/bluez-alsa/archive/master.zip
--2020-02-11 22:38:22-- https://github.com/Arkq/bluez-alsa/archive/master.zip
Resolving github.com (github.com)... 140.82.113.4
Connecting to github.com (github.com)|140.82.113.4|:443... connected.
HTTP request sent, awaiting response... 302 Found
Location: https://codeload.github.com/Arkq/bluez-alsa/zip/master [following]
--2020-02-11 22:38:22-- https://codeload.github.com/Arkq/bluez-alsa/zip/master
Resolving codeload.github.com (codeload.github.com)... 140.82.114.10
Connecting to codeload.github.com (codeload.github.com)|140.82.114.10|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: unspecified [application/zip]
Saving to: ‘master.zip’
master.zip [ <=> ] 168.10K 702KB/s in 0.2s
2020-02-11 22:38:23 (702 KB/s) - ‘master.zip’ saved [172136]
opipc@opipc2:~$ unzip master.zip
Then I just followed the instructions to configure and build the
library. There are just four or five commands involved.
opipc@opipc2:~$ cd bluez-alsa-master/
opipc@opipc2:~/bluez-alsa-master$ autoreconf --install
...
opipc@opipc2:~/bluez-alsa-master$ mkdir build && cd build
...
opipc@orangepipc2:~/bluez-alsa-master/build$ ../configure
...
opipc@opipc2:~/bluez-alsa-master/build$ make -j4 && sudo make install
...
However there is a lot going on, so I kept a record of some of the details.
opipc@opipc2:~$ cd bluez-alsa-master/
opipc@opipc2:~/bluez-alsa-master$ autoreconf --install
aclocal: warning: couldn't open directory 'm4': No such file or directory
libtoolize: putting auxiliary files in '.'.
libtoolize: copying file './ltmain.sh'
libtoolize: putting macros in AC_CONFIG_MACRO_DIRS, 'm4'.
libtoolize: copying file 'm4/libtool.m4'
libtoolize: copying file 'm4/ltoptions.m4'
libtoolize: copying file 'm4/ltsugar.m4'
libtoolize: copying file 'm4/ltversion.m4'
libtoolize: copying file 'm4/lt~obsolete.m4'
configure.ac:16: installing './config.guess'
configure.ac:16: installing './config.sub'
opipc@opipc2:~/bluez-alsa-master$ mkdir build && cd build
opipc@orangepipc2:~/bluez-alsa-master/build$ ../configure
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /bin/mkdir -p
checking for gawk... no
checking for mawk... mawk
checking whether make sets $(MAKE)... yes
checking whether make supports nested variables... yes
checking for style of include used by make... GNU
checking for gcc... gcc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables...
checking whether we are cross compiling... no
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ISO C89... none needed
checking whether gcc understands -c and -o together... yes
checking dependency style of gcc... gcc3
checking how to run the C preprocessor... gcc -E
checking for grep that handles long lines and -e... /bin/grep
checking for egrep... /bin/grep -E
checking for ANSI C header files... yes
checking for sys/types.h... yes
checking for sys/stat.h... yes
checking for stdlib.h... yes
checking for string.h... yes
checking for memory.h... yes
checking for strings.h... yes
checking for inttypes.h... yes
checking for stdint.h... yes
checking for unistd.h... yes
checking minix/config.h usability... no
checking minix/config.h presence... no
checking for minix/config.h... no
checking whether it is safe to define __EXTENSIONS__... yes
checking for gcc... (cached) gcc
checking whether we are using the GNU C compiler... (cached) yes
checking whether gcc accepts -g... (cached) yes
checking for gcc option to accept ISO C89... (cached) none needed
checking whether gcc understands -c and -o together... (cached) yes
checking dependency style of gcc... (cached) gcc3
checking for ar... ar
checking the archiver (ar) interface... ar
checking build system type... aarch64-unknown-linux-gnu
checking host system type... aarch64-unknown-linux-gnu
checking how to print strings... printf
checking for a sed that does not truncate output... /bin/sed
checking for fgrep... /bin/grep -F
checking for ld used by gcc... /usr/bin/ld
checking if the linker (/usr/bin/ld) is GNU ld... yes
checking for BSD- or MS-compatible name lister (nm)... /usr/bin/nm -B
checking the name lister (/usr/bin/nm -B) interface... BSD nm
checking whether ln -s works... yes
checking the maximum length of command line arguments... 1572864
checking how to convert aarch64-unknown-linux-gnu file names to aarch64-unknown-linux-gnu format... func_convert_file_noop
checking how to convert aarch64-unknown-linux-gnu file names to toolchain format... func_convert_file_noop
checking for /usr/bin/ld option to reload object files... -r
checking for objdump... objdump
checking how to recognize dependent libraries... pass_all
checking for dlltool... no
checking how to associate runtime and link libraries... printf %s\n
checking for archiver @FILE support... @
checking for strip... strip
checking for ranlib... ranlib
checking command to parse /usr/bin/nm -B output from gcc object... ok
checking for sysroot... no
checking for a working dd... /bin/dd
checking how to truncate binary pipes... /bin/dd bs=4096 count=1
checking for mt... mt
checking if mt is a manifest tool... no
checking for dlfcn.h... yes
checking for objdir... .libs
checking if gcc supports -fno-rtti -fno-exceptions... no
checking for gcc option to produce PIC... -fPIC -DPIC
checking if gcc PIC flag -fPIC -DPIC works... yes
checking if gcc static flag -static works... yes
checking if gcc supports -c -o file.o... yes
checking if gcc supports -c -o file.o... (cached) yes
checking whether the gcc linker (/usr/bin/ld) supports shared libraries... yes
checking whether -lc should be explicitly linked in... no
checking dynamic linker characteristics... GNU/Linux ld.so
checking how to hardcode library paths into programs... immediate
checking whether stripping libraries is possible... yes
checking if libtool supports shared libraries... yes
checking whether to build shared libraries... yes
checking whether to build static libraries... yes
checking pkg-config m4 macros... yes
checking for splice... yes
checking for library containing clock_gettime... none required
checking for library containing pow... -lm
checking for library containing pthread_create... -lpthread
checking for pkg-config... /usr/bin/pkg-config
checking pkg-config is at least version 0.9.0... yes
checking for ALSA... yes
checking for BLUEZ... yes
checking for DBUS1... yes
checking for GLIB2... yes
checking for GIO2... yes
checking for SBC... yes
checking that generated files are newer than configure... done
configure: creating ./config.status
config.status: creating Makefile
config.status: creating src/Makefile
config.status: creating src/asound/Makefile
config.status: creating utils/Makefile
config.status: creating test/Makefile
config.status: creating config.h
config.status: config.h is unchanged
config.status: executing depfiles commands
config.status: executing libtool commands
configure: WARNING: *** alsa-lib >= 1.1.2 ***
configure: WARNING: Starting from alsa-lib 1.1.2, it is possible to enable
configure: WARNING: thread-safe API functions. Unfortunately, this feature
configure: WARNING: is not mature enough - software plugins may experience
configure: WARNING: random deadlocks (bluez-alsa PCM plugin is affected).
configure: WARNING: Either compile alsa-lib without this feature or export
configure: WARNING: LIBASOUND_THREAD_SAFE=0 while using bluealsa PCM.
opipc@opipc2:~/bluez-alsa-master/build$ make -j4 && sudo make install
make all-recursive
...
----------------------------------------------------------------------
Libraries have been installed in:
/usr/lib/aarch64-linux-gnu/alsa-lib
If you ever happen to want to link against installed libraries
in a given directory, LIBDIR, you must either use libtool, and
specify the full pathname of the library, or use the '-LLIBDIR'
flag during linking and do at least one of the following:
- add LIBDIR to the 'LD_LIBRARY_PATH' environment variable
during execution
- add LIBDIR to the 'LD_RUN_PATH' environment variable
during linking
- use the '-Wl,-rpath -Wl,LIBDIR' linker flag
- have your system administrator add LIBDIR to '/etc/ld.so.conf'
See any operating system documentation about shared libraries for
more information, such as the ld(1) and ld.so(8) manual pages.
----------------------------------------------------------------------
make[3]: Leaving directory '/home/opipc/bluez-alsa-master/build/src/asound'
make[2]: Leaving directory '/home/opipc/bluez-alsa-master/build/src/asound'
make[2]: Entering directory '/home/opipc/bluez-alsa-master/build/src'
make[3]: Entering directory '/home/opipc/bluez-alsa-master/build/src'
/bin/mkdir -p '/usr/bin'
/bin/bash ../libtool --mode=install /usr/bin/install -c bluealsa '/usr/bin'
libtool: install: /usr/bin/install -c bluealsa /usr/bin/bluealsa
/bin/mkdir -p '/etc/dbus-1/system.d'
/usr/bin/install -c -m 644 ../../src/bluealsa.conf '/etc/dbus-1/system.d'
make[3]: Leaving directory '/home/opipc/bluez-alsa-master/build/src'
make[2]: Leaving directory '/home/opipc/bluez-alsa-master/build/src'
make[1]: Leaving directory '/home/opipc/bluez-alsa-master/build/src'
Making install in utils
make[1]: Entering directory '/home/opipc/bluez-alsa-master/build/utils'
make[2]: Entering directory '/home/opipc/bluez-alsa-master/build/utils'
/bin/mkdir -p '/usr/bin'
/bin/bash ../libtool --mode=install /usr/bin/install -c bluealsa-aplay '/usr/bin'
libtool: install: /usr/bin/install -c bluealsa-aplay /usr/bin/bluealsa-aplay
make[2]: Nothing to be done for 'install-data-am'.
make[2]: Leaving directory '/home/opipc/bluez-alsa-master/build/utils'
make[1]: Leaving directory '/home/opipc/bluez-alsa-master/build/utils'
make[1]: Entering directory '/home/opipc/bluez-alsa-master/build'
make[2]: Entering directory '/home/opipc/bluez-alsa-master/build'
make[2]: Nothing to be done for 'install-exec-am'.
make[2]: Nothing to be done for 'install-data-am'.
make[2]: Leaving directory '/home/opipc/bluez-alsa-master/build'
make[1]: Leaving directory '/home/opipc/bluez-alsa-master/build'
I was worried about the warnings at the end of ./configure
. I found the following issue in the repository which made things a bit clearer.
Now I see, that this troubleshooting section is misleading. The --disable-thread-safety is a configuration option for alsa-lib >= 1.1.2, not for bluez-alsa. If you are using alsa-lib from a distro repository, the easiest approach is to define LIBASOUND_THREAD_SAFE=0 in your .profile file as follows:
export LIBASOUND_THREAD_SAFE=0
In the end, I did nothing about this, and so far it does not seem to matter at all.
Since there was no fatal errors when compiling, it was time to test that blueALSA
in conjunction with bluez
provides a solution for sound over BT. First start bluealsa
in the background and then try to connect to a BT speaker.
opipc@orangepipc2:~/bluez-alsa-master/build$ sudo bluealsa &
[1] 10251
The blueALSA
"shim" or bridge between the bluez
(the BT stack) and ALSA
(the Linux sound module) is now running in the background and it's process ID (a.k.a. pid
) is 10251.
opipc@orangepipc2:~/bluez-alsa-master/build$ bluetoothctl
Agent registered
[bluetooth]# scan on Not needed if paired previously
Discovery started
[CHG] Controller 00:1A:7D:DA:71:13 Discovering: yes
[NEW] Device 30:21:5C:30:F1:C4 AUDIOPOD2
[bluetooth]# pair 30:21:5C:30:F1:C4 Not needed if paired previously
Attempting to pair with 30:21:5C:30:F1:C4
[CHG] Device 30:21:5C:30:F1:C4 Connected: yes
[CHG] Device 30:21:5C:30:F1:C4 UUIDs: 00001108-0000-1000-8000-00805f9b34fb
[CHG] Device 30:21:5C:30:F1:C4 UUIDs: 0000110b-0000-1000-8000-00805f9b34fb
[CHG] Device 30:21:5C:30:F1:C4 UUIDs: 0000110c-0000-1000-8000-00805f9b34fb
[CHG] Device 30:21:5C:30:F1:C4 UUIDs: 0000110e-0000-1000-8000-00805f9b34fb
[CHG] Device 30:21:5C:30:F1:C4 UUIDs: 0000111e-0000-1000-8000-00805f9b34fb
[CHG] Device 30:21:5C:30:F1:C4 ServicesResolved: yes
[CHG] Device 30:21:5C:30:F1:C4 Paired: yes
Pairing successful
[CHG] Device 30:21:5C:30:F1:C4 ServicesResolved: no
[CHG] Device 30:21:5C:30:F1:C4 Connected: no
[NEW] Controller 00:1A:7D:DA:71:13 orangepipc2 [default]
[NEW] Device 30:21:5C:30:F1:C4 AUDIOPOD2
Agent registered
[bluetooth]# connect 30:21:5C:30:F1:C4
Attempting to connect to 30:21:5C:30:F1:C4
[CHG] Device 30:21:5C:30:F1:C4 Connected: yes
Connection successful
[CHG] Device 30:21:5C:30:F1:C4 ServicesResolved: yes
[AUDIOPOD2]# quit
Agent unregistered
[DEL] Controller 00:1A:7D:DA:71:13 orangepipc2 [default]
That worked, now to play some sound, download a wav
file to the board and start the mixer in a separate SSH session.
opipc@orangepipc2:~$
alsamixer -D bluealsa
┌────────────────────────────── AlsaMixer v1.1.3 ──────────────────────────────┐
│ Card: BlueALSA F1: Help │
│ Chip: BlueALSA Plugin F2: System information │
│ View: F3:[Playback] F4: Capture F5: All F6: Select sound card │
│ Item: AUDIOPOD2 - A2DP Esc: Exit │
│ │
│ ┌──┐ ┌──┐ ┌──┐ │
│ │▒▒│ │ │ │▒▒│ │
│ │▒▒│ │ │ │▒▒│ │
│ │▒▒│ │ │ │▒▒│ │
│ │▒▒│ │ │ │▒▒│ │
│ │▒▒│ │ │ │▒▒│ │
│ │▒▒│ │ │ │▒▒│ │
│ │▒▒│ │ │ │▒▒│ │
│ │▒▒│ │▒▒│ │▒▒│ │
│ │▒▒│ │▒▒│ │▒▒│ │
│ │▒▒│ │▒▒│ │▒▒│ │
│ │▒▒│ │▒▒│ │▒▒│ │
│ ├──┤ ├──┤ └──┘ │
│ │OO│ │OO│ │
│ └──┘ └──┘ │
│ 100<>100 33 255 │
│ < AUDIOPOD2 - A2DP > AUDIOPOD2 - SCO AUDIOPOD2 | Battery │
└──────────────────────────────────────────────────────────────────────────────┘
Back in the first session, attempt to play the wav
file.
opipc@orangepipc2:~$ aplay -D bluealsa:DEV=30:21:5C:30:F1:C4,PROFILE=a2dp sound/sound-off.wav
Playing WAVE 'sound/sound-off.wav' : Signed 16 bit Little Endian, Rate 44100 Hz, Stereo
That worked. Since by default only the a2dp BT profile is activated by blueALSA
, there is no need to specify it in the command line.
opipc@orangepipc2:~$ aplay -D bluealsa:DEV=30:21:5C:30:F1:C4 sound/sound-off.wav
Playing WAVE 'sound/sound-off.wav' : Signed 16 bit Little Endian, Rate 44100 Hz, Stereo
To test audio streaming in the other direction, it will be necessary to have speakers connected to the 3.5 mm jack or an HDMI monitor with built-in speakers (do stand-alone HDMI speakers exist?) and a source which is BT capable, such as a tablet or smart phone. I used an Android tablet on which a YouTube video was playing.
If blueALSA
is still running, it will have to be stopped.
opipc@orangepipc2:~$ pidof bluealsa
10251
opipc@orangepipc2:~$ kill 10
opipc@orangepipc2:~$ sudo kill 10251
Now blueALSA
has to be restarted but with command line options such that two profiles will be available, a2dp-source
, which was available by default, and a2dp-sink
.
opipc@orangepipc2:~$ sudo bluealsa -p a2dp-source -p a2dp-sink &
[1] 1639
Do not forget the sudo
, I lost a lot of time because of that slip when checking with a second tablet. I will not go into the details of connecting the tablet with the OPiPC2 over Bluetooth. They depend on the operating system of the tablet. Even on Android systems, the details changed with different versions of the OS. On the OPiPC side, bluetoothctl
has to be used to make the OPiPC discoverable and after the OPiPC and the tablet have been paired, usually on the tablet side, bluetoothctl
on the OPiPC2 is used to connect with the tablet. Finally, the blueALSA
player has to be started.
opipc@orangepipc2:~$ bluealsa-aplay 00:00:00:00:00:00
The speaker on the table should be disconnected because the sound will be sent to the OPiPC2 that will play it over the speakers connected to the 3.5mm jack. If you have an Android device, the instructions at ha/rpi/bluetooth_02_en.html#streaming could be of help. Remember that the OPiPC2 will show up as a BT device on the tablet under its hostname which is orangepipc2
.
In those instructions it said that once the connection has been made, alsamixer
could be used to set the volume of the sound out of the speaker connected to the OPiPC2. Here is what will be seen
opipc@orangepipc2:~$
alsamixer
┌────────────────────────────── AlsaMixer v1.1.3 ──────────────────────────────┐
│ Card: H3 Audio Codec F1: Help │
│ Chip: F2: System information │
│ View: F3:[Playback] F4: Capture F5: All F6: Select sound card │
│ Item: Line Out [dB gain: -6.00] Esc: Exit │
│ │
│ ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐ │
│ │ │ │ │ │ │ │▒▒│ │▒▒│ │▒▒│ │▒▒│ │
│ │ │ │ │ │ │ │▒▒│ │▒▒│ │▒▒│ │▒▒│ │
│ │ │ │▒▒│ │▒▒│ │▒▒│ │▒▒│ │▒▒│ │▒▒│ →
│ │▒▒│ │▒▒│ │▒▒│ │▒▒│ │▒▒│ │▒▒│ │▒▒│ →
│ │▒▒│ │▒▒│ │▒▒│ │▒▒│ │▒▒│ │▒▒│ │▒▒│ →
│ │▒▒│ │▒▒│ │▒▒│ │▒▒│ │▒▒│ │▒▒│ │▒▒│ →
│ │▒▒│ │▒▒│ │▒▒│ │▒▒│ │▒▒│ │▒▒│ │▒▒│ →
│ │▒▒│ │▒▒│ │▒▒│ │▒▒│ │▒▒│ │▒▒│ │▒▒│ →
│ │▒▒│ │▒▒│ │▒▒│ │▒▒│ │▒▒│ │▒▒│ │▒▒│ →
│ │▒▒│ │▒▒│ │▒▒│ │▒▒│ │▒▒│ │▒▒│ │▒▒│ │
│ │▒▒│ │▒▒│ │▒▒│ │▒▒│ │▒▒│ │▒▒│ │▒▒│ │
│ ├──┤ ├──┤ Stereo ├──┤ └──┘ ├──┤ └──┘ ├──┤ │
│ │MM│ │OO│ │MM│ │MM│ │OO│ │
│ └──┘ └──┘ └──┘ └──┘ └──┘ │
│ 71 79bluealsa: E: SBC decoding error: No such file or directory │
│ Line In <Line Out>Line Out Mic1 Mic1 Boo Mic2 Mic2 Boo DAC │
└──────────────────────────────────────────────────────────────────────────────┘
Two mixers influence the volume of the sound playing through the speakers: Line Out
and DAC
. Furthermore the volume control on the tablet also determines the output volume.
The audio playback on the Orange Pi PC 2 lags behind the video playing on the tablet just as observed with the Raspberry Pi 3 B. On the other hand, I did not notice stuttering during the short tests done and thus there is no need to disable the Wi-Fi.
A systemd
service unit file has to be created to start bluealsa
. Unfortunately, the simple unit file created in A Note on BlueAlsa 0.9 with BlueZ 5.43 on Rasbian Stretch will not be good enough because systemd
cannot start it automatically. However the BlueALSA wiki has a page that provides detailed instructions on Using bluealsa with systemd. I followed the instructions to the letter and everything seemed to work well. When creating the unit file, /etc/systemd/system/bluealsa.service
, the D-bus service file, /usr/share/dbus-1/system-services/org.bluealsa.service
and the default options file /etc/default/bluealsa
, don't forget to use the sudo
prefix. These three files should belong to root
and they are stored in directories not accessible by the default user.
Everything looks fine after booting; both the bluetooth
and bluealsa
services are running.
opipc@orangepipc2:~$ sudo systemctl status bluetooth*
● bluetooth.target - Bluetooth
Loaded: loaded (/lib/systemd/system/bluetooth.target; static; vendor preset: enabled)
Active: active since Thu 2020-02-27 21:11:48 AST; 1min 15s ago
Docs: man:systemd.special(7)
Feb 27 21:11:48 orangepipc2 systemd[1]: Reached target Bluetooth.
● bluetooth.service - Bluetooth service
Loaded: loaded (/lib/systemd/system/bluetooth.service; enabled; vendor preset: enabled)
Active: active (running) since Thu 2020-02-27 21:11:48 AST; 1min 16s ago
Docs: man:bluetoothd(8)
Main PID: 759 (bluetoothd)
Status: "Running"
Tasks: 1 (limit: 1021)
CGroup: /system.slice/bluetooth.service
└─759 /usr/lib/bluetooth/bluetoothd
Feb 27 21:11:47 orangepipc2 systemd[1]: Starting Bluetooth service...
Feb 27 21:11:47 orangepipc2 bluetoothd[759]: Bluetooth daemon 5.48
Feb 27 21:11:47 orangepipc2 bluetoothd[759]: Starting SDP server
Feb 27 21:11:48 orangepipc2 bluetoothd[759]: Bluetooth management interface 1.14 initialized
Feb 27 21:11:48 orangepipc2 systemd[1]: Started Bluetooth service.
Feb 27 21:11:48 orangepipc2 bluetoothd[759]: Endpoint registered: sender=:1.7 path=/org/bluez/hci0/A2DP/SBC/Source/1
Feb 27 21:11:48 orangepipc2 bluetoothd[759]: Endpoint registered: sender=:1.7 path=/org/bluez/hci0/A2DP/SBC/Source/2
Feb 27 21:11:48 orangepipc2 bluetoothd[759]: Endpoint registered: sender=:1.7 path=/org/bluez/hci0/A2DP/SBC/Sink/1
Feb 27 21:11:48 orangepipc2 bluetoothd[759]: Endpoint registered: sender=:1.7 path=/org/bluez/hci0/A2DP/SBC/Sink/2
opipc@orangepipc2:~$ sudo systemctl status bluealsa*
● bluealsa.service - Bluealsa daemon
Loaded: loaded (/etc/systemd/system/bluealsa.service; enabled; vendor preset: enabled)
Active: active (running) since Thu 2020-02-27 21:11:48 AST; 2min 9s ago
Docs: https://github.com/Arkq/bluez-alsa/
Main PID: 884 (bluealsa)
Tasks: 3 (limit: 1021)
CGroup: /system.slice/bluealsa.service
└─884 /usr/bin/bluealsa -p a2dp-source -p a2dp-sink
Feb 27 21:11:48 orangepipc2 systemd[1]: Starting Bluealsa daemon...
Feb 27 21:11:48 orangepipc2 systemd[1]: Started Bluealsa daemon.
Once again, this is a post mostly composed of information collated from much more knowledgable persons. I had occasion to give references to some of their work on a particular topic. The contribution of others is wider in scope. Chief among these are Arkadiusz Bokowy and his collaborators who have created the Blueetooth Audio ALSA Backend variously called bluez-alsa
and BlueALSA
. Two Wiki pages on the repository were particularly useful Installation from soucre and Systemd integration. Finally, I should mention guidol who is quite active on the Armbian Forum because his February 15, 2018 post BlueALSA: Bluetooth-Audio using ALSA (not PulseAudio), showed that it was possible to stream BT audio in Armbian without installing PulseAudio, just as in Raspbian.