1 // Copyright 2013 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.
5 #include "content/renderer/media/media_stream_audio_processor_options.h"
7 #include "base/files/file_path.h"
8 #include "base/logging.h"
9 #include "base/path_service.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "content/common/media/media_stream_options.h"
12 #include "content/renderer/media/rtc_media_constraints.h"
13 #include "media/audio/audio_parameters.h"
14 #include "third_party/WebKit/public/platform/WebMediaConstraints.h"
15 #include "third_party/libjingle/source/talk/app/webrtc/mediaconstraintsinterface.h"
16 #include "third_party/webrtc/modules/audio_processing/include/audio_processing.h"
22 // Constant constraint keys which enables default audio constraints on
23 // mediastreams with audio.
27 } const kDefaultAudioConstraints[] = {
28 { webrtc::MediaConstraintsInterface::kEchoCancellation,
29 webrtc::MediaConstraintsInterface::kValueTrue },
30 #if defined(OS_CHROMEOS) || defined(OS_MACOSX)
31 // Enable the extended filter mode AEC on platforms with known echo issues.
32 { webrtc::MediaConstraintsInterface::kExperimentalEchoCancellation,
33 webrtc::MediaConstraintsInterface::kValueTrue },
35 { webrtc::MediaConstraintsInterface::kAutoGainControl,
36 webrtc::MediaConstraintsInterface::kValueTrue },
37 { webrtc::MediaConstraintsInterface::kExperimentalAutoGainControl,
38 webrtc::MediaConstraintsInterface::kValueTrue },
39 { webrtc::MediaConstraintsInterface::kNoiseSuppression,
40 webrtc::MediaConstraintsInterface::kValueTrue },
41 { webrtc::MediaConstraintsInterface::kHighpassFilter,
42 webrtc::MediaConstraintsInterface::kValueTrue },
43 { webrtc::MediaConstraintsInterface::kTypingNoiseDetection,
44 webrtc::MediaConstraintsInterface::kValueTrue },
46 { content::kMediaStreamAudioDucking,
47 webrtc::MediaConstraintsInterface::kValueTrue },
53 void ApplyFixedAudioConstraints(RTCMediaConstraints* constraints) {
54 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kDefaultAudioConstraints); ++i) {
55 bool already_set_value;
56 if (!webrtc::FindConstraint(constraints, kDefaultAudioConstraints[i].key,
57 &already_set_value, NULL)) {
58 constraints->AddOptional(kDefaultAudioConstraints[i].key,
59 kDefaultAudioConstraints[i].value, false);
61 DVLOG(1) << "Constraint " << kDefaultAudioConstraints[i].key
62 << " already set to " << already_set_value;
67 bool NeedsAudioProcessing(const blink::WebMediaConstraints& constraints,
69 RTCMediaConstraints native_constraints(constraints);
70 ApplyFixedAudioConstraints(&native_constraints);
71 if (effects & media::AudioParameters::ECHO_CANCELLER) {
72 // If platform echo canceller is enabled, disable the software AEC.
73 native_constraints.AddOptional(
74 MediaConstraintsInterface::kEchoCancellation,
75 MediaConstraintsInterface::kValueFalse, true);
77 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kDefaultAudioConstraints); ++i) {
79 if (webrtc::FindConstraint(&native_constraints,
80 kDefaultAudioConstraints[i].key, &value, NULL) &&
89 bool GetPropertyFromConstraints(const MediaConstraintsInterface* constraints,
90 const std::string& key) {
92 return webrtc::FindConstraint(constraints, key, &value, NULL) && value;
95 void EnableEchoCancellation(AudioProcessing* audio_processing) {
96 #if defined(OS_ANDROID)
97 // Mobile devices are using AECM.
98 int err = audio_processing->echo_control_mobile()->set_routing_mode(
99 webrtc::EchoControlMobile::kSpeakerphone);
100 err |= audio_processing->echo_control_mobile()->Enable(true);
103 int err = audio_processing->echo_cancellation()->set_suppression_level(
104 webrtc::EchoCancellation::kHighSuppression);
106 // Enable the metrics for AEC.
107 err |= audio_processing->echo_cancellation()->enable_metrics(true);
108 err |= audio_processing->echo_cancellation()->enable_delay_logging(true);
109 err |= audio_processing->echo_cancellation()->Enable(true);
114 void EnableNoiseSuppression(AudioProcessing* audio_processing) {
115 int err = audio_processing->noise_suppression()->set_level(
116 webrtc::NoiseSuppression::kHigh);
117 err |= audio_processing->noise_suppression()->Enable(true);
121 void EnableHighPassFilter(AudioProcessing* audio_processing) {
122 CHECK_EQ(audio_processing->high_pass_filter()->Enable(true), 0);
125 void EnableTypingDetection(AudioProcessing* audio_processing) {
126 int err = audio_processing->voice_detection()->Enable(true);
127 err |= audio_processing->voice_detection()->set_likelihood(
128 webrtc::VoiceDetection::kVeryLowLikelihood);
132 void EnableExperimentalEchoCancellation(AudioProcessing* audio_processing) {
133 webrtc::Config config;
134 config.Set<webrtc::DelayCorrection>(new webrtc::DelayCorrection(true));
135 audio_processing->SetExtraOptions(config);
138 void StartAecDump(AudioProcessing* audio_processing) {
139 // TODO(grunell): Figure out a more suitable directory for the audio dump
142 #if defined(CHROMEOS)
143 PathService::Get(base::DIR_TEMP, &path);
144 #elif defined(ANDROID)
145 path = base::FilePath(FILE_PATH_LITERAL("sdcard"));
147 PathService::Get(base::DIR_EXE, &path);
149 base::FilePath file = path.Append(FILE_PATH_LITERAL("audio.aecdump"));
152 const std::string file_name = base::WideToUTF8(file.value());
154 const std::string file_name = file.value();
156 if (audio_processing->StartDebugRecording(file_name.c_str()))
157 DLOG(ERROR) << "Fail to start AEC debug recording";
160 void StopAecDump(AudioProcessing* audio_processing) {
161 if (audio_processing->StopDebugRecording())
162 DLOG(ERROR) << "Fail to stop AEC debug recording";
165 void EnableAutomaticGainControl(AudioProcessing* audio_processing) {
166 #if defined(OS_ANDROID) || defined(OS_IOS)
167 const webrtc::GainControl::Mode mode = webrtc::GainControl::kFixedDigital;
169 const webrtc::GainControl::Mode mode = webrtc::GainControl::kAdaptiveAnalog;
171 int err = audio_processing->gain_control()->set_mode(mode);
172 err |= audio_processing->gain_control()->Enable(true);
176 } // namespace content