Fix spectrum analyzer

This commit is contained in:
Akosmo
2025-12-26 17:05:45 -03:00
parent 98782b6c8c
commit 34e246399d
5 changed files with 62 additions and 42 deletions

View File

@@ -18,8 +18,6 @@
<member name="fft_size" type="int" setter="set_fft_size" getter="get_fft_size" enum="AudioEffectSpectrumAnalyzer.FFTSize" default="2">
The size of the [url=https://en.wikipedia.org/wiki/Fast_Fourier_transform]Fast Fourier transform[/url] buffer. Higher values smooth out the spectrum analysis over time, but have greater latency. The effects of this higher latency are especially noticeable with sudden amplitude changes.
</member>
<member name="tap_back_pos" type="float" setter="set_tap_back_pos" getter="get_tap_back_pos" default="0.01">
</member>
</members>
<constants>
<constant name="FFT_SIZE_256" value="0" enum="FFTSize">

View File

@@ -0,0 +1,8 @@
GH-114355
---------
Validate extension JSON: API was removed: classes/AudioEffectSpectrumAnalyzer/methods/set_tap_back_pos
Validate extension JSON: API was removed: classes/AudioEffectSpectrumAnalyzer/methods/get_tap_back_pos
Validate extension JSON: API was removed: classes/AudioEffectSpectrumAnalyzer/properties/tap_back_pos
Removed this property because it caused buggy behavior for no discernible benefit.
Compatibility methods registered.

View File

@@ -0,0 +1,47 @@
/**************************************************************************/
/* audio_effect_spectrum_analyzer.compat.inc */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef DISABLE_DEPRECATED
void AudioEffectSpectrumAnalyzer::_set_tap_back_pos_bind_compat_114355(float p_seconds) {
WARN_PRINT_ONCE("AudioEffectSpectrumAnalyzer.set_tap_back_pos() is deprecated and the value will be discarded.");
}
float AudioEffectSpectrumAnalyzer::_get_tap_back_pos_bind_compat_114355() {
WARN_PRINT_ONCE("AudioEffectSpectrumAnalyzer.get_tap_back_pos() is deprecated and will only return the original default value.");
return 0.01;
}
void AudioEffectSpectrumAnalyzer::_bind_compatibility_methods() {
ClassDB::bind_compatibility_method(D_METHOD("set_tap_back_pos", "seconds"), &AudioEffectSpectrumAnalyzer::_set_tap_back_pos_bind_compat_114355);
ClassDB::bind_compatibility_method(D_METHOD("get_tap_back_pos"), &AudioEffectSpectrumAnalyzer::_get_tap_back_pos_bind_compat_114355);
}
#endif // DISABLE_DEPRECATED

View File

@@ -29,6 +29,7 @@
/**************************************************************************/
#include "audio_effect_spectrum_analyzer.h"
#include "audio_effect_spectrum_analyzer.compat.inc"
#include "servers/audio/audio_server.h"
static void smbFft(float *fftBuffer, long fftFrameSize, long sign)
@@ -99,8 +100,6 @@ static void smbFft(float *fftBuffer, long fftFrameSize, long sign)
}
void AudioEffectSpectrumAnalyzerInstance::process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count) {
uint64_t time = OS::get_singleton()->get_ticks_usec();
//copy everything over first, since this only really does capture
for (int i = 0; i < p_frame_count; i++) {
p_dst_frames[i] = p_src_frames[i];
@@ -143,10 +142,6 @@ void AudioEffectSpectrumAnalyzerInstance::process(const AudioFrame *p_src_frames
temporal_fft_pos = 0;
}
}
//determine time of capture
double remainder_sec = (temporal_fft_pos / mix_rate); //subtract remainder from mix time
last_fft_time = time - uint64_t(remainder_sec * 1000000.0);
}
void AudioEffectSpectrumAnalyzerInstance::_bind_methods() {
@@ -156,24 +151,8 @@ void AudioEffectSpectrumAnalyzerInstance::_bind_methods() {
}
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;
}
}
int begin_pos = p_begin * fft_size / (mix_rate * 0.5);
int end_pos = p_end * fft_size / (mix_rate * 0.5);
@@ -216,7 +195,6 @@ Ref<AudioEffectInstance> AudioEffectSpectrumAnalyzer::instantiate() {
ins->mix_rate = AudioServer::get_singleton()->get_mix_rate();
ins->fft_count = (buffer_length / (float(ins->fft_size) / ins->mix_rate)) + 1;
ins->fft_pos = 0;
ins->last_fft_time = 0;
ins->fft_history.resize(ins->fft_count);
ins->temporal_fft.resize(ins->fft_size * 8); //x2 stereo, x2 amount of samples for freqs, x2 for input
ins->temporal_fft_pos = 0;
@@ -237,14 +215,6 @@ float AudioEffectSpectrumAnalyzer::get_buffer_length() const {
return buffer_length;
}
void AudioEffectSpectrumAnalyzer::set_tap_back_pos(float p_seconds) {
tapback_pos = p_seconds;
}
float AudioEffectSpectrumAnalyzer::get_tap_back_pos() const {
return tapback_pos;
}
void AudioEffectSpectrumAnalyzer::set_fft_size(FFTSize p_fft_size) {
ERR_FAIL_INDEX(p_fft_size, FFT_SIZE_MAX);
fft_size = p_fft_size;
@@ -258,14 +228,10 @@ void AudioEffectSpectrumAnalyzer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_buffer_length", "seconds"), &AudioEffectSpectrumAnalyzer::set_buffer_length);
ClassDB::bind_method(D_METHOD("get_buffer_length"), &AudioEffectSpectrumAnalyzer::get_buffer_length);
ClassDB::bind_method(D_METHOD("set_tap_back_pos", "seconds"), &AudioEffectSpectrumAnalyzer::set_tap_back_pos);
ClassDB::bind_method(D_METHOD("get_tap_back_pos"), &AudioEffectSpectrumAnalyzer::get_tap_back_pos);
ClassDB::bind_method(D_METHOD("set_fft_size", "size"), &AudioEffectSpectrumAnalyzer::set_fft_size);
ClassDB::bind_method(D_METHOD("get_fft_size"), &AudioEffectSpectrumAnalyzer::get_fft_size);
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "buffer_length", PROPERTY_HINT_RANGE, "0.1,4,0.1,suffix:s"), "set_buffer_length", "get_buffer_length");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tap_back_pos", PROPERTY_HINT_RANGE, "0.1,4,0.1"), "set_tap_back_pos", "get_tap_back_pos");
ADD_PROPERTY(PropertyInfo(Variant::INT, "fft_size", PROPERTY_HINT_ENUM, "256,512,1024,2048,4096"), "set_fft_size", "get_fft_size");
BIND_ENUM_CONSTANT(FFT_SIZE_256);
@@ -278,6 +244,5 @@ void AudioEffectSpectrumAnalyzer::_bind_methods() {
AudioEffectSpectrumAnalyzer::AudioEffectSpectrumAnalyzer() {
buffer_length = 2;
tapback_pos = 0.01;
fft_size = FFT_SIZE_1024;
}

View File

@@ -54,7 +54,6 @@ private:
int fft_count;
int fft_pos;
float mix_rate;
uint64_t last_fft_time;
protected:
static void _bind_methods();
@@ -82,18 +81,21 @@ public:
public:
friend class AudioEffectSpectrumAnalyzerInstance;
float buffer_length;
float tapback_pos;
FFTSize fft_size;
protected:
static void _bind_methods();
#ifndef DISABLE_DEPRECATED
void _set_tap_back_pos_bind_compat_114355(float p_seconds);
float _get_tap_back_pos_bind_compat_114355();
static void _bind_compatibility_methods();
#endif
public:
Ref<AudioEffectInstance> instantiate() override;
void set_buffer_length(float p_seconds);
float get_buffer_length() const;
void set_tap_back_pos(float p_seconds);
float get_tap_back_pos() const;
void set_fft_size(FFTSize);
FFTSize get_fft_size() const;