Path: blob/master/scene/3d/audio_stream_player_3d.cpp
9905 views
/**************************************************************************/1/* audio_stream_player_3d.cpp */2/**************************************************************************/3/* This file is part of: */4/* GODOT ENGINE */5/* https://godotengine.org */6/**************************************************************************/7/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */8/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */9/* */10/* Permission is hereby granted, free of charge, to any person obtaining */11/* a copy of this software and associated documentation files (the */12/* "Software"), to deal in the Software without restriction, including */13/* without limitation the rights to use, copy, modify, merge, publish, */14/* distribute, sublicense, and/or sell copies of the Software, and to */15/* permit persons to whom the Software is furnished to do so, subject to */16/* the following conditions: */17/* */18/* The above copyright notice and this permission notice shall be */19/* included in all copies or substantial portions of the Software. */20/* */21/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */22/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */23/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */24/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */25/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */26/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */27/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */28/**************************************************************************/2930#include "audio_stream_player_3d.h"31#include "audio_stream_player_3d.compat.inc"3233#include "core/config/project_settings.h"34#include "scene/3d/audio_listener_3d.h"35#include "scene/3d/camera_3d.h"36#include "scene/3d/velocity_tracker_3d.h"37#include "scene/audio/audio_stream_player_internal.h"38#include "scene/main/viewport.h"39#include "servers/audio/audio_stream.h"4041#ifndef PHYSICS_3D_DISABLED42#include "scene/3d/physics/area_3d.h"43#endif // PHYSICS_3D_DISABLED4445// Based on "A Novel Multichannel Panning Method for Standard and Arbitrary Loudspeaker Configurations" by Ramy Sadek and Chris Kyriakakis (2004)46// Speaker-Placement Correction Amplitude Panning (SPCAP)47class Spcap {48private:49struct Speaker {50Vector3 direction;51real_t effective_number_of_speakers = 0; // precalculated52mutable real_t squared_gain = 0; // temporary53};5455Vector<Speaker> speakers;5657public:58Spcap(unsigned int speaker_count, const Vector3 *speaker_directions) {59speakers.resize(speaker_count);60Speaker *w = speakers.ptrw();61for (unsigned int speaker_num = 0; speaker_num < speaker_count; speaker_num++) {62w[speaker_num].direction = speaker_directions[speaker_num];63w[speaker_num].squared_gain = 0.0;64w[speaker_num].effective_number_of_speakers = 0.0;65}66for (unsigned int speaker_num = 0; speaker_num < speaker_count; speaker_num++) {67for (unsigned int other_speaker_num = 0; other_speaker_num < speaker_count; other_speaker_num++) {68w[speaker_num].effective_number_of_speakers += 0.5 * (1.0 + w[speaker_num].direction.dot(w[other_speaker_num].direction));69}70}71}7273unsigned int get_speaker_count() const {74return (unsigned int)speakers.size();75}7677Vector3 get_speaker_direction(unsigned int index) const {78return speakers.ptr()[index].direction;79}8081void calculate(const Vector3 &source_direction, real_t tightness, unsigned int volume_count, real_t *volumes) const {82const Speaker *r = speakers.ptr();83real_t sum_squared_gains = 0.0;84for (unsigned int speaker_num = 0; speaker_num < (unsigned int)speakers.size(); speaker_num++) {85real_t initial_gain = 0.5 * std::pow(1.0 + r[speaker_num].direction.dot(source_direction), tightness) / r[speaker_num].effective_number_of_speakers;86r[speaker_num].squared_gain = initial_gain * initial_gain;87sum_squared_gains += r[speaker_num].squared_gain;88}8990for (unsigned int speaker_num = 0; speaker_num < MIN(volume_count, (unsigned int)speakers.size()); speaker_num++) {91volumes[speaker_num] = std::sqrt(r[speaker_num].squared_gain / sum_squared_gains);92}93}94};9596//TODO: hardcoded main speaker directions for 2, 3.1, 5.1 and 7.1 setups - these are simplified and could also be made configurable97static const Vector3 speaker_directions[7] = {98Vector3(-1.0, 0.0, -1.0).normalized(), // front-left99Vector3(1.0, 0.0, -1.0).normalized(), // front-right100Vector3(0.0, 0.0, -1.0).normalized(), // center101Vector3(-1.0, 0.0, 1.0).normalized(), // rear-left102Vector3(1.0, 0.0, 1.0).normalized(), // rear-right103Vector3(-1.0, 0.0, 0.0).normalized(), // side-left104Vector3(1.0, 0.0, 0.0).normalized(), // side-right105};106107void AudioStreamPlayer3D::_calc_output_vol(const Vector3 &source_dir, real_t tightness, Vector<AudioFrame> &output) {108unsigned int speaker_count = 0; // only main speakers (no LFE)109switch (AudioServer::get_singleton()->get_speaker_mode()) {110case AudioServer::SPEAKER_MODE_STEREO:111speaker_count = 2;112break;113case AudioServer::SPEAKER_SURROUND_31:114speaker_count = 3;115break;116case AudioServer::SPEAKER_SURROUND_51:117speaker_count = 5;118break;119case AudioServer::SPEAKER_SURROUND_71:120speaker_count = 7;121break;122}123124Spcap spcap(speaker_count, speaker_directions); //TODO: should only be created/recreated once the speaker mode / speaker positions changes125real_t volumes[7];126spcap.calculate(source_dir, tightness, speaker_count, volumes);127128switch (AudioServer::get_singleton()->get_speaker_mode()) {129case AudioServer::SPEAKER_SURROUND_71:130output.write[3].left = volumes[5]; // side-left131output.write[3].right = volumes[6]; // side-right132[[fallthrough]];133case AudioServer::SPEAKER_SURROUND_51:134output.write[2].left = volumes[3]; // rear-left135output.write[2].right = volumes[4]; // rear-right136[[fallthrough]];137case AudioServer::SPEAKER_SURROUND_31:138output.write[1].right = 1.0; // LFE - always full power139output.write[1].left = volumes[2]; // center140[[fallthrough]];141case AudioServer::SPEAKER_MODE_STEREO:142output.write[0].right = volumes[1]; // front-right143output.write[0].left = volumes[0]; // front-left144break;145}146}147148// Set the volume to cosine of half horizontal the angle from the source to the left/right speaker direction ignoring elevation.149// Then scale `cosx` so that greatest ratio of the speaker volumes is `1-panning_strength`.150// See https://github.com/godotengine/godot/issues/103989 for evidence that this is the most standard implementation.151AudioFrame AudioStreamPlayer3D::_calc_output_vol_stereo(const Vector3 &source_dir, real_t panning_strength) {152double flatrad = sqrt(source_dir.x * source_dir.x + source_dir.z * source_dir.z);153double g = CLAMP((1.0 - panning_strength) * (1.0 - panning_strength), 0.0, 1.0);154double f = (1.0 - g) / (1.0 + g);155double cosx = CLAMP(source_dir.x / (flatrad == 0.0 ? 1.0 : flatrad), -1.0, 1.0);156double fcosx = cosx * f;157return AudioFrame(sqrt((-fcosx + 1.0) / 2.0), sqrt((fcosx + 1.0) / 2.0));158}159160#ifndef PHYSICS_3D_DISABLED161void AudioStreamPlayer3D::_calc_reverb_vol(Area3D *area, Vector3 listener_area_pos, Vector<AudioFrame> direct_path_vol, Vector<AudioFrame> &reverb_vol) {162reverb_vol.resize(4);163reverb_vol.write[0] = AudioFrame(0, 0);164reverb_vol.write[1] = AudioFrame(0, 0);165reverb_vol.write[2] = AudioFrame(0, 0);166reverb_vol.write[3] = AudioFrame(0, 0);167168float uniformity = area->get_reverb_uniformity();169float area_send = area->get_reverb_amount();170171if (uniformity > 0.0) {172float distance = listener_area_pos.length();173float attenuation = Math::db_to_linear(_get_attenuation_db(distance));174175// Determine the fraction of sound that would come from each speaker if they were all driven uniformly.176float center_val[3] = { 0.5f, 0.25f, 0.16666f };177int channel_count = AudioServer::get_singleton()->get_channel_count();178AudioFrame center_frame(center_val[channel_count - 1], center_val[channel_count - 1]);179180if (attenuation < 1.0) {181//pan the uniform sound182Vector3 rev_pos = listener_area_pos;183rev_pos.y = 0;184rev_pos.normalize();185186// Stereo pair.187float c = rev_pos.x * 0.5 + 0.5;188reverb_vol.write[0].left = 1.0 - c;189reverb_vol.write[0].right = c;190191if (channel_count >= 3) {192// Center pair + Side pair193float xl = Vector3(-1, 0, -1).normalized().dot(rev_pos) * 0.5 + 0.5;194float xr = Vector3(1, 0, -1).normalized().dot(rev_pos) * 0.5 + 0.5;195196reverb_vol.write[1].left = xl;197reverb_vol.write[1].right = xr;198reverb_vol.write[2].left = 1.0 - xr;199reverb_vol.write[2].right = 1.0 - xl;200}201202if (channel_count >= 4) {203// Rear pair204// FIXME: Not sure what math should be done here205reverb_vol.write[3].left = 1.0 - c;206reverb_vol.write[3].right = c;207}208209for (int i = 0; i < channel_count; i++) {210reverb_vol.write[i] = reverb_vol[i].lerp(center_frame, attenuation);211}212} else {213for (int i = 0; i < channel_count; i++) {214reverb_vol.write[i] = center_frame;215}216}217218for (int i = 0; i < channel_count; i++) {219reverb_vol.write[i] = direct_path_vol[i].lerp(reverb_vol[i] * attenuation, uniformity);220reverb_vol.write[i] *= area_send;221}222223} else {224for (int i = 0; i < 4; i++) {225reverb_vol.write[i] = direct_path_vol[i] * area_send;226}227}228}229#endif // PHYSICS_3D_DISABLED230231float AudioStreamPlayer3D::_get_attenuation_db(float p_distance) const {232float att = 0;233switch (attenuation_model) {234case ATTENUATION_INVERSE_DISTANCE: {235att = Math::linear_to_db(1.0 / ((p_distance / unit_size) + CMP_EPSILON));236} break;237case ATTENUATION_INVERSE_SQUARE_DISTANCE: {238float d = (p_distance / unit_size);239d *= d;240att = Math::linear_to_db(1.0 / (d + CMP_EPSILON));241} break;242case ATTENUATION_LOGARITHMIC: {243att = -20 * Math::log(p_distance / unit_size + CMP_EPSILON);244} break;245case ATTENUATION_DISABLED:246break;247default: {248ERR_PRINT("Unknown attenuation type");249break;250}251}252253att += internal->volume_db;254if (att > max_db) {255att = max_db;256}257258return att;259}260261void AudioStreamPlayer3D::_notification(int p_what) {262internal->notification(p_what);263switch (p_what) {264case NOTIFICATION_ENTER_TREE: {265velocity_tracker->reset(get_global_transform().origin);266AudioServer::get_singleton()->add_listener_changed_callback(_listener_changed_cb, this);267} break;268269case NOTIFICATION_EXIT_TREE: {270AudioServer::get_singleton()->remove_listener_changed_callback(_listener_changed_cb, this);271} break;272273case NOTIFICATION_TRANSFORM_CHANGED: {274if (doppler_tracking != DOPPLER_TRACKING_DISABLED) {275velocity_tracker->update_position(get_global_transform().origin);276}277} break;278279case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {280// Update anything related to position first, if possible of course.281Vector<AudioFrame> volume_vector;282if (setplay.get() > 0 || (internal->active.is_set() && last_mix_count != AudioServer::get_singleton()->get_mix_count()) || force_update_panning) {283force_update_panning = false;284volume_vector = _update_panning();285}286287if (setplayback.is_valid() && setplay.get() >= 0) {288internal->active.set();289HashMap<StringName, Vector<AudioFrame>> bus_map;290bus_map[_get_actual_bus()] = volume_vector;291AudioServer::get_singleton()->start_playback_stream(setplayback, bus_map, setplay.get(), actual_pitch_scale, linear_attenuation, attenuation_filter_cutoff_hz);292setplayback.unref();293setplay.set(-1);294}295296if (!internal->stream_playbacks.is_empty() && internal->active.is_set()) {297internal->process();298}299internal->ensure_playback_limit();300} break;301}302}303304#ifndef PHYSICS_3D_DISABLED305// Interacts with PhysicsServer3D, so can only be called during _physics_process306Area3D *AudioStreamPlayer3D::_get_overriding_area() {307//check if any area is diverting sound into a bus308Ref<World3D> world_3d = get_world_3d();309ERR_FAIL_COND_V(world_3d.is_null(), nullptr);310311Vector3 global_pos = get_global_transform().origin;312313PhysicsDirectSpaceState3D *space_state = PhysicsServer3D::get_singleton()->space_get_direct_state(world_3d->get_space());314315PhysicsDirectSpaceState3D::ShapeResult sr[MAX_INTERSECT_AREAS];316317PhysicsDirectSpaceState3D::PointParameters point_params;318point_params.position = global_pos;319point_params.collision_mask = area_mask;320point_params.collide_with_bodies = false;321point_params.collide_with_areas = true;322323int areas = space_state->intersect_point(point_params, sr, MAX_INTERSECT_AREAS);324325for (int i = 0; i < areas; i++) {326if (!sr[i].collider) {327continue;328}329330Area3D *tarea = Object::cast_to<Area3D>(sr[i].collider);331if (!tarea) {332continue;333}334335if (!tarea->is_overriding_audio_bus() && !tarea->is_using_reverb_bus()) {336continue;337}338339return tarea;340}341return nullptr;342}343#endif // PHYSICS_3D_DISABLED344345// Interacts with PhysicsServer3D, so can only be called during _physics_process.346StringName AudioStreamPlayer3D::_get_actual_bus() {347#ifndef PHYSICS_3D_DISABLED348Area3D *overriding_area = _get_overriding_area();349if (overriding_area && overriding_area->is_overriding_audio_bus() && !overriding_area->is_using_reverb_bus()) {350return overriding_area->get_audio_bus_name();351}352#endif // PHYSICS_3D_DISABLED353return internal->bus;354}355356// Interacts with PhysicsServer3D, so can only be called during _physics_process.357Vector<AudioFrame> AudioStreamPlayer3D::_update_panning() {358Vector<AudioFrame> output_volume_vector;359output_volume_vector.resize(4);360for (AudioFrame &frame : output_volume_vector) {361frame = AudioFrame(0, 0);362}363364if (!internal->active.is_set() || internal->stream.is_null()) {365return output_volume_vector;366}367368Vector3 linear_velocity;369370//compute linear velocity for doppler371if (doppler_tracking != DOPPLER_TRACKING_DISABLED) {372linear_velocity = velocity_tracker->get_tracked_linear_velocity();373}374375Vector3 global_pos = get_global_transform().origin;376377Ref<World3D> world_3d = get_world_3d();378ERR_FAIL_COND_V(world_3d.is_null(), output_volume_vector);379380HashSet<Camera3D *> cameras = world_3d->get_cameras();381cameras.insert(get_viewport()->get_camera_3d());382383#ifndef PHYSICS_3D_DISABLED384PhysicsDirectSpaceState3D *space_state = PhysicsServer3D::get_singleton()->space_get_direct_state(world_3d->get_space());385#endif // PHYSICS_3D_DISABLED386387for (Camera3D *camera : cameras) {388if (!camera) {389continue;390}391Viewport *vp = camera->get_viewport();392if (!vp) {393continue;394}395if (!vp->is_audio_listener_3d()) {396continue;397}398399Node3D *listener_node = camera;400401AudioListener3D *listener = vp->get_audio_listener_3d();402if (listener) {403listener_node = listener;404}405406Vector3 local_pos = listener_node->get_global_transform().orthonormalized().affine_inverse().xform(global_pos);407408float dist = local_pos.length();409410#ifndef PHYSICS_3D_DISABLED411Vector3 area_sound_pos;412Vector3 listener_area_pos;413414Area3D *area = _get_overriding_area();415if (area && area->is_using_reverb_bus() && area->get_reverb_uniformity() > 0) {416area_sound_pos = space_state->get_closest_point_to_object_volume(area->get_rid(), listener_node->get_global_transform().origin);417listener_area_pos = listener_node->get_global_transform().affine_inverse().xform(area_sound_pos);418}419#endif // PHYSICS_3D_DISABLED420421if (max_distance > 0) {422float total_max = max_distance;423424#ifndef PHYSICS_3D_DISABLED425if (area && area->is_using_reverb_bus() && area->get_reverb_uniformity() > 0) {426total_max = MAX(total_max, listener_area_pos.length());427}428#endif // PHYSICS_3D_DISABLED429if (dist > total_max || total_max > max_distance) {430if (!was_further_than_max_distance_last_frame) {431HashMap<StringName, Vector<AudioFrame>> bus_volumes;432for (Ref<AudioStreamPlayback> &playback : internal->stream_playbacks) {433// So the player gets muted and mostly stops mixing when out of range.434AudioServer::get_singleton()->set_playback_bus_volumes_linear(playback, bus_volumes);435}436was_further_than_max_distance_last_frame = true; // Cache so we don't set the volume over and over.437}438continue; //can't hear this sound in this listener439}440}441was_further_than_max_distance_last_frame = false;442443float multiplier = Math::db_to_linear(_get_attenuation_db(dist));444if (max_distance > 0) {445multiplier *= MAX(0, 1.0 - (dist / max_distance));446}447448float db_att = (1.0 - MIN(1.0, multiplier)) * attenuation_filter_db;449450if (emission_angle_enabled) {451Vector3 listenertopos = global_pos - listener_node->get_global_transform().origin;452float c = listenertopos.normalized().dot(get_global_transform().basis.get_column(2).normalized()); //it's z negative453float angle = Math::rad_to_deg(Math::acos(c));454if (angle > emission_angle) {455db_att -= -emission_angle_filter_attenuation_db;456}457}458459linear_attenuation = Math::db_to_linear(db_att);460for (Ref<AudioStreamPlayback> &playback : internal->stream_playbacks) {461AudioServer::get_singleton()->set_playback_highshelf_params(playback, linear_attenuation, attenuation_filter_cutoff_hz);462}463464if (AudioServer::get_singleton()->get_speaker_mode() == AudioServer::SPEAKER_MODE_STEREO) {465output_volume_vector.write[0] = _calc_output_vol_stereo(local_pos, cached_global_panning_strength * panning_strength);466output_volume_vector.write[1] = AudioFrame(0, 0);467output_volume_vector.write[2] = AudioFrame(0, 0);468output_volume_vector.write[3] = AudioFrame(0, 0);469} else {470// Bake in a constant factor here to allow the project setting defaults for 2d and 3d to be normalized to 1.0.471float tightness = cached_global_panning_strength * 2.0f;472tightness *= panning_strength;473_calc_output_vol(local_pos.normalized(), tightness, output_volume_vector);474}475476for (unsigned int k = 0; k < 4; k++) {477output_volume_vector.write[k] = multiplier * output_volume_vector[k];478}479480HashMap<StringName, Vector<AudioFrame>> bus_volumes;481#ifndef PHYSICS_3D_DISABLED482if (area) {483if (area->is_overriding_audio_bus()) {484//override audio bus485bus_volumes[area->get_audio_bus_name()] = output_volume_vector;486}487488if (area->is_using_reverb_bus()) {489StringName reverb_bus_name = area->get_reverb_bus_name();490Vector<AudioFrame> reverb_vol;491_calc_reverb_vol(area, listener_area_pos, output_volume_vector, reverb_vol);492bus_volumes[reverb_bus_name] = reverb_vol;493}494} else495#endif // PHYSICS_3D_DISABLED496{497bus_volumes[internal->bus] = output_volume_vector;498}499500for (Ref<AudioStreamPlayback> &playback : internal->stream_playbacks) {501AudioServer::get_singleton()->set_playback_bus_volumes_linear(playback, bus_volumes);502}503504if (doppler_tracking != DOPPLER_TRACKING_DISABLED) {505Vector3 listener_velocity;506507if (listener) {508listener_velocity = listener->get_doppler_tracked_velocity();509} else {510listener_velocity = camera->get_doppler_tracked_velocity();511}512513Vector3 local_velocity = listener_node->get_global_transform().orthonormalized().basis.xform_inv(linear_velocity - listener_velocity);514515if (local_velocity != Vector3()) {516float approaching = local_pos.normalized().dot(local_velocity.normalized());517float velocity = local_velocity.length();518float speed_of_sound = 343.0;519520float doppler_pitch_scale = internal->pitch_scale * speed_of_sound / (speed_of_sound + velocity * approaching);521doppler_pitch_scale = CLAMP(doppler_pitch_scale, (1 / 8.0), 8.0); //avoid crazy stuff522523actual_pitch_scale = doppler_pitch_scale;524} else {525actual_pitch_scale = internal->pitch_scale;526}527} else {528actual_pitch_scale = internal->pitch_scale;529}530for (Ref<AudioStreamPlayback> &playback : internal->stream_playbacks) {531AudioServer::get_singleton()->set_playback_pitch_scale(playback, actual_pitch_scale);532if (playback->get_is_sample()) {533Ref<AudioSamplePlayback> sample_playback = playback->get_sample_playback();534if (sample_playback.is_valid()) {535AudioServer::get_singleton()->update_sample_playback_pitch_scale(sample_playback, actual_pitch_scale);536}537}538}539}540return output_volume_vector;541}542543void AudioStreamPlayer3D::set_stream(Ref<AudioStream> p_stream) {544internal->set_stream(p_stream);545}546547Ref<AudioStream> AudioStreamPlayer3D::get_stream() const {548return internal->stream;549}550551void AudioStreamPlayer3D::set_volume_db(float p_volume) {552ERR_FAIL_COND_MSG(Math::is_nan(p_volume), "Volume can't be set to NaN.");553internal->volume_db = p_volume;554}555556float AudioStreamPlayer3D::get_volume_db() const {557return internal->volume_db;558}559560void AudioStreamPlayer3D::set_volume_linear(float p_volume) {561set_volume_db(Math::linear_to_db(p_volume));562}563564float AudioStreamPlayer3D::get_volume_linear() const {565return Math::db_to_linear(get_volume_db());566}567568void AudioStreamPlayer3D::set_unit_size(float p_volume) {569unit_size = p_volume;570update_gizmos();571}572573float AudioStreamPlayer3D::get_unit_size() const {574return unit_size;575}576577void AudioStreamPlayer3D::set_max_db(float p_boost) {578max_db = p_boost;579}580581float AudioStreamPlayer3D::get_max_db() const {582return max_db;583}584585void AudioStreamPlayer3D::set_pitch_scale(float p_pitch_scale) {586internal->set_pitch_scale(p_pitch_scale);587}588589float AudioStreamPlayer3D::get_pitch_scale() const {590return internal->pitch_scale;591}592593void AudioStreamPlayer3D::play(float p_from_pos) {594Ref<AudioStreamPlayback> stream_playback = internal->play_basic();595if (stream_playback.is_null()) {596return;597}598setplayback = stream_playback;599setplay.set(p_from_pos);600601// Sample handling.602if (stream_playback->get_is_sample() && stream_playback->get_sample_playback().is_valid()) {603Ref<AudioSamplePlayback> sample_playback = stream_playback->get_sample_playback();604sample_playback->offset = p_from_pos;605sample_playback->bus = _get_actual_bus();606607AudioServer::get_singleton()->start_sample_playback(sample_playback);608}609}610611void AudioStreamPlayer3D::seek(float p_seconds) {612internal->seek(p_seconds);613}614615void AudioStreamPlayer3D::stop() {616setplay.set(-1);617internal->stop_basic();618}619620bool AudioStreamPlayer3D::is_playing() const {621if (setplay.get() >= 0) {622return true; // play() has been called this frame, but no playback exists just yet.623}624return internal->is_playing();625}626627float AudioStreamPlayer3D::get_playback_position() {628if (setplay.get() >= 0) {629return setplay.get(); // play() has been called this frame, but no playback exists just yet.630}631return internal->get_playback_position();632}633634void AudioStreamPlayer3D::set_bus(const StringName &p_bus) {635internal->bus = p_bus; // This will be pushed to the audio server during the next physics timestep, which is fast enough.636}637638StringName AudioStreamPlayer3D::get_bus() const {639return internal->get_bus();640}641642void AudioStreamPlayer3D::set_autoplay(bool p_enable) {643internal->autoplay = p_enable;644}645646bool AudioStreamPlayer3D::is_autoplay_enabled() const {647return internal->autoplay;648}649650void AudioStreamPlayer3D::_set_playing(bool p_enable) {651internal->set_playing(p_enable);652}653654void AudioStreamPlayer3D::_validate_property(PropertyInfo &p_property) const {655internal->validate_property(p_property);656}657658void AudioStreamPlayer3D::set_max_distance(float p_metres) {659ERR_FAIL_COND(p_metres < 0.0);660max_distance = p_metres;661update_gizmos();662}663664float AudioStreamPlayer3D::get_max_distance() const {665return max_distance;666}667668void AudioStreamPlayer3D::set_area_mask(uint32_t p_mask) {669area_mask = p_mask;670}671672uint32_t AudioStreamPlayer3D::get_area_mask() const {673return area_mask;674}675676void AudioStreamPlayer3D::set_emission_angle_enabled(bool p_enable) {677emission_angle_enabled = p_enable;678update_gizmos();679}680681bool AudioStreamPlayer3D::is_emission_angle_enabled() const {682return emission_angle_enabled;683}684685void AudioStreamPlayer3D::set_emission_angle(float p_angle) {686ERR_FAIL_COND(p_angle < 0 || p_angle > 90);687emission_angle = p_angle;688update_gizmos();689}690691float AudioStreamPlayer3D::get_emission_angle() const {692return emission_angle;693}694695void AudioStreamPlayer3D::set_emission_angle_filter_attenuation_db(float p_angle_attenuation_db) {696emission_angle_filter_attenuation_db = p_angle_attenuation_db;697}698699float AudioStreamPlayer3D::get_emission_angle_filter_attenuation_db() const {700return emission_angle_filter_attenuation_db;701}702703void AudioStreamPlayer3D::set_attenuation_filter_cutoff_hz(float p_hz) {704attenuation_filter_cutoff_hz = p_hz;705}706707float AudioStreamPlayer3D::get_attenuation_filter_cutoff_hz() const {708return attenuation_filter_cutoff_hz;709}710711void AudioStreamPlayer3D::set_attenuation_filter_db(float p_db) {712attenuation_filter_db = p_db;713}714715float AudioStreamPlayer3D::get_attenuation_filter_db() const {716return attenuation_filter_db;717}718719void AudioStreamPlayer3D::set_attenuation_model(AttenuationModel p_model) {720ERR_FAIL_INDEX((int)p_model, 4);721attenuation_model = p_model;722update_gizmos();723}724725AudioStreamPlayer3D::AttenuationModel AudioStreamPlayer3D::get_attenuation_model() const {726return attenuation_model;727}728729void AudioStreamPlayer3D::set_doppler_tracking(DopplerTracking p_tracking) {730if (doppler_tracking == p_tracking) {731return;732}733734doppler_tracking = p_tracking;735736if (doppler_tracking != DOPPLER_TRACKING_DISABLED) {737set_notify_transform(true);738velocity_tracker->set_track_physics_step(doppler_tracking == DOPPLER_TRACKING_PHYSICS_STEP);739if (is_inside_tree()) {740velocity_tracker->reset(get_global_transform().origin);741}742} else {743set_notify_transform(false);744}745}746747AudioStreamPlayer3D::DopplerTracking AudioStreamPlayer3D::get_doppler_tracking() const {748return doppler_tracking;749}750751void AudioStreamPlayer3D::set_stream_paused(bool p_pause) {752internal->set_stream_paused(p_pause);753}754755bool AudioStreamPlayer3D::get_stream_paused() const {756return internal->get_stream_paused();757}758759bool AudioStreamPlayer3D::has_stream_playback() {760return internal->has_stream_playback();761}762763Ref<AudioStreamPlayback> AudioStreamPlayer3D::get_stream_playback() {764return internal->get_stream_playback();765}766767void AudioStreamPlayer3D::set_max_polyphony(int p_max_polyphony) {768internal->set_max_polyphony(p_max_polyphony);769}770771int AudioStreamPlayer3D::get_max_polyphony() const {772return internal->max_polyphony;773}774775void AudioStreamPlayer3D::set_panning_strength(float p_panning_strength) {776ERR_FAIL_COND_MSG(p_panning_strength < 0, "Panning strength must be a positive number.");777panning_strength = p_panning_strength;778}779780float AudioStreamPlayer3D::get_panning_strength() const {781return panning_strength;782}783784AudioServer::PlaybackType AudioStreamPlayer3D::get_playback_type() const {785return internal->get_playback_type();786}787788void AudioStreamPlayer3D::set_playback_type(AudioServer::PlaybackType p_playback_type) {789internal->set_playback_type(p_playback_type);790}791792bool AudioStreamPlayer3D::_set(const StringName &p_name, const Variant &p_value) {793return internal->set(p_name, p_value);794}795796bool AudioStreamPlayer3D::_get(const StringName &p_name, Variant &r_ret) const {797return internal->get(p_name, r_ret);798}799800void AudioStreamPlayer3D::_get_property_list(List<PropertyInfo> *p_list) const {801internal->get_property_list(p_list);802}803804void AudioStreamPlayer3D::_bind_methods() {805ClassDB::bind_method(D_METHOD("set_stream", "stream"), &AudioStreamPlayer3D::set_stream);806ClassDB::bind_method(D_METHOD("get_stream"), &AudioStreamPlayer3D::get_stream);807808ClassDB::bind_method(D_METHOD("set_volume_db", "volume_db"), &AudioStreamPlayer3D::set_volume_db);809ClassDB::bind_method(D_METHOD("get_volume_db"), &AudioStreamPlayer3D::get_volume_db);810811ClassDB::bind_method(D_METHOD("set_volume_linear", "volume_linear"), &AudioStreamPlayer3D::set_volume_linear);812ClassDB::bind_method(D_METHOD("get_volume_linear"), &AudioStreamPlayer3D::get_volume_linear);813814ClassDB::bind_method(D_METHOD("set_unit_size", "unit_size"), &AudioStreamPlayer3D::set_unit_size);815ClassDB::bind_method(D_METHOD("get_unit_size"), &AudioStreamPlayer3D::get_unit_size);816817ClassDB::bind_method(D_METHOD("set_max_db", "max_db"), &AudioStreamPlayer3D::set_max_db);818ClassDB::bind_method(D_METHOD("get_max_db"), &AudioStreamPlayer3D::get_max_db);819820ClassDB::bind_method(D_METHOD("set_pitch_scale", "pitch_scale"), &AudioStreamPlayer3D::set_pitch_scale);821ClassDB::bind_method(D_METHOD("get_pitch_scale"), &AudioStreamPlayer3D::get_pitch_scale);822823ClassDB::bind_method(D_METHOD("play", "from_position"), &AudioStreamPlayer3D::play, DEFVAL(0.0));824ClassDB::bind_method(D_METHOD("seek", "to_position"), &AudioStreamPlayer3D::seek);825ClassDB::bind_method(D_METHOD("stop"), &AudioStreamPlayer3D::stop);826827ClassDB::bind_method(D_METHOD("is_playing"), &AudioStreamPlayer3D::is_playing);828ClassDB::bind_method(D_METHOD("get_playback_position"), &AudioStreamPlayer3D::get_playback_position);829830ClassDB::bind_method(D_METHOD("set_bus", "bus"), &AudioStreamPlayer3D::set_bus);831ClassDB::bind_method(D_METHOD("get_bus"), &AudioStreamPlayer3D::get_bus);832833ClassDB::bind_method(D_METHOD("set_autoplay", "enable"), &AudioStreamPlayer3D::set_autoplay);834ClassDB::bind_method(D_METHOD("is_autoplay_enabled"), &AudioStreamPlayer3D::is_autoplay_enabled);835836ClassDB::bind_method(D_METHOD("set_playing", "enable"), &AudioStreamPlayer3D::_set_playing);837838ClassDB::bind_method(D_METHOD("set_max_distance", "meters"), &AudioStreamPlayer3D::set_max_distance);839ClassDB::bind_method(D_METHOD("get_max_distance"), &AudioStreamPlayer3D::get_max_distance);840841ClassDB::bind_method(D_METHOD("set_area_mask", "mask"), &AudioStreamPlayer3D::set_area_mask);842ClassDB::bind_method(D_METHOD("get_area_mask"), &AudioStreamPlayer3D::get_area_mask);843844ClassDB::bind_method(D_METHOD("set_emission_angle", "degrees"), &AudioStreamPlayer3D::set_emission_angle);845ClassDB::bind_method(D_METHOD("get_emission_angle"), &AudioStreamPlayer3D::get_emission_angle);846847ClassDB::bind_method(D_METHOD("set_emission_angle_enabled", "enabled"), &AudioStreamPlayer3D::set_emission_angle_enabled);848ClassDB::bind_method(D_METHOD("is_emission_angle_enabled"), &AudioStreamPlayer3D::is_emission_angle_enabled);849850ClassDB::bind_method(D_METHOD("set_emission_angle_filter_attenuation_db", "db"), &AudioStreamPlayer3D::set_emission_angle_filter_attenuation_db);851ClassDB::bind_method(D_METHOD("get_emission_angle_filter_attenuation_db"), &AudioStreamPlayer3D::get_emission_angle_filter_attenuation_db);852853ClassDB::bind_method(D_METHOD("set_attenuation_filter_cutoff_hz", "degrees"), &AudioStreamPlayer3D::set_attenuation_filter_cutoff_hz);854ClassDB::bind_method(D_METHOD("get_attenuation_filter_cutoff_hz"), &AudioStreamPlayer3D::get_attenuation_filter_cutoff_hz);855856ClassDB::bind_method(D_METHOD("set_attenuation_filter_db", "db"), &AudioStreamPlayer3D::set_attenuation_filter_db);857ClassDB::bind_method(D_METHOD("get_attenuation_filter_db"), &AudioStreamPlayer3D::get_attenuation_filter_db);858859ClassDB::bind_method(D_METHOD("set_attenuation_model", "model"), &AudioStreamPlayer3D::set_attenuation_model);860ClassDB::bind_method(D_METHOD("get_attenuation_model"), &AudioStreamPlayer3D::get_attenuation_model);861862ClassDB::bind_method(D_METHOD("set_doppler_tracking", "mode"), &AudioStreamPlayer3D::set_doppler_tracking);863ClassDB::bind_method(D_METHOD("get_doppler_tracking"), &AudioStreamPlayer3D::get_doppler_tracking);864865ClassDB::bind_method(D_METHOD("set_stream_paused", "pause"), &AudioStreamPlayer3D::set_stream_paused);866ClassDB::bind_method(D_METHOD("get_stream_paused"), &AudioStreamPlayer3D::get_stream_paused);867868ClassDB::bind_method(D_METHOD("set_max_polyphony", "max_polyphony"), &AudioStreamPlayer3D::set_max_polyphony);869ClassDB::bind_method(D_METHOD("get_max_polyphony"), &AudioStreamPlayer3D::get_max_polyphony);870871ClassDB::bind_method(D_METHOD("set_panning_strength", "panning_strength"), &AudioStreamPlayer3D::set_panning_strength);872ClassDB::bind_method(D_METHOD("get_panning_strength"), &AudioStreamPlayer3D::get_panning_strength);873874ClassDB::bind_method(D_METHOD("has_stream_playback"), &AudioStreamPlayer3D::has_stream_playback);875ClassDB::bind_method(D_METHOD("get_stream_playback"), &AudioStreamPlayer3D::get_stream_playback);876877ClassDB::bind_method(D_METHOD("set_playback_type", "playback_type"), &AudioStreamPlayer3D::set_playback_type);878ClassDB::bind_method(D_METHOD("get_playback_type"), &AudioStreamPlayer3D::get_playback_type);879880ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "stream", PROPERTY_HINT_RESOURCE_TYPE, "AudioStream"), "set_stream", "get_stream");881ADD_PROPERTY(PropertyInfo(Variant::INT, "attenuation_model", PROPERTY_HINT_ENUM, "Inverse,Inverse Square,Logarithmic,Disabled"), "set_attenuation_model", "get_attenuation_model");882ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volume_db", PROPERTY_HINT_RANGE, "-80,80,suffix:dB"), "set_volume_db", "get_volume_db");883ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volume_linear", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_volume_linear", "get_volume_linear");884ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "unit_size", PROPERTY_HINT_RANGE, "0.1,100,0.01,or_greater"), "set_unit_size", "get_unit_size");885ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_db", PROPERTY_HINT_RANGE, "-24,6,suffix:dB"), "set_max_db", "get_max_db");886ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pitch_scale", PROPERTY_HINT_RANGE, "0.01,4,0.01,or_greater"), "set_pitch_scale", "get_pitch_scale");887ADD_PROPERTY(PropertyInfo(Variant::BOOL, "playing", PROPERTY_HINT_ONESHOT, "", PROPERTY_USAGE_EDITOR), "set_playing", "is_playing");888ADD_PROPERTY(PropertyInfo(Variant::BOOL, "autoplay"), "set_autoplay", "is_autoplay_enabled");889ADD_PROPERTY(PropertyInfo(Variant::BOOL, "stream_paused", PROPERTY_HINT_NONE, ""), "set_stream_paused", "get_stream_paused");890ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_distance", PROPERTY_HINT_RANGE, "0,4096,0.01,or_greater,suffix:m"), "set_max_distance", "get_max_distance");891ADD_PROPERTY(PropertyInfo(Variant::INT, "max_polyphony", PROPERTY_HINT_NONE, ""), "set_max_polyphony", "get_max_polyphony");892ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "panning_strength", PROPERTY_HINT_RANGE, "0,3,0.01,or_greater"), "set_panning_strength", "get_panning_strength");893ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "bus", PROPERTY_HINT_ENUM, ""), "set_bus", "get_bus");894ADD_PROPERTY(PropertyInfo(Variant::INT, "area_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_area_mask", "get_area_mask");895ADD_PROPERTY(PropertyInfo(Variant::INT, "playback_type", PROPERTY_HINT_ENUM, "Default,Stream,Sample"), "set_playback_type", "get_playback_type");896ADD_GROUP("Emission Angle", "emission_angle");897ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emission_angle_enabled"), "set_emission_angle_enabled", "is_emission_angle_enabled");898ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_angle_degrees", PROPERTY_HINT_RANGE, "0.1,90,0.1,degrees"), "set_emission_angle", "get_emission_angle");899ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_angle_filter_attenuation_db", PROPERTY_HINT_RANGE, "-80,0,0.1,suffix:dB"), "set_emission_angle_filter_attenuation_db", "get_emission_angle_filter_attenuation_db");900ADD_GROUP("Attenuation Filter", "attenuation_filter_");901ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "attenuation_filter_cutoff_hz", PROPERTY_HINT_RANGE, "1,20500,1,suffix:Hz"), "set_attenuation_filter_cutoff_hz", "get_attenuation_filter_cutoff_hz");902ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "attenuation_filter_db", PROPERTY_HINT_RANGE, "-80,0,0.1,suffix:dB"), "set_attenuation_filter_db", "get_attenuation_filter_db");903ADD_GROUP("Doppler", "doppler_");904ADD_PROPERTY(PropertyInfo(Variant::INT, "doppler_tracking", PROPERTY_HINT_ENUM, "Disabled,Idle,Physics"), "set_doppler_tracking", "get_doppler_tracking");905906BIND_ENUM_CONSTANT(ATTENUATION_INVERSE_DISTANCE);907BIND_ENUM_CONSTANT(ATTENUATION_INVERSE_SQUARE_DISTANCE);908BIND_ENUM_CONSTANT(ATTENUATION_LOGARITHMIC);909BIND_ENUM_CONSTANT(ATTENUATION_DISABLED);910911BIND_ENUM_CONSTANT(DOPPLER_TRACKING_DISABLED);912BIND_ENUM_CONSTANT(DOPPLER_TRACKING_IDLE_STEP);913BIND_ENUM_CONSTANT(DOPPLER_TRACKING_PHYSICS_STEP);914915ADD_SIGNAL(MethodInfo("finished"));916}917918AudioStreamPlayer3D::AudioStreamPlayer3D() {919internal = memnew(AudioStreamPlayerInternal(this, callable_mp(this, &AudioStreamPlayer3D::play), callable_mp(this, &AudioStreamPlayer3D::stop), true));920velocity_tracker.instantiate();921set_disable_scale(true);922cached_global_panning_strength = GLOBAL_GET_CACHED(float, "audio/general/3d_panning_strength");923}924925AudioStreamPlayer3D::~AudioStreamPlayer3D() {926memdelete(internal);927}928929930