-
-
Notifications
You must be signed in to change notification settings - Fork 764
Description
Ebitengine Version
v2.9.8
Operating System
- Windows
- macOS
- Linux
- FreeBSD
- OpenBSD
- Android
- iOS
- Nintendo Switch
- PlayStation 5
- Xbox
- Web Browsers
Go Version (go version)
go version go1.26.0 windows/amd64
What steps will reproduce the problem?
This example shows the problem:
go run github.com/hajimehoshi/ebiten/v2/examples/audiopanning@latest
But to make the problem easier to hear, I made a modified version that uses a sine tone instead of music:
go run github.com/31/ebitengine-panning-compare/sin-pan@2990b748c08894d1092ff7865fa1cd4ec49ed0fb
What is the expected result?
The panning should be smooth, and the music (or sine tone) sounds good.
I made more samples that use two Players and adjusts their volumes instead, and this works:
https://github.com/31/ebitengine-panning-compare/blob/2990b748c08894d1092ff7865fa1cd4ec49ed0fb/pan-2p/main.go
https://github.com/31/ebitengine-panning-compare/blob/2990b748c08894d1092ff7865fa1cd4ec49ed0fb/sin-pan-2p/main.go
Here's what the sine tone should sound like:
sin-pan-2p.mp4
Here's what it looks like as a spectrogram: notice smooth changes in volume (one channel shown):
What happens instead?
The music panning is delayed compared to the position on screen and suddenly changes panning in a stuttering way rather than being smooth.
audiopanning.mp4
It's more obvious with the sine tone:
sin-pan.mp4
The spectrogram (one channel shown) makes it pretty clear:
Anything else you feel useful to add?
My understanding is that sound systems need to read in a decently large buffer at a time, and when this happens, the example implementation feeds the sound system a buffer with the pan value "frozen" at a certain value. The length of the freeze is based on however far into the future the sound system has to pull into its internal buffer. When the buffer is read again, the pan value is significantly different, so it changes pretty violently. This can even sound like a periodic very loud "click" because of the sudden change from one volume level to another in the final waveform.
The buffer time might be different for specific machines. Maybe some people have a much smaller buffer, so the reads are more frequent and the result sounds reasonable. For me (and a friend), however, this problem stands out a lot and it's impossible to ignore.
When I tried this example, I was concerned that there was some inherent problem in ebitengine, but I think the example just needs to swap to a two-player approach. Fortunately, SetVolume does behave smoothly!