Skip to content

ALSA devices with bluealsa‐aplay

borine edited this page Sep 13, 2024 · 16 revisions

Important

This document refers to BlueALSA components by the names used in the latest sources. For release v4.3.01or earlier please note that:

  • The bluealsad daemon was called bluealsa
  • The bluealsactl utility was called bluealsa-cli

Please consult the bluealsa-aplay manual page for bluealsa-aplay usage instructions. The purpose of this article is to provide some additional context, particularly to help users who may have little previous experience of working directly with the ALSA audio layer.

1. Audio Output Device

bluealsa-aplay plays the audio stream using ALSA, so the output device must be specified as an ALSA PCM device. If no device is specified on the command line bluealsa-aplay will select the ALSA default PCM, which on most systems will be the analogue output of the first sound card with automatic conversions, channel mapping and stream mixing enabled (assuming the user's ALSA config has not modified the definition of default). The user can use bluealsa-aplay command-line options to specify any alternative PCM device to use, and also to fine-tune some of the parameters of that device.

Selecting the output device

If the simple default ALSA device is not on the correct sound card on your system, you can tell bluealsa-aplay to use a different card, but still with all default settings. A card can be specified by index or by name. The index of a card is allocated sequentially as it is "discovered" by the kernel, and is therefore dependent on the order in which the kernel probes for devices on boot, and also the order in which removable cards such as USB audio adapters are added or removed by the user. Cards are numbered from 0, and if the card is not specified ALSA will assume card 0. For example, the following will use the default device on card 0:

bluealsa-aplay --pcm=default

to use the default device on card number 1, use

bluealsa-aplay --pcm=default:CARD=1

It may be preferable to use the card name rather than its index number if removable cards such as USB are in use, to avoid the issue of index number varying from one boot to the next. To see a list of connected sound card names, use:

cat /proc/asound/cards

In the output of that command, the first digit is the card index number, and the string within square brackets [ ... ] is the card name. The remaining text helps identify which card is which. So for example:

 0 [IQaudIODAC     ]: IQaudIODAC - IQaudIODAC
                      IQaudIODAC
 1 [Device         ]: USB-Audio - USB Audio Device
                      C-Media Electronics Inc. USB Audio Device at usb-3f980000.usb-1.2, full speed

In the above card 0 is called IQaudIODAC and card 1 is called Device. So the default PCM device on card 1 can also be specified with:

bluealsa-aplay --pcm=default:CARD=Device

Throughout this document we will use card numbers for simplicity, but in every example it is possible to use the card name instead of the number.

If default does not give the desired result, even when a specific card is selected, then alternative PCM devices can be used. ALSA provides a standard set of simple PCM devices that generally cover all the common usage scenarios for bluealsa-aplay. It is therefore unlikely that a user will need to define any complex PCM devices in their own ALSA config files. We consider each of these standard PCMs:

hw

The hw PCM device gives an application direct access to the sound card; alsa-lib does not apply any additional processing to the stream. Therefore, this PCM gives the highest possible fidelity and efficiency, but is also the least flexible. The stream configurations available are exactly those provided by the hardware so may not always be compatible with the bluealsa-aplay audio output streams. hw is the best choice when the sound card directly supports the bluetooth audio PCM formats and only one client connection at a time is required. Most sound cards will support only one client connection per PCM device, so with such cards bluealsa-aplay will only be able to support one connected bluetooth client at a time when using the hw PCM.

hw allows to specify the desired sound card and the device on that card as arguments. By default the first card and first device on that card are selected, so hw is equivalent to hw:0,0. For example, to output audio directly to device number 2 on card number 1, with no conversions:

bluealsa-aplay --pcm=hw:1,2

or

bluealsa-aplay --pcm=hw:CARD=1,DEV=2

Note that the DEV argument is always a number, only the CARD argument will accept a name, not the DEV argument.

You can obtain a list of all available device numbers using

aplay -l

Example output:

**** List of PLAYBACK Hardware Devices ****
card 0: PCH [HDA Intel PCH], device 0: ALC236 Analog [ALC236 Analog]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 0: PCH [HDA Intel PCH], device 3: HDMI 0 [HDMI 0]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 0: PCH [HDA Intel PCH], device 7: HDMI 1 [HDMI 1]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 0: PCH [HDA Intel PCH], device 8: HDMI 2 [HDMI 2]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 0: PCH [HDA Intel PCH], device 9: HDMI 3 [HDMI 3]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 0: PCH [HDA Intel PCH], device 10: HDMI 4 [HDMI 4]
  Subdevices: 1/1
  Subdevice #0: subdevice #0

Here device 0 is the analog output and devices 3,7,8,9 and 10 are HDMI digital outputs.

plughw

The plughw PCM device applies some conversions to the audio stream where necessary before passing it to the sound card. This PCM can modify:

  • access - bluealsa-aplay always opens its output PCM in interleaved read-write mode, if the card requires non-interleaved or memory-mapped mode plughw will perform this conversion automatically. This conversion does not degrade the audio stream in any way.

  • sample rate - bluealsa-aplay outputs audio at the sample rate sent by the bluetooth client; plughw can re-sample the stream to a different rate, however any such conversion will inevitably result in some loss of information and some "artefacts" which may potentially result in a noticeable loss of fidelity. Also the conversion may be approximate in which case there may be dropouts in the sound caused by underruns or overruns of the PCM buffer.

  • sample format - bluealsa-aplay outputs audio samples with the same PCM format as sent by the bluetooth client. Typically, this is signed 16-bit integer ("S16_LE"). plughw can re-sample to a different format if necessary; this can lead to some loss of fidelity, especially if the number of bits per sample is reduced.

  • channels - A2DP streams are generally stereo (2 channels), HSP/HFP streams are always mono (1 channel). If the card supports more channels than the Bluetooth stream, then plughw will leave the additional channels of the card unused, except in the case of a mono stream feeding a stereo output device in which case it will copy the mono stream to channels 0 and 1 of the card, each at 50% volume. If the output PCM supports only one channel, then for a stereo stream plughw will combine the two channels by averaging.

plughw performs only those conversions that are necessary to make the stream compatible with the card. So it is a good general choice when support for only one Bluetooth device at a time is required. It accepts the same arguments, with the same defaults, as the hw PCM to select card and device.

For example, to use plughw with card 0, device 0:

bluealsa-aplay --pcm=plughw

... or with card 1, device 3:

bluealsa-aplay --pcm=plughw:CARD=1,DEV=3

default

The purpose of the ALSA default PCM device is to ensure, as far as is possible, that there is always at least one PCM available that will just "work" with any stream. It will try to apply whatever converters and other plugins are required to permit multiple simultaneous client connections sending any stream format to some device on the selected card. It takes one argument, which specifies which card to use, and defaults to card 0. Note that the default PCM device does not accept a DEV argument: the default device for a card is pre-set in the ALSA configuration (it is almost always device 0).

It is common practice to re-define default in user configurations to support some specific application. If for any reason you have found it necessary to re-define default to support some other application, then bluealsa-aplay will use this new definition.

default is the best choice for initial testing, and in production for many budget or low-quality cards (e.g. the Raspberry Pi on-board jack-plug audio output). It is also a good choice in general, unless you require output to a card that has multiple devices (e.g. digital outputs) or multiple channels, and the output you require is not configured as default for the card.

Example:

bluealsa-aplay --pcm=default:CARD=1

sysdefault

The sysdefault PCM device initially is an alias for default in an out-of-the-box ALSA configuration. If default has been re-defined in the user configuration then the original definition is still available by using sysdefault.

bluealsa-aplay --pcm=sysdefault:CARD=1

dmix

The dmix PCM device implements stream mixing in software before passing the resulting mixed stream directly to a hw PCM device. This allows multiple clients to connect simultaneously to a card that would otherwise not allow this. This device requires that all clients use the same audio format and sample rate, and the same buffer and period sizes. All of the hardware parameters are set by the dmix PCM device. It ignores the values requested by the clients for buffer and period. The default values used are:

  • period size: 1024 frames
  • buffer size: 16384 frames (i.e. 16 periods)

Channels, rate and format can be selected by the first client to open the dmix device, but only by using arguments to the device name when it is opened. The default values are:

  • channels: 2
  • rate: 48000
  • format: the default format of the underlying hw device

For example, to open the dmix device on the default card, but with a rate of 44100 and format S16_LE, use:

bluealsa-aplay --pcm=dmix:RATE=44100,FORMAT=S16_LE

This will only succeed if the underlying hw device natively supports those parameters, is not already opened (for example by a client using the hw device directly) and this dmix device is not already opened using a different set of parameters.

To use a different card (e.g. card 1), or different device on the card (e.g. device 2) the above example would be used as:

bluealsa-aplay --pcm=dmix:CARD=1,DEV=2,RATE=44100,FORMAT=S16_LE

The dmix PCM device can be a good choice when the user knows that the all Bluetooth clients will use the same audio parameters (i.e. channels, rate and format). Note that a standard-compliant Bluetooth speaker must allow A2DP clients to use either 48000 or 44100 sample rate, so in general it is not guaranteed that all clients will use the same audio parameters. See the plug PCM device below for more information.

dsnoop

dsnoop is for audio capture only, so is not relevant to bluealsa-aplay.

file

The file PCM device stores the output stream to a file or FIFO (it can also create a command pipeline and send the PCM stream to the pipeline standard input). It does not send the audio to any sound card or other audio device. The file path must be provided as a parameter. By default the file will contain raw PCM; if you wish to create a .wav file, add wav as a second parameter. For example:

bluealsa-aplay --pcm=file:/tmp/recording.wav,wav

or

bluealsa-aplay --pcm=file:FILE=/tmp/recording.wav,FORMAT=wav

The filename can contain placeholders which are substituted by the sample format (%f), sample rate (%r) and channels (%c). This can be especially useful when creating a raw PCM file, which otherwise would include no information about its contents. For example:

bluealsa-aplay --pcm=file:/tmp/recording-%f-%r-%c.pcm

null

The null PCM device just discards all samples, so we mention it here only for completeness as on its own it has little practical use with bluealsa-aplay

Multi-channel abstractions

For cards that are known to ALSA, the standard configuration also includes some PCM devices that map the stream to specific multi-channel layouts. These PCM devices do not apply any conversions to the audio. Since BlueALSA streams are either 1 or 2 channel only, these are of little practical use with bluealsa-aplay. They are:

  • surround21
  • surround40
  • surround41
  • surround50
  • surround51
  • surround71

There is also a PCM device called front that may be useful with a multi-channel card if the hw device directs the audio to the rear or side speakers of a multi-channel card. Like the other multi-channel abstractions if performs no audio conversions.

See the upmix plugin below for a way to generate a synthetic multi-channel output from a BlueALSA stereo stream.

Digital Outputs

If the card has digital audio outputs, and ALSA has a configuration for the card, then PCM devices are available for these outputs. These devices perform no audio conversions or channel mapping. There are two types:

  • hdmi
  • spdif

spdif may also be called iec958. Both types accept the card id and a device number as arguments. Note that some HDMI devices only enable the audio when there is also a video stream. Examples:

Use the S/PDIF output on the default card:

bluealsa-aplay --pcm=spdif

Use the default HDMI output:

bluealsa-aplay --pcm=hdmi

The hdmi PCM has its own device numbering scheme. Looking at the example aplay -l output above, we see on that particular card hw device 3 is HDMI device 0, and hw device 7 is HDMI device 1, etc. When using the hdmi PCM the DEV argument is the HDMI number. Most HDMI devices will identify themselves when connected, and if so aplay -l will indicate that device identity in its output. So for example, if an HDMI socket on the computer is connected to an LG TV, the output from aplay -l may be:

**** List of PLAYBACK Hardware Devices ****
card 0: PCH [HDA Intel PCH], device 0: ALC236 Analog [ALC236 Analog]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 0: PCH [HDA Intel PCH], device 3: HDMI 0 [HDMI 0]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 0: PCH [HDA Intel PCH], device 7: HDMI 1 [LG TV]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 0: PCH [HDA Intel PCH], device 8: HDMI 2 [HDMI 2]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 0: PCH [HDA Intel PCH], device 9: HDMI 3 [HDMI 3]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 0: PCH [HDA Intel PCH], device 10: HDMI 4 [HDMI 4]
  Subdevices: 1/1
  Subdevice #0: subdevice #0

This tells us that HDMI device 1 is the connection to the TV. So we can use that with:

bluealsa-aplay --pcm=hdmi:CARD=0,DEV=1

Neither of these digital devices perform any audio conversions, so it may be necessary to use the plug PCM device to make them compatible with bluealsa-aplay.

Wrappers

The standard ALSA PCM device set also includes two PCM devices that can be used in conjunction with the above devices to improve compatibility and allow recording while playing to a device. The actual output device must be specified as an argument, which may need careful quoting.

plug

The plug PCM device can be used to convert audio format for use with those devices above that do not do this themselves. The conversions it can do are the same as the plughw device, please see that device for more details. For example, to use the dmix PCM device on card 1 device 2 when the underlying hw device does not support the BlueALSA audio format:

bluealsa-aplay --pcm="plug:'dmix:CARD=1,DEV=2'"

tee

The tee PCM device copies the audio stream to a file (or fifo, or command pipeline) and also sends it to an output PCM device. See the file PCM device description above for details of the file naming. It requires the output PCM device, file name, and optional file format as arguments. For example:

bluealsa-aplay --pcm="tee:SLAVE='plughw:CARD=1,DEV=2',FILE=/tmp/recording.wav,FORMAT=wav"

upmix

If the sound card has 4, 6, or 8 output channels, then it is possible to create a virtual surround effect from a BlueALSA stereo stream using the ALSA upmix plugin. upmix is an external plugin, not included within the alsa-lib libasound2 library, it is part of the ALSA alsa-plugins repository. Most distributions include it in a package; some (e.g. Fedora) call the package alsa-plugins others (e.g. Debian and derivatives) call the package libasound2-plugins.

upmix has parameters SLAVE, CHANNELS, and DELAY, with defaults "plug:hw", 6, and 0 respectively. So, for example to create a virtual 5.1 sound effect using a sound card with 6 channels:

bluealsa-aplay --pcm=upmix

or a virtual 4.0 sound effect using the default device on card 1 (which must have 4 channels for this to work):

bluealsa-aplay --pcm="upmix:SLAVE='default:CARD=1',CHANNELS=4"

The DELAY parameter adds a delay (in milliseconds) to the rear channels, which can enhance the 3-D effect:

bluealsa-aplay --pcm="upmix:SLAVE='default:CARD=1',CHANNELS=4,DELAY=50"

Advanced configuration

The ALSA configuration can be extended by defining new PCMs, and the default values for various parameters can be modified by defining special keys in the configuration or by setting some special environment variables.

To set configuration keys they should be defined in either /etc/asound.conf (for all users, choose this if running bluealsa-aplay as root or some service account) or ~/.asoundrc (if running bluealsa-aplay under your own account). Some useful configuration keys:

  • defaults.pcm.card
    This key is used by all the above ALSA standard PCM devices to set the card number. Card names will not work here, so its usefulness is limited if removable cards are used. This key can be used instead of setting the card via the CARD argument when selecting the output device. If the CARD argument is used, the argument overrides this defaults key value. For example:

    defaults.pcm.card 1
    
  • defaults.ctl.card
    Similarly, this key sets the default mixer card.

  • defaults.pcm.device
    Sets the default device number for all the above ALSA standard PCM devices.

  • defaults.pcm.file_format
    Sets the default file format for the file and tee PCM devices. Takes the values raw or wav. The initial value is raw.

  • defaults.pcm.file_truncate
    If set to true, the file used by the file and tee PCM devices will be overwritten, if set to false then new audio data will be appended to the file. The initial value is true.

Defining your own PCMs is an advanced topic which is out of scope for this document, please consult your distribution's documentation or the ALSA documentation for more information.

Output device parameters

bluealsa-aplay needs to set the ALSA PCM device buffer time and period time (period time is the interval between interrupts from the device); and bluealsa-aplay must ensure that there is always at least one period of audio frames available in the buffer when a device interrupt occurs. By default, bluealsa-aplay sets the buffer time to 500000 µs, and the period time to 100000 µs. bluealsa-aplay starts the PCM device when BlueALSA has delivered enough audio frames to reduce the space in the buffer to one period or less. Decreasing the buffer time will therefore decrease latency, but will also increase the risk of audio drop-outs. A drop-out occurs either when there is less than one period of audio frames in the buffer when the device requests it, or when the buffer is full and audio needs to be transferred from BlueALSA. The period time should be set such that there is a whole number of periods in the buffer, because some ALSA devices (especially those that involve sample rate changes) may otherwise suffer increased risk of audio drop-outs. Reducing the number of periods in the buffer (the default is five) may slightly reduce latency but will increase CPU load. For example, to set the buffer time to 320000 µs with 4 periods in the buffer:

bluealsa-aplay --buffer-time=320000 --period-time=80000

To avoid drop-outs when the sound card cannot natively support the BlueALSA audio sample rate, it is advisable to ensure that the period time represents a whole number of audio frames at both the BlueALSA rate and the sound card rate. See the bluealsa-aplay manual page for more details. In practice this can achieved by ensuring that the period time is a multiple of 10000 µs.

Note that, for A2DP at least, the default values of buffer time and period time used by bluealsa-aplay work well and it is not normally necessary to set them explicitly.

dmix is a special case worth mentioning here. As noted above, it ignores the buffer_time and period_time settings requested by the application and applies its own default values, which are not multiples of 10000µs. This can a problem when the Bluetooth audio is not sampled at the rate set by dmix for the card, for example if the Bluetooth client sends audio sampled at 44100Hz.

To overcome this it is necessary to set new defaults for the dmix PCM device. This is achieved by setting special configuration keys. The defaults are specific to a card name. So, to set a period time of 100000µs with buffer of 5 periods using the example system above with an i2s card and a USB card, for the IQaudio card we need to define:

defaults.dmix.IQaudIODAC.period_time 100000
defaults.dmix.IQaudIODAC.periods 5

and for the USB card:

defaults.dmix.Device.period_time 100000
defaults.dmix.Device.periods 5

2. Volume Control

Bluetooth allows an audio source (e.g. phone) to control the playback volume of the audio sink (e.g. headphones, speaker). This requires that both devices support the necessary protocols.

BlueALSA supports remote volume control for both A2DP and HSP/HFP. A volume change request from the remote device can be implemented either internally by the bluealsad daemon, or bluealsa-aplay can operate an ALSA volume control for the output ALSA PCM device. In this article we discuss using the ALSA volume control.

With BlueALSA release 4.2.0 and later bluealsa-aplay has an option --volume to select the method used for volume control. To use the ALSA volume control, start bluealsa-aplay with this option set to mixer:

bluealsa-aplay --volume=mixer

With BlueALSA release 4.1.1 and earlier bluealsa-aplay did not have that option, and so in order to use the ALSA mixer for volume control with those releases it was necessary to have the bluealsa daemon set to "native" volume control. For HFP/HSP that was the default, but for A2DP it was necessary to start bluealsa with the option --a2dp-volume.

The BlueALSA service informs bluealsa-aplay whenever a volume change request is received from the remote device, and bluealsa-aplay then applies the requested change to its configured ALSA mixer control.

bluealsa-aplay by default will attempt to implement the volume change request by operating a control called Master in a mixer called default. Not all mixers have a control called Master so it is often necessary to give the correct name on the command-line. This is generally the case when using USB or i2c sound cards. default may not refer to the correct mixer if more than one sound card is attached, so it may also be necessary to specify the mixer device on the command line.

Note that the ALSA in-built digital PCM devices (hdmi and s/pdif,iec958) do not normally have hardware volume controls, so without any advanced configuration only software volume control is available to bluealsa-aplay with these devices.

ALSA mixers

In ALSA, a mixer is a CTL device. There are some standard pre-defined CTLs in ALSA, and it is also possible to define new CTL devices within the configuration. We will only consider the standard CTL devices here, use of bluealsa-aplay does not normally require bespoke definitions. The CTL devices of interest here are:

default

The default CTL device is normally defined to refer to the mixer that controls the card used by the default PCM device. Like the default PCM device it is often redefined in local configurations. This mixer takes its card number as an argument, so if you wish to use default card number 1:

bluealsa-aplay --mixer-device=default:1

or

bluealsa-aplay --mixer-device=default:CARD=1

If the --mixer-device= option is not given, bluealsa-aplay assumes --mixer-device=default.

sysdefault

The sysdefault CTL device is the same as the ALSA standard configuration default definition. Use this if you wish to use the original default definition on an installation in which default has been re-defined.

hw

The hw CTL device passes control requests directly to the sound card. In a standard installation sysdefault is in practice the same as hw.

ALSA controls

ALSA documentation uses the word "control" to refer to different, but related, concepts depending on the abstraction layer being discussed. In this document we use "control" to refer to an object that the ALSA documentation calls "simple control" or "simple mixer control". Possibly the easiest way to see a list of these controls for a connected sound card is to use alsamixer. If you have two cards connected, you can select the one you want with the --card= option. For example, to see the controls for card 1

alsamixer --card=1

Controls that show Item: ... [dB gain: ... ] in the top left when selected are volume controls of some kind that can be used by bluealsa-aplay; however to be certain of which is the correct control for your chosen PCM device you should consult the documentation for your card. If the documentation is missing or unclear, you could try each of the dB gain controls until you find one that works.

If Master is not the correct control for your PCM device, then you can specify the one to use on the command line. For example, to use a control called Speaker

bluealsa-aplay --mixer-name=Speaker