1 | /* |
2 | Copyright 2018 Google Inc. All Rights Reserved. |
3 | |
4 | Licensed under the Apache License, Version 2.0 (the "License"); |
5 | you may not use this file except in compliance with the License. |
6 | You may obtain a copy of the License at |
7 | |
8 | http://www.apache.org/licenses/LICENSE-2.0 |
9 | |
10 | Unless required by applicable law or agreed to in writing, software |
11 | distributed under the License is distributed on an "AS-IS" BASIS, |
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | See the License for the specific language governing permissions and |
14 | limitations 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 | |
26 | namespace vraudio { |
27 | |
28 | namespace { |
29 | |
30 | // Find the absolute difference between two size_t values. |
31 | inline size_t absdiff(size_t lhs, size_t rhs) { |
32 | return lhs > rhs ? lhs - rhs : rhs - lhs; |
33 | } |
34 | |
35 | } // namespace |
36 | |
37 | ReverbOnsetUpdateProcessor::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 | |
53 | void 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 | |
79 | bool 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 | |