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

AudioEffectSpectrumAnalyzerInstance.get_magnitude_for_frequency_range reports jittered values #67650

Open
Zylann opened this issue Oct 19, 2022 · 5 comments

Comments

@Zylann
Copy link
Contributor

Zylann commented Oct 19, 2022

Godot version

3.5 stable
4.0 beta3

System information

Windows 10 64 bits NVIDIA GeForce GTX 1060

Issue description

I started playing with rendering a spectrum, and even after some smoothing and peaking, noticed it was kinda low quality. Then I noticed that the reported frequencies were actually jittering along the frequency axis.

It happens for all FFT sizes, but can be mistaken for a "normal precision issue" with the default 1024. It is a lot more obvious with larger FFT sizes and a chirp sound. The frequency peak "wiggles" constantly around the frequency it is supposed to be "following".

2022-10-19.22-58-06.mp4

After seeing this, it becomes clear other FFT sizes also have this problem, but around a shorter width.
It seems the issue is temporal: reported values alternate between some time close to now and some time in the past. To the point when the chirp restarts, we can see values from the previous chirp still flicker back and forth for a brief moment.

Such discrepancy is not expected. It really looks like something is wrong in the way values are reported. Maybe the data from the ringbuffer is read in the wrong way?

Steps to reproduce

Test project:

3.5:
AudioAnalyzerFFTBug.zip
4.0 beta3:
AudioAnalyzerFFTBug_GD4.zip

Minimal reproduction project

No response

@Calinou
Copy link
Member

Calinou commented Oct 19, 2022

Related to #67611, #20198 and #55090. See #57985, which tried to improve on this issue but had to be reverted.

@EspeuteClement
Copy link
Contributor

I can also confirm this bug. The vaues produced get_magnitude_for_frequency_range produce values that appear correct at first glance but are far too noisy when comparing to other FFT implementations done in other software. I also don't think that is bug is new, as if I recall correcly even the demo project for the feature when it was announced back in godot 3.2 (see here : https://godotengine.org/article/godot-32-will-get-new-audio-features ) did suffer from the same issue.

As the reporter suggested it looks like the problem is time related, as the fft calculations looks correct, but they seem scrambled accros time, and thus produce jittery values.

I tried to dig out in the c++ implementation to try to find out where the bug came from but I didn't have enough experience in audio alalysis to find where whe bug could have come from.

@jcommander
Copy link

Still happening on 4.2,
I wish this got more attention especially since there's an official demo for an audio spectrum.
Lerping the results to midigate this issue doesn't produce acceptable results for any audio spectrum project imo.
I'll try naively poking at the code.

@20kdc
Copy link
Contributor

20kdc commented Jan 22, 2024

Also happening on 3.5.3, especially with larger FFT sizes
2024-01-22_21-08
To me, it seems reasonably clear that past FFT frames are repeating themselves.
It is also worth noting that I have attempted locking/unlocking AudioServer, as the code very clearly does not perform any such locking itself.
Looking at the code, I'm not sure what to do except to simply remove the part that tries to compensate for latency/etc. (It isn't functioning, and the current state of things is worse)

@jcommander
Copy link

jcommander commented Feb 24, 2024

Looking at the code, I'm not sure what to do except to simply remove the part that tries to compensate for latency/etc. (It isn't functioning, and the current state of things is worse)

i tried changing the code a bit but to no avail...for anyone interested in researching this further maybe I can save you some time by pointing you to the code snippet that causes this.
If calculation is as should be, AudioServer::get_singleton()->get_output_latency(); is probably the biggest suspect here. (see #38215)
The problem should be caused by the while loop or rather, the diff var it depends on in the snippet below:

Vector2 AudioEffectSpectrumAnalyzerInstance::get_magnitude_for_frequency_range(float p_begin, float p_end, MagnitudeMode p_mode) const {
	if (last_fft_time == 0) {
		return Vector2();
	}
	uint64_t time = OS::get_singleton()->get_ticks_usec();
	float diff = double(time - last_fft_time) / 1000000.0 + base->get_tap_back_pos();
	diff -= AudioServer::get_singleton()->get_output_latency();
	float fft_time_size = float(fft_size) / mix_rate;

	int fft_index = fft_pos;

	while (diff > fft_time_size) {
		diff -= fft_time_size;
		fft_index -= 1;
		if (fft_index < 0) {
			fft_index = fft_count - 1;
		}
	}

Link to Code

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

No branches or pull requests

5 participants