|
@@ -63,6 +63,8 @@ public:
|
|
w[speaker_num].direction = speaker_directions[speaker_num];
|
|
w[speaker_num].direction = speaker_directions[speaker_num];
|
|
w[speaker_num].squared_gain = 0.0;
|
|
w[speaker_num].squared_gain = 0.0;
|
|
w[speaker_num].effective_number_of_speakers = 0.0;
|
|
w[speaker_num].effective_number_of_speakers = 0.0;
|
|
|
|
+ }
|
|
|
|
+ for (unsigned int speaker_num = 0; speaker_num < speaker_count; speaker_num++) {
|
|
for (unsigned int other_speaker_num = 0; other_speaker_num < speaker_count; other_speaker_num++) {
|
|
for (unsigned int other_speaker_num = 0; other_speaker_num < speaker_count; other_speaker_num++) {
|
|
w[speaker_num].effective_number_of_speakers += 0.5 * (1.0 + w[speaker_num].direction.dot(w[other_speaker_num].direction));
|
|
w[speaker_num].effective_number_of_speakers += 0.5 * (1.0 + w[speaker_num].direction.dot(w[other_speaker_num].direction));
|
|
}
|
|
}
|
|
@@ -144,6 +146,18 @@ void AudioStreamPlayer3D::_calc_output_vol(const Vector3 &source_dir, real_t tig
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+// Set the volume to cosine of half horizontal the angle from the source to the left/right speaker direction ignoring elevation.
|
|
|
|
+// Then scale `cosx` so that greatest ratio of the speaker volumes is `1-panning_strength`.
|
|
|
|
+// See https://github.com/godotengine/godot/issues/103989 for evidence that this is the most standard implementation.
|
|
|
|
+AudioFrame AudioStreamPlayer3D::_calc_output_vol_stereo(const Vector3 &source_dir, real_t panning_strength) {
|
|
|
|
+ double flatrad = sqrt(source_dir.x * source_dir.x + source_dir.z * source_dir.z);
|
|
|
|
+ double g = CLAMP((1.0 - panning_strength) * (1.0 - panning_strength), 0.0, 1.0);
|
|
|
|
+ double f = (1.0 - g) / (1.0 + g);
|
|
|
|
+ double cosx = CLAMP(source_dir.x / (flatrad == 0.0 ? 1.0 : flatrad), -1.0, 1.0);
|
|
|
|
+ double fcosx = cosx * f;
|
|
|
|
+ return AudioFrame(sqrt((-fcosx + 1.0) / 2.0), sqrt((fcosx + 1.0) / 2.0));
|
|
|
|
+}
|
|
|
|
+
|
|
#ifndef PHYSICS_3D_DISABLED
|
|
#ifndef PHYSICS_3D_DISABLED
|
|
void AudioStreamPlayer3D::_calc_reverb_vol(Area3D *area, Vector3 listener_area_pos, Vector<AudioFrame> direct_path_vol, Vector<AudioFrame> &reverb_vol) {
|
|
void AudioStreamPlayer3D::_calc_reverb_vol(Area3D *area, Vector3 listener_area_pos, Vector<AudioFrame> direct_path_vol, Vector<AudioFrame> &reverb_vol) {
|
|
reverb_vol.resize(4);
|
|
reverb_vol.resize(4);
|
|
@@ -449,10 +463,18 @@ Vector<AudioFrame> AudioStreamPlayer3D::_update_panning() {
|
|
for (Ref<AudioStreamPlayback> &playback : internal->stream_playbacks) {
|
|
for (Ref<AudioStreamPlayback> &playback : internal->stream_playbacks) {
|
|
AudioServer::get_singleton()->set_playback_highshelf_params(playback, linear_attenuation, attenuation_filter_cutoff_hz);
|
|
AudioServer::get_singleton()->set_playback_highshelf_params(playback, linear_attenuation, attenuation_filter_cutoff_hz);
|
|
}
|
|
}
|
|
- // 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;
|
|
|
|
- tightness *= panning_strength;
|
|
|
|
- _calc_output_vol(local_pos.normalized(), tightness, output_volume_vector);
|
|
|
|
|
|
+
|
|
|
|
+ if (AudioServer::get_singleton()->get_speaker_mode() == AudioServer::SPEAKER_MODE_STEREO) {
|
|
|
|
+ output_volume_vector.write[0] = _calc_output_vol_stereo(local_pos, cached_global_panning_strength * panning_strength);
|
|
|
|
+ output_volume_vector.write[1] = AudioFrame(0, 0);
|
|
|
|
+ output_volume_vector.write[2] = AudioFrame(0, 0);
|
|
|
|
+ output_volume_vector.write[3] = AudioFrame(0, 0);
|
|
|
|
+ } else {
|
|
|
|
+ // 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;
|
|
|
|
+ tightness *= panning_strength;
|
|
|
|
+ _calc_output_vol(local_pos.normalized(), tightness, output_volume_vector);
|
|
|
|
+ }
|
|
|
|
|
|
for (unsigned int k = 0; k < 4; k++) {
|
|
for (unsigned int k = 0; k < 4; k++) {
|
|
output_volume_vector.write[k] = multiplier * output_volume_vector[k];
|
|
output_volume_vector.write[k] = multiplier * output_volume_vector[k];
|