1/*
2Copyright 2018 Google Inc. All Rights Reserved.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS-IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17#include "dsp/distance_attenuation.h"
18
19#include <algorithm>
20#include <cmath>
21
22#include "base/constants_and_types.h"
23
24namespace vraudio {
25
26float ComputeLogarithmicDistanceAttenuation(
27 const WorldPosition& listener_position,
28 const WorldPosition& source_position, float min_distance,
29 float max_distance) {
30 const float distance = (listener_position - source_position).norm();
31 if (distance > max_distance) {
32 return 0.0f;
33 }
34 // Logarithmic attenuation.
35 const float min_distance_allowed =
36 std::max(a: min_distance, b: kNearFieldThreshold);
37 if (distance > min_distance_allowed) {
38 const float attenuation_interval = max_distance - min_distance_allowed;
39 if (attenuation_interval > kEpsilonFloat) {
40 // Compute the distance attenuation value by the logarithmic curve
41 // "1 / (d + 1)" with an offset of |min_distance_allowed|.
42 const float relative_distance = distance - min_distance_allowed;
43 const float attenuation = 1.0f / (relative_distance + 1.0f);
44 // Shift the curve downwards by the attenuation value at |max_distance|,
45 // and scale the value by the inverse of it in order to keep the curve's
46 // peak value 1 at |min_distance_allowed|.
47 const float attenuation_max = 1.0f / (1.0f + attenuation_interval);
48 return (attenuation - attenuation_max) / (1.0f - attenuation_max);
49 }
50 }
51 return 1.0f;
52}
53
54float ComputeLinearDistanceAttenuation(const WorldPosition& listener_position,
55 const WorldPosition& source_position,
56 float min_distance, float max_distance) {
57 const float distance = (listener_position - source_position).norm();
58 if (distance > max_distance) {
59 return 0.0f;
60 }
61 // Linear attenuation.
62 const float min_distance_allowed =
63 std::max(a: min_distance, b: kNearFieldThreshold);
64 if (distance > min_distance_allowed) {
65 const float attenuation_interval = max_distance - min_distance_allowed;
66 if (attenuation_interval > kEpsilonFloat) {
67 return (max_distance - distance) / attenuation_interval;
68 }
69 }
70 return 1.0f;
71}
72
73float ComputeNearFieldEffectGain(const WorldPosition& listener_position,
74 const WorldPosition& source_position) {
75 const float distance = (listener_position - source_position).norm();
76 if (distance < kNearFieldThreshold) {
77 return (1.0f / std::max(a: distance, b: kMinNearFieldDistance)) - 1.0f;
78 }
79 return 0.0f;
80}
81
82void UpdateAttenuationParameters(float master_gain, float reflections_gain,
83 float reverb_gain,
84 const WorldPosition& listener_position,
85 SourceParameters* parameters) {
86 // Compute distance attenuation.
87 const WorldPosition& source_position = parameters->object_transform.position;
88 const auto rolloff_model = parameters->distance_rolloff_model;
89 const float min_distance = parameters->minimum_distance;
90 const float max_distance = parameters->maximum_distance;
91
92 float distance_attenuation = 0.0f;
93 switch (rolloff_model) {
94 case DistanceRolloffModel::kLogarithmic:
95 distance_attenuation = ComputeLogarithmicDistanceAttenuation(
96 listener_position, source_position, min_distance, max_distance);
97 break;
98 case DistanceRolloffModel::kLinear:
99 distance_attenuation = ComputeLinearDistanceAttenuation(
100 listener_position, source_position, min_distance, max_distance);
101 break;
102 case DistanceRolloffModel::kNone:
103 default:
104 // Distance attenuation is already set by the user.
105 distance_attenuation = parameters->distance_attenuation;
106 break;
107 }
108 // Update gain attenuations.
109 const float input_gain = master_gain * parameters->gain;
110 const float direct_attenuation = input_gain * distance_attenuation;
111 const float room_effects_attenuation = parameters->room_effects_gain;
112
113 parameters->attenuations[AttenuationType::kInput] = input_gain;
114 parameters->attenuations[AttenuationType::kDirect] = direct_attenuation;
115 parameters->attenuations[AttenuationType::kReflections] =
116 room_effects_attenuation * direct_attenuation * reflections_gain;
117 parameters->attenuations[AttenuationType::kReverb] =
118 room_effects_attenuation * input_gain * reverb_gain;
119}
120
121} // namespace vraudio
122

source code of qtmultimedia/src/3rdparty/resonance-audio/resonance_audio/dsp/distance_attenuation.cc