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/gain_processor.h" |
18 | |
19 | #include <algorithm> |
20 | #include <cmath> |
21 | |
22 | #include "base/constants_and_types.h" |
23 | |
24 | #include "dsp/gain.h" |
25 | |
26 | namespace vraudio { |
27 | |
28 | // Delegate default constructor. |
29 | GainProcessor::GainProcessor() : current_gain_(0.0f), is_initialized_(false) {} |
30 | |
31 | GainProcessor::GainProcessor(float initial_gain) |
32 | : current_gain_(initial_gain), is_initialized_(true) {} |
33 | |
34 | void GainProcessor::ApplyGain(float target_gain, |
35 | const AudioBuffer::Channel& input, |
36 | AudioBuffer::Channel* output, |
37 | bool accumulate_output) { |
38 | |
39 | DCHECK(output); |
40 | |
41 | if (!is_initialized_) { |
42 | Reset(gain: target_gain); |
43 | } |
44 | |
45 | // Check buffer length. |
46 | const size_t input_length = input.size(); |
47 | DCHECK_GT(input_length, 0U); |
48 | DCHECK_EQ(input_length, output->size()); |
49 | |
50 | // Index for where to stop interpolating. |
51 | size_t ramp_length = |
52 | static_cast<size_t>(std::abs(x: target_gain - current_gain_) * |
53 | static_cast<float>(kUnitRampLength)); |
54 | |
55 | // Check if there is a new gain value. |
56 | if (ramp_length > 0) { |
57 | // Apply gain ramp to buffer. |
58 | current_gain_ = LinearGainRamp(ramp_length, start_gain: current_gain_, end_gain: target_gain, |
59 | input_samples: input, output_samples: output, accumulate_output); |
60 | } else { |
61 | // No ramping needed. |
62 | current_gain_ = target_gain; |
63 | } |
64 | |
65 | // Apply constant gain to the rest of the buffer. |
66 | if (ramp_length < input_length) { |
67 | if (IsGainNearZero(gain: current_gain_)) { |
68 | // Skip processing if the gain is zero. |
69 | if (!accumulate_output) { |
70 | // Directly fill the remaining output with zeros. |
71 | std::fill(first: output->begin() + ramp_length, last: output->end(), value: 0.0f); |
72 | } |
73 | return; |
74 | } else if (IsGainNearUnity(gain: current_gain_) && !accumulate_output) { |
75 | // Skip processing if the gain is unity. |
76 | if (&input != output) { |
77 | // Directly copy the remaining input samples into output. |
78 | std::copy(first: input.begin() + ramp_length, last: input.end(), |
79 | result: output->begin() + ramp_length); |
80 | } |
81 | return; |
82 | } |
83 | ConstantGain(offset_index: ramp_length, gain: current_gain_, input_samples: input, output_samples: output, accumulate_output); |
84 | } |
85 | } |
86 | |
87 | float GainProcessor::GetGain() const { return current_gain_; } |
88 | |
89 | void GainProcessor::Reset(float gain) { |
90 | current_gain_ = gain; |
91 | is_initialized_ = true; |
92 | } |
93 | |
94 | } // namespace vraudio |
95 | |