PortAudio / portaudio

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

OSS: device cannot be selected correctly when SNDIO is enabled #894

Open tatsuki-makino opened 5 months ago

tatsuki-makino commented 5 months ago

Describe the bug DeviceIndex and HostApiDeviceIndex are not used separately, so devices cannot be selected correctly if SNDIO, which is initialized before OSS, is enabled.

To Reproduce

  1. Allow one or more devices to be used with SNDIO.
  2. Build PortAudio with SNDIO and OSS enabled.
  3. Select OSS device in Audacity 3.4, etc.

Expected behavior Sound is produced on the selected device.

Actual behavior The number of devices in SNDIO will result in devices that cannot be used in OSS.

Desktop (please complete the following information):

Additional context A workaround patch will be attached. Adding an offset here would be consistent with the behavior of the other HostAPI without changing the software that is already running. patch.txt

tatsuki-makino commented 5 months ago

This may only be available to FreeBSD users in a reproducible environment. Therefore, I have attached an image of the Audacity GUI that may be used to point out the problem. screenshot

RossBencina commented 5 months ago

This sounds like a bug or misunderstanding in your client code (or in Audacity?). Certainly your patch is incorrect.

DeviceIndex is the global device index that is passed to Pa_OpenStream. It seems to me that you are passing a host-API-specific index to Pa_OpenStream when in-fact you should be passing a global device index.

If you still think that there is a bug please provide a test case that demonstrates the issue using the PortAudio public API.

tatsuki-makino commented 5 months ago

The problem seems to occur somewhere in Pa_IsFormatSupported function. Audacity (3.5.1) gives errors depending on the result, so I cut it out. test.c.txt When it is executed, the result is as follows:

[0:0]sndio deviceCount: 1 defaultInputDevice: 0; defaultOutputDevice: 0 [ 0: 0]default Pa_IsFormatSupported: (in) Success Pa_IsFormatSupported: (out) Success [1:1]OSS deviceCount: 5 defaultInputDevice: 1; defaultOutputDevice: 1 [ 0: 1]/dev/dsp Pa_IsFormatSupported: (in) Invalid device Pa_IsFormatSupported: (out) Invalid device [ 1: 2]/dev/dsp0 Pa_IsFormatSupported: (out) Success [ 2: 3]/dev/dsp1 Pa_IsFormatSupported: (in) Device unavailable Pa_IsFormatSupported: (out) Success [ 3: 4]/dev/dsp2 Pa_IsFormatSupported: (in) Success Pa_IsFormatSupported: (out) Success [ 4: 5]/dev/dsp3 Pa_IsFormatSupported: (out) Success [2:2]ALSA deviceCount: 35 defaultInputDevice: 40; defaultOutputDevice: 40 [ 0: 6]sysdefault Pa_IsFormatSupported: (in) Success Pa_IsFormatSupported: (out) Success [ 1: 7]front Pa_IsFormatSupported: (out) Success [ 2: 8]rear Pa_IsFormatSupported: (out) Success ... Omitted below.

OSS gives an error that should not have occurred. /dev/dsp is the same thing as /dev/dsp1, but it fails because it can't point to it correctly. /dev/dsp0 is a device that cannot be captured, so the input side is not checked. On the output side, it means that the check using /dev/dsp is successful. /dev/dsp1 is a device that can capture and playback, so it checks both input and output, but because /dev/dsp0 is checked, the input side is treated as unavailable.

Around this point, the global device index has changed to a host-API-specific index, but I think it means that OSS host-API has used the changed value for a function that assumes that it will be used in a global device index.

tatsuki-makino commented 4 months ago

It was my mistake to close it for a moment :) This is the place to escape if any errors are found, but it already seems to be at the proper value by all the checks. Therefore, I think it is just a matter of changing it like this. patch.txt