Git Product home page Git Product logo

Comments (11)

mgeier avatar mgeier commented on July 28, 2024

Ignoring the settings of other host APIs would raise several problems:

  1. It violates one of the Python Zen mantras: "Errors should never pass silently." If you want to use WASAPI exclusive mode, but by mistake use a non-WASAPI device, you will get no error. People might simply forget to specify a device and they would think they are using a WASAPI device while in reality they are using the non-WASAPI default device.
  2. To be consistent, it would have to be possible to use multiple extra_settings at the same time, which is currently not possible.
  3. Now I'm just following the PortAudio API, so I can blame it for being unintuitive. If I change the behavior, I'll have to take the blame myself ...

What about something completely new instead of extra_settings?
Any ideas?

Currently, extra_settings can only be used for two things: WASAPI exclusive mode and ASIO channel selection. It seems a bit strange to have this whole extra_settings thing just for 2 parameters.
Theoretically, there could be more platform-specific features in the future, but some of them won't work with extra_settings, like e.g. PaAlsa_EnableRealtimeScheduling or PaJack_SetClientName. See also #4.

Another thing that's currently strange, is that I can set WASPI exclusive mode on the input and non-exclusive mode on the output (and vice versa). I don't know if that even makes sense? Is this even possible?

I would be open to removing the platform-specific settings from Stream and play() and all the other classes and functions and just keeping them as module-level settings.
I'm not sure, however, how a sensible API for that would look like.
I guess this would have to be done with individual function calls like sd.set_wasapi_something(some_setting).

from python-sounddevice.

hiccup7 avatar hiccup7 commented on July 28, 2024

WASAPI is unusual because it supports separate client apps for input and output. This suggests independent streams, so maybe one could be shared mode and the other exclusive mode. I have not tried that yet, as I have only been developing Python code for output. With ASIO and WDM-KS, on the other hand, I have experienced failures when I try to use one app for input and another for output to the same device.

Exclusive mode is supported for some WASAPI devices, while other WASAPI devices only support shared mode. So WASAPI settings are not necessarily fixed for a platform. I just happen to have a Python module where exclusive mode is desired for all WASAPI devices used (I won't use WASAPI devices that don't support exclusive mode in this module).

I posted this PR because I found WASAPI settings a little unintuitive -- not really a problem for me. Please consider my feedback in the evolution of sounddevice settings. Module default settings would work well for platform settings, while stream class settings would work well for device-specific settings.

from python-sounddevice.

mgeier avatar mgeier commented on July 28, 2024

I have not tried that yet

Would be nice if you could try that.

Please consider my feedback

Sure, I'm thankful for that and I mentioned my concerns above.

Do you agree that ignoring non-matching extra_settings has some disadvantages?

Do you have a concrete suggestion for a different API for the host API specific settings?

from python-sounddevice.

hiccup7 avatar hiccup7 commented on July 28, 2024

Do you agree that ignoring non-matching extra_settings has some disadvantages?

Yes. Your Python Zen philosophy has been working well.

Do you have a concrete suggestion for a different API for the host API specific settings?

How about class settings for each host API? Then support all of them in the default class for use as platform settings, with no exception checking. And also support all of them as separate keyword arguments in Stream and play(), but raise an exception if a keyword argument's associated host API does not match the selected device's associated host API. This way, the sounddevice user has the choice of whether he/she wants exception checking or not.

The reason I would like this is because PortAudio provides five virtual devices for one hardware device on my PC. I know which hardware device I want to use when I write my code, so I want to configure all host APIs in the default class. Then I switch between the (virtual) devices to compare latency, sound quality, etc.

from python-sounddevice.

mgeier avatar mgeier commented on July 28, 2024

I think I understand most of your suggestion but not everything. Can you please provide some concrete (but still hypothetical) code examples which show the proposed usage?

If I understand correctly, you want to pass the default object to the individual functions.
I definitely don't like that idea. The function arguments should be passed individually, not packed into some container object.
If you want a container object (e.g. a dict), you can try something like this (untested!):

settings1 = dict(device=3)
settings2 = dict(device=7, extra_settings=extra_settings)

settings = settings1

sd.play(mydata, fs, **settings)

This way, you could collect all your possible combinations of settings but still quickly switch between them.

from python-sounddevice.

hiccup7 avatar hiccup7 commented on July 28, 2024

I haven't spent enough time reading sounddevice.py to understand it in detail. How are settings from the default object used by Stream and play()? Is there a base class common to all of these?

from python-sounddevice.

mgeier avatar mgeier commented on July 28, 2024

You don't need to understand the current implementation, I'd just like to do some brainstorming how the usage could look like in the future. Let's worry about the implementation afterwards.

But since you asked: The default object is just sitting there in the module namespace and any function that needs to know about a default value, just gets it from there. There nothing more behind it.

All stream classes have a common base class (named _StreamBase), but that's not really relevant for how the default object works.
play() is just a free function that happens to use an OutputStream inside.

from python-sounddevice.

hiccup7 avatar hiccup7 commented on July 28, 2024

So I am imaging a common base class with some extra settings specific to each host API. These settings could be read and written using a default class. The Stream class would use settings from the base class unless over-ridden by parameters to self._init_().

Since the default class doesn't know which host API will be used, it would not raise an exception for writing WASAPI extra settings even if the Stream class later uses an ASIO device. But the Stream class would raise an exception for WASAPI parameters when an ASIO device is selected.

from python-sounddevice.

mgeier avatar mgeier commented on July 28, 2024

Now I understand your suggestion less than before.
Can you please give concrete code examples how your suggested API should be used (not how it should be implemented!) and which calls should be successful and which calls should raise errors.

from python-sounddevice.

mgeier avatar mgeier commented on July 28, 2024

@hiccup7 Do you want to continue on this?

from python-sounddevice.

hiccup7 avatar hiccup7 commented on July 28, 2024

sounddevice is working great for me. As I mentioned in the opening post, this issue is a minor annoyance for me. I have worked around it, so I am satisfied. No need to continue on this topic.

from python-sounddevice.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.