Skip to content
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

Bitrate-like artifact when playing low frequency sounds #23544

Closed
Zylann opened this issue Nov 6, 2018 · 42 comments · Fixed by #46086
Closed

Bitrate-like artifact when playing low frequency sounds #23544

Zylann opened this issue Nov 6, 2018 · 42 comments · Fixed by #46086

Comments

@Zylann
Copy link
Contributor

Zylann commented Nov 6, 2018

Godot 2.1.5
Godot 3.0.6
Godot 3.1 alpha 2
Windows 10 64 bits

I noticed when I play a specific low-frequency sound with Godot, it always comes with a small high-frequency artifact noise.
This happens for both WAV and OGG formats.
This does not happen when I play the sounds in Audacity or VLC.

Example project:
LowFrequencySound.zip

Video:
https://zylannprods.fr/dl/godot/GodotLowFrequencySound.mp4

@Zylann Zylann changed the title Sampling artifact when playing low frequency sounds Bitrate artifact when playing low frequency sounds Nov 6, 2018
@Zylann Zylann changed the title Bitrate artifact when playing low frequency sounds Bitrate-like artifact when playing low frequency sounds Nov 6, 2018
@marcelofg55
Copy link
Contributor

marcelofg55 commented Nov 6, 2018

You're testing this using the WASAPI driver, right? What's the sampling rate of your device? I suspect that those artifacts may be a resampling issue.

@Zylann
Copy link
Contributor Author

Zylann commented Nov 6, 2018

I don't even know which driver Godot uses, how do I check this?

@marcelofg55
Copy link
Contributor

If you start godot with --verbose you'll see what driver it's using.

@Zylann
Copy link
Contributor Author

Zylann commented Nov 6, 2018

Testing on another computer, I don't get the artifact. The log says:

WASAPI: detected 2 channels
WASAPI: audio buffer frames: 970 calculated latency: 21ms

I'll test on my own machine once I'm back home.

@Zylann
Copy link
Contributor Author

Zylann commented Nov 6, 2018

My home computer prints the same thing:

WASAPI: detected 2 channels
WASAPI: audio buffer frames: 1962 calculated latency: 44ms

But it has the artifact.

My Audacity was playing using MME, but if I change it to WASAPI there is no problem either.

@marcelofg55
Copy link
Contributor

I've tested this on OS X using different sample rates and there is no artifact.
After that I've tested this on Windows 10 using WASAPI, with 44100 Hz there is no artifact but when I set my device with 48000 Hz there is an artifact.

Can you check the sample rate of your device? Let me know if you can confirm that with 44100 Hz there is no artifact and with higher sampling rates there is an artifact.

@Zylann
Copy link
Contributor Author

Zylann commented Nov 6, 2018

Where can I check that sample rate?

@Zylann
Copy link
Contributor Author

Zylann commented Nov 6, 2018

I am indeed set to 24 bit 48000Hz.

@norton-corbett
Copy link
Contributor

On Windows I hear this aliasing regardless of my audio device's sample rate.

@norton-corbett
Copy link
Contributor

norton-corbett commented Apr 13, 2020

After some investigation I don't think this is actually a Godot issue. In summary, I can reproduce this in other applications using WASAPI or otherwise non-ASIO audio driver.

Anyone hoping to utilize Godot for any serious professional audio application will probably want to set their project's audio driver to "Dummy" and write their own audio backend as I'm doing now.

Which is a bit of a shame, since Godot's audio effects library and mixer/bus system might lead some to believe it's ideal for an audio app out of the box, but without ASIO support on Windows I think it's a no-go.

@starry-abyss
Copy link
Contributor

starry-abyss commented Apr 13, 2020

Why set driver to dummy though? If you add your own audio driver in Godot (and then select it, not dummy one), there shouldn't be a need for rewriting other audio functionality as well.

@norton-corbett
Copy link
Contributor

Because it's easier to just use portaudio instead.

@Calinou
Copy link
Member

Calinou commented Apr 13, 2020

Godot has an XAudio2 driver, but it's not compiled in by default and probably not working anymore. You can build it by passing xaudio2=yes on the SCons command line.

Godot also used RtAudio in the past on Windows, but that driver was removed entirely in 3.1 (or 3.0, I don't remember).

@norton-corbett
Copy link
Contributor

Well it would be cool to get ASIO support back in, which RtAudio apparently provided, but I'm also aware that professional audio is outside the scope of a game engine which is why I'm not pushing the issue.

Disabling Godot's audio and going the portaudio route also allows me to switch driver at runtime (common in audio applications). As far as I can tell Godot's AudioServer currently has no interface for doing that.

@RockyMadio
Copy link

i also confirm this issue. In our fighting game (similar to street fighter V ) where punching, wooshing and shouting sounds are played/ resetted frequently, you can easily spot the "clicking" noise everytime a new sound is launched. The issue occurs with different export settings for .WAV from Audacity.

Or when you just make a simple scene with a timer that loops between play and stop just one sound in an AudioStreamPlayer3D, you can hear the noise as well.

@Zylann
Copy link
Contributor Author

Zylann commented May 26, 2020

@RockyMadio note that this issue is not about "clicking", but high-frequency artifacts that persist when low-frequency sounds are played. Clicks can have another cause.

@Calinou
Copy link
Member

Calinou commented May 27, 2020

@RockyMadio The audio clicking issue is being tracked in #22016.

@griffinjennings
Copy link

Something of note here: this effect seems to be slightly reduced (but not entirely gone) when run through the HTML5 exporter (see video attachment). Maybe something to do with how the browser handles audio devices?

godot.audio.test.compress.mp4

This is on 3.2.3. I'm hoping this at least gets another look before 4.0, as this is a fairly critical issue for me.

@Calinou
Copy link
Member

Calinou commented Dec 19, 2020

Something of note here: this effect seems to be slightly reduced (but not entirely gone) when run through the HTML5 exporter (see video attachment). Maybe something to do with how the browser handles audio devices?

The HTML5 uses a different audio driver than native platforms (Web Audio API), that's probably why. Also, the default output latency is higher on HTML5 compared to other platforms.

@akien-mga akien-mga added this to the 4.0 milestone Feb 19, 2021
@wingedadventurer
Copy link
Contributor

@ellenhp I have tested this in 3.2.4 RC3 and it doesn't solve the issue. There's no noticeable "ringing" reduction between 3.2.3 stable and 3.2.4 RC3.

Below I've recorded playing all 3 supported audio formats in VLC (where they sound normal), and then in 3.2.4 RC3. I recommend headphones to be able to hear low-end frequencies better, since kicks are used in the video, as ringing is most noticeable in low-end of the spectrum.

ringing_3.2.4-rc3.mp4

@akien-mga
Copy link
Member

Can you provide these files for testing?

@wingedadventurer
Copy link
Contributor

Sure, here: kicks.zip.

@akien-mga
Copy link
Member

Interesting, I can't reproduce the issue with those sounds on 3.2.3-stable nor 3.2.4-rc2 or 3.2.4-rc3. The sounds play fine in all version, the same as with ffplay (and similar to the VLC output in your video, though they do sound significantly different with my headphones or PC speakers).

I'm on Mageia 8 using PulseAudio 14.2.

@wingedadventurer
Copy link
Contributor

(Should've written before, I'm on Windows 10)

Ok, so I just checked the sample rate of the 2 devices I used for testing and they were set to 48000 Hz by default. Changing them to 44100 Hz that Godot uses makes ringing gone even on 3.2.3-stable.

I had a somewhat related issue 2 years ago where setting the sample rate for devices to 44100 Hz fixed large audio latencies.

So there's now no ringing on my end even in 3.2.3-stable, for any file format.

However, if device sample rate being different from Godot's mix rate in project settings creates these issues, how should this be handled? I haven't seen any video game offer the "sample rate" setting. All audio played just fine.

Godot's tooltip for mix rate setting says In general, it's better to not touch this and leave it to the host operating system.

@Zylann
Copy link
Contributor Author

Zylann commented Mar 2, 2021

I confirm that sample rate of the device is what caused it for me originally, and I have the same questionning as to how every other software is able to cope with that just fine, while Godot does not.

@akien-mga
Copy link
Member

This might be worth tracking in a new issue then as it's likely a different issue specific to the WASAPI Windows audio driver.

@wingedadventurer
Copy link
Contributor

I will do more testing, then open a new issue for this.

@ellenhp Sorry for another ping, but I compared 3.2.3-stable and 3.2.4-rc3 with matching sample rates now, and slight ringing can be heard in OGG in 3.2.3-stable but it's gone in 3.2.4-rc3. WAV and MP3 play without any ringing.

So I can confirm that #46086 fixes this issue (when sample rates are matching). 😃

@ellenhp
Copy link
Contributor

ellenhp commented Jul 31, 2021

@Zylann The PR that originally fixed this issue will be reverted by #51082 because of some regressions it caused, FYI. I was wondering if you'd be willing to help test that new PR to make sure it doesn't introduce any more regressions? I'm tired of introducing regressions, would be nice to get it right this time. :)

@Zylann
Copy link
Contributor Author

Zylann commented Jul 31, 2021

I tested with your PR applied to my fork of Godot 3.x (I have no setup for Godot 4 yet), but the problem still happens. I notice however that I'm unable to stop at a breakpoint in AudioStreamPlaybackResampled, which hints that it might not be running.
Is there something else I have to pull from Godot 4 in order for this to work?

Also looking at the files you changed in #51082, I don't see what you reverted. Only the resampling formula was changed, and the previous version is the same as what Godot 3.x had, and the issue happened with it too.

@ellenhp
Copy link
Contributor

ellenhp commented Jul 31, 2021

I reverted #46086 (because it caused #49131) in the first commit of #51082, and the second commit changes the resampling algorithm coefficients to actually sound okay. Would you mind pushing the code that you tested with or is there stuff in there you can't share? I just double-checked my change works on the master branch, and I can't imagine why it wouldn't work on 3.x.

If you're on Windows, you could be running into this bug, which I might try and tackle next.

@Zylann
Copy link
Contributor Author

Zylann commented Jul 31, 2021

There is no particular code to share, the project is really just empty with a sound file in it (as in the first post), the problem can be heard by double-clicking and playing the sound in the inspector.

@ellenhp
Copy link
Contributor

ellenhp commented Jul 31, 2021

I'm more interested in the 3.x fork that you rebased my changes onto. I'll rebase myself and see what happens though, but I can't imagine this being dependent on anything in 4.0, because the original change was cherrypicked for 3.3 with no issues.

@Zylann
Copy link
Contributor Author

Zylann commented Jul 31, 2021

About the fork, it's really just latest 3.x with the few lines in #51082 applied on top of here

void AudioStreamPlaybackResampled::mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) {

		/*AudioFrame even1 = y2 + y1, odd1 = y2 - y1;
		AudioFrame even2 = y3 + y0, odd2 = y3 - y0;
		AudioFrame c0 = even1 * 0.46835497211269561 + even2 * 0.03164502784253309;
		AudioFrame c1 = odd1 * 0.56001293337091440 + odd2 * 0.14666238593949288;
		AudioFrame c2 = even1 * -0.250038759826233691 + even2 * 0.25003876124297131;
		AudioFrame c3 = odd1 * -0.49949850957839148 + odd2 * 0.16649935475113800;
		AudioFrame c4 = even1 * 0.00016095224137360 + even2 * -0.00016095810460478;
		p_buffer[i] = (((c4 * mu + c3) * mu + c2) * mu + c1) * mu + c0;*/

		float mu2 = mu * mu;
		AudioFrame a0 = 3 * y1 - 3 * y2 + y3 - y0;
		AudioFrame a1 = 2 * y0 - 5 * y1 + 4 * y2 - y3;
		AudioFrame a2 = y2 - y0;
		AudioFrame a3 = 2 * y1;

		p_buffer[i] = (a0 * mu * mu2 + a1 * mu2 + a2 * mu + a3) / 2;

But as I said, this function doesn't seem to run in the first place.

@ellenhp
Copy link
Contributor

ellenhp commented Jul 31, 2021

Oh you know what, I just noticed that you're on windows and noticing this with wav and ogg files. I strongly suspect this is same issue as #46595. Sorry for bugging you! I'll go fix that when I get a chance. I'll need to install windows in a VM or something to test it though which is why I haven't fixed it in one of my previous audio bug bash sessions 😄

The bug I'm fixing right now applies only to OGG files.

@akien-mga akien-mga modified the milestones: 4.0, 3.3 Feb 6, 2022
@wareya
Copy link
Contributor

wareya commented Feb 14, 2022

Apologies in advance if this is the wrong issue to post this on, but it looks like the same issue from what I can tell. Why does cubic resampling not apply to .wav files like it applies to .ogg? I'm getting a loud low frequency bitcrushy artifact when playing bell/chime sound effects because of linear resampling. Is there an open issue for wav resampling that I can comment on that I missed?

The base .wav and .ogg files in this zip are 48khz, the resampled .wavs are 44.1khz (to demonstrate what the two resampling algorithms sound like). The base .wav exhibits the ringing when played back in a 44.1khz godot project, but the .ogg does not. This happens regardless of what I have my audio card's sample rate set to in Windows (44.1khz or 48khz) as long as the project is set to 44.1khz. I'm using Godot 3.4.2.

entrance_bell_edit_original_and_resampled.zip

2022-02-14_16-38-37.mp4

@ellenhp
Copy link
Contributor

ellenhp commented Feb 14, 2022 via email

@wareya
Copy link
Contributor

wareya commented Feb 14, 2022

Yes, I can hear an obvious difference. There is a distinct distorted tone around 650hz on the .wav that is much quieter on the .ogg. I am using studio monitor headphones. The video's audio looks like this under a spectrogram:

image

The tone at 650hz is distinctly louder and longer-lasting in the linear-resampled .wav than the .ogg. (Both tones near 600hz are coming from resampling, but the hermite resampling that the .ogg goes through produces much quieter tones that are easier to ignore.)

I also don't think linear resampling should be introducing low frequency components but I could be wrong there because I'm not a DSP person really.

This is mostly true when upsampling, but not when downsampling. Downsampling can introduce new information anywhere depending on the particular combination of signal and resampling ratio, if the resampling filter does not involve properly lowpassing the original signal.

@ellenhp
Copy link
Contributor

ellenhp commented Feb 14, 2022 via email

@wareya
Copy link
Contributor

wareya commented Feb 14, 2022

Wavs currently use linear resampling for performance reasons but I think computers have gotten fast enough that we can change that.

Yeah; imo, hermite sampling will probably be fast enough to not make a difference. It's not like sinc where you have to call a trig function a dozen times per sample, it's basically just a handful of extra multiplications and additions.

Would you mind opening a new issue with all this information? This is a different bug than what this issue originally tracked.

Will do! (when I have a spare hour)

@ellenhp
Copy link
Contributor

ellenhp commented Feb 14, 2022 via email

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

Successfully merging a pull request may close this issue.