Skip to content

Add ASIO/WASAPI drivers to Reduce Audio Latency #705

Open

Description

@posesix

Opening an issue for discussion since this is something that should be included in the official distribution.

osu! uses default BASS procedures, which use DirectSound on Windows, causing large latencies due to high latency software mixing in Windows Vista and Windows 7 (as I've tested). I get 70ms latency on average using 240FPS on both my Windows 7 64-bit PC and Windows Vista 32-bit laptop. This may be less of a problem on Linux since BASS defaults to the ALSA driver, which is a low-level & low-latency driver, but I have not tested it fully.

The BASS API has extensions for ASIO and WASAPI support under the same licenses.
We can effectively (hopefully) reduce the latency to less than 4ms on ASIO, and a worse case on WASAPI (Exclusive).

BASS does not unify their main API with ASIO and WASAPI APIs for some reason, so some changes and additions to audio code will be needed. These APIs are very easy to work with, and pretty much the same as using their main API once you've got them initialised. We have to set up a BASS MIXER and load sounds and music as BASS STREAMS, instead of SAMPLES. The STREAMS are connected to the MIXER and the MIXER feeds audio data to the ASIO/WASAPI event procedures. BASS CHANNEL procedures can be used with streams just like samples.

We will also need to add options for sound drivers in the options menu. It will simply list available drivers depending on your platform. A simple drop-down box can be created after detecting available drivers. Options could be "Default", "ASIO", "WASAPI (Shared)", and "WASAPI (Exclusive)". A note should be added to WASAPI (Exclusive) and ASIO since they take exclusive access of an audio device, so only osu! can be playing sound from that device.

Linux does not use ASIO, so this will not affect Linux. WASAPI is Windows-exclusive, but does not achieve lower latencies compared to ASIO.

This will also add some dynamic-link dependencies and the use of add-ons from ManagedBass. BASSMIX, BASSASIO, and BASSWASAPI will be used.

I can work on the code for ASIO & WASAPI support, but some minor design changes may be required.

Activity

  1. Tom94 commented on May 9, 2017

    @Tom94
    Collaborator

    The latency you describe is not inherent to windows audio mixing. I've had many sound cards, and for most of them there was no perceptible delay, even through DirectSound and an active audio mixer. Therefore, the fault can't lie with windows' audio pipeline. Seems to me like the fault lies with the hardware / driver and not DirectSound.

    Of course, if you have a sound card where ASIO / WASAPI actually makes a difference (on all the ones I had, if there was a delay, then it persisted with ASIO / WASAPI; believe me, I tried hard to get rid of it, as I also find it annoying), then feel free to implement it. Design changes can be discussed as they come up.

  2. posesix commented on May 9, 2017

    @posesix
    Author

    I felt my conclusion is fact because I've worked on and compared low latency code myself and there was significant improvement when using ASIO or WASAPI. I conducted my tests by recording with a microphone and a click input and measured the space between both sounds. Sure enough there was 2ms latency using ASIO and a large 70ms when using DirectSound. The delay is easily noticeable if you're one who makes taps after hearing the instrument and getting that feedback.

  3. Tom94 commented on May 9, 2017

    @Tom94
    Collaborator

    I'm not claiming your setup doesn't exhibit delay. As I said, feel free to implement ASIO / WASAPI. I'm just saying, that it's most likely a specific problem with your setup (I had similar issues with my old Xonar Essence STX and a bunch of onboard sound cards), and not that of the windows audio mixer. I've got multiple working setups that prove that the latency with DirectSound and the audio mixer turned on can be (and should be) close to none.

  4. thomastanck commented on May 9, 2017

    @thomastanck
    Contributor

    Hi, I'm a chronic sufferer from audio latency. While it was possible for me to fix my setup, it was EXTREMELY difficult to do so, having to try out many different drivers and rebooting many times, and sometimes the driver only works under specific circumstances (if I unplug my external monitor and use the laptop monitor, it suddenly stops working!) and sometimes the driver will decide to uninstall itself (I don't have automatic updates enabled, I don't know what's uninstalling it...)

    If ASIO / WASAPI is going to remove all this pain, it doesn't actually matter if it's possible to fix my setup or not, because it would actually fix my setup, and save a decent number of players some grief.

    @posesix It'd be great if you could submit a PR for this, else I don't think much can be done ^^;

  5. kabaru commented on May 9, 2017

    @kabaru

    +1 To this. I've been through 6 months of reinstalls, multiple sound cards, custom drivers, and more. My headphones are connected directly to the sound card so there's definitely no hardware problem. Basically, I've dragged myself through hell to play without latency and am still stuck where I was before. Prior to this I had some drivers which I somehow broke the APO on which had no latency. Obviously I haven't been able to replicate this. My hardware supports ASIO. Please please please add support.

  6. peppy commented on May 9, 2017

    @peppy
    SponsorMember

    In many cases ASIO is not implemented perfectly and can introduce issues (I've experienced this personally in the past). It should not be considered a solves-all solution but instead a fallback for users with problems.

    Also please note we do not need +1 comments. We have no issue with ASIO support being added (although do note it is an extra BASS product with a separate license requirement) so feel free to PR support for this.

  7. added this to the milestone on Nov 21, 2017
  8. deleted a comment from on Jan 10, 2018
  9. removed this from the milestone on Mar 17, 2020
  10. Nouko61 commented on Aug 28, 2021

    @Nouko61

    Audio system is switched to bassmix now, can we raise the priority of this issue?

  11. peppy commented on Aug 28, 2021

    @peppy
    SponsorMember

    You are welcome to give implementing this a shot at any point, if that's what you're asking!

  12. jackiechan420 commented on Jul 24, 2025

    @jackiechan420

    Has there been any update on this?

  13. peppy commented on Jul 25, 2025

    @peppy
    SponsorMember

    Not yet, but it's on the radar still. Thanks for your patience 😄

  14. 33 remaining items

  15. bdach commented on Oct 28, 2025

    @bdach
    Collaborator

    For the record, the following is a more charitable depiction of where I personally stand on "multiple audio backends":

    • I don't know what is specifically referred as to "audio backend" when it comes to code, even when limited to unspecific "playback" as @LastExceed did on discord. Is every single audio-related class (tracks/samples) going to receive a "backend"-specific implementation? What warrants doing that? What is the backend going to be? What is it going to be doing different?
    • Is there a real reason to introduce "backend" abstractions? A real reason as far as I'm concerned would entail having situations where sometimes "backend" A performs worse than B, but sometimes performs better, in some respect, or there are other tradeoffs involved that actually warrant being able to switch things. Which is very much the case with graphics. If there's no such reason to do it then "backends" shouldn't exist, and the only implementation in source should be the one that is the best at all times, which is sort of where (as far as I'm aware) the current plugin-based implementation of WASAPI is, and why I'm more open to just deleting BASS in favour of SDL audio if it improves the situation all around (which isn't clear either).
    • An additional caveat to the above is that determining whether there is a "real reason" in terms defined above will likely result from pushing the change to users and seeing what happens. The current improved WASAPI hasn't even seen a full proper lazer release. I don't discount the possibility than when pushed to a larger userbase, issues will surface that may warrant reevaluating the audio situation, but I won't put wagers on it before said release happens.

    If some of the above can be elaborated on / explained to my out-of-touch self, I may be more open to the possibility, and may be more willing to provide commitments from my side that any further work on these "backends" is going to be considered further. But I am very aggressive on cutting complexity when it's not warranted otherwise.

  16. mirh commented on Oct 28, 2025

    @mirh

    Yeah, complexity just for its own sake is pointless.

    Though besides perhaps audio devices that don't even expose a HDA endpoint, why you may not want to stick with the basic driver seems easy to guess.
    Particularly in this day and age of spatial audio (to be sure you aren't running your DTS:X Ultra or Sound Unbound license without the OEM cruft) and DSP-driven array speakers.
    Plus I guess even if it's just an extra 1 or 2 ms (tops) on the table to improve, it's nice to even pull off that ease of mind.

    So that's why besides WASAPI only whatever had WDM-KS/ASIO (which would also have the added benefit of bypassing whatever fuck technical limitation vendor drivers have?) seems to make sense.

  17. acid-chicken commented on Oct 28, 2025

    @acid-chicken

    The abstraction introduced in #6628 initially aimed to organize the audio processing structure to avoid worsening issues mentioned in places like

    // TODO: All this bass init stuff should probably not be in this class.
    when working on it.

    To ensure compatibility with BASSASIO and/or SDL, this abstraction needs to be advanced anyway. However, if there is no opportunity for that, of course, it is also possible to maintain the current structure. In that case, I'll isolate WASAPI exclusive mode as a simple option from the PR.

  18. bdach commented on Oct 28, 2025

    @bdach
    Collaborator

    Refactors to move logic out of places where it probably shouldn't be, hopefully isn't the same thing as 1.8k line diff stat refactors of half the audio subsystem. A more gradual cleanup of the code, without "pluggable modules" or anything, might be viewed more amicably.

  19. LastExceed commented on Oct 29, 2025

    @LastExceed
    Contributor

    link to discord conversation for full context


    I'm really disappointed to receive such a prejudiced lecture in response to a trivial technical question. I know you probably mean no evil, but please try to be more mindful about your attitude in the future, because this has been very uncomfortable and discouraging. I'm also not the first person to feel this way about interactions with you. Feel free to DM me if you want to discuss this.

    Lets start over:

    Terminology

    Forget backends, lets just use the terms DSP and playback.

    • With Digital Signal Processing I am referring to any code related to modifying audio signals in any way. Examples are

      • decoding
      • resampling
      • mixing
      • format conversion
      • effects

      This makes up the vast majority of audio related code, and I don't intend to touch any of it

    • With playback I am referring to any code related to getting audio to, well, play back. This is the realm of native APIs like WASAPI and ASIO (and whatever the other platforms use), and by extension the libraries built on top of them (BASS, BASSWASAPI, BASSASIO, SDL, NAudio, ...).

    Goal

    Ultimately I want to enable users to use specialized playback APIs like ASIO or WASAPI exclusive when they fulfill the respective requirements.

    Motivation

    Specialized playback APIs can achieve much better latency than a generic one ever could (see my measurements further up in the thread), but aren't available (or even desirable) to everyone. I went into details, concerns, and workarounds about this during my research as well.

    Obstacles

    Currently, we're using the same library (BASS) for both DSP and playback, so we need to do some decoupling first.

    We already have the option to switch between playback via BASS or BASSWASAPI, and while the latter library is designed as a module of the former, we're not actually making use of their interop. This is because, instead of initializing BASSWASAPI by passing the global mixer handle along with WASAPIPROC_BASS to BASS_WASAPI_Init(), we instead register a generic callback where we manually transfer the raw audio data from one to the other on a byte[] level. In such a configuration you technically don't even need BASS in order for BASSWASAPI to function, as it has its own device enumeration, too. So really, as far as the current code is concerned, BASS and BASSWASAPI might as well be completely independent libraries. This is also why I disagree with peppy's statement

    it's the way it's supposed to be used

    because it most certainly is not. It defeats the whole point of BASSWASAPI being a BASS module. But it IS something that's needed for decoupling now.

    they have serious usability concerns

    I've searched through issues, PRs, and discord chatlogs for any mention of either API, but failed to find anything of concern that isn't already addressed in this thread. The only new thing worth mentioning I found is GC stutters (brought up in the SDL PR), but since this doesn't seem to be an issue with my recent tweaks, it might have been a misattribution (even my local ASIO based build which runs at an unreasonably low 166μs buffersize works fine).

    If you have any other concerns in mind, please voice them constructively.

    Design

    In the end, I want each playback implementation to be nothing more than a single subclass or similar, maybe 1 extra enum constant for the settings menu. I don't have an exact design yet, I'm still at the stage of figuring out the current ecosystem after all. And if you're still worried about code complexity, just consider the proof of concept from earlier (#6649). It is really not that much.

  20. bdach commented on Oct 30, 2025

    @bdach
    Collaborator

    I'm really disappointed to receive such a prejudiced lecture in response to a trivial technical question. I know you probably mean no evil, but please try to be more mindful about your attitude in the future

    The 'lecture' is XY problem prevention and a measure to set expectations early so that both sides are clear on where they stand. Being 'more mindful' doesn't work in my experience because if I'm not firm with where I stand the other side might not understand what my position is or think there's room for negotiation where there is none. It's not designed to be a 'comfortable' or 'encouraging' conversation.

    The only other remaining move I have to not have 'attitude' and yet still convey my position is not to reply which I'm probably going to deploy going forward.

    Ultimately I want to enable users to use specialized playback APIs like ASIO or WASAPI exclusive when they fulfill the respective requirements.

    Here's the thing though: I don't personally agree that this is something that the game should be supporting.

    • WASAPI shared mode has already made marked improvements to latency. In comparison, WASAPI exclusive / ASIO don't look all that enticing. It's questionable whether the remaining gains from exclusive audio are even relevant in terms of human cognition or other sources of timing inaccuracies like frame pacing or thread scheduling.

    • (Personal opinion) I don't think the game should be able to take exclusive control over device audio in any circumstances.

    • If the game is going to be interfacing natively with WASAPI / ASIO, then we (read: the osu! dev team) are indefinitely on the hook for maintaining a native audio implementation forevermore, which right now is more or less handled for us by BASS (or will potentially be handled for us by SDL, if that ever happens). You've even mentioned that documentation on these is scarce and it gets to levels of near alchemy. I don't want to be beholden to maintaining this code.

    • I won't even mention the support burden of this. People have so many hardware configurations and I can guarantee that more audio knobs to twist is going to result in us getting a lot more support requests for arcane configurations being broken.

      This is already evident by what the linux pipewire crowd is reporting to us (and we basically drop all of it on the spot because we can't fix any of it), and will get amplified by incorrect technical advice proliferating which has been the case several times over in the past and we're still fighting with (see e.g. "unlimited frame rate always"). Even shared WASAPI has begun to show signs of this after the recent release (Buggy audio while using experimental audio mode with Virtual audio drivers. osu#35513, Audio stops working when switching windows sound output device with osu open and using WASAPI osu#35533).

    In light of the above - to me personally - WASAPI shared mode is the 80/20 solution to audio latency and I don't see strong incentives to pushing any further. Maybe you'll have more luck convincing other maintainers, but right now, I haven't seen anything that would make me interested.

    A more productive work effort in terms of issues with the audio subsystem would be investigating and hopefully resolving ppy/osu#31843 (note that there have been a few reports claiming that WASAPI shared mode does fix that already).

  21. LastExceed commented on Oct 30, 2025

    @LastExceed
    Contributor

    Being 'more mindful' doesn't work in my experience
    &
    It's not designed to be a 'comfortable' or 'encouraging' conversation

    ...wow. That is shockingly self-aware. My codolences for the awful world you seem to live in. Genuinely. I'm not even gonna argue the XY thing anymore, it is clear that you've already been vulnerated way more than I have. Hope you find peace some day.


    It's questionable whether the remaining gains from exclusive audio are even relevant in terms of human cognition

    The scepticism is understandable. However, these APIs wouldn't be so popular in the pro audio world if the difference they make wasn't meaningful. Just wait and see for yourself when I got a PR ready

    other sources of timing inaccuracies like frame pacing or thread scheduling

    Neither of those is remotely comparable in magnitude, and at least one of them isn't even audio related

    I don't think the game should be able to take exclusive control over device audio in any circumstances.

    I totally understand (and share) the apprehensive feeling when there's only 1 output device available, but thats not really the use-case anyway. We could even inhibit such a configuration entirely if we really wanted (though I don't see the benefit of doing so). With multiple outputs however, (which are otherwise completely dormant anyway) this is a quite trivial thing to do

    indefinitely on the hook for maintaining a native audio implementation forevermore

    No you're not. Nobody is forcing you to do anything. And if things go south so badly that you really cant do nothing (zero day or whatever) then you can just do what you've already done before: //

    more or less handled for us by BASS
    &
    documentation on these is scarce and it gets to levels of near alchemy

    and see how well that turned out. Not only did BASS not remove the need to be familiar with the underlying API, it actually made the research MORE difficult (closed source, and its own documentation isnt much better), only to reward us with literally doubling our latency in a way we cannot control.

    more support requests for arcane configurations being broken

    so instead of some users being unable to use these, you'd rather have nobody being able to?

    80 / 20

    kinda sad that this is the bar for audio latency in the worlds leading rythm game


    I'm gonna drop the thread now as well, as none of this is really moving things forward. I'm just gonna work on a PR so there's actually something to talk about, then you guys can actually try things out (or not), and whatever happens, happens.

  22. Devocub commented on Dec 20, 2025

    @Devocub

    Great to see it's finally implemented! 👍

    @LastExceed I implemented same thing in McOsu few years ago(2021) and have been using it since. Except I didn't use Event flag for BASS because it made no difference for me or maybe there's something else in code.
    I posted my results in McOsu discord server and on osu! forum (for some reason screenshots are now lost from osu! servers but they are present in webarchive - 7th post) https://web.archive.org/web/20230115212434/https://osu.ppy.sh/community/forums/topics/794196?n=7 . Note these tests show full chain latency, from keyboard scanning, usb polling, game engine, BASS, audio driver, audio hardware, etc.

    But I also implemented a feature which changes sample rate of playing hitsound based on how far it is from ideal - higher pitch for earlier, lower pitch for later. Example: youtu.be/p96Bob8A8J4 . This required me to use BASS_ChannelSetAttribute(handle, BASS_ATTRIB_FREQ, 44101 for example); in each play() call (it is applied right below this line in my personal fork). After few hours of playing hitsounds (many thousands) I noticed slight visual lags, they were caused by BASS and were noticeable due to McOsu being single-threaded (up to 15 ms before another hitsound starts to be playing). This will be not noticeable in osu! and osu!lazer (or old osu! and osu! ?) because they are async. It seems something happens in BASS due to this frequency change, seems like there are a lot of dangling streams silently staying forever in playing queue? idk. discord message where I discovered it. I dirty fixed it by forcefully freeing 6 oldest streams no matter what if their amount is >12. in this commit modify like that

    if (m_danglingWasapiStreams.size() > 12) // execute only when more than 12 are active
    	for (size_t i=0; i<m_danglingWasapiStreams.size()-6; i++) // remove 6 oldest streams
    		{
    			//if (BASS_ChannelIsActive(m_danglingWasapiStreams[i]) != BASS_ACTIVE_PLAYING) // ← line is commented. even if it's playing it will be freed
    			BASS_StreamFree(m_danglingWasapiStreams[i]);
    			...
    		}

    this is acceptable for casual human playing but totally not acceptable for more advanced cases like longer hitsounds or aspire or high bpm maps such as centipede - at moments of a lot of burst-playing hitsounds some of them will be terminated prematurely. This bug should be fixed in BASS library code. I recommend to thoroughly test it in osu!. Also this hitsound pitch feature is weird at first but cool and worth being implemented.

    P.S. don't forget about this bug miniant-git/REAL#9 . It happens with anything which asks windows for small period, and persists even after the application is not running anymore

  23. LastExceed commented on Dec 24, 2025

    @LastExceed
    Contributor

    RE: miniant-git/REAL#9
    This is definitely good to be aware of. I looked into it and left a comment there.

    RE: McOsu developments
    Please don't take this the wrong way, but that's off-topic. While I do personally find it interesting, this is not the right place for such tangents. I'll happily discuss those lags if you DM me though!


    While I'm back here, I wanna bring up a potential solution to the problem of exclusive audio not really being viable for single-device setups: We could capture the output of the sound server and mix it into the osu's output ourselves. This would add a second indirection to the audio streams of other applications (app -> sound server -> osu -> hardware), but for secondary application the added latency is insignificant. Combined with switching back to shared mode when the game window isn't focused (discussed further up in the thread), this should remedy most concerns about exclusive audio, save for code complexity, which I still plan to make a case against in form of a PR

  24. Devocub commented on Dec 28, 2025

    @Devocub

    You seem to misunderstood me. I believe this bug is in BASS library so it should be reproducible in osu! the same way - playing many times hitsounds with BASS_ATTRIB_FREQ flag set (in shared low latency mode).
    https://github.com/ppy/osu-framework/blob/master/osu.Framework/Audio/BassRelativeFrequencyHandler.cs#L73
    https://github.com/ppy/osu/blob/master/osu.Game/Graphics/UserInterface/HoverClickSounds.cs#L77
    I just advise to test if this bug is still present because it is nasty and appears hidden late during gaming because something in BASS accumulates. Play, for example, PlayClickSample() 60k times and use same technique to measure audio latency (without restarting audio engine anyhow obviously). Good, if it's not reproducible.

  25. LastExceed commented on Jan 11, 2026

    @LastExceed
    Contributor

    Small update on the driver situation:

    I couldn't resist the temptation to try implementing WDM-KS directly, just to see what its actually like. I still think its a bad idea (even more so now than I did before), but it was quite insightful.

    PortAudio is literally the only resource on the topic I can find (everything else is either closed source, or points back to PortAudio), so I once again spent an excruciating amount of time making sense of its horribly copy-pasty, hardcore memory-overoptimized source (even they themselves currently lack a maintainer that understands it, lol), and learned a lot about drivers in the process, which is why I now feel much more comfortable recommending to switch. The bottomline ultimately didn't change:

    I could imagine that it breaks stuff like OEM configuration software or propietary stream formats and whatnot

    It obviously depends on the individual hardware, so just try and see if it works. Worst thing that can happen is that the device is no longer recognized as an audio endpoint, in which case you can simply switch back. This is done the same way, and pretty straight-forward.

    As for progress on alternative playback APIs (i.e. actually completing this issue), it is currently blocked by #6697

  26. remi-scarlet-1 commented on Apr 19, 2026

    @remi-scarlet-1

    If I understood correctly from the discussion in this issue there are no plans on supporting ASIO?

    I've had extremely bad audio latency on the Windows build of osu!lazer (specifically with my Scarlet 3i3). In comparison, on the same machine running the Linux build of osu!lazer with pipewire the hitsound latency is near instantaneous.

    I assume most osu players likely aren't running the game through a dedicated audio interface but for me and a few friends of mine it's a real blocker preventing us from making the switch to lazer. It's a shame really...

  27. LastExceed commented on Apr 19, 2026

    @LastExceed
    Contributor

    instead of "not having plans to support it", I think it is more accurate to speak of "having plans to not support it"

    i really wanted to make this happen. I spent so much time on this. I did the research. I wrote the proof of concept. I've literally been playing on a dev build with ASIO support for months, eagerly awaiting the day I can get it upstreamed. i did everything I could to bring this to the community. Yet my latest PR remains pending to this day, ghosted halfway through the review because I wasnt having their shit.

    Maintainers have been frustrating to work with at every step of the way, and I just can't take it anymore. My love for the game is dead, and my enthusiam for the technology too got killed like never before.

    You are right: This really is a shame.

  28. remi-scarlet-1 commented on Apr 19, 2026

    @remi-scarlet-1

    Would you be willing to share your progress? Do you have a public fork with ASIO support?

    I'd love to try it out even if it doesn't make it upstream. It would be an even bigger shame if we didn't get a chance to play around offline with the feature if you already spend all this time implementing it.

  29. LastExceed commented on Apr 20, 2026

    @LastExceed
    Contributor

    Its not in a state where you can just build and run without tailoring it to your specific machine first, but anything worth posting for development purposes, I have already posted.

    If you're only looking for the low latency experience, KeyASIO should do the trick

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions