Open beisenreich opened 1 month ago
Weird... no I have not encountered this before. It's odd because it seems like query_devices
is the first thing that we do:
It gets weirder. I did some more testing today and expyfun appears to be calling the right sounddevice library. I'm running version 0.4.7 which has the ASIO driver support included and calling sounddevice.version from line 56 of _rtmixer.py returns version 0.4.7. I thought maybe the issue is with the import of rtmixer loading a different sounddevice library, this also returned back as version 0.4.7. When I pull up the available hostapis expyfun can see from sounddevices I get a return of the ASIO but with devices=[].
Now the real weird part, if you import sounddevice before importing expyfun and initializing the ec. Everything works, version returns as 0.4.7, hostapis show ASIO driver support and devices return the Madiface USB. Thoughts?
I'm not sure why the import order should matter. If you import python-rtmixer
before sounddevice
does it change the behavior?
Importing rtmixer before sounddevice does not impact the behavior. Instead it appears importing either rtmixer or sounddevice before importing or calling expyfun fixes the issue.
:exploding_head: interesting... I wonder if we have code that sets a problematic env var or similar. Or maybe it's importing pyglet
that is somehow problematic.
You could in theory try commenting out various parts of what import expyfun
does (by digging into expyfun/__init__.py
etc. and commenting stuff out) but for now I'm just relieved that there is some workaround for you!
devices = sounddevice.query_devices() with os.environ["SD_ENABLE_ASIO"] = "1" silently fails in many python environments (like a Qt GUI app for example). No errors, nothing as python will not even get passed importing sounddevice for anything to be written as an error. e.g. this works in a cli script to get an ASIO device at known index:
import os
# Enable ASIO on Windows if applicable
if os.name == "nt":
os.environ["SD_ENABLE_ASIO"] = "1"
import sounddevice as sd
print("Starting device query...")
try:
device = sd.query_devices(49) # Jack ASIO
print(device)
except Exception as e:
print(f"Error querying devices: {e}")
(venv)
Starting device query...
{'name': 'JackRouter', 'index': 49, 'hostapi': 2, 'max_input_channels': 4, 'max_output_channels': 4, 'default_low_input_latency': 0.010666666666666666, 'default_low_output_latency': 0.010666666666666666, 'default_high_input_latency': 0.010666666666666666, 'default_high_output_latency': 0.010666666666666666, 'default_samplerate': 48000.0}
In a Qt6 window, this code below will never run until you remove os.environ["SD_ENABLE_ASIO"] = "1" or place import sounddevice as sd before PyQt import. Took a week to realise import order affects sounddevice and ASIO.
import os
import sys
from PyQt6.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout, QLabel
# Enable ASIO on Windows if applicable
if os.name == "nt":
os.environ["SD_ENABLE_ASIO"] = "1"
import sounddevice as sd
print("Starting device query...")
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
# Set window title and dimensions
self.setWindowTitle("Blank Qt6 GUI")
self.setGeometry(100, 100, 800, 600)
# Create a central widget
central_widget = QWidget(self)
self.setCentralWidget(central_widget)
# Set up layout and add a placeholder label
layout = QVBoxLayout()
label = QLabel("This is a blank Qt6 GUI.")
layout.addWidget(label)
central_widget.setLayout(layout)
# Get ASIO device
self.device = sd.query_devices(49) # Jack ASIO
device_as_text = "\n".join([f"{key}: {value}" for key, value in self.device.items()])
label.setText(device_as_text)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec())
In a Qt6 window, this code below will never run until you remove os.environ["SD_ENABLE_ASIO"] = "1" or place import sounddevice as sd before PyQt import. Took a week to realise import order affects sounddevice and ASIO.
Yikes! No idea why this would be the case. I know PyQt6 (and in most recent PySide6 as well) does some magic with PyOS_Inputhook
but not sure that would be related
Yeah, it's weird, I wasted so much time trying to figure out why nothing ASIO could ever be found with sounddevice depsite several rebuilds, custom libportaudio.dll builds etc etc and all it was was sounddevice needs to be imported first.
There appears to be an issue with using ASIO devices on windows 11 with the expyfun sound_controller _rtmixer.
1) It should be noted that the current release of sounddevice has ASIO disabled as default (see issue 496 ).
2) Rolling back sounddevice to version 0.4.7 produces the following behavior:
i. running python(3.11) and importing expyfun in the initial call to _rtmixer.py, ASIO devices are not found by sounddevice.query_devices() (line 55)
ii. when running python(3.11) and importing sounddevice and rtmixer directly, sounddevice.query_devices() does return the ASIO devices, and playback through the ASIO soundcard works
Has anyone else encountered this issue?