Skip to content

examples/audiopanning: example is choppy/clicky and lags behind expected pan value #3396

@31

Description

@31

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:

https://github.com/hajimehoshi/ebiten/blob/e8a9c3581a1f361ebbb843754297d7ed4b980e36/examples/audiopanning/main.go

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:

https://github.com/31/ebitengine-panning-compare/blob/2990b748c08894d1092ff7865fa1cd4ec49ed0fb/sin-pan/main.go

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):

Image

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:

Image

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!

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions