Music on Console, ALSA, and Bluetooth on Raspbian Stretch
May 8, 2018
<-Baby Bluetooth Steps on Raspberry Pi 3 - Raspbian (Stretch) Bluetooth Audio with Rasbian Stretch on the Raspberry Pi 3->
<-Music on Console with Armbian on an Orange Pi Zero

Installing Music On Console (MOC) on a Raspberry Pi 3 (model B, not the new B+) running with Raspbian Stretch (march 2018 edition) was just as simple as it had been when I installed it on an Orange Pi Zero running with Armbian a few weeks ago. Things got interesting when I tried to pump the sound out to a Bluetooth speaker. Once again, I found myself immersed up to the eyeballs in ALSA configuration files, ALSA utility command line options and the MOC configuration file. It is all rather confusing and, to be honest, very frustrating especially as this is not something I really need to do. I just wanted to tie together two previous posts.

Table of Contents

  1. Installing MOC on the Raspberry Pi 3
  2. Using a Bluetooth Speaker
  3. Conclusion

  1. Installing MOC on the Raspberry Pi 3
  2. As mentioned before, installing MOC was very straight forward.

    pi@raspberrypi:~ $ sudo apt update && sudo apt upgrade pi@raspberrypi:~ $ sudo apt install moc moc-ffmpeg-plugin

    To make initial testing as simple as possible, I deleted the user ALSA configuration file, /home/pi/.asoundrc, that I had after setting up Bluetooth as explained in a previous post (Baby Bluetooth Steps on Raspberry Pi 3 - Raspbian (Stretch). I also copied a couple of wav files and a m3u playlist containing URLs of streaming Web radios to a directory called /home/pi/sound. Finally, after connecting powered speakers to the 3.5mm jack of the Raspberry Pi, the player was launched.

    pi@raspberrypi:~ $ mocp Running the server... Trying JACK... Trying ALSA... Warning: Your system may be vulnerable to stuttering audio. You should read the example configuration file comments for the 'ALSAStutterDefeat' option and set it accordingly. Setting the option will remove this warning.

    It worked "out of the box", without a ALSA user configuration file and without MOC user configuration file. And it worked if the audio output was selected automatically or the 3.5mm jack was explicitly selected.

    Just a reminder: the audio output device can be selected with the raspi-config utility or with the command line utility amixer.

    pi@raspberrypi:~ $ amixer numid=3 value
    13.5 mm jack

    The hdmi output was not tested but presumably it would work. See Audio configuration from the Rapsberry Pi Foundation.

    Two things in MOC were tested: the ability to play a sound file or stream a Web radio and the ability to control the volume of the sound. I also verified that the ALSA utility aplay could be used to listen to a sound file while controlling the volume with the graphic alsamixer utility opened in another terminal window.

    pi@raspberrypi:~ $ alsamixer

    pi@raspberrypi:~ $ aplay sound/test.wav Playing WAVE 'sound/test.wav' : Signed 16 bit Little Endian, Rate 16000 Hz, Mono

    Instead of using the ncurses based alsamixer the command line ALSA utility amixer can be used.

    pi@raspberrypi:~ $ amixer sset PCM 80 Simple mixer control 'PCM',0 Capabilities: pvolume pvolume-joined pswitch pswitch-joined Playback channels: Mono Limits: Playback -10239 - 400 Mono: Playback 80 [97%] [0.80dB] [on]

    Of course you have to know that the volume control is named PCM, but that could be deduced from the alsamixer display. It could also have been obtained from amixer itself.

    pi@raspberrypi:~ $ amixer scontrols Simple mixer control 'PCM',0

    The commands amixer controls and amixer contents yield even more information but I find it more confusing than anything else.

    By the way, the control in alsamixer in the first terminal will be updated when amixer is run in another terminal to adjust the volume.

  3. Using a Bluetooth Speaker
  4. I turned on a Bluetooth speaker that had already been paired and trusted which meant that it was automatically connected. Recall that I had Bluetooth running on this system.

    The ALSA mixer utilities alsamixer and amixer could be used except that the device had to be specified since the 3.5 mm jack is the default.

    pi@raspberrypi:~ $ alsamixer -D bluealsa

    pi@raspberrypi:~ $ amixer -D bluealsa scontrols Simple mixer control 'AUDIOPOD2 - A2DP',0 Simple mixer control 'AUDIOPOD2 - SCO',0 Simple mixer control 'AUDIOPOD2 | Battery',0 pi@raspberrypi:~ $ amixer -D bluealsa sset 'AUDIOPOD2 - A2DP' 40 Simple mixer control 'AUDIOPOD2 - A2DP',0 Capabilities: pvolume pswitch Playback channels: Front Left - Front Right Limits: Playback 0 - 127 Mono: Front Left: Playback 40 [31%] [on] Front Right: Playback 40 [31%] [on]

    As we have already seen, the aplay utility requires more details to be able to output the sound to the Bluetooth device.

    pi@raspberrypi:~ $ aplay -D bluealsa:HCI=hci0,DEV=30:21:3E:31:C6:2B,PROFILE=a2dp sound/test.wav Playing WAVE 'sound/test.wav' : Signed 16 bit Little Endian, Rate 16000 Hz, Mono

    Actually, all that is truly needed is the device type or name and Bluetooth speaker MAC address.

    pi@raspberrypi:~ $ aplay -D bluealsa:DEV=30:21:3E:31:C6:2B sound/test.wav Playing WAVE 'sound/test.wav' : Signed 16 bit Little Endian, Rate 16000 Hz, Mono

    Playback volume can be adjusted with the alsamixer and amixer utilities. However there is an inconsistency; the control in alsamixer is not updated when the volume is modified with amixer as shown above.

    I tried to launch the MOC player with the correct command line options so that it would also use the Bluetooth speaker. Note that the -O command line options are equivalent to adding definitions in the /home/pi/.moc/config file.

    pi@raspberrypi:~ $ mocp -O ALSADevice="bluealsa" -O ALSAMixer1="AUDIOPOD2 - A2DP" Running the server... Trying JACK... Trying ALSA... Trying OSS... FATAL_ERROR: No valid sound driver!

    Adding -SF to the mocp command line options results in more error output. That is how I found out that mocp required at least one named mixer (volume) control specified with the ALSAMixer1 option. The exception to that rule is if it can find a default named control ('MASTER' or 'PCM' from what I gathered), but there is not control with either name in the bluealsa card. Once that problem was solved, the other reported error was

    ... ALSA said: Unable to find definition 'defaults.bluealsa.device'
    It seemed like "bluealsa" was not the correct way to specify the ALSADevice parameter. So I tried the parameter used with the aplay utility. Unfortunately, ALSDEVICE="bluealsa:HCI=hci0,DEV=30:21:3E:31:C6:2B,PROFILE=a2dp" was not correct either. I tried all sorts of combinations without success. In the end, I created the following /home/pi/.asoundrc as suggested in the bluez-alsa github site.
    defaults.bluealsa.interface "hci0" defaults.bluealsa.device "30:21:3E:31:C6:2B" defaults.bluealsa.profile "a2dp"

    After rebooting and waiting for the Bluetooth speaker to be connected again, I launched the player as follows

    pi@raspberrypi:~ $ mocp -O ALSADevice="bluealsa" -O ALSAMixer1="AUDIOPOD2 - A2DP"

    This worked, including the volume (mixer) control! Finally. But..

    It seemed inevitable that there would be a "but". After exiting the player, it can be relaunched with a simple  mocp command, and that will start bluealsa again. This behaviour was strange because, if the system is rebooted and then the simple  mocp command is issued, the player will use the bcm2835 card, in other words, the sound will be send to the 3.5 mm jack (or perhaps HDMI connector). Surprisingly, restarting the player with  mocp -O ALSADevice="bluealsa" -O ALSAMixer1="AUDIOPOD2 - A2DP" would not start the bluealsa device; the player would continue sending the output to the bcm2835 card.

    As far as I can make out, this behaviour is linked to the MOC tendency to leave certain files behind the /home/pi/.moc directory. If the socket2 file is removed from the directory before launching the player with the simple  mocp command, the latter will always connect with card 0 (the 3.5 mm jack or HDMI connection) and  mocp -O ALSADevice="bluealsa" -O ALSAMixer1="AUDIOPOD2 - A2DP" will connect with the Bluetooth speaker. That is consistent with the behaviour of aplay.

    With the new .asoundrc configuration file,

    pi@raspberrypi:~ $ aplay -D bluealsa sound/test.wav"
    sends the sound file out to the Bluetooth speaker while
    pi@raspberrypi:~ $ aplay sound/test.wav"
    outputs the sound through the Raspberry Pi physical connector.

    MOC sometimes leaves a pid file in the /home/pi/.moc directory. Again, it is a good idea to erase that file because it can happen that the player will not start at all if the file is present.

  5. Conclusion
  6. There seems to be two morals here. The first is that "less is better." Do not create a MOC configuration file if you want to use the player with a Bluetooth speaker at times and with the Rapsberry sound hardware at other times. I never figured out what command line overrides would allow me to use the bcm2835 sound card if I had defined ALSADevice and ALSAMixer1 options in the /home/pi/.moc/config file.

    The other moral of this story may be that MOC should be launched with a script file that starts by deleting any left over pid and socket2 files in the /home/pi/.moc directory.

    I have no intention of pursuing this matter any further. This stuff is hard; way above my pay scale. Beside this was all caused by idle curiosity. It is time that I tackled my real project using a Raspberry Pi which might require Bluetooth connectivity. My long-term goal is to update a decent small size compact stereo receiver so that it can play Web radio streams. As an option, it would be nice if it could also stream audio from a tablet played through a Bluetooth connection which would mean connecting the Raspberry Pi as a Bluetooth receiver (sink) instead of a source.

    I will end this with some references that could be useful for those that have more complex setups than discussed above.

    PCM - pulse code modulation in Wikipedia. Explains what PCM is.
    A close look at ALSA by Volker Schatz. The author created a program, alsacap, which displays the true capabilities of a sound card and its ALSA driver.
    Linux ALSA sound notes Opiniated views.
    ALSA project - the C library reference
    Independent ALSA and linux audio support site
    Bluetooth Audio ALSA Backend
<-Baby Bluetooth Steps on Raspberry Pi 3 - Raspbian (Stretch) Bluetooth Audio with Rasbian Stretch on the Raspberry Pi 3->
<-Music on Console with Armbian on an Orange Pi Zero