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/reverb_onset_update_processor.h"
18
19#include <algorithm>
20
21#include "base/constants_and_types.h"
22#include "base/simd_utils.h"
23#include "dsp/spectral_reverb_constants_and_tables.h"
24#include "dsp/utils.h"
25
26namespace vraudio {
27
28namespace {
29
30// Find the absolute difference between two size_t values.
31inline size_t absdiff(size_t lhs, size_t rhs) {
32 return lhs > rhs ? lhs - rhs : rhs - lhs;
33}
34
35} // namespace
36
37ReverbOnsetUpdateProcessor::ReverbOnsetUpdateProcessor(
38 size_t frames_per_buffer, int sampling_rate, AudioBuffer* base_curves,
39 AudioBuffer* adder_curves)
40 : sampling_rate_(sampling_rate),
41 tail_update_cursor_(0),
42 tail_length_(CeilToMultipleOfFramesPerBuffer(size: kCorrectionCurveLength,
43 frames_per_buffer)),
44 gain_(1.0f),
45 curve_indices_(GetNumReverbOctaveBands(sampling_rate: sampling_rate_), kInvalidIndex),
46 pure_decay_coefficients_(curve_indices_.size(), 0.0f),
47 pure_decay_exponents_(curve_indices_.size(), 0.0f),
48 band_buffer_(kNumStereoChannels, frames_per_buffer),
49 envelope_buffer_(kNumMonoChannels, frames_per_buffer),
50 base_curves_(base_curves),
51 adder_curves_(adder_curves) {}
52
53void ReverbOnsetUpdateProcessor::SetReverbTimes(const float* rt60_values) {
54 DCHECK(rt60_values);
55 const size_t num_octave_bands = curve_indices_.size();
56 const float sampling_rate_float = static_cast<float>(sampling_rate_);
57 tail_update_cursor_ = 0;
58 // Choose curves for each band.
59 for (size_t band = 0; band < num_octave_bands; ++band) {
60 curve_indices_[band] =
61 GetFeedbackIndexFromRt60(reverberation_time: rt60_values[band], sample_rate: sampling_rate_float);
62 // Deal with the case where only the convolution is needed.
63 if (curve_indices_[band] == kInvalidIndex) {
64 const float min_reverb_time =
65 kMinReverbTimeForFeedback48kHz *
66 (sampling_rate_float / kDefaultSpectralReverbSampleRate);
67 const float effective_rt =
68 rt60_values[band] <= min_reverb_time ? rt60_values[band] : 0.0f;
69 pure_decay_exponents_[band] =
70 std::abs(x: effective_rt) > kEpsilonFloat
71 ? std::exp(x: kNegativeLog1000 /
72 (sampling_rate_float * effective_rt))
73 : 0.0f;
74 pure_decay_coefficients_[band] = pure_decay_exponents_[band];
75 }
76 }
77}
78
79bool ReverbOnsetUpdateProcessor::Process(
80 const std::vector<AudioBuffer>& bandpassed_noise_left,
81 const std::vector<AudioBuffer>& bandpassed_noise_right,
82 AudioBuffer::Channel* kernel_channel_left,
83 AudioBuffer::Channel* kernel_channel_right) {
84 if (tail_update_cursor_ >= tail_length_) {
85 // Processing the reverb tail is finished.
86 tail_update_cursor_ = 0;
87 return false;
88 }
89 const size_t frames_per_buffer = band_buffer_.num_frames();
90 DCHECK(kernel_channel_left);
91 DCHECK(kernel_channel_right);
92 DCHECK_EQ(bandpassed_noise_left.size(), curve_indices_.size());
93 DCHECK_EQ(bandpassed_noise_right.size(), curve_indices_.size());
94 DCHECK_EQ(bandpassed_noise_left[0].num_frames(), tail_length_);
95 DCHECK_EQ(bandpassed_noise_right[0].num_frames(), tail_length_);
96 DCHECK_GE(tail_length_, kCorrectionCurveLength);
97 DCHECK_EQ(kernel_channel_left->size(), frames_per_buffer);
98 DCHECK_EQ(kernel_channel_right->size(), frames_per_buffer);
99
100 // Clear for accumulation per frequency band.
101 kernel_channel_left->Clear();
102 kernel_channel_right->Clear();
103
104 AudioBuffer::Channel& band_channel_left = band_buffer_[0];
105 AudioBuffer::Channel& band_channel_right = band_buffer_[1];
106 // Define the number of samples we are still able to copy from the multiplier
107 // and adder curves.
108 const size_t copy_length =
109 frames_per_buffer + tail_update_cursor_ <= kCorrectionCurveLength
110 ? frames_per_buffer
111 : absdiff(lhs: kCorrectionCurveLength, rhs: tail_update_cursor_);
112 AudioBuffer::Channel* envelope_channel = &envelope_buffer_[0];
113 // Compute the band buffer for each band response.
114 for (size_t band = 0; band < curve_indices_.size(); ++band) {
115 const AudioBuffer::Channel& noise_channel_left =
116 bandpassed_noise_left[band][0];
117 const AudioBuffer::Channel& noise_channel_right =
118 bandpassed_noise_right[band][0];
119 // Fill the band buffer with the next noise buffer and apply gain.
120 ScalarMultiply(length: frames_per_buffer, gain: gain_,
121 input: noise_channel_left.begin() + tail_update_cursor_,
122 output: band_channel_left.begin());
123 ScalarMultiply(length: frames_per_buffer, gain: gain_,
124 input: noise_channel_right.begin() + tail_update_cursor_,
125 output: band_channel_right.begin());
126 // Skip the band if we have an invalid index
127 const int curve_index = curve_indices_[band];
128 if (curve_index != kInvalidIndex) {
129 // Apply the correct compensation curve to the buffer.
130 const float scale = kCurveCorrectionMultipliers[curve_index];
131 AudioBuffer::Channel* adder_curve_channel;
132 if (tail_update_cursor_ < kCorrectionCurveLength) {
133 // Use either the high frequency or low frequency curve.
134 if (static_cast<size_t>(curve_index) >= kCurveChangeoverIndex) {
135 adder_curve_channel = &(*adder_curves_)[1];
136 std::copy_n(first: (*base_curves_)[1].begin() + tail_update_cursor_,
137 n: copy_length, result: envelope_channel->begin());
138 } else {
139 adder_curve_channel = &(*adder_curves_)[0];
140 std::copy_n(first: (*base_curves_)[0].begin() + tail_update_cursor_,
141 n: copy_length, result: envelope_channel->begin());
142 }
143 // Construct the correct envelope (chunk thereof).
144 ScalarMultiplyAndAccumulate(
145 length: copy_length, gain: scale,
146 input: adder_curve_channel->begin() + tail_update_cursor_,
147 accumulator: envelope_channel->begin());
148 // Ensure the end part of the envelope does not contain spurious data.
149 std::fill(first: envelope_channel->begin() + copy_length,
150 last: envelope_channel->end(), value: 0.0f);
151 } else {
152 // If we have moved past the length of the correction curve, fill the
153 // envelope chunk with zeros.
154 envelope_channel->Clear();
155 }
156
157 // Apply that envelope to the given band and accumulate into the output.
158 MultiplyAndAccumulatePointwise(
159 length: frames_per_buffer, input_a: envelope_channel->begin(),
160 input_b: band_channel_left.begin(), accumulator: kernel_channel_left->begin());
161 MultiplyAndAccumulatePointwise(
162 length: frames_per_buffer, input_a: envelope_channel->begin(),
163 input_b: band_channel_right.begin(), accumulator: kernel_channel_right->begin());
164 } else {
165 // If the decay time is too short for the spectral reverb to make a
166 // contribution (0.15s @48kHz), the compensation filter will consist of
167 // the entire tail.
168 for (size_t frame = 0; frame < frames_per_buffer; ++frame) {
169 (*kernel_channel_left)[frame] +=
170 pure_decay_coefficients_[band] * band_channel_left[frame];
171 (*kernel_channel_right)[frame] +=
172 pure_decay_coefficients_[band] * band_channel_right[frame];
173 // Update the decay coefficient.
174 pure_decay_coefficients_[band] *= pure_decay_exponents_[band];
175 }
176 }
177 }
178 // Update the cursor.
179 tail_update_cursor_ += frames_per_buffer;
180
181 return true;
182}
183
184} // namespace vraudio
185

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