Skip to content

Commit

Permalink
Add resonance audio
Browse files Browse the repository at this point in the history
* Add Eigen, pffft and resonance audio to thirdparty/
* Audio works in the editor.
* Default resonance audio on.
* Resolve ResonanceAudioBus leak warning.

Co-authored-by: Ellen Poe <[email protected]>
Co-authored-by: K. S. Ernest (iFire) Lee <[email protected]>
Add resonance audio

* Add Eigen, pffft and resonance audio to thirdparty/
* Audio works in the editor.
* Default resonance audio on.
* Resolve ResonanceAudioBus leak warning.

Co-authored-by: Ellen Poe <[email protected]>
Co-authored-by: K. S. Ernest (iFire) Lee <[email protected]>
  • Loading branch information
fire and ellenhp committed Sep 15, 2023
1 parent 5f1e56f commit bd2810f
Show file tree
Hide file tree
Showing 608 changed files with 174,750 additions and 37 deletions.
8 changes: 8 additions & 0 deletions SConstruct
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,8 @@ opts.Add(BoolVariable("use_precise_math_checks", "Math checks use very precise e
opts.Add(BoolVariable("scu_build", "Use single compilation unit build", False))
opts.Add("scu_limit", "Max includes per SCU file when using scu_build (determines RAM use)", "0")

opts.Add(BoolVariable("use_resonance_audio", "Use the audio spatializer.", True))

# Thirdparty libraries
opts.Add(BoolVariable("builtin_brotli", "Use the built-in Brotli library", True))
opts.Add(BoolVariable("builtin_certs", "Use the built-in SSL certificates bundles", True))
Expand Down Expand Up @@ -429,6 +431,12 @@ if env_base.debug_features:
# to give *users* extra debugging information for their game development.
env_base.Append(CPPDEFINES=["DEBUG_ENABLED"])

# ensure that anything depending on eigen will only be linked with permissively licensed code.
env_base.Append(CPPDEFINES=["EIGEN_MPL2_ONLY"])

if env_base["use_precise_math_checks"]:
env_base.Append(CPPDEFINES=["PRECISE_MATH_CHECKS"])

if env_base.dev_build:
# DEV_ENABLED enables *engine developer* code which should only be compiled for those
# working on the engine itself.
Expand Down
5 changes: 4 additions & 1 deletion core/math/audio_frame.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,10 @@ struct AudioFrame {
l = p_v2.x;
r = p_v2.y;
}
_ALWAYS_INLINE_ AudioFrame() {}
_ALWAYS_INLINE_ AudioFrame() {
l = 0.0f;
r = 0.0f;
}
};

_ALWAYS_INLINE_ AudioFrame operator*(float p_scalar, const AudioFrame &p_frame) {
Expand Down
3 changes: 3 additions & 0 deletions doc/classes/ProjectSettings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,9 @@
<member name="audio/driver/output_latency.web" type="int" setter="" getter="" default="50">
Safer override for [member audio/driver/output_latency] in the Web platform, to avoid audio issues especially on mobile devices.
</member>
<member name="audio/enable_resonance_audio" type="bool" setter="" getter="" default="true">
Use spatialized audio for a more immersive playback.
</member>
<member name="audio/general/2d_panning_strength" type="float" setter="" getter="" default="0.5">
The base strength of the panning effect for all [AudioStreamPlayer2D] nodes. The panning strength can be further scaled on each Node using [member AudioStreamPlayer2D.panning_strength]. A value of [code]0.0[/code] disables stereo panning entirely, leaving only volume attenuation in place. A value of [code]1.0[/code] completely mutes one of the channels if the sound is located exactly to the left (or right) of the listener.
The default value of [code]0.5[/code] is tuned for headphones. When using speakers, you may find lower values to sound better as speakers have a lower stereo separation compared to headphones.
Expand Down
9 changes: 9 additions & 0 deletions main/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
#include "core/io/file_access_zip.h"
#include "core/io/image_loader.h"
#include "core/io/ip.h"
#include "core/io/resource.h"
#include "core/io/resource_loader.h"
#include "core/object/message_queue.h"
#include "core/os/os.h"
Expand Down Expand Up @@ -76,6 +77,7 @@
#include "servers/physics_server_3d.h"
#include "servers/register_server_types.h"
#include "servers/rendering/rendering_server_default.h"
#include "servers/resonanceaudio/resonance_audio_wrapper.h"
#include "servers/text/text_server_dummy.h"
#include "servers/text_server.h"
#include "servers/xr_server.h"
Expand Down Expand Up @@ -136,6 +138,7 @@ static MessageQueue *message_queue = nullptr;

// Initialized in setup2()
static AudioServer *audio_server = nullptr;
static ResonanceAudioServer *resonance_audio_server = nullptr;
static DisplayServer *display_server = nullptr;
static RenderingServer *rendering_server = nullptr;
static CameraServer *camera_server = nullptr;
Expand Down Expand Up @@ -2376,6 +2379,8 @@ Error Main::setup2() {
audio_server = memnew(AudioServer);
audio_server->init();

resonance_audio_server = memnew(ResonanceAudioServer);

// also init our xr_server from here
xr_server = memnew(XRServer);

Expand Down Expand Up @@ -3701,6 +3706,10 @@ void Main::cleanup(bool p_force) {
memdelete(audio_server);
}

if (resonance_audio_server) {
memdelete(resonance_audio_server);
}

if (camera_server) {
memdelete(camera_server);
}
Expand Down
3 changes: 2 additions & 1 deletion scene/2d/audio_stream_player_2d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include "scene/2d/audio_listener_2d.h"
#include "scene/main/window.h"
#include "scene/resources/world_2d.h"
#include "servers/resonanceaudio/resonance_audio_wrapper.h"

void AudioStreamPlayer2D::_notification(int p_what) {
switch (p_what) {
Expand Down Expand Up @@ -212,7 +213,7 @@ void AudioStreamPlayer2D::_update_panning() {
}

for (const Ref<AudioStreamPlayback> &playback : stream_playbacks) {
AudioServer::get_singleton()->set_playback_bus_exclusive(playback, _get_actual_bus(), volume_vector);
AudioServer::get_singleton()->set_playback_bus_exclusive(playback, _get_actual_bus(), volume_vector, AudioSourceId(-1));
}

for (Ref<AudioStreamPlayback> &playback : stream_playbacks) {
Expand Down
36 changes: 30 additions & 6 deletions scene/3d/audio_stream_player_3d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@
#include "scene/3d/camera_3d.h"
#include "scene/main/viewport.h"
#include "scene/scene_string_names.h"
#include "servers/resonanceaudio/resonance_audio_wrapper.h"

#include "core/config/project_settings.h"

// Based on "A Novel Multichannel Panning Method for Standard and Arbitrary Loudspeaker Configurations" by Ramy Sadek and Chris Kyriakakis (2004)
// Speaker-Placement Correction Amplitude Panning (SPCAP)
Expand Down Expand Up @@ -240,17 +243,22 @@ float AudioStreamPlayer3D::_get_attenuation_db(float p_distance) const {
void AudioStreamPlayer3D::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
if (GLOBAL_GET("audio/enable_resonance_audio")) {
audio_source_id = ResonanceAudioServer::get_singleton()->register_audio_source();
}
velocity_tracker->reset(get_global_transform().origin);
AudioServer::get_singleton()->add_listener_changed_callback(_listener_changed_cb, this);
if (autoplay && !Engine::get_singleton()->is_editor_hint()) {
play();
}
set_stream_paused(false);
} break;

case NOTIFICATION_EXIT_TREE: {
set_stream_paused(true);
AudioServer::get_singleton()->remove_listener_changed_callback(_listener_changed_cb, this);
if (GLOBAL_GET("audio/enable_resonance_audio")) {
ResonanceAudioServer::get_singleton()->unregister_audio_source(audio_source_id);
}
} break;

case NOTIFICATION_PREDELETE: {
Expand All @@ -273,9 +281,12 @@ void AudioStreamPlayer3D::_notification(int p_what) {
velocity_tracker->update_position(get_global_transform().origin);
}
} break;

case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
// Update anything related to position first, if possible of course.
if (GLOBAL_GET("audio/enable_resonance_audio")) {
ResonanceAudioServer::get_singleton()->set_source_transform(audio_source_id, get_global_transform());
}
//update anything related to position first, if possible of course
Vector<AudioFrame> volume_vector;
if (setplay.get() > 0 || (active.is_set() && last_mix_count != AudioServer::get_singleton()->get_mix_count()) || force_update_panning) {
force_update_panning = false;
Expand All @@ -287,10 +298,15 @@ void AudioStreamPlayer3D::_notification(int p_what) {
HashMap<StringName, Vector<AudioFrame>> bus_map;
bus_map[_get_actual_bus()] = volume_vector;
AudioServer::get_singleton()->start_playback_stream(setplayback, bus_map, setplay.get(), actual_pitch_scale, linear_attenuation, attenuation_filter_cutoff_hz);
if (GLOBAL_GET("audio/enable_resonance_audio")) {
AudioServer::get_singleton()->start_playback_stream(setplayback, bus_map, setplay.get(), actual_pitch_scale, linear_attenuation, attenuation_filter_cutoff_hz, audio_source_id);
} else {
AudioServer::get_singleton()->start_playback_stream(setplayback, bus_map, setplay.get(), actual_pitch_scale, linear_attenuation, attenuation_filter_cutoff_hz);
}
stream_playbacks.push_back(setplayback);
setplayback.unref();
setplay.set(-1);
}

if (!stream_playbacks.is_empty() && active.is_set()) {
// Stop playing if no longer active.
Vector<Ref<AudioStreamPlayback>> playbacks_to_remove;
Expand All @@ -312,7 +328,6 @@ void AudioStreamPlayer3D::_notification(int p_what) {
emit_signal(SNAME("finished"));
}
}

while (stream_playbacks.size() > max_polyphony) {
AudioServer::get_singleton()->stop_playback_stream(stream_playbacks[0]);
stream_playbacks.remove_at(0);
Expand Down Expand Up @@ -428,6 +443,10 @@ Vector<AudioFrame> AudioStreamPlayer3D::_update_panning() {

Area3D *area = _get_overriding_area();

//TODO: The lower the second parameter (tightness) the more the sound will "enclose" the listener (more undirected / playing from
// speakers not facing the source) - this could be made distance dependent.
_calc_output_vol(local_pos.normalized(), 4.0, output_volume_vector);

if (area && area->is_using_reverb_bus() && area->get_reverb_uniformity() > 0) {
area_sound_pos = space_state->get_closest_point_to_object_volume(area->get_rid(), listener_node->get_global_transform().origin);
listener_area_pos = listener_node->get_global_transform().affine_inverse().xform(area_sound_pos);
Expand Down Expand Up @@ -462,7 +481,12 @@ Vector<AudioFrame> AudioStreamPlayer3D::_update_panning() {

linear_attenuation = Math::db_to_linear(db_att);
for (Ref<AudioStreamPlayback> &playback : stream_playbacks) {
AudioServer::get_singleton()->set_playback_highshelf_params(playback, linear_attenuation, attenuation_filter_cutoff_hz);
if (GLOBAL_GET("audio/enable_resonance_audio")) {
ResonanceAudioServer::get_singleton()->set_source_attenuation(audio_source_id, linear_attenuation);
AudioServer::get_singleton()->set_playback_highshelf_params(playback, linear_attenuation, attenuation_filter_cutoff_hz, audio_source_id);
} else {
AudioServer::get_singleton()->set_playback_highshelf_params(playback, linear_attenuation, attenuation_filter_cutoff_hz, AudioSourceId(-1));
}
}
// Bake in a constant factor here to allow the project setting defaults for 2d and 3d to be normalized to 1.0.
float tightness = cached_global_panning_strength * 2.0f;
Expand Down Expand Up @@ -491,7 +515,7 @@ Vector<AudioFrame> AudioStreamPlayer3D::_update_panning() {
}

for (Ref<AudioStreamPlayback> &playback : stream_playbacks) {
AudioServer::get_singleton()->set_playback_bus_volumes_linear(playback, bus_volumes);
AudioServer::get_singleton()->set_playback_bus_volumes_linear(playback, bus_volumes, AudioSourceId(-1));
}

if (doppler_tracking != DOPPLER_TRACKING_DISABLED) {
Expand Down
4 changes: 4 additions & 0 deletions scene/3d/audio_stream_player_3d.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,14 @@
#define AUDIO_STREAM_PLAYER_3D_H

#include "core/os/mutex.h"
#include "core/templates/safe_refcount.h"
#include "scene/3d/area_3d.h"
#include "scene/3d/node_3d.h"
#include "scene/3d/velocity_tracker_3d.h"
#include "servers/audio/audio_filter_sw.h"
#include "servers/audio/audio_stream.h"
#include "servers/audio_server.h"
#include "servers/resonanceaudio/resonance_audio_wrapper.h"

class Camera3D;
class AudioStreamPlayer3D : public Node3D {
Expand Down Expand Up @@ -120,6 +122,8 @@ class AudioStreamPlayer3D : public Node3D {
float panning_strength = 1.0f;
float cached_global_panning_strength = 0.5f;

AudioSourceId audio_source_id;

protected:
void _validate_property(PropertyInfo &p_property) const;
void _notification(int p_what);
Expand Down
8 changes: 7 additions & 1 deletion scene/3d/camera_3d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,11 @@
#include "camera_3d.h"

#include "collision_object_3d.h"
#include "core/config/project_settings.h"
#include "core/math/projection.h"
#include "scene/main/viewport.h"
#include "servers/audio_server.h"
#include "servers/resonanceaudio/resonance_audio_wrapper.h"

void Camera3D::_update_audio_listener_state() {
}
Expand Down Expand Up @@ -120,6 +123,10 @@ void Camera3D::_notification(int p_what) {
} break;

case NOTIFICATION_TRANSFORM_CHANGED: {
if (viewport->is_audio_listener_3d() && GLOBAL_GET("audio/enable_resonance_audio")) {
ResonanceAudioServer::get_singleton()->set_head_transform(get_global_transform());
}

_request_camera_update();
if (doppler_tracking != DOPPLER_TRACKING_DISABLED) {
velocity_tracker->update_position(get_global_transform().origin);
Expand Down Expand Up @@ -708,7 +715,6 @@ RID Camera3D::get_pyramid_shape_rid() {
pyramid_shape_points = get_near_plane_points();
pyramid_shape = PhysicsServer3D::get_singleton()->convex_polygon_shape_create();
PhysicsServer3D::get_singleton()->shape_set_data(pyramid_shape, pyramid_shape_points);

} else { //check if points changed
Vector<Vector3> local_points = get_near_plane_points();

Expand Down
5 changes: 3 additions & 2 deletions scene/audio/audio_stream_player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include "core/config/engine.h"
#include "core/math/audio_frame.h"
#include "servers/audio_server.h"
#include "servers/resonanceaudio/resonance_audio_wrapper.h"

void AudioStreamPlayer::_notification(int p_what) {
switch (p_what) {
Expand Down Expand Up @@ -102,7 +103,7 @@ void AudioStreamPlayer::set_volume_db(float p_volume) {

Vector<AudioFrame> volume_vector = _get_volume_vector();
for (Ref<AudioStreamPlayback> &playback : stream_playbacks) {
AudioServer::get_singleton()->set_playback_all_bus_volumes_linear(playback, volume_vector);
AudioServer::get_singleton()->set_playback_all_bus_volumes_linear(playback, volume_vector, AudioSourceId(-1));
}
}

Expand Down Expand Up @@ -190,7 +191,7 @@ float AudioStreamPlayer::get_playback_position() {
void AudioStreamPlayer::set_bus(const StringName &p_bus) {
bus = p_bus;
for (const Ref<AudioStreamPlayback> &playback : stream_playbacks) {
AudioServer::get_singleton()->set_playback_bus_exclusive(playback, p_bus, _get_volume_vector());
AudioServer::get_singleton()->set_playback_bus_exclusive(playback, p_bus, _get_volume_vector(), AudioSourceId(-1));
}
}

Expand Down
1 change: 1 addition & 0 deletions servers/SCsub
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ SConscript("physics_3d/SCsub")
SConscript("physics_2d/SCsub")
SConscript("rendering/SCsub")
SConscript("audio/SCsub")
SConscript("resonanceaudio/SCsub")
SConscript("text/SCsub")
SConscript("debugger/SCsub")
SConscript("extensions/SCsub")
Expand Down
Loading

0 comments on commit bd2810f

Please sign in to comment.