-
Notifications
You must be signed in to change notification settings - Fork 77
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ASIO backend #67
Comments
Sadly, PortAudio does not support opening a full-duplex stream where the input and output devices are on different backends (Host APIs). Adding such support in PortAudio, or implementing it directly in FlexASIO, is not trivial. I wouldn't expect this feature to be implemented any time soon (or ever). There's another potential problem with regard to using ASIO as a FlexASIO backend. ASIO was never designed for multiple drivers to be used in the same process - it uses global process state which gets in the way. I suspect that's a problem that can be worked around with some trickery, but it makes things more difficult. |
Another approach would be to create a virtual WDM playback device like VoiceMeeter / Hi-Fi CABLE & ASIO Bridge / Virtual Audio Cable (all by the same developer) which mixes WASAPI + ASIO audio into the backend running in WASAPI Exclusive / WDM-KS mode. I could use VoiceMeeter for this, but I'm unable to achieve < 10 ms round-trip latency with its virtual ASIO & WDM devices. |
That's way, waaaaay harder than anything else I mentioned so far. Writing a kernel-mode WDM audio driver is not for the faint of heart. I have neither the skills, nor the time, nor the motivation to embark on such a project.
Virtual Audio Cable is not from the same developer as the other three. |
The SysVAD sample from the WDK seems to build a fully installable driver and virtual playback device. It's still a complicated task of course. I assumed the ASIO driver was similarly complex. All those applications seem to be hosted on the same VB-Audio website. In any case, thanks for building FlexASIO - it's great! |
It's absolutely not. An ASIO driver is just a DLL that implements a fairly simple user-space API, nothing more. (It's really more of a "plug-in" than a "driver" from an OS perspective.) A kernel-space driver is a vastly more complicated piece of machinery with a much wider interface, different development workflows, different challenges, many more moving parts, and way more opportunities for things to go wrong.
Ah, right, I was confused because there are two things called "Virtual Audio Cable", and I was thinking of the other one. |
Usage question: I'm currently using PortAudio and ASIO4ALL for my custom audio (Windows 10) app. How do I use FlexASIO in place of ASIO4ALL? Do I need to uninstall ASIO4ALL tp try it? Is there any code change require in how I set up the device using PortAudio? This seems like a great tool! Thanks in advance! |
I'm confused by the question. No matter how I look at it, your use case doesn't make sense to me. Do you mean that you use ASIO4ALL through PortAudio, or that you're using ASIO and PortAudio side-by-side? And what would be the point of using FlexASIO, which is a wrapper around PortAudio, if you are already using PortAudio directly? |
Sorry for the confusion. My intention is to take advantage of your Shared mode which ASIO4ALL doesn't support. Another purpose is to see if I can get better latency and performance in a remote setup (via Windows RDP). Currently, for remote setup, I use WMME as the backend which is bad with latency. I was hoping FlexASIO going through WASAPI may work better. I'm using ASIO4ALL through PortAudio by defining a compile flag in PortAudio DLL build and in my project if that makes sense. Thanks! |
Either you're confused and don't understand what FlexASIO is, or I'm confused and still don't understand what you're trying to do. FlexASIO is a thin wrapper around PortAudio. If you use FlexASIO as a PortAudio ASIO backend, what you'll end up doing is PortAudio → FlexASIO → PortAudio. In other words you're back where you're started, just with more layers (and thus more complexity, more latency and more places for things to go wrong). It's pointless. Because FlexASIO is just an ASIO driver gateway to PortAudio, there is nothing you can do with FlexASIO that you can't already do in a simpler, more direct way using PortAudio itself. You don't need FlexASIO to implement FlexASIO features in your application, because all FlexASIO features are PortAudio features behind the scenes, and you can just use these PortAudio features directly. I'm not sure how I can make this clearer because I don't understand your reasoning for wanting to do this in the first place. |
I admitted I was confused. Thanks for your explanation! |
I gather that an ASIO backend could enable FlexASIO to be used as a multi-client wrapper around some other ASIO driver, so that two applications can share low-latency access to IO. Interestingly, it appears to be possible to replace the PortAudio DLL shipped with FlexASIO with one that supports ASIO. I'm going to see if this is enough to get a "multi-client adapter" working.
|
Sadly it looks like my trick causes ASIO client applications to crash on startup. Presumably this has to do with (a) FlexASIO attempting to interact with the ASIO SDK as both a frontend and backend or (b) FlexASIO attempting to scan its own ASIO device when it initializes PortAudio. If it's (b), this problem might be solved by compiling a modified PortAudio DLL that blocks FlexASIO from being loaded as part of its ASIO device enumeration. If it's (a), then we need another process so that we have another instance of the ASIO SDK global state... That might be achieved by spawning another process and communicating with it through pipes. |
No, that won't be "enough". Just enabling the PortAudio ASIO backend is not sufficient to have multiple processes share the same ASIO driver instance. For that to work you'd need some kind of IPC for the client processes to coordinate with each other and mediate access to the ASIO driver. That's not going to happen magically. Instead, what's going to happen is that the multiple PortAudio instances are going to act independently and each of them will try to initialize the backend ASIO driver for themselves. The behaviour is identical to using the backend ASIO driver directly… just with more steps, more complexity, and more opportunities for things to go wrong. As I said earlier in this thread, it's pointless.
Yes, you'll end up with a situation similar to #47 - FlexASIO will reenter init() in that case, and it's not designed to handle that. (Though you might also hit other issues such as PortAudio DLL ABI incompatibilities, depending on how your PortAudio DLL was built. If you want to make changes to the PortAudio DLL bundled with FlexASIO, I would recommend doing them inside the FlexASIO CMake superbuild system instead.) There are probably ways to make a FlexASIO ASIO backend work (e.g. by having FlexASIO detect when it's re-entering init() and refuse to initialize in that case) but, again, just because you can, doesn't mean it makes sense. I still don't see how that could possibly be useful. If you want to build some kind of multi-client ASIO driver wrapper, then it would make more sense to write a new ASIO driver that does just that (e.g. by coordinating around some kind of IPC mechanism). This doesn't really have anything to do with FlexASIO or PortAudio. |
In #239 @josephernest wrote:
This is an interesting use case and the first time I see someone mention a good reason to want to use an ASIO backend behind FlexASIO. However, I'm afraid I would still be unwilling to enable the ASIO PortAudio Host API in FlexASIO. The reason for this is PortAudio/portaudio#696 - the PortAudio ASIO support suffers from a significant design flaw that can seriously compromise the stability and performance of the driver, and it's not a flaw that can easily be fixed. I am not willing to compromise FlexASIO in that way. There is one alternative: bypass PortAudio and have FlexASIO act as a thin wrapper between the host application and the underlying driver. This would be cleaner and vastly more reliable and performant. It wouldn't be too hard to implement, either (although there may be some subtleties around "injecting" reset requests behind the back of the driver when the config file changes). However I am not sure I would want to commit to implementing and maintaining that code for such a niche use case (i.e. just to make it possible to switch to a different ASIO driver through a FlexASIO config file). Especially since choosing a driver is supposed to be the host application's job - if the application makes that inconvenient then that seems like something the application should fix. |
Thanks @dechamps for the report.
Do you think we could do the test in a branch? I'll document all the findings here for future reference. Thanks in advance if we can try this little test :) |
It is indeed a one-line change: abb8f98 (installer, workflow) I don't have any reason to believe this wouldn't work, but to be clear, I have not tested this at all, nor do I plan to. Assuming it works, the backend name is Feel free to give this a try if you like, but to be clear this will remain an experiment - due to PortAudio/portaudio#696 I will never accept this in FlexASIO proper. The only reason I made this build is because it took me literally 30 seconds to do it. If you want to keep using this and keep up with FlexASIO updates you'll essentially have to maintain your own fork. |
Thanks a million @dechamps for the build, I'll be happy to play with this :) Edit: Report after trying this test version: I tried
No support asked of course, I know that I'm on my own if I want to continue this route, but I just wanted to post this for future reference 😄 |
It runs on GitHub's servers. See GitHub-hosted runners.
It is free of charge for public (i.e. open source) repositories. FlexASIO is a public repository. See their billing docs. (And yes, that does sound too good to be true, but it is!)
Nope, all the config is in that file. If you want to try this yourself, you can for example fork FlexASIO, enable GitHub Actions on your fork, and then just push any commit. You will see in the Actions tab that the workflow immediately springs into life and a few minutes later your very own FlexASIO installer will be ready for you.
That's surprising, but yeah you're on your own for that one. |
I want to combine a WASAPI input device with an ASIO output device as a single FlexASIO device because most recording & monitoring applications only support opening a single ASIO device for both input and output. This seems technically possible if you support multiple backends simultaneously. It looks like PortAudio already supports ASIO backends.
Additionally, my output device supports simultaneous ASIO and WDM playback, so I can still use it in WASAPI applications while FlexASIO uses the ASIO interface.
I can work around it right now by using WASAPI shared mode in FlexASIO for both input and output, but that adds a lot of latency.
The text was updated successfully, but these errors were encountered: