arkq/bluez-alsa

increasing delay as a sink

Closed this issue · 8 comments

Hello,

I using AAC sink, with blueasla-aplay on Raspberry Pi Zero W. I tried to play with settings in /src/transport.c

https://github.com/Arkq/bluez-alsa/blob/dbfa1dc3fe339276955cb9163848d3d4ee49996b/src/transport.c#L867-L870

and flags of bluealsa-aplay
--pcm-buffer-time=20000 --pcm-period-time=10000

I achieved low delay and sound become almost synch in videos, but the longer I watch the longer the delay. Аlmost 0.5 sec of delay every 2-3 min of watching.

I don't clearly understand how it happends because I didn't notice any gaps and sound seems to play at normal speed.
So am I doing it right with parameters and how to stop increasing of the sound delay?

Thanks for this tool, using it makes my day happier.

I have the same issue, restarting bluealsa-aplay periodically is a somewhat viable workaround. But of course you hear the sound stutter everytime, you restart it. Is there any way to flush bluealsa-aplay's buffer?

So I'm using my Raspberry Pi 3 Model B as an A2DP sink over Bluetooth. More specifically, I want to use my Samsung phone's dual-audio over Bluetooth feature, which allows it to pair to two Bluetooth speakers at the same time.

I've been trying to get my UE Megaboom speaker to play in-sync with the non-Bluetooth speaker connected to my RPi's audio jack. I also stumbled onto those bluealsa-aplay flags you mentioned: pcm-buffer-time and pcm-period-time.

I looked more into those flags, and found this on the aplay man page:

-F, --period-time=#
Distance between interrupts is # microseconds. If no period time and no period size is given then a quarter of the buffer time is set.

-B, --buffer-time=#
Buffer duration is # microseconds If no buffer time and no buffer size is given then the maximal allowed buffer time but not more than 500ms is set.

--period-size=#
Distance between interrupts is # frames If no period size and no period time is given then a quarter of the buffer size is set.

--buffer-size=#
Buffer duration is # frames If no buffer time and no buffer size is given then the maximal allowed buffer time but not more than 500ms is set.

So it seems bluealsa-aplay only allows us to adjust aplay's period-time and buffer-time. If we don't set these values, then bluealsa-aplay defaults to a buffer-time of 500000us (500ms) and a period-time of 100000us (100ms).

However, I noticed something interesting about the output of the command:
bluealsa-aplay -vv 00:00:00:00:00:00

Output:

Selected configuration:
  HCI device: hci0
  PCM device: default
  PCM buffer time: 500000 us
  PCM period time: 100000 us
  Bluetooth device(s): ANY
  Profile: A2DP
Used configuration for [REDACTED MAC_ADDRESS]:
  PCM buffer time: 500000 us (88200 bytes)
  PCM period time: 100045 us (17648 bytes)
  Sampling rate: 44100 Hz
  Channels: 2

Specifically, this line: PCM period time: 100045 us (17648 bytes)
I'm not sure if there is some kind of rounding error going on here or if this could be responsible for the delay drift you are talking about, but I've noticed that delay drift on occasion as well.

For period time, aplay's man page says:

Distance between interrupts is # microseconds. If no period time and no period size is given then a quarter of the buffer time is set

So I decided to set pcm-period-time only to values that are 1/4th the value of pcm-buffer-time, and this seems to have stabilized the audio stream quite a bit. However I'm still very new to all this so there could be a much better approach/solution.

And if anyone else who reads this is interested, I've tested different pcm-buffer-time values to try and get it in-sync with the UE Megaboom. Here's the command and output for what I found to be the closest match: bluealsa-aplay --pcm-buffer-time=135000 --pcm-period-time=33750 -vv 00:00:00:00:00:00

Output:

Selected configuration:
  HCI device: hci0
  PCM device: default
  PCM buffer time: 135000 us
  PCM period time: 33750 us
  Bluetooth device(s): ANY
  Profile: A2DP
Used configuration for [REDACTED MAC_ADDRESS]:
  PCM buffer time: 135011 us (23816 bytes)
  PCM period time: 33741 us (5952 bytes)
  Sampling rate: 44100 Hz
  Channels: 2

Notice the buffer time and period time are still slightly off (maybe it has to do with rounding to the nearest byte?--I have no idea). I would think this, in turn, means that aplay's period-size is not exactly 1/4th of the buffer-size. The delay drift still occasionally happens, but it seems to correct itself after several seconds. It could also be wireless interference that's causing the occasional loss of audio sync--but I'm not entirely sure of the cause.

All this to say, setting a pcm-period-time value that's 1/4th of your pcm-buffer-time value seems to stabilize things a bit. I also wouldn't set a pcm-buffer-time shorter than 50000us (50ms) since it seems too short, but you may want to test that out yourself.

I am now also using bluealsa-aplay --pcm-buffer-time=135000 --pcm-period-time=33750 -vv 00:00:00:00:00:00 and it seems to fix my increasing delay I experience with Raspberry Pi 2 Model B with an external Bluetooth adapter.

I suggest to keep this issue open until the actual cause of the problem gets more clear.

alsa period time and buffer time settings are not supposed to affect the playback speed, so (in theory) should not change the relative delay between two streams. I think the most likely underlying cause is this:

The common factor in the above reports is that they all appear to be using the RPi's on-board DAC, which is of notoriously poor quality. Try with a USB or i2c HAT DAC and see if that cures the problem.

In my setup, I used the RPi 2 Model B with an external USB sound card that is part of the speaker system. So in this case it should be a quality DAC. Still, I experienced this increasing delay before I found this work-around.

A recent change in alsa-lib may have improved synchronization when using the rate plugin to convert sample rates. See #451 (comment) for references. If anyone is experiencing this issue, it may be worth compiling alsa-lib to see if that helps.

A recent change in alsa-lib may have improved synchronization

Unfortunately that change has not made any difference to the rounding error.

However, since this issue was raised (nearly 3 years ago) there have many improvements to BlueALSA. In particular commit bacbf5d has removed the cause of the period time anomaly seen here. Rounding error still exists in the rate plugin, but can be avoided by choosing period time that is a multiple of 10ms when converting between 48000 and 44100 sample rates. The default period time of bluealsa-aplay is therefore now OK for this particular conversion.

There is still an issue of clock drift between the bluetooth clock and soundcard clock, but that should be considerably smaller than the amount originally reported here. To compensate for the clock drift, PR #459 if eventually committed, should suffice.

The latest update to the bluealsa-aplay manual page now includes some hints on choosing period times to avoid rate plugin rounding errors, and explains the effect of the dmix plugin and how to mitigate that. So the original issue raised here, of large timing drift, is now fixed, as far as is possible within the bluez-alsa project, by documenting how to configure ALSA to avoid it.

There still remains the issue of much smaller time drift which results from different clocks in the Bluetooth adapter and the soundcard. PR #459 proposes one way to address that, so please follow progress on that PR if you need to further improve synchronization.