godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
89.1k stars 20.2k forks source link

`Area3D`'s reverb bus makes `AudioStreamPlayer3D` not output to its own bus. #96480

Open AinaVT opened 2 weeks ago

AinaVT commented 2 weeks ago

Tested versions

System information

Godot v4.4.dev (88197d4a5) - Windows 10.0.22631 - Vulkan (Forward+) - dedicated NVIDIA GeForce RTX 4060 (NVIDIA; 31.0.15.4617) - AMD Ryzen 5 3600 6-Core Processor (12 Threads)

Issue description

When an AudioStreamPlayer3D is inside an Area3D that has its reverb bus enabled, the correct amount of the audio is sent to the bus set as the reverb bus, but the player stops sending any signal to its own bus.

Example: If we have a single AudioStreamPlayer3D in a scene set to the "Dry" bus, and it's inside an Area3D that has its reverb bus set to the "Wet" bus, the "Dry" bus will become silent.

image Silent "Dry" bus when inside Area3D with "Wet" reverb bus.

https://github.com/user-attachments/assets/1ec0a6f2-b101-4927-b1da-12283e6ed927

From what I understand, according to these docs, this was meant to still send the signal to the player's bus with the purpose of it being the "dry" signal and the reverb bus being the "wet" signal. If i misunderstood this and what i described in this issue is the expected behavior, feel free to close the issue.

Steps to reproduce

Minimal reproduction project (MRP)

area3d_reverb.zip

AinaVT commented 2 weeks ago

Assuming this is an actual issue, and isn't the expected behavior... Seems to happen inside AudioStreamPlayer3D::_update_panning(), at line 438:

HashMap<StringName, Vector<AudioFrame>> bus_volumes;
if (area) {
    if (area->is_overriding_audio_bus()) {
        //override audio bus
        bus_volumes[area->get_audio_bus_name()] = output_volume_vector;
    }

    if (area->is_using_reverb_bus()) {
        StringName reverb_bus_name = area->get_reverb_bus_name();
        Vector<AudioFrame> reverb_vol;
        _calc_reverb_vol(area, listener_area_pos, output_volume_vector, reverb_vol);
        bus_volumes[reverb_bus_name] = reverb_vol;
    }
} else {
    bus_volumes[internal->bus] = output_volume_vector;
}

If there is an area present, the bus_volumes[internal->bus], which is the AudioStreamPlayer3D's set bus, is never set. Tested it by changing it to this and it seemed to do the behavior I was initially expecting:

HashMap<StringName, Vector<AudioFrame>> bus_volumes;
if (area) {
    if (area->is_overriding_audio_bus()) {
        //override audio bus
        bus_volumes[area->get_audio_bus_name()] = output_volume_vector;
    } else {
        bus_volumes[internal->bus] = output_volume_vector; // <--- Sets the volume for the player's bus in case there's no override.
    }

    if (area->is_using_reverb_bus()) {
        StringName reverb_bus_name = area->get_reverb_bus_name();
        Vector<AudioFrame> reverb_vol;
        _calc_reverb_vol(area, listener_area_pos, output_volume_vector, reverb_vol);
        bus_volumes[reverb_bus_name] = reverb_vol;
    }
} else {
    bus_volumes[internal->bus] = output_volume_vector;
}