2020-02-29
md
ALSA and Bluetooth on the Orange Pi PC 2 with Armbian Bionic
I2C on the Orange Pi PC 2 with Armbian Bionic-> <-A Second Look at the Orange Pi PC 2

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

  1. Sound ALSA
    1. Playing Sound
    2. Recording Sound
  2. Bluetooth
    1. Compiling BlueALSA
    2. Sending an Audio Stream to Bluetooth Speakers
    3. Playing an Audio Stream from a Bluetooth Device
    4. BlueALSA systemd Service File
  3. References

Sound - ALSA toc

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.

Playing Sound toc

I connected a powered pair of speakers to the 3.5 mm jack and tested sound output following the SUNXI Audio Codec instructions.

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:

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.

Recording Sound toc

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]

Bluetooth toc

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.

Compiling BlueALSA toc

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.

Sending an Audio Stream to Bluetooth Speakers toc

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

Playing an Audio Stream from a Bluetooth Device bt-sink toc

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.

BlueALSA systemd Service File toc

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.

References toc

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.

I2C on the Orange Pi PC 2 with Armbian Bionic-> <-A Second Look at the Orange Pi PC 2