Repository navigation
Conversation
9d150b0 to
445ec95
Compare
|
This is super cool, though I don't see osu! using this in the near future if ever. I'd see this implemented as an additive nuget package, and exposed through some way that isn't the framework config. For example, it could be included in |
|
I'd actually like to experiment with this and see how good support is for the upcoming changes I want to make with WASAPI initialisation. So I don't want to throw this out. Moving away from bass would be a huge consideration, but I wouldn't throw it away. I'm going to mark this as a draft as I don't see it getting reviewed or merged anytime soon, but I still useful to have around as a reference for what is involved in making this work, and potential performance / latency cross-checking in a future. |
|
I'll maintain this until some of you have anything to do with this, mostly because I am now so used to playing the game with these patches, I can't really go back to BASS... |
fe6c986 to
d19377f
Compare
d781cbe to
bb275f2
Compare
|
@hwsmm thanks for keeping this up-to-date. curious on your thoughts on the move to sdl3 – does this help in any way on the audio side of things? i don't want to promise anything but we have internally discussed the potential of moving to sdl3 as an audio provider at some point. curious on how wasapi is looking specifically, as i read that sdl3 was going to add better support, potentially replacing my attempt at initialising for lower latency (#6088) which ended up having compatibility issues and limited results. |
|
SDL3 Audio doesn't give any improvements over SDL2 for the usecase of osu!framework in my opinion. SDL has a good WASAPI implementation, but they don't provide any means to adjust buffer sizes (https://github.com/libsdl-org/SDL/blob/main/src/audio/wasapi/SDL_wasapi.c#L635 -- only uses default '0' value). However, the problem that hinders real low latency lies in .NET GC overhead. As I wrote in the PR description and the previous comment, audio stutters a lot if I force low latency on Linux, and it should be the same on Windows, too. So what I am trying to say here is, that even with the Windows API above, it's going to be pretty hard to get the stable low latency audio experience unless audio is handled in completely unmanaged land. ... if you ask me what's the point of this PR then:
|
That's, honestly, the first time I'm hearing of this. I would imagine that code returns in a fraction of a microsecond so I wouldn't expect the GC to have that sort of impact on it, but I suppose it would make sense for super small buffer lengths. If it is GC and not e.g. the cost of context switching, there's a few things I'd try:
Perhaps, all at the same time. |
|
I guess my comment was a bit ambiguous. I meant that the audio callback returns fast, but the problem is supposedly 'stop-the-world' effect of GC. Here are my test results for things you mentioned:
|
|
It would be nice to combine all of this audio component work and make a new open-source BASS-compatible audio library |
|
First of all, this PR is not compatible with BASS. It just implements o!f audio components in C# and SDL, while the current o!f audio backend is written in BASS API. I do love open source, and it's true that I wrote this PR to get rid of a closed source lib from osu!framework, but there is only little point to both audio library consumers and us in maintaining a new audio library when there are mature open-source audio libraries out there. Better contribute to them if they are missing some features. It could be another example for xkcd new standard in my opinion. Just consider this as a random audio backend for a game engine. Unity, Unreal and Godot, they all have their own audio backend, but they are not standalone, right? |
|
I've just sent a mail! Forgot to add in the mail. I am planning to implement decoder in .NET side, because it adds a bit of complexity and may cause link problems with FFmpeg. |
|
Starting from https://discord.com/channels/188630481301012481/589331078574112768/1396539637861847141, I copied most part from this PR to the new library, and I got most things working... on my PC. As a side note, I was actually a few hours before (pre-)releasing my native library here when smoogi sent me that message since it had been pretty stable lately, so I was not motivated to write it again in NativeAOT, but I ended up deciding to do because it required much less effort because I already had some in C#. I honestly got surprised with Satori. When I finished the basic implementation and tested with plain NativeAOT, the result was not good on very small buffer (around 1ms). However, with Satori, it still had some underruns, but was very acceptable than plain NativeAOT and this PR. Anyway, here are some points to know:
How to try:
This thing is still very early, so it may be (completely) broken in some cases. I'd be grateful if you can try and let me know if it works well. |
|
@smoogipoo I am not expecting an immediate response, but here is a mention in case you didn't enable notification on this thread. |
|
@hwsmm I tested your changes. Note that I'm using 2025.816.0-lazer, not the latest version, because your framework is a bit outdated. I'm on Linux (Fedora 42). I tried with this beatmap. Note that I’ve set a 10 ms audio offset, since that’s what I use in my regular lazer client, that I deactivate beatmap hitsound, and that I use argon pro. With BASS:
With SDL3 (without set SDL_AUDIO_DEVICE_SAMPLE_FRAMES):
With SDL3 (SDL_AUDIO_DEVICE_SAMPLE_FRAMES = 128):
With SDL3 (SDL_AUDIO_DEVICE_SAMPLE_FRAMES = 64)
For SDL3 and SDL_AUDIO_DEVICE_SAMPLE_FRAMES set to 64 and 128, the hitsound feels more responsive, feel like I was often clicking early. Didn't encounter audio issues with these values. In the editor, I feel like the hitsound are early. With SDL_AUDIO_DEVICE_SAMPLE_FRAMES set to 32, sound start crackling, didn't try playing a beatmap. Hope this help, you can ask me to test things if you want. Maybe I should have test with no audio offset? I can do it if you want. |
|
@Rudicito Hey, thanks for testings! Reporting issues you encounter while using it is sufficient for now (you may use whatever offset you want). sdl-audio-alt branch is now updated, so you can probably update your game. |
|
The following was written with AI assistance based on my own testing and findings. I am not an audio developer, so I cannot evaluate the architectural or maintenance concerns involved in merging this work. My contribution here is empirical: I am an experienced taiko player, and input-to-hitsound latency is the main reason I normally avoid osu! and prefer OpenTaiko with ASIO on Windows. I tested the newer To get the current game compiling, I used:
On the osu! side, the additional adaptation was small: six newer The result compiled successfully. I was then able to play stably with PipeWire running at a 48-frame quantum at 44.1 kHz. The gameplay difference was not subtle. Input-to-hitsound response felt dramatically tighter, and osu! felt better to me than it ever has before, including my experience playing on Windows. I only play taiko, so that is the mode I can confidently evaluate. I understand that a working local build does not address all of the architectural, maintenance, mobile, or cross-platform concerns involved in upstreaming an alternative audio backend. However, it does demonstrate that the newer SDL3 audio work can still run on the current game, and that its practical benefit for latency-sensitive Linux players can be enormous. I would really like to see this work revisited and given a concrete path toward an officially supported low-latency audio option, even if it initially remains experimental or Linux-only. I can provide the exact osu! diff and testing details if they are useful. |
|
I am sorry, but osu! project does not accept any kind of AI assistance (including documentation things). Please take a look at this section: https://github.com/ppy/osu-framework#contributing I just updated my patches in the Also I moved the old branch to |
b3dacf9 to
a3262c9
Compare
| { | ||
| public enum Type | ||
| { | ||
| BASS, |
| /// <param name="trackStore">The resource store containing all audio tracks to be used in the future.</param> | ||
| /// <param name="sampleStore">The sample store containing all audio samples to be used in the future.</param> | ||
| /// <param name="config"></param> | ||
| public SDL3AudioManager(AudioThread audioThread, ResourceStore<byte[]> trackStore, ResourceStore<byte[]> sampleStore, [CanBeNull] FrameworkConfigManager config) |
| { | ||
| public enum AudioDriver | ||
| { | ||
| BASS, |
| public static readonly SDL3AudioDecoderQueue INSTANCE = new SDL3AudioDecoderQueue(); | ||
|
|
||
| private readonly LinkedList<IWorker> workers = new LinkedList<IWorker>(); | ||
| private readonly object lockHandle = new object(); |
|
|
||
| private static volatile bool libraryPrepared; | ||
|
|
||
| private static readonly object sync_lock = new object(); |
| SDL3AudioDecoderQueue.INSTANCE.Enqueue(this); | ||
| } | ||
|
|
||
| private readonly object lockHandle = new object(); |
| } | ||
|
|
||
| private IntPtr decoder = IntPtr.Zero; | ||
| private readonly object lockHandle = new object(); |




This PR lets the framework use SDL3 as an alternative audio backend. It requires no change to the game (osu!).
To use it, change AudioDriver to SDL3 in
framework.ini.Limitation: