Open
Description
Hi, I've been having a crash I can't figure out how to debug. I'm trying to use the base classes to implement a custom audio effect, and everything compiles and links until I try to add this empty effect to the audio bus. The following happens:
ERROR: Required virtual method CustomAudioEffect::_instantiate must be overridden before calling.
at: _gdvirtual__instantiate_call (servers/audio/audio_effect.h:57)
================================================================
handle_crash: Program crashed with signal 11
Engine version: Godot Engine v4.0.1.stable.flathub (cacf49999e3fb37281d66cc591ca8bebc5712d4d)
Dumping the backtrace. Please include this when reporting the bug to the project developer.
ERROR: FATAL: Index p_index = 1 is out of bounds (size() = 0).
at: get (./core/templates/cowdata.h:155)
================================================================
handle_crash: Program crashed with signal 4
Engine version: Godot Engine v4.0.1.stable.flathub (cacf49999e3fb37281d66cc591ca8bebc5712d4d)
Dumping the backtrace. Please include this when reporting the bug to the project developer.
ERROR: FATAL: Index p_index = 1 is out of bounds (size() = 0).
at: get (./core/templates/cowdata.h:155)
I don't really know why Godot thinks CustomAudioEffect::_instantiate() needs to be overriden since it's a non-virtual override of AudioEffect, and I don't have any code that handles arrays (presumably the out-of-bound errors are in some internal stuff).
Here's the code (sorry, this is the shortest I could get it to be):
// custom_effect.hpp
#ifndef CUSTOM_EFFECT_HPP
#define CUSTOM_EFFECT_HPP
#include <godot_cpp/classes/audio_effect.hpp>
#include <godot_cpp/classes/audio_effect_instance.hpp>
#include <godot_cpp/classes/audio_frame.hpp>
using namespace godot;
class CustomAudioEffect;
class CustomAudioEffectInstance : public AudioEffectInstance {
GDCLASS(CustomAudioEffectInstance, AudioEffectInstance)
friend class CustomAudioEffect;
Ref<CustomAudioEffect> base;
protected:
static void _bind_methods();
public:
void _process(const void *src_buffer, AudioFrame *dst_buffer, int32_t frame_count) override;
bool _process_silence() const override;
};
class CustomAudioEffect : public AudioEffect {
GDCLASS(CustomAudioEffect, AudioEffect)
friend class CustomAudioEffectInstance;
protected:
static void _bind_methods();
public:
Ref<AudioEffectInstance> _instantiate() override;
CustomAudioEffect();
};
#endif
// -----------------
// custom_effect.cpp
#include "custom_effect.hpp"
void CustomAudioEffectInstance::_process(const void *src_buffer, AudioFrame *dst_buffer, int32_t frame_count) {
}
bool CustomAudioEffectInstance::_process_silence() const {
return false;
}
void CustomAudioEffectInstance::_bind_methods() {
}
void CustomAudioEffect::_bind_methods() {
}
Ref<AudioEffectInstance> CustomAudioEffect::_instantiate() {
Ref<CustomAudioEffectInstance> ins;
ins.instantiate();
ins->base = Ref<CustomAudioEffect>(this);
return ins;
}
CustomAudioEffect::CustomAudioEffect() {
}
// ------------
// register_types.hpp
#ifndef GDEXAMPLE_REGISTER_TYPES_H
#define GDEXAMPLE_REGISTER_TYPES_H
void init_fs_exts();
void uninit_fs_exts();
#endif // GDEXAMPLE_REGISTER_TYPES_H
// ------------
// register_types.cpp
#include "register_types.hpp"
#include "custom_effect.hpp"
#include <gdextension_interface.h>
#include <godot_cpp/core/class_db.hpp>
#include <godot_cpp/core/defs.hpp>
#include <godot_cpp/godot.hpp>
using namespace godot;
void init_fs_exts(ModuleInitializationLevel p_level) {
if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) {
return;
}
ClassDB::register_class<CustomAudioEffect>();
}
void uninit_fs_exts(ModuleInitializationLevel p_level) {
if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) {
return;
}
}
extern "C" {
// Initialization.
GDExtensionBool GDE_EXPORT lib_init(const GDExtensionInterface *p_interface, const GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization) {
godot::GDExtensionBinding::InitObject init_obj(p_interface, p_library, r_initialization);
init_obj.register_initializer(init_fs_exts);
init_obj.register_terminator(uninit_fs_exts);
init_obj.set_minimum_library_initialization_level(MODULE_INITIALIZATION_LEVEL_SCENE);
return init_obj.init();
}
}