Skip to content

Commit 10c36bb

Browse files
borinearkq
authored andcommitted
aplay: Simplify ALSA PCM buffering selection
1 parent fe5cc21 commit 10c36bb

File tree

2 files changed

+58
-36
lines changed

2 files changed

+58
-36
lines changed

doc/bluealsa-aplay.1.rst

Lines changed: 36 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ bluealsa-aplay
66
a simple BlueALSA player
77
------------------------
88

9-
:Date: August 2024
9+
:Date: February 2025
1010
:Manual section: 1
1111
:Manual group: General Commands Manual
1212
:Version: $VERSION$
@@ -58,7 +58,8 @@ OPTIONS
5858
(i.e., all messages are logged).
5959

6060
-v, --verbose
61-
Make the output more verbose.
61+
Make the output more verbose. This option may be given multiple times to
62+
increase the verbosity.
6263

6364
-l, --list-devices
6465
List connected Bluetooth audio devices.
@@ -89,35 +90,40 @@ OPTIONS
8990

9091
--pcm-buffer-time=INT
9192
Set the playback PCM buffer duration time to *INT* microseconds.
92-
The default is 200000. It is recommended to choose a buffer time that is
93-
an exact multiple of the period time to avoid potential issues with some
94-
ALSA plugins (see --pcm-period-time option below).
95-
ALSA may choose the nearest available alternative if the requested value is
96-
not supported.
93+
The default is four times the period time. It is recommended to choose a
94+
buffer time that is an exact multiple of the period time to avoid potential
95+
issues with some ALSA plugins (see --pcm-period-time option below). For
96+
reliable performance the buffer time should be at least 3 times the period
97+
time.
9798

98-
If you experience underruns on the ALSA device then a larger buffer may
99-
help. However, a larger buffer will also increase the latency. For reliable
100-
performance the buffer time should be at least 3 times the period time.
99+
ALSA may choose the nearest available alternative if the requested value is
100+
not supported; and some ALSA devices may ignore the requested value
101+
completely (e.g. **dmix**, see dmix_ in the **NOTES** section below).
101102

102103
--pcm-period-time=INT
103-
Set the playback PCM period duration time to *INT* microseconds.
104-
The default is 50000.
104+
Set the playback PCM period duration time to *INT* microseconds. The
105+
default is 50000 for A2DP and 20000 for SCO profiles.
105106
ALSA may choose the nearest available alternative if the requested value is
106-
not supported.
107+
not supported; and some ALSA devices may ignore the requested value
108+
completely (e.g. **dmix**, see dmix_ in the **NOTES** section below).
109+
110+
If you experience underruns on the ALSA device or overruns on the Bluetooth
111+
stream then a larger period time may help. However, a larger period time
112+
will also increase the latency.
107113

108114
The ALSA **rate** plugin, which may be invoked by **plug**, does not always
109115
produce the exact required effective sample rate because of rounding errors
110116
in the conversion between period time and period size. This can have a
111117
significant impact on synchronization "drift", especially with small period
112118
sizes, and can also result in stream underruns (if the effective rate is
113-
too fast) or dropped A2DP frames in the **bluealsad(8)** server (if the
114-
effective rate is too slow). This effect is avoided if the selected period
115-
time results in an exact integer number of frames for both the source rate
116-
(Bluetooth) and sink rate (hardware card). For example, in the case of
117-
Bluetooth stream sampled at 44100Hz playing to a hardware device that
118-
supports only 48000Hz, choosing a period time that is a multiple of 10000
119-
microseconds will result in zero rounding error. (10000 µs at 44100Hz is
120-
441 frames, and at 48000Hz is 480 frames).
119+
too fast) or dropped frames (if the effective rate is too slow). This
120+
effect is avoided if the selected period time results in an exact integer
121+
number of frames for both the source rate (Bluetooth) and sink rate
122+
(hardware card). For example, in the case of Bluetooth stream sampled at
123+
44100 Hz playing to a hardware device that supports only 48000 Hz, choosing
124+
a period time that is a multiple of 10000 microseconds will result in zero
125+
rounding error. (10000 µs at 44100 Hz is 441 frames, and at 48000 Hz is 480
126+
frames).
121127

122128
See also dmix_ in the **NOTES** section below for more information on
123129
rate calculation rounding errors.
@@ -226,13 +232,14 @@ control.
226232
dmix
227233
----
228234

229-
The ALSA `dmix` plugin will ignore the period and buffer times selected by the
230-
application (because it has to allow connections from multiple applications).
231-
Instead it will choose its own values, which can lead to rounding errors in the
232-
period size calculation when used with the ALSA `rate` plugin. To avoid this,
233-
it is recommended to explicitly define the hardware period size and buffer size
234-
for dmix in your ALSA configuration. For example, suppose we want a period time
235-
of 50000 µs and a buffer holding 4 periods with an Intel 'PCH' card:
235+
The ALSA **dmix** plugin will ignore the period and buffer times selected by
236+
the application (because it has to allow connections from multiple
237+
applications). Instead it will choose its own values, which can lead to
238+
rounding errors in the period size calculation when used with the ALSA **rate**
239+
plugin. To avoid this, it is recommended to explicitly define the hardware
240+
period size and buffer size for **dmix** in your ALSA configuration. For
241+
example, suppose we want a period time of 50000 µs and a buffer holding 4
242+
periods with an Intel 'PCH' card:
236243

237244
::
238245

@@ -260,7 +267,7 @@ EXAMPLES
260267
========
261268

262269
The simplest usage of **bluealsa-aplay** is to run it with no arguments. It
263-
will play audio from all connected Bluetooth devices to the ``default`` ALSA
270+
will play audio from all connected Bluetooth devices to the **default** ALSA
264271
playback PCM.
265272

266273
::

utils/aplay/aplay.c

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,14 @@
4848
#include "dbus.h"
4949
#include "delay-report.h"
5050

51+
/* Many devices cannot synchronize A/V with very high audio latency. To keep
52+
* the overall latency below 400ms we choose default ALSA parameters such that
53+
* the ALSA latency for A2DP is below 200ms. For SCO we choose to prioritize
54+
* much lower latency over audio quality. */
55+
#define DEFAULT_PERIOD_TIME_A2DP 50000
56+
#define DEFAULT_PERIOD_TIME_SCO 20000
57+
#define DEFAULT_PERIODS 4
58+
5159
enum volume_type {
5260
VOL_TYPE_AUTO,
5361
VOL_TYPE_MIXER,
@@ -85,11 +93,8 @@ static bool ba_profile_a2dp = true;
8593
static bool ba_addr_any = false;
8694
static bdaddr_t *ba_addrs = NULL;
8795
static size_t ba_addrs_count = 0;
88-
/* Many devices cannot synchronize A/V with very high audio latency. To keep
89-
* the overall latency below 400ms we choose ALSA parameters such that the
90-
* ALSA latency is below 200ms. */
91-
static unsigned int pcm_buffer_time = 200000;
92-
static unsigned int pcm_period_time = 50000;
96+
static unsigned int pcm_buffer_time = 0;
97+
static unsigned int pcm_period_time = 0;
9398

9499
/* local PCM muted state for software mute */
95100
static bool pcm_muted = false;
@@ -1116,6 +1121,16 @@ int main(int argc, char *argv[]) {
11161121
if (volume_type == VOL_TYPE_NONE || volume_type == VOL_TYPE_SOFTWARE)
11171122
mixer_device = NULL;
11181123

1124+
if (pcm_buffer_time == 0) {
1125+
if (pcm_period_time == 0)
1126+
pcm_period_time = ba_profile_a2dp ?
1127+
DEFAULT_PERIOD_TIME_A2DP : DEFAULT_PERIOD_TIME_SCO;
1128+
pcm_buffer_time = pcm_period_time * DEFAULT_PERIODS;
1129+
}
1130+
else if (pcm_period_time == 0) {
1131+
pcm_period_time = pcm_buffer_time / DEFAULT_PERIODS;
1132+
}
1133+
11191134
if (verbose >= 1) {
11201135

11211136
char *ba_str = malloc(19 * ba_addrs_count + 1);
@@ -1137,16 +1152,16 @@ int main(int argc, char *argv[]) {
11371152
" ALSA PCM device: %s\n"
11381153
" ALSA PCM buffer time: %u us\n"
11391154
" ALSA PCM period time: %u us\n"
1140-
" Volume control type: %s\n"
11411155
" ALSA mixer device: %s\n"
11421156
" ALSA mixer element: %s\n"
1157+
" Volume control type: %s\n"
11431158
" Bluetooth device(s): %s\n"
11441159
" Profile: %s",
11451160
dbus_ba_service,
11461161
pcm_device, pcm_buffer_time, pcm_period_time,
1147-
volume_type_str,
11481162
mixer_device_str,
11491163
mixer_element_str,
1164+
volume_type_str,
11501165
ba_addr_any ? "ANY" : &ba_str[2],
11511166
ba_profile_a2dp ? "A2DP" : "SCO");
11521167

0 commit comments

Comments
 (0)