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/reverb_node.h"
18
19#include <algorithm>
20#include <cmath>
21
22#include "base/constants_and_types.h"
23#include "base/logging.h"
24
25
26namespace vraudio {
27
28namespace {
29
30// Default time in seconds to update the rt60s over.
31const float kUpdateTimeSeconds = 1.0f;
32
33// Interpolates between the current and target values in steps of |update_step|,
34// will set |current| to |target| when the diff between them is less than
35// |update_step|.
36inline void InterpolateFloatParam(float update_step, float target,
37 float* current) {
38 if (std::abs(x: target - *current) <= std::abs(x: update_step)) {
39 *current = target;
40 } else {
41 *current += update_step;
42 }
43}
44
45} // namespace
46
47ReverbNode::ReverbNode(const SystemSettings& system_settings,
48 FftManager* fft_manager)
49 : system_settings_(system_settings),
50 rt60_band_update_steps_(kNumReverbOctaveBands, 0.0f),
51 gain_update_step_(0.0f),
52 rt60_updating_(false),
53 gain_updating_(false),
54 buffers_to_update_(
55 static_cast<float>(system_settings_.GetSampleRateHz()) *
56 kUpdateTimeSeconds /
57 static_cast<float>(system_settings_.GetFramesPerBuffer())),
58 spectral_reverb_(system_settings_.GetSampleRateHz(),
59 system_settings_.GetFramesPerBuffer()),
60 onset_compensator_(system_settings_.GetSampleRateHz(),
61 system_settings_.GetFramesPerBuffer(), fft_manager),
62 num_frames_processed_on_empty_input_(0),
63 reverb_length_frames_(0),
64 output_buffer_(kNumStereoChannels, system_settings_.GetFramesPerBuffer()),
65 compensator_output_buffer_(kNumStereoChannels,
66 system_settings_.GetFramesPerBuffer()),
67 silence_mono_buffer_(kNumMonoChannels,
68 system_settings_.GetFramesPerBuffer()) {
69 EnableProcessOnEmptyInput(enable: true);
70 output_buffer_.Clear();
71 silence_mono_buffer_.Clear();
72 Update();
73}
74
75void ReverbNode::Update() {
76 new_reverb_properties_ = system_settings_.GetReverbProperties();
77
78 rt60_updating_ = !EqualSafe(lhs_begin: std::begin(arr&: reverb_properties_.rt60_values),
79 lhs_end: std::end(arr&: reverb_properties_.rt60_values),
80 rhs_begin: std::begin(arr&: new_reverb_properties_.rt60_values),
81 rhs_end: std::end(arr&: new_reverb_properties_.rt60_values));
82 if (rt60_updating_) {
83 for (size_t i = 0; i < kNumReverbOctaveBands; ++i) {
84 rt60_band_update_steps_[i] = (new_reverb_properties_.rt60_values[i] -
85 reverb_properties_.rt60_values[i]) /
86 buffers_to_update_;
87 }
88 }
89 // Update the reverb gain if necessary.
90 gain_updating_ = reverb_properties_.gain != new_reverb_properties_.gain;
91 if (gain_updating_) {
92 gain_update_step_ =
93 (new_reverb_properties_.gain - reverb_properties_.gain) /
94 buffers_to_update_;
95 }
96}
97
98const AudioBuffer* ReverbNode::GetOutputBuffer() const
99{
100 return &output_buffer_;
101}
102
103const AudioBuffer* ReverbNode::AudioProcess(const NodeInput& input) {
104 if (rt60_updating_) {
105 for (size_t i = 0; i < kNumReverbOctaveBands; ++i) {
106 InterpolateFloatParam(update_step: rt60_band_update_steps_[i],
107 target: new_reverb_properties_.rt60_values[i],
108 current: &reverb_properties_.rt60_values[i]);
109 }
110 spectral_reverb_.SetRt60PerOctaveBand(reverb_properties_.rt60_values);
111 const auto max_rt_it =
112 std::max_element(first: std::begin(arr&: reverb_properties_.rt60_values),
113 last: std::end(arr&: reverb_properties_.rt60_values));
114 reverb_length_frames_ = static_cast<size_t>(
115 *max_rt_it * static_cast<float>(system_settings_.GetSampleRateHz()));
116 onset_compensator_.Update(rt60_values: reverb_properties_.rt60_values,
117 gain: reverb_properties_.gain);
118 // |InterpolateFloatParam| will set the two values below to be equal on
119 // completion of interpolation.
120 rt60_updating_ = !EqualSafe(lhs_begin: std::begin(arr&: reverb_properties_.rt60_values),
121 lhs_end: std::end(arr&: reverb_properties_.rt60_values),
122 rhs_begin: std::begin(arr&: new_reverb_properties_.rt60_values),
123 rhs_end: std::end(arr&: new_reverb_properties_.rt60_values));
124 }
125
126 if (gain_updating_) {
127 InterpolateFloatParam(update_step: gain_update_step_, target: new_reverb_properties_.gain,
128 current: &reverb_properties_.gain);
129 spectral_reverb_.SetGain(reverb_properties_.gain);
130 onset_compensator_.Update(rt60_values: reverb_properties_.rt60_values,
131 gain: reverb_properties_.gain);
132 // |InterpolateFloatParam| will set the two values below to be equal on
133 // completion of interpolation.
134 gain_updating_ = reverb_properties_.gain != new_reverb_properties_.gain;
135 }
136
137 const AudioBuffer* input_buffer = input.GetSingleInput();
138 if (input_buffer == nullptr) {
139 // If we have no input, generate a silent input buffer until the node states
140 // are cleared.
141 if (num_frames_processed_on_empty_input_ < reverb_length_frames_) {
142 const size_t num_frames = system_settings_.GetFramesPerBuffer();
143 num_frames_processed_on_empty_input_ += num_frames;
144 spectral_reverb_.Process(input: silence_mono_buffer_[0], left_out: &output_buffer_[0],
145 right_out: &output_buffer_[1]);
146 return &output_buffer_;
147 } else {
148 // Skip processing entirely when the states are fully cleared.
149 return nullptr;
150 }
151 }
152 DCHECK_EQ(input_buffer->num_channels(), kNumMonoChannels);
153 num_frames_processed_on_empty_input_ = 0;
154 spectral_reverb_.Process(input: (*input_buffer)[0], left_out: &output_buffer_[0],
155 right_out: &output_buffer_[1]);
156 onset_compensator_.Process(input: *input_buffer, output: &compensator_output_buffer_);
157 output_buffer_[0] += compensator_output_buffer_[0];
158 output_buffer_[1] += compensator_output_buffer_[1];
159 return &output_buffer_;
160}
161
162} // namespace vraudio
163

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