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 "graph/occlusion_node.h"
18
19#include <cmath>
20
21#include "base/logging.h"
22#include "base/spherical_angle.h"
23
24#include "dsp/occlusion_calculator.h"
25
26namespace vraudio {
27
28namespace {
29
30// Low pass filter coefficient for smoothing the applied occlusion. This avoids
31// sudden unrealistic changes in the volume of a sound object. Range [0, 1].
32// The value below has been calculated empirically.
33const float kOcclusionSmoothingCoefficient = 0.75f;
34
35// This function provides first order low-pass filtering. It is used to smooth
36// the occlusion parameter.
37float Interpolate(float coefficient, float previous_value, float target_value) {
38 return target_value + coefficient * (previous_value - target_value);
39}
40
41} // namespace
42
43OcclusionNode::OcclusionNode(SourceId source_id,
44 const SystemSettings& system_settings)
45 : system_settings_(system_settings),
46 low_pass_filter_(0.0f),
47 current_occlusion_(0.0f),
48 output_buffer_(kNumMonoChannels, system_settings.GetFramesPerBuffer()) {
49 output_buffer_.Clear();
50 output_buffer_.set_source_id(source_id);
51}
52
53const AudioBuffer* OcclusionNode::AudioProcess(const NodeInput& input) {
54
55 const AudioBuffer* input_buffer = input.GetSingleInput();
56 DCHECK(input_buffer);
57 DCHECK_EQ(input_buffer->source_id(), output_buffer_.source_id());
58
59 const auto source_parameters =
60 system_settings_.GetSourceParameters(source_id: input_buffer->source_id());
61 if (source_parameters == nullptr) {
62 LOG(WARNING) << "Could not find source parameters";
63 return nullptr;
64 }
65
66 const WorldPosition& listener_position = system_settings_.GetHeadPosition();
67 const WorldRotation& listener_rotation = system_settings_.GetHeadRotation();
68 const ObjectTransform& source_transform = source_parameters->object_transform;
69 // Compute the relative listener/source direction in spherical angles.
70 WorldPosition relative_direction;
71 GetRelativeDirection(from_position: listener_position, from_rotation: listener_rotation,
72 to_position: source_transform.position, relative_direction: &relative_direction);
73 const SphericalAngle listener_direction =
74 SphericalAngle::FromWorldPosition(world_position: relative_direction);
75
76 GetRelativeDirection(from_position: source_transform.position, from_rotation: source_transform.rotation,
77 to_position: listener_position, relative_direction: &relative_direction);
78 const SphericalAngle source_direction =
79 SphericalAngle::FromWorldPosition(world_position: relative_direction);
80 // Calculate low-pass filter coefficient based on listener/source directivity
81 // and occlusion values.
82 const float listener_directivity = CalculateDirectivity(
83 alpha: source_parameters->listener_directivity_alpha,
84 order: source_parameters->listener_directivity_order, spherical_angle: listener_direction);
85 const float source_directivity = CalculateDirectivity(
86 alpha: source_parameters->directivity_alpha,
87 order: source_parameters->directivity_order, spherical_angle: source_direction);
88 current_occlusion_ =
89 Interpolate(coefficient: kOcclusionSmoothingCoefficient, previous_value: current_occlusion_,
90 target_value: source_parameters->occlusion_intensity);
91 const float filter_coefficient = CalculateOcclusionFilterCoefficient(
92 directivity: listener_directivity * source_directivity, occlusion_intensity: current_occlusion_);
93 low_pass_filter_.SetCoefficient(filter_coefficient);
94 if (!low_pass_filter_.Filter(input: (*input_buffer)[0], output: &output_buffer_[0])) {
95 return input_buffer;
96 }
97 // Copy buffer parameters.
98 return &output_buffer_;
99}
100
101} // namespace vraudio
102

source code of qtmultimedia/src/3rdparty/resonance-audio/resonance_audio/graph/occlusion_node.cc