PortAudio / portaudio

PortAudio is a cross-platform, open-source C language library for real-time audio input and output.
Other
1.49k stars 305 forks source link

Allow to open stream with "current" sample rate #970

Open Spacechild1 opened 6 days ago

Spacechild1 commented 6 days ago

Sometimes we just want to open a stream with its "current" sample rate. This is particularly true for backends where the sample rate is fixed or has been set by another application. Prominent examples are Jack and ASIO.

Now, you might thank that we could simply use PaDeviceInfo.sampleRate for this purpose. Unfortunately, this does not always work.

While Jack gets the default sample rate directly from the Jack server, ASIO follows a rather peculiar strategy:

  1. Iterate over an arbitrary list of sample rates and ask the driver if the rate is supported.
  2. Pick the first rate that works.

Typically, this always results in a default sample rate of 44100 Hz, as this rate is pretty much always supported.

Now here's the problem: Just because ASIO tells you that the rate is supported does not mean that you can actually use it for opening a new stream!

Modern ASIO drivers typically support multiple client, but they all must use the same sample rate. If another ASIO client has already opened a stream at, say, 48000 Hz, the device has been set to that rate. If you then attempt to open a new stream using the "default sample rate" as reported by PortAudio, you would get an error!

IMO a "default sample rate" should be a sample rate that is guaranteed to work. In the case of ASIO that would be the current driver sample rate (as reported by ASIOGetSampleRate).


Originally, I thought that we could simple set PaDeviceInfo.defaultSampleRate to the current ASIO device sample rate and be done.

However, there's a more fundamental issue: since PaDeviceInfo is immutable, defaultSampleRate is chosen at the time of library initialization. However, the ASIO/Jack sample rate may change anytime!

I think the best solution would be an option that tells Pa_OpenStream to use the actual current sample rate. This could be a new stream flag like paUseCurrentSampleRate. After the stream has been opened, the user could query the actual sample rate with Pa_GetStreamInfo.

Any thoughts?

dechamps commented 6 days ago

However, there's a more fundamental issue: since PaDeviceInfo is immutable, defaultSampleRate is chosen at the time of library initialization. However, the ASIO/Jack sample rate may change anytime!

This is just a specific instance of the wider problem of the PortAudio API not having a way to report changes to device properties. The same problem applies to reporting addition and removal of devices, for example.

You could work around the issue by completely re-initializing PortAudio every time you want to "refresh" the device list, though obviously this is not exactly a cheap operation.

Spacechild1 commented 6 days ago

I'm aware of the wider problem, but I think it would be impossible to fix without a complete redesign of the library (which likely isn't going to happen).

However, I've raised a specific issue and proposed a very concrete and workable fix. (I might also make a PR if there is some positive feedback.)