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/gain_mixer.h"
18
19#include <cmath>
20
21#include "base/logging.h"
22
23namespace vraudio {
24
25GainMixer::GainMixer(size_t num_channels, size_t frames_per_buffer)
26 : num_channels_(num_channels),
27 output_(num_channels_, frames_per_buffer),
28 is_empty_(false) {
29 DCHECK_NE(num_channels_, 0U);
30 Reset();
31}
32
33void GainMixer::AddInput(const AudioBuffer& input,
34 const std::vector<float>& gains) {
35 DCHECK_EQ(gains.size(), num_channels_);
36 DCHECK_EQ(input.num_channels(), num_channels_);
37 DCHECK_EQ(input.num_frames(), output_.num_frames());
38
39 auto* gain_processors = GetOrCreateProcessors(source_id: input.source_id());
40 // Accumulate the input buffers into the output buffer.
41 for (size_t i = 0; i < num_channels_; ++i) {
42 if (input[i].IsEnabled()) {
43 (*gain_processors)[i].ApplyGain(target_gain: gains[i], input: input[i], output: &output_[i],
44 accumulate_output: true /* accumulate_output */);
45 } else {
46 // Make sure the gain processor is initialized.
47 (*gain_processors)[i].Reset(gain: gains[i]);
48 }
49 }
50 is_empty_ = false;
51}
52
53void GainMixer::AddInputChannel(const AudioBuffer::Channel& input,
54 SourceId source_id,
55 const std::vector<float>& gains) {
56 DCHECK_EQ(gains.size(), num_channels_);
57 DCHECK_EQ(input.size(), output_.num_frames());
58
59 auto* gain_processors = GetOrCreateProcessors(source_id);
60 // Accumulate the input buffers into the output buffer.
61 for (size_t i = 0; i < num_channels_; ++i) {
62 if (input.IsEnabled()) {
63 (*gain_processors)[i].ApplyGain(target_gain: gains[i], input, output: &output_[i],
64 accumulate_output: true /* accumulate_output */);
65 } else {
66 // Make sure the gain processor is initialized.
67 (*gain_processors)[i].Reset(gain: gains[i]);
68 }
69 }
70 is_empty_ = false;
71}
72
73const AudioBuffer* GainMixer::GetOutput() const {
74 if (is_empty_) {
75 return nullptr;
76 }
77 return &output_;
78}
79
80void GainMixer::Reset() {
81 if (!is_empty_) {
82 // Delete the processors for sources which no longer exist.
83 for (auto it = source_gain_processors_.begin();
84 it != source_gain_processors_.end();
85 /* no increment */) {
86 if (it->second.processors_active) {
87 it->second.processors_active = false;
88 ++it;
89 } else {
90 source_gain_processors_.erase(position: it++);
91 }
92 }
93 // Reset the output buffer.
94 output_.Clear();
95 }
96 is_empty_ = true;
97}
98
99GainMixer::GainProcessors::GainProcessors(size_t num_channels)
100 : processors_active(true), processors(num_channels) {}
101
102std::vector<GainProcessor>* GainMixer::GetOrCreateProcessors(
103 SourceId source_id) {
104 // Attempt to find a |ScaleAndAccumulateProcessor| for the given |source_id|,
105 // if none can be found add one. In either case mark that the processor has
106 // been used so that it is not later deleted.
107 if (source_gain_processors_.find(x: source_id) ==
108 source_gain_processors_.end()) {
109 source_gain_processors_.insert(x: {source_id, GainProcessors(num_channels_)});
110 }
111 source_gain_processors_.at(k: source_id).processors_active = true;
112 return &(source_gain_processors_.at(k: source_id).processors);
113}
114
115} // namespace vraudio
116

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