Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bluealsa-aplay delay reporting improvements #738

Merged
merged 2 commits into from
Nov 17, 2024
Merged

Conversation

borine
Copy link
Collaborator

@borine borine commented Nov 12, 2024

This PR attempts to resolve two issues I've found with the new sink delay
reporting.

The first is that although A/V sync is mostly good with BlueALSA devices as source,
my iphone is unable to sync. I found that a typical commercial sink has a delay
between 100ms and 200ms with both SBC and AAC codecs, whereas my BlueALSA sink
has a delay of over 400ms. By adjusting the bluealsa-aplay ALSA parameters to
reduce the delay, I can achieve very good A/V sync with both the iphone and
BlueALSA sources.

The second is that although A/V sync is generally very good, it can on occasion
be understated by over 100ms (as measured by setting the ClientDelay property on
a BlueALSA source to correct the sync). I believe this is caused by the
relative payload sizes of the L2CAP frames, codec frames, and ALSA start
threshold, combined with the precise timing of the arrival of the initial L2CAP
frames. In some runs, sufficient PCM frames accumulate in the pcm pipe and/or
bluealsa-aplay read buffer so that they cannot all be transferred to the ALSA
buffer in a single iteration. So I have extended the delay calculation to
account for these buffers, and so far with this change I have had always had
good A/V sync with all source devices .

This needs testing with a variety of sources and sink devices to check that the
reduced default ALSA start threshold and buffer size do not lead underruns; I
have not found any data to help select the "best" compromise values, so the
values chosen here are somewhat arbitrary.

Copy link

codecov bot commented Nov 12, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 70.49%. Comparing base (1002906) to head (e77b82b).
Report is 2 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #738      +/-   ##
==========================================
- Coverage   70.49%   70.49%   -0.01%     
==========================================
  Files          96       96              
  Lines       15999    16005       +6     
  Branches     2510     2508       -2     
==========================================
+ Hits        11278    11282       +4     
- Misses       4604     4606       +2     
  Partials      117      117              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@arkq
Copy link
Owner

arkq commented Nov 13, 2024

I found that a typical commercial sink has a delay between 100ms and 200ms with both SBC and AAC codecs

I've just pulled your PR and when streaming from Android to RPi I still can see ClientDelay ~500 ms. I've tested with AAC, so SBC should be ~450 (AAC has total codec delay ~75ms). When starting bluealsa-aplay while the A2DP is already started the delay is ~300 ms. So, maybe the PCM start threshold should be changed (now it starts when the buffer is full), or at least allowed to be tuned by the user?

@arkq
Copy link
Owner

arkq commented Nov 13, 2024

Also, regarding delay reporting, I'm still not sure what is wrong with Windows™. With this PR the A/V sync seems to be better, but I'm rather far from stating that the A/V works as expected. The case is that now the initial overall delay is lower, so it appears that A/V is in sync... but it's not :D Also, I think that now, since the delay reporting is in place (and at least works with BlueZ-BlueZ setup) it's time to have another look at the problem reported in #459 Because when playing video I can see steady delay accumulation (Windows sends audio faster than RPi plays it)...

@borine
Copy link
Collaborator Author

borine commented Nov 13, 2024

I still can see ClientDelay ~500 ms

Hmm, that is disappointing indeed. This PR sets the ALSA buffer size to 200ms, so for a hw device the maximum ALSA delay cannot be significantly higher than that. I can only assume that the balance of the delay is from samples in the fifo or read buffer. Can you provide more info about the hw setup and stream parameters? I'm using plughw with an IQAudio i2c DAC, the source streams are variously sampled at 44100 and 48000, and I've tried AAC from iphone, and SBC, AAC and aptX from linux.

now [the ALSA PCM] starts when the buffer is full

With this PR the start threshold is 100ms, so I would expect a typical delay to be just over 100ms; and in fact in my testing I see ClientDelay values between 120ms and 150ms.

maybe the PCM start threshold should be ... allowed to be tuned by the user?

Sure, if you find that really helps, but I note that alsaloop does not offer that option so it is clearly not an essential parameter for streaming between two devices.

Windows sends audio faster than RPi plays it

I don't have any Windows to test with. I do find it bizarre that one OS would run a clock significantly faster than Linux or iOS. Does Windows perhaps use a different sample rate? The only time I've seen a significant difference in clock rates is when using dmix with rate where the rate conversion can cause samples to be consumed from the buffer faster than the hw device plays them - this is documented in the manual page.

@borine
Copy link
Collaborator Author

borine commented Nov 14, 2024

I've now set up a USB audio card on the pi zero, and I see the same results as with the i2c card: excellent A/V sync with iphone, linux/pipewire and linux/bluealsa; steady ClientDelay with both 48000 rate streams and 44100 rate streams (value changes only when the stream is paused then unpaused, and is always in the range 105ms to 140ms)

I've also tried with "plug:'dmix:IQaudIODAC'". In this case when using 44100 rate streams the ClientDelay does steadily increase with default ALSA config, but is constant when dmix is configured according to the note in the bluealsa-aplay manual page (as amended by this PR).

Is there any other specific config I need to use to reproduce your results? I may be able to set up an old pi 1B+ with USB bluetooth to try the (really poor) on-board jack-plug audio output on that, but will need several days to get all the pieces together.

@arkq
Copy link
Owner

arkq commented Nov 14, 2024

Hmm, that is disappointing indeed. This PR sets the ALSA buffer size to 200ms, so for a hw device the maximum ALSA delay cannot be significantly higher than that.

Hmm... so maybe I will have to do testing again... I've been testing on RPi4 with connected JBL GO2 (Bluetooth speaker) via USB. And yes, I've put dmix in front of hw, so maybe that's the case. I'll try test it on my laptop later today. Anyway, if you are saying that you have excellent A/V sync with this smaller buffer, I think that we can go with this PR. In case of underrruns user can always increate the buffer, but at least the default will be tuned for lower latency.

@borine
Copy link
Collaborator Author

borine commented Nov 17, 2024

I've now done some long-running tests, and in these I can clearly see the ClientDelay value increasing. The rate of increase is small, somewhere between 50ms and 70ms per hour, so I can play audio for over 4 hours before the fifo becomes full and frames are dropped by the server. Throughout this time the A/V sync remains correct (as far as I can tell from watching lip-sync for speech, and drum stick beats etc for music). So I conclude that the delay reporting is accurate enough for typical bluetooth audio usage.

it's time to have another look at the problem reported in #459

There may be some use-cases where it would be beneficial to limit the absolute size of ClientDelay by using frame rate adjustment, but I see that as a separate issue which does not affect the validity of this PR.

I would like to re-word the commit comments slightly, then I will mark this PR as ready for code review. I am happy to make any other changes that you request.

@arkq
Copy link
Owner

arkq commented Nov 17, 2024

it's time to have another look at the problem reported in #459

There may be some use-cases where it would be beneficial to limit the absolute size of ClientDelay by using frame rate adjustment, but I see that as a separate issue which does not affect the validity of this PR.

Yes, I was not referring to that PR, but for something that might be worth looking at in the future :)

I would like to re-word the commit comments slightly, then I will mark this PR as ready for code review. I am happy to make any other changes that you request.

Yes, sure. I have no additional comments regarding this PR. Like I've said, changing default buffer size is OK as long as there are no underruns in common default usage.

@borine borine marked this pull request as ready for review November 17, 2024 17:37
It seems that safari on the iPhone cannot adjust A/V sync when
the audio latency exceeds about 400ms. So to keep the default
delay when using bluealsa-aplay below that critical value, change
the default ALSA hw params to lower values which are still
compatible with the majority of sound cards.
@arkq arkq merged commit e77b82b into arkq:master Nov 17, 2024
21 checks passed
@borine borine deleted the aplay-buffering branch November 19, 2024 08:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants