spatialaudio / python-sounddevice

:sound: Play and Record Sound with Python :snake:
https://python-sounddevice.readthedocs.io/
MIT License
1.07k stars 150 forks source link

Wrong number of inputs reported #298

Open Moaneschien opened 3 years ago

Moaneschien commented 3 years ago

After running a few times in to sounddevice.PortAudioError: Error opening InputStream: Invalid number of channels [PaErrorCode -9998] I noticed sounddevice reports the wrong number of inputs in some cases. It should be 4 in 4 out for the Behringer, as PyAudio reports.

sounddevice: 1246720 PortAudio V19.6.0-devel, revision 396fe4b6699ae929d3a685b3ef8a7e97396139a4
pyaudio    : 1246720 PortAudio V19.6.0-devel, revision 396fe4b6699ae929d3a685b3ef8a7e97396139a4

Sounddevice devices:
   0 Microsoft Sound Mapper - Input, MME (2 in, 0 out)
>  1 Line (2- BEHRINGER UMC404HD 192, MME (2 in, 0 out)
   2 Microsoft Sound Mapper - Output, MME (0 in, 2 out)
<  3 Speakers (2- BEHRINGER UMC404HD, MME (0 in, 2 out)
   4 Digitale audio (S/PDIF) (High D, MME (0 in, 2 out)
   5 Primary Sound Capture Driver, Windows DirectSound (2 in, 0 out)
   6 Line (2- BEHRINGER UMC404HD 192k), Windows DirectSound (2 in, 0 out)
   7 Primary Sound Driver, Windows DirectSound (0 in, 2 out)
   8 Speakers (2- BEHRINGER UMC404HD 192k), Windows DirectSound (0 in, 2 out)
   9 Digitale audio (S/PDIF) (High Definition Audio Device), Windows DirectSound (0 in, 2 out)
  10 UMC ASIO Driver, ASIO (4 in, 4 out)
  11 Speakers (2- BEHRINGER UMC404HD 192k), Windows WASAPI (0 in, 2 out)
  12 Digitale audio (S/PDIF) (High Definition Audio Device), Windows WASAPI (0 in, 2 out)
  13 Line (2- BEHRINGER UMC404HD 192k), Windows WASAPI (4 in, 0 out)
  14 Speakers (UMC404HD 192k Output), Windows WDM-KS (0 in, 4 out)
  15 Line (UMC404HD 192k Input), Windows WDM-KS (4 in, 0 out)
  16 SPDIF Out (HD Audio SPDIF out), Windows WDM-KS (0 in, 2 out)

PyAudio:
 0   Microsoft Sound Mapper - Input    2 in, 0 out
 1   Line (2- BEHRINGER UMC404HD 192   4 in, 0 out
 2   Microsoft Sound Mapper - Output   0 in, 2 out
 3   Speakers (2- BEHRINGER UMC404HD   0 in, 4 out
 4   Digitale audio (S/PDIF) (High D   0 in, 2 out
 5   Primary Sound Capture Driver      2 in, 0 out
 6   Line (2- BEHRINGER UMC404HD 192k) 4 in, 0 out
 7   Primary Sound Driver              0 in, 2 out
 8   Speakers (2- BEHRINGER UMC404HD 192k) 0 in, 4 out
 9   Digitale audio (S/PDIF) (High Definition Audio Device)   0 in, 2 out
10   UMC ASIO Driver   4 in,  4 out
11   Speakers (2- BEHRINGER UMC404HD 192k)   0 in,  2  out
12   Digitale audio (S/PDIF) (High Definition Audio Device)   0 in, 2 out
13   Line (2- BEHRINGER UMC404HD 192k)   4 in,  0 out
14   Speakers (UMC404HD 192k Output)   0 in,  4 out
15   Line (UMC404HD 192k Input)   4 in,  0 out
16   SPDIF Out (HD Audio SPDIF out)   0 in,  2 out
mgeier commented 3 years ago

This is indeed very strange.

Since they appear to be using the same PortAudio version, I'd expect the sounddevice module and PyAudio to report exactly the same information ...

Did you run the two queries in exactly the same way? Same command line, same device permissions?

Moaneschien commented 3 years ago

All data gathered in one run. The script, manually edited the out put too look as above.

import sounddevice
import pyaudio
p = pyaudio.PyAudio()

version, description = sounddevice.get_portaudio_version()
print("sounddevice: {} {}".format(version, description))
print("pyaudio    : {} {}".format(pyaudio.get_portaudio_version(), pyaudio.get_portaudio_version_text()))

print("\nSounddevice devices:\n",sounddevice.query_devices())

print("\nPyAudio")
print("Host API")
for host in enumerate(range(0, p.get_host_api_count())):
    info = p.get_host_api_info_by_index(host[1])
    print (f"\t{host[0]}: {info['name']}")
    print("\t\tAudio device")
    for device in enumerate(range(0, p.get_device_count())):
        info = p.get_device_info_by_index(device[1])
        if host[0] == info["hostApi"]:
            print (f"\t\t{device[0]}: {info['name']}\tmax in: {info['maxInputChannels']} max out: {info['maxOutputChannels']}")
    print("")
mgeier commented 3 years ago

Thanks for the update.

I still have no clue, though.

I must assume that different DLLs are in use. Can you somehow find out which DLLs are used?

For sounddevice, you can check sounddevice._libname.

Moaneschien commented 3 years ago

All I could find was a _portaudio.cp38-win_amd64.pyd I assume is for PyAudio.

I tried a bit more and got more confused. Running sounddevice:

python wire -i1 -o3 -c4
PortAudioError: Error opening Stream: Invalid number of channels [PaErrorCode -9998]

1 & 3 are windows MME and should only support 2 channels i.i.r.c. So the error is right.

Running a similar wire with PyAudio works fine. Recording 4 channels with the MME works fine too.

Had a look at Audacity, with the same PortAudio version, only two channels for MME. My guess would be there's a problem in PyAudio, not in Sounddevice.

mgeier commented 3 years ago

How did you install the sounddevice module?

There are at least 3 ways described at https://python-sounddevice.readthedocs.io/en/0.4.1/installation.html, which all should lead to different DLLs to be used.

Can you please try all three and report the sounddevice._libname for each of them?

Moaneschien commented 3 years ago

Installed with pip.

Just created two new venv's and tried pip again and Gohlke. Don't have Anaconda or WinPython installed.


Python 3.8.2 (tags/v3.8.2:7b3ab59, Feb 25 2020, 23:03:10) [MSC v.1916 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import sounddevice
>>> print(sounddevice._libname)
C:\Users\ingo\Documents\Python\envSD_pip\lib\site-packages\_sounddevice_data\portaudio-binaries\libportaudio64bit.dll
>>> version, description = sounddevice.get_portaudio_version()
>>> print("sounddevice: {} {}".format(version, description))
sounddevice: 1246720 PortAudio V19.6.0-devel, revision 396fe4b6699ae929d3a685b3ef8a7e97396139a4
>>> print("\nSounddevice devices:\n",sounddevice.query_devices())

Sounddevice devices:
    0 Microsoft Sound Mapper - Input, MME (2 in, 0 out)
>  1 Line (2- BEHRINGER UMC404HD 192, MME (2 in, 0 out)
   2 Microsoft Sound Mapper - Output, MME (0 in, 2 out)
<  3 Speakers (2- BEHRINGER UMC404HD, MME (0 in, 2 out)
   4 Digitale audio (S/PDIF) (High D, MME (0 in, 2 out)
   5 Primary Sound Capture Driver, Windows DirectSound (2 in, 0 out)
   6 Line (2- BEHRINGER UMC404HD 192k), Windows DirectSound (2 in, 0 out)
   7 Primary Sound Driver, Windows DirectSound (0 in, 4 out)
   8 Speakers (2- BEHRINGER UMC404HD 192k), Windows DirectSound (0 in, 4 out)
   9 Digitale audio (S/PDIF) (High Definition Audio Device), Windows DirectSound (0 in, 2 out)
  10 UMC ASIO Driver, ASIO (4 in, 4 out)
  11 Speakers (2- BEHRINGER UMC404HD 192k), Windows WASAPI (0 in, 4 out)
  12 Digitale audio (S/PDIF) (High Definition Audio Device), Windows WASAPI (0 in, 2 out)
  13 Line (2- BEHRINGER UMC404HD 192k), Windows WASAPI (4 in, 0 out)
  14 Speakers (UMC404HD 192k Output), Windows WDM-KS (0 in, 4 out)
  15 Line (UMC404HD 192k Input), Windows WDM-KS (4 in, 0 out)
  16 SPDIF Out (HD Audio SPDIF out), Windows WDM-KS (0 in, 2 out)
>>>

Gohlke:
Python 3.8.2 (tags/v3.8.2:7b3ab59, Feb 25 2020, 23:03:10) [MSC v.1916 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import sounddevice
>>> print(sounddevice._libname)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: module 'sounddevice' has no attribute '_libname'
>>> version, description = sounddevice.get_portaudio_version()
>>> print("sounddevice: {} {}".format(version, description))
sounddevice: 1246720 PortAudio V19.6.0-devel, revision 396fe4b6699ae929d3a685b3ef8a7e97396139a4

In the Gohlke venv the library is at ...\Documents\Python\envSD_gohlke\Lib\site-packages\portaudio.dll

Sounddevice devices:
    0 Microsoft Sound Mapper - Input, MME (2 in, 0 out)
>  1 Line (2- BEHRINGER UMC404HD 192, MME (4 in, 0 out)
   2 Microsoft Sound Mapper - Output, MME (0 in, 2 out)
<  3 Speakers (2- BEHRINGER UMC404HD, MME (0 in, 4 out)
   4 Digitale audio (S/PDIF) (High D, MME (0 in, 2 out)
   5 Primary Sound Capture Driver, Windows DirectSound (2 in, 0 out)
   6 Line (2- BEHRINGER UMC404HD 192k), Windows DirectSound (4 in, 0 out)
   7 Primary Sound Driver, Windows DirectSound (0 in, 4 out)
   8 Speakers (2- BEHRINGER UMC404HD 192k), Windows DirectSound (0 in, 4 out)
   9 Digitale audio (S/PDIF) (High Definition Audio Device), Windows DirectSound (0 in, 2 out)
  10 UMC ASIO Driver, ASIO (4 in, 4 out)
  11 Speakers (2- BEHRINGER UMC404HD 192k), Windows WASAPI (0 in, 4 out)
  12 Digitale audio (S/PDIF) (High Definition Audio Device), Windows WASAPI (0 in, 2 out)
  13 Line (2- BEHRINGER UMC404HD 192k), Windows WASAPI (4 in, 0 out)
  14 Speakers (UMC404HD 192k Output), Windows WDM-KS (0 in, 4 out)
  15 Line (UMC404HD 192k Input), Windows WDM-KS (4 in, 0 out)
  16 SPDIF Out (HD Audio SPDIF out), Windows WDM-KS (0 in, 2 out)
>>>```
mgeier commented 3 years ago

Thanks for the update!

So the Gohlke package works as expected, right?

Moaneschien commented 3 years ago

Yes, it works like the PyAudio version.

mgeier commented 3 years ago

OK, good to know, you should use the Gohlke package then!

AFAIK, the main difference is that the Gohlke DLL was created on Windows with the MS compiler, while the DLL in the "official" package was cross-compiled on Linux using MXE/MinGW-w64/GCC, see https://github.com/spatialaudio/portaudio-binaries.

If anybody has an idea how to fix the problem in the cross-compilation, please let me know!

Moaneschien commented 3 years ago

Thanks for your effort. Guten Rutsch!

davircarvalho commented 2 years ago

Hello,

I'm having the same problem, @Moaneschien could you please clarify how did you solve this issue?

thanks!

Moaneschien commented 2 years ago

@davircarvalho I used the binaries from https://www.lfd.uci.edu/~gohlke/pythonlibs/ Search the page for Sounddevice.