GNOME Bugzilla – Bug 753601
alsa: Probe a fixed set of rates instead of a range
Last modified: 2018-05-06 13:15:31 UTC
The ALSA library lacks PCM functions to query for a set of supported sample rates, and instead only allows for probing an allowed range. This however is at odds with many modern DACs, which only support specific sample rates. For example, some TI codecs support 44100, 48000, 96000, 192000, but not, say, 88200. A solution would be to instead call snd_pcm_hw_params_test_rate() for a fixed set of sample rates, like: 8000, 11025, 22050, 24000, 32000, 44100, 48000, 88200, 96000, 176400, 192000, 352800, 384000. Sample rates other than these are pretty uncommon these days. This alternative behavior could be added as an opt-in, and the existing range-based probing could still be the default. Thoughts?
What problem are you trying to solve with this exactly?
Suppose an audio device can only output 48000 and 96000 Hz. But you try to play an 88200 Hz signal. The range will be [48000, 96000] and mislead the pipeline into thinking that the alsasink can handle 88200 Hz.
Right, the probing mechanism should not announce [48000, 96000] if the device doesn't actually support the values in between. I thought the probing mechanism covers this already (tries random 'uneven' rates to see if it's a range or not), but perhaps it doesn't work right or I'm imagining things again.
Do you intend to make a patch?
Yes. I won't have time for it before mid January though. I do however have a proof of concept patch already, just need to rework it.
Created attachment 327185 [details] [review] Patch for probing a fixed set of sample rates Here is a patch for this enhancement. The list of possible sample rates is given as a GstCaps. There is currently no "good" way of specifying a list of integers as a property, and parsing a string that contains a comma-separated list of integers would duplicate a lot of what GstCaps & GstStructure already do.
That doesn't sound like the kind of patch I had in mind. The probing mechanism should figure out automatically if the device supports any random sample rate within the range, and if not it should just probe/try a set of common rates. It should be possible to do the right thing without a property / user input, no?
The question is: how? By probing if it can use 48001 Hz? Doesn't sound that stable or clean to me. Also, without any user input, you'd have to call snd_pcm_hw_params_test_rate () for every single integer from rate_min to rate_max , which is wasteful.
Well, about the last point: we could try a patch that does exactly that (probe every single integer), and see how it performs on a beaglebone for example..
Hmm ok it seems that this would actually be safe to do, since no syscalls appear to actually be invoked. I'll try probing like this on such an embedded platform and upload a new patch.
My suggestion would be to try a few 'unusual' sample rates within the advertised range, and if the device is okay with them we assume that it's probably okay with anything, and if it's not okay with those it's probably not okay with other unusual rates either. What do you think? I'm sure I've seen such code somewhere, maybe in another audio sink.
(In reply to Tim-Philipp Müller from comment #11) > My suggestion would be to try a few 'unusual' sample rates within the > advertised range, and if the device is okay with them we assume that it's > probably okay with anything, and if it's not okay with those it's probably > not okay with other unusual rates either. What do you think? > > I'm sure I've seen such code somewhere, maybe in another audio sink. The problem is: what is the "unusual rate"? 48001 Hz? 44000 Hz? Etc. It seems fairly arbitrary. And I have seen hardware where the crystal was chosen badly, so you got something like a 46.02 kHz sample rate etc. Also, if you detect that this unusual rate isn't supported ... what then? You test a hardcoded set of sample rates? If so, shouldn't this set be configurable? If we stick with the "unusual rate" idea, then I think this one should be configurable too. Or, we simply do a brute-force probing of ALL sample rates between the min and max rates. If this doesn't consume a lot of resources, it is probably the easiest option. When I get the chance, I'll try it on a single-core TI platform.
I've been reading TI McASP controller doc last week. It works with a single rate master clock (hard wired) and use sampling and bit clock dividers. HW engineer usually will chose a master clock the properly divides into most used rates, which is why we get the same set of rate all over the place. Other fact, is that Pulseaudio probing routing uses a fixed list of rates. It's a bit unfortunate that ALSA API does not provide this information directly though. Long term, proposing a new API through linux-media mailing list would probably be more constructive.
I ran a test with a Sitara AM3352 based platform, and probing all sample rates in the min-max range took 3 seconds. So this is not a viable option. So I guess we'll have to live with the fixed list of sample rates and make it configurable.
I would suggest to first implement the discrete rates detection/option with a fixed list. If we then find a need for a configuration option we can add that on top of that later.
Let's close this. You know what to do if you'd like to improve this in alsasink ;) I don't think having a philosophical discussion about what constitutes an "unusual" sample rate and what not makes much sense here. I'm fairly sure that a few data points will be decent-enough heuristics to determine if we can assume the full range is supported or just discrete rates.