blob: 93cbc77f66508b6345fc5ea55d4b262aadee3cb0 [file] [log] [blame]
Hsin-Yu Chaob6f63cd2018-03-17 16:52:35 +08001/* Copyright (c) 2018 The Chromium Authors. All rights reserved.
2 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file.
4 */
5
Hsin-Yu Chaob3dfb0e2021-04-20 08:04:00 +00006#include <metrics/metrics_library.h>
7
Hsin-Yu Chaob6f63cd2018-03-17 16:52:35 +08008#include "api/audio/echo_canceller3_factory.h"
Hsin-Yu Chaof76cafb2019-04-01 13:54:10 +08009#include "api/task_queue/default_task_queue_factory.h"
Hsin-Yu Chao2583e8a2018-11-13 17:13:09 +080010#include "cras-config/aec_config.h"
11#include "cras-config/apm_config.h"
Hsin-Yu Chaob6f63cd2018-03-17 16:52:35 +080012#include "modules/audio_processing/aec_dump/aec_dump_factory.h"
13#include "modules/audio_processing/include/aec_dump.h"
14#include "modules/audio_processing/include/audio_processing.h"
Hsin-Yu Chaob6f63cd2018-03-17 16:52:35 +080015#include "rtc_base/task_queue.h"
Hsin-Yu Chaob3dfb0e2021-04-20 08:04:00 +000016#include "system_wrappers/include/metrics.h"
Hsin-Yu Chaob6f63cd2018-03-17 16:52:35 +080017
18extern "C" {
Hsin-Yu Chao1bda95a2018-10-17 15:30:12 +080019#include <errno.h>
20
Hsin-Yu Chaob6f63cd2018-03-17 16:52:35 +080021#include "webrtc_apm.h"
22
Hsin-Yu Chaob3dfb0e2021-04-20 08:04:00 +000023using webrtc::metrics::SampleInfo;
24
25static std::string hist_name_prefix_;
26static std::unique_ptr<MetricsLibraryInterface> metrics_lib_;
27
28void webrtc_apm_init_metrics(const char *prefix)
29{
30 if (prefix == NULL)
31 return;
32
33 webrtc::metrics::Enable();
34 hist_name_prefix_ = prefix;
35 metrics_lib_ = std::make_unique<MetricsLibrary>();
36}
Per Åhgrenaa5a43f2021-03-30 08:29:43 +020037
38webrtc_apm webrtc_apm_create(
39 unsigned int num_channels,
40 unsigned int frame_rate,
41 dictionary *aec_ini,
42 dictionary *apm_ini) {
43
44 return webrtc_apm_create_with_enforced_effects(num_channels, frame_rate,
45 aec_ini,apm_ini,0,0,0);
46}
47
48webrtc_apm webrtc_apm_create_with_enforced_effects(
49 unsigned int num_channels,
50 unsigned int frame_rate,
51 dictionary *aec_ini,
52 dictionary *apm_ini,
53 unsigned int enforce_aec_on,
54 unsigned int enforce_ns_on,
55 unsigned int enforce_agc_on)
Hsin-Yu Chaob6f63cd2018-03-17 16:52:35 +080056{
57 int err;
58 webrtc::AudioProcessing *apm;
59 webrtc::AudioProcessing::ChannelLayout channel_layout;
60 webrtc::AudioProcessingBuilder apm_builder;
Hsin-Yu Chaoede78de2018-05-04 11:10:47 +080061 webrtc::EchoCanceller3Config aec3_config;
62 std::unique_ptr<webrtc::EchoControlFactory> ec3_factory;
Hsin-Yu Chaob6f63cd2018-03-17 16:52:35 +080063
64 switch (num_channels) {
65 case 1:
66 channel_layout = webrtc::AudioProcessing::kMono;
67 break;
68 case 2:
69 channel_layout = webrtc::AudioProcessing::kStereo;
70 break;
71 default:
72 return NULL;
73 }
74
Per Åhgrenaa5a43f2021-03-30 08:29:43 +020075 /* Set the AEC-tunings. */
Hsin-Yu Chao2583e8a2018-11-13 17:13:09 +080076 if (aec_ini) {
77 aec_config_get(aec_ini, &aec3_config);
78 ec3_factory.reset(
79 new webrtc::EchoCanceller3Factory(aec3_config));
80 } else {
81 ec3_factory.reset(new webrtc::EchoCanceller3Factory());
82 }
83
Hsin-Yu Chaob6f63cd2018-03-17 16:52:35 +080084 apm_builder.SetEchoControlFactory(std::move(ec3_factory));
85 apm = apm_builder.Create();
86
Per Åhgrenaa5a43f2021-03-30 08:29:43 +020087 /* Set the rest of the all settings/tunings. */
88 webrtc::AudioProcessing::Config config = apm->GetConfig();
89 bool config_changed = false;
90 if (aec_ini || enforce_aec_on == 1) {
91 config.echo_canceller.enabled = true;
Hsin-Yu Chaoaf702852021-05-18 09:47:54 +000092 /* Activate playout stereo processing by default. This can be
93 * turned off in |apm_ini|.
94 */
95 if (enforce_aec_on) {
96 config.pipeline.multi_channel_render = true;
97 }
Per Åhgrenaa5a43f2021-03-30 08:29:43 +020098 config_changed = true;
99 }
100
101 if (apm_ini) {
102 apm_config_set(apm_ini, &config);
103 config_changed = true;
104 }
105
106 if (enforce_ns_on == 1) {
107 config.noise_suppression.enabled = true;
108 config_changed = true;
109 }
110
111 if (enforce_agc_on == 1) {
112 config.gain_controller1.enabled = true;
113 config.gain_controller1.mode =
114 webrtc::AudioProcessing::Config::GainController1::Mode::kAdaptiveAnalog;
115 config.capture_level_adjustment.enabled = true;
116 config.capture_level_adjustment.analog_mic_gain_emulation.enabled = true;
117 config_changed = true;
118 }
119
120 if (config_changed) {
121 apm->ApplyConfig(config);
122 }
Hsin-Yu Chao78745762018-08-14 14:32:40 +0800123
Hsin-Yu Chaob6f63cd2018-03-17 16:52:35 +0800124 err = apm->Initialize(frame_rate, frame_rate, frame_rate,
125 channel_layout, channel_layout, channel_layout);
126 if (err) {
127 delete apm;
128 return NULL;
129 }
130
131 return reinterpret_cast<webrtc_apm>(apm);
132}
133
Hsin-Yu Chao2583e8a2018-11-13 17:13:09 +0800134void webrtc_apm_dump_configs(dictionary *apm_ini,
135 dictionary *aec_ini)
136{
137 if (apm_ini)
138 apm_config_dump(apm_ini);
139 if (aec_ini)
140 aec_config_dump(aec_ini);
141}
142
Hsin-Yu Chaob6f63cd2018-03-17 16:52:35 +0800143int webrtc_apm_process_reverse_stream_f(
144 webrtc_apm ptr,
145 int num_channels, int rate,
146 float *const *data)
147{
148 webrtc::AudioProcessing *apm;
149 webrtc::StreamConfig config =
150 webrtc::StreamConfig(rate, num_channels);
151
152 apm = reinterpret_cast<webrtc::AudioProcessing *>(ptr);
153
154 return apm->ProcessReverseStream(data, config, config, data);
155}
156
Hsin-Yu Chaob6f63cd2018-03-17 16:52:35 +0800157int webrtc_apm_process_stream_f(webrtc_apm ptr,
158 int num_channels,
159 int rate,
160 float *const *data)
161{
162 webrtc::AudioProcessing *apm;
163
164 webrtc::StreamConfig config =
165 webrtc::StreamConfig(rate, num_channels);
166 apm = reinterpret_cast<webrtc::AudioProcessing *>(ptr);
167 return apm->ProcessStream(data, config, config, data);
168}
169
Hsin-Yu Chaob6f63cd2018-03-17 16:52:35 +0800170void webrtc_apm_destroy(webrtc_apm ptr)
171{
172 webrtc::AudioProcessing *apm;
173 apm = reinterpret_cast<webrtc::AudioProcessing *>(ptr);
174 delete apm;
Hsin-Yu Chaob3dfb0e2021-04-20 08:04:00 +0000175
176 std::map<std::string, std::unique_ptr<SampleInfo>> hist;
177
178 if (!metrics_lib_)
179 return;
180
181 webrtc::metrics::GetAndReset(&hist);
182
183 for (auto it = hist.begin(); it != hist.end(); it++) {
184 SampleInfo *info = it->second.get();
185 std::string name = info->name;
186 name.insert(0, hist_name_prefix_);
187 /* info->samples stores <value, # of events> */
188 for (auto sample = info->samples.begin();
189 sample != info->samples.end(); sample++) {
190 for (int i = 0; i < sample->second; i++)
191 metrics_lib_->SendToUMA(name, sample->first,
192 info->min, info->max,
193 info->bucket_count);
194 }
195 }
Hsin-Yu Chaob6f63cd2018-03-17 16:52:35 +0800196}
197
198int webrtc_apm_set_stream_delay(webrtc_apm ptr, int delay_ms)
199{
200 webrtc::AudioProcessing *apm;
201
202 apm = reinterpret_cast<webrtc::AudioProcessing *>(ptr);
203 return apm->set_stream_delay_ms(delay_ms);
204}
205
206int webrtc_apm_aec_dump(webrtc_apm ptr, void** wq_ptr, int start, FILE *handle)
207{
208 webrtc::AudioProcessing *apm;
209 rtc::TaskQueue *work_queue;
210
211 apm = reinterpret_cast<webrtc::AudioProcessing *>(ptr);
212
213 if (start) {
Hsin-Yu Chao8873da32020-11-30 07:50:42 +0000214 work_queue = new rtc::TaskQueue(webrtc::CreateDefaultTaskQueueFactory()->CreateTaskQueue("aecdump-worker-queue",
215 rtc::TaskQueue::Priority::LOW));
Hsin-Yu Chaob6f63cd2018-03-17 16:52:35 +0800216 auto aec_dump = webrtc::AecDumpFactory::Create(handle, -1, work_queue);
217 if (!aec_dump)
218 return -ENOMEM;
219 apm->AttachAecDump(std::move(aec_dump));
220 *wq_ptr = reinterpret_cast<void *>(work_queue);
221 } else {
222 apm->DetachAecDump();
223 work_queue = reinterpret_cast<rtc::TaskQueue *>(*wq_ptr);
224 if (work_queue) {
225 delete work_queue;
226 work_queue = NULL;
227 }
228 }
229 return 0;
230}
231
Hsin-Yu Chaob6f63cd2018-03-17 16:52:35 +0800232} // extern "C"