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

HW Card not PCM #325

Closed
am4c130d opened this issue Apr 20, 2020 · 9 comments
Closed

HW Card not PCM #325

am4c130d opened this issue Apr 20, 2020 · 9 comments

Comments

@am4c130d
Copy link

This is a feature request

I use Roon (www.roonlabs.com) for music playback which only uses HW/card audio devices in Linux, not PCM/SW devices. I'd like to be able to use Roon with Bluetooth connected headphones/speakers, as such is it possible to instantiate connected headphones/speakers as HW cards, preferably with device volume control and due to Roon's very high quality resampling engine, with the optimal bitrates/bit depths for the connected headphone/A2DP codec pairing so that Roon can choose the optimal resampling.

Thanks Alan

@borine
Copy link
Collaborator

borine commented Apr 20, 2020

only uses HW/card audio devices

Are you quite sure about that? I have no experience with Roon, but the home page you link above clearly claims that it will play to Airplay and squeezebox devices - these are most definitely not HW cards!

@am4c130d
Copy link
Author

Unfortunately yes, https://kb.roonlabs.com/Audio_On_Linux. They support a variety of network based interfaces (with lots of caveats about performance), but for directly connected devices (USB, SPDIF, AES, I2S mainly), they want HW access so that they can bypass mixers/resamplers etc.

@arkq
Copy link
Owner

arkq commented Apr 21, 2020

From linked page:

in ALSA terms, we are using hw:X,X device identifiers

It is rather impossible with current BlueZ/BlueALSA/ALSA architecture - it will complicate things A LOT.

If I may suggest. You can bypass ALSA by communicating directly with BlueALSA server via D-Bus interface. So in order to have access to "hardware" you shall use this API by creating another backend for Roonlabs. If you care about performance and latency, and want to use BlueALSA, that's the only way.

But for audiophile solutions BT is not an option, I think :D There is no lossless codec for BT. Once I thought about FLAC support as a PoC and see how it will perform, but I've got not much time for such experiment :D (of course it will be "bluealsa to bluealsa" connection only, unless some headset will also support FLAC).

@am4c130d
Copy link
Author

Understood on the complexity - I feared as much. I'll have a look in to the D-BUS approach.

I agree, BT has some real audio quality limitations - but there are some very interesting headphones available now that are BT and audio focused as opposed to ANC or sports focused. But BT wins hands down on convenience over being wired, and Roon seamlessly integrates local and streaming libraries in to one with amazing curated and interlinked content - the combination of the two is very tempting.

If this is beyond the scope of the project, please close the request, I totally get it, thanks.

@nheir
Copy link

nheir commented Apr 23, 2020

You can try with Alsa Loopback device, see #48 and https://alsa.opensrc.org/Jack_and_Loopback_device_as_Alsa-to-Jack_bridge (dropping Jack stuff)

NB: when alsaloop fails, you can try arecord | aplay

@am4c130d
Copy link
Author

Thank you! I'll give it a go.

@am4c130d
Copy link
Author

I have had this working twice, using

alsaloop -C loophw01 -P BTHeadset -bn -t 50000

I had to add -n (resample) to get pretty much anything to play by the loop back, and then -b to get the audio to play smoothly - it was flicking between left/right channels rapidly as it played.

My asound.conf is

`
pcm.loophw00 {
type hw
card Loopback
device 0
subdevice 0
}

pcm.loophw01 {
type hw
card Loopback
device 1
subdevice 0
}

pcm.BTHeadset {
type plug
slave {
pcm {
type bluealsa
device XX:XX:XX:XX:XX
profile "a2dp"
delay 10000
}
}
hint {
show on
description "BT Headset"
}
}
`

The two times everything worked, I had no errors, but most of the time I get underruns for BTHeadset reported when running alsaloop. Once I stop and start the playback, I have to restart bluealsa.service to get things clean again. I never get these issue when I use aplay directly with the headset.

Any thoughts?

@borine
Copy link
Collaborator

borine commented Jul 10, 2020

I've been looking into alsaloop with bluealsa recently, and have proposed some changes to the bluealsa alsa plugin which hopefully can mitigate some of the issues. You will find the code in the "improve_alsa_poll" branch of my fork here: https://github.com/borine/bluez-alsa/tree/improve_alsa_poll

@am4c130d if you are still working on this, I would be interested to know if you observe any improvements.

alsaloop has some issues anyway, without the involvement of bluealsa: if the target latency is not achievable then it can become unstable, either running one core at 100% CPU, or falling over completely. So the first thing to consider if the stream is not stable is to increase the target latency; normally -t 500000 (ie half a second) is sufficient. In testing my changes above, I have got good results with latency set as low as -t 50000, but have to set DELAY=0 as a parameter to the bluealsa pcm to achieve this.

in addition to managing latency, alsaloop also attempts to compensate for relative clock drift by resampling to adjust the sampling rate. This raises the cpu load and when used with bluealsa is, I think, wasted effort as the internal buffering within bluealsa is more than enough to even out jitter. So I would also recommend using --sync=none.

The -n parameter selects whether to use libsamplerate or libasound for resampling. I have found that libsamplerate on my raspberry pi is buggy, so I always use -n to disable it. Putting all this together, I recommend:

alsaloop -C loophw01 -P BTHeadset -n --sync=none -t 500000

together with

delay 0
in the alsa config for pcm.BTHeadset.slave

@borine
Copy link
Collaborator

borine commented Jun 21, 2021

I think this issue has gone as far as it can. There are no plans to implement a kernel driver ("hw:" plugin) for bluez-alsa. The latest bluez-alsa code works well with alsaloop so long as the target latency is achievable, so the use of the Loopback device is feasible but difficult to set up.

@borine borine closed this as completed Jun 21, 2021
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

No branches or pull requests

4 participants