blob: f8ae8e500329a4e97d4ce0071c83c14cf7b3cbbd [file] [log] [blame]
andrew@webrtc.org40ee3d02014-04-03 21:56:01 +00001/*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "voice_engine/transmit_mixer.h"
andrew@webrtc.org40ee3d02014-04-03 21:56:01 +000012
kwibergb7f89d62016-02-17 10:04:18 -080013#include <memory>
14
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020015#include "audio/utility/audio_frame_operations.h"
16#include "rtc_base/format_macros.h"
17#include "rtc_base/location.h"
18#include "rtc_base/logging.h"
19#include "system_wrappers/include/event_wrapper.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020020#include "voice_engine/channel.h"
21#include "voice_engine/channel_manager.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020022#include "voice_engine/utility.h"
andrew@webrtc.org40ee3d02014-04-03 21:56:01 +000023
andrew@webrtc.org40ee3d02014-04-03 21:56:01 +000024namespace webrtc {
25namespace voe {
26
solenbergfc3a2e32017-09-26 09:35:01 -070027// TODO(solenberg): The thread safety in this class is dubious.
andrew@webrtc.org40ee3d02014-04-03 21:56:01 +000028
andrew@webrtc.org40ee3d02014-04-03 21:56:01 +000029int32_t
Fredrik Solenberg4332d092017-10-04 09:53:35 +020030TransmitMixer::Create(TransmitMixer*& mixer)
andrew@webrtc.org40ee3d02014-04-03 21:56:01 +000031{
Fredrik Solenberg4332d092017-10-04 09:53:35 +020032 mixer = new TransmitMixer();
andrew@webrtc.org40ee3d02014-04-03 21:56:01 +000033 if (mixer == NULL)
34 {
Fredrik Solenberg4332d092017-10-04 09:53:35 +020035 LOG(LS_ERROR) << "TransmitMixer::Create() unable to allocate memory "
36 "for mixer";
andrew@webrtc.org40ee3d02014-04-03 21:56:01 +000037 return -1;
38 }
39 return 0;
40}
41
42void
43TransmitMixer::Destroy(TransmitMixer*& mixer)
44{
45 if (mixer)
46 {
47 delete mixer;
48 mixer = NULL;
49 }
50}
51
solenbergfc3a2e32017-09-26 09:35:01 -070052TransmitMixer::~TransmitMixer() = default;
andrew@webrtc.org40ee3d02014-04-03 21:56:01 +000053
solenbergfc3a2e32017-09-26 09:35:01 -070054void TransmitMixer::SetEngineInformation(ChannelManager* channelManager) {
55 _channelManagerPtr = channelManager;
andrew@webrtc.org40ee3d02014-04-03 21:56:01 +000056}
57
58int32_t
59TransmitMixer::SetAudioProcessingModule(AudioProcessing* audioProcessingModule)
60{
andrew@webrtc.org40ee3d02014-04-03 21:56:01 +000061 audioproc_ = audioProcessingModule;
62 return 0;
63}
64
Peter Kasting69558702016-01-12 16:26:35 -080065void TransmitMixer::GetSendCodecInfo(int* max_sample_rate,
66 size_t* max_channels) {
andrew@webrtc.org40ee3d02014-04-03 21:56:01 +000067 *max_sample_rate = 8000;
68 *max_channels = 1;
69 for (ChannelManager::Iterator it(_channelManagerPtr); it.IsValid();
70 it.Increment()) {
71 Channel* channel = it.GetChannel();
72 if (channel->Sending()) {
Karl Wiberg88182372017-10-17 01:02:46 +020073 const auto props = channel->GetEncoderProps();
74 RTC_CHECK(props);
75 *max_sample_rate = std::max(*max_sample_rate, props->sample_rate_hz);
76 *max_channels = std::max(*max_channels, props->num_channels);
andrew@webrtc.org40ee3d02014-04-03 21:56:01 +000077 }
78 }
79}
80
81int32_t
82TransmitMixer::PrepareDemux(const void* audioSamples,
Peter Kastingdce40cf2015-08-24 14:52:23 -070083 size_t nSamples,
Peter Kasting69558702016-01-12 16:26:35 -080084 size_t nChannels,
andrew@webrtc.org40ee3d02014-04-03 21:56:01 +000085 uint32_t samplesPerSec,
86 uint16_t totalDelayMS,
87 int32_t clockDrift,
88 uint16_t currentMicLevel,
89 bool keyPressed)
90{
andrew@webrtc.org40ee3d02014-04-03 21:56:01 +000091 // --- Resample input audio and create/store the initial audio frame
92 GenerateAudioFrame(static_cast<const int16_t*>(audioSamples),
93 nSamples,
94 nChannels,
95 samplesPerSec);
96
andrew@webrtc.org40ee3d02014-04-03 21:56:01 +000097 // --- Near-end audio processing.
98 ProcessAudio(totalDelayMS, clockDrift, currentMicLevel, keyPressed);
99
100 if (swap_stereo_channels_ && stereo_codec_)
101 // Only bother swapping if we're using a stereo codec.
102 AudioFrameOperations::SwapStereoChannels(&_audioFrame);
103
104 // --- Annoying typing detection (utilizes the APM/VAD decision)
henrik.lundinf00082d2016-12-05 02:22:12 -0800105#if WEBRTC_VOICE_ENGINE_TYPING_DETECTION
andrew@webrtc.org40ee3d02014-04-03 21:56:01 +0000106 TypingDetection(keyPressed);
107#endif
108
andrew@webrtc.org40ee3d02014-04-03 21:56:01 +0000109 // --- Measure audio level of speech after all processing.
zsteine76bd3a2017-07-14 12:17:49 -0700110 double sample_duration = static_cast<double>(nSamples) / samplesPerSec;
zstein3c451862017-07-20 09:57:42 -0700111 _audioLevel.ComputeLevel(_audioFrame, sample_duration);
zsteine76bd3a2017-07-14 12:17:49 -0700112
andrew@webrtc.org40ee3d02014-04-03 21:56:01 +0000113 return 0;
114}
115
henrikaec6fbd22017-03-31 05:43:36 -0700116void TransmitMixer::ProcessAndEncodeAudio() {
117 RTC_DCHECK_GT(_audioFrame.samples_per_channel_, 0);
118 for (ChannelManager::Iterator it(_channelManagerPtr); it.IsValid();
119 it.Increment()) {
120 Channel* const channel = it.GetChannel();
121 if (channel->Sending()) {
122 channel->ProcessAndEncodeAudio(_audioFrame);
andrew@webrtc.org40ee3d02014-04-03 21:56:01 +0000123 }
andrew@webrtc.org40ee3d02014-04-03 21:56:01 +0000124 }
125}
126
127uint32_t TransmitMixer::CaptureLevel() const
128{
129 return _captureLevel;
130}
131
andrew@webrtc.org40ee3d02014-04-03 21:56:01 +0000132int32_t
133TransmitMixer::StopSend()
134{
andrew@webrtc.org40ee3d02014-04-03 21:56:01 +0000135 _audioLevel.Clear();
136 return 0;
137}
138
andrew@webrtc.org40ee3d02014-04-03 21:56:01 +0000139int8_t TransmitMixer::AudioLevel() const
140{
141 // Speech + file level [0,9]
142 return _audioLevel.Level();
143}
144
145int16_t TransmitMixer::AudioLevelFullRange() const
146{
147 // Speech + file level [0,32767]
148 return _audioLevel.LevelFullRange();
149}
150
zsteine76bd3a2017-07-14 12:17:49 -0700151double TransmitMixer::GetTotalInputEnergy() const {
zstein3c451862017-07-20 09:57:42 -0700152 return _audioLevel.TotalEnergy();
zsteine76bd3a2017-07-14 12:17:49 -0700153}
154
155double TransmitMixer::GetTotalInputDuration() const {
zstein3c451862017-07-20 09:57:42 -0700156 return _audioLevel.TotalDuration();
zsteine76bd3a2017-07-14 12:17:49 -0700157}
158
andrew@webrtc.org40ee3d02014-04-03 21:56:01 +0000159void TransmitMixer::GenerateAudioFrame(const int16_t* audio,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700160 size_t samples_per_channel,
Peter Kasting69558702016-01-12 16:26:35 -0800161 size_t num_channels,
andrew@webrtc.org40ee3d02014-04-03 21:56:01 +0000162 int sample_rate_hz) {
163 int codec_rate;
Peter Kasting69558702016-01-12 16:26:35 -0800164 size_t num_codec_channels;
andrew@webrtc.org40ee3d02014-04-03 21:56:01 +0000165 GetSendCodecInfo(&codec_rate, &num_codec_channels);
andrew@webrtc.org40ee3d02014-04-03 21:56:01 +0000166 stereo_codec_ = num_codec_channels == 2;
167
Alejandro Luebscdfe20b2015-09-23 12:49:12 -0700168 // We want to process at the lowest rate possible without losing information.
169 // Choose the lowest native rate at least equal to the input and codec rates.
170 const int min_processing_rate = std::min(sample_rate_hz, codec_rate);
171 for (size_t i = 0; i < AudioProcessing::kNumNativeSampleRates; ++i) {
172 _audioFrame.sample_rate_hz_ = AudioProcessing::kNativeSampleRatesHz[i];
173 if (_audioFrame.sample_rate_hz_ >= min_processing_rate) {
174 break;
175 }
andrew@webrtc.org40ee3d02014-04-03 21:56:01 +0000176 }
Alejandro Luebscdfe20b2015-09-23 12:49:12 -0700177 _audioFrame.num_channels_ = std::min(num_channels, num_codec_channels);
178 RemixAndResample(audio, samples_per_channel, num_channels, sample_rate_hz,
179 &resampler_, &_audioFrame);
andrew@webrtc.org40ee3d02014-04-03 21:56:01 +0000180}
181
andrew@webrtc.org40ee3d02014-04-03 21:56:01 +0000182void TransmitMixer::ProcessAudio(int delay_ms, int clock_drift,
183 int current_mic_level, bool key_pressed) {
184 if (audioproc_->set_stream_delay_ms(delay_ms) != 0) {
pbosad856222015-11-27 09:48:36 -0800185 // Silently ignore this failure to avoid flooding the logs.
andrew@webrtc.org40ee3d02014-04-03 21:56:01 +0000186 }
187
188 GainControl* agc = audioproc_->gain_control();
189 if (agc->set_stream_analog_level(current_mic_level) != 0) {
pbosad856222015-11-27 09:48:36 -0800190 LOG(LS_ERROR) << "set_stream_analog_level failed: current_mic_level = "
191 << current_mic_level;
andrew@webrtc.org40ee3d02014-04-03 21:56:01 +0000192 assert(false);
193 }
194
195 EchoCancellation* aec = audioproc_->echo_cancellation();
196 if (aec->is_drift_compensation_enabled()) {
197 aec->set_stream_drift_samples(clock_drift);
198 }
199
200 audioproc_->set_stream_key_pressed(key_pressed);
201
202 int err = audioproc_->ProcessStream(&_audioFrame);
203 if (err != 0) {
204 LOG(LS_ERROR) << "ProcessStream() error: " << err;
205 assert(false);
206 }
207
208 // Store new capture level. Only updated when analog AGC is enabled.
209 _captureLevel = agc->stream_analog_level();
andrew@webrtc.org40ee3d02014-04-03 21:56:01 +0000210}
211
henrik.lundinf00082d2016-12-05 02:22:12 -0800212#if WEBRTC_VOICE_ENGINE_TYPING_DETECTION
solenbergfc3a2e32017-09-26 09:35:01 -0700213void TransmitMixer::TypingDetection(bool key_pressed)
andrew@webrtc.org40ee3d02014-04-03 21:56:01 +0000214{
215 // We let the VAD determine if we're using this feature or not.
216 if (_audioFrame.vad_activity_ == AudioFrame::kVadUnknown) {
217 return;
218 }
219
solenbergfc3a2e32017-09-26 09:35:01 -0700220 bool vad_active = _audioFrame.vad_activity_ == AudioFrame::kVadActive;
221 bool typing_detected = typing_detection_.Process(key_pressed, vad_active);
222
223 rtc::CritScope cs(&lock_);
224 typing_noise_detected_ = typing_detected;
andrew@webrtc.org40ee3d02014-04-03 21:56:01 +0000225}
226#endif
227
andrew@webrtc.org40ee3d02014-04-03 21:56:01 +0000228void TransmitMixer::EnableStereoChannelSwapping(bool enable) {
229 swap_stereo_channels_ = enable;
230}
231
232bool TransmitMixer::IsStereoChannelSwappingEnabled() {
233 return swap_stereo_channels_;
234}
235
solenbergfc3a2e32017-09-26 09:35:01 -0700236bool TransmitMixer::typing_noise_detected() const {
237 rtc::CritScope cs(&lock_);
238 return typing_noise_detected_;
239}
240
andrew@webrtc.org40ee3d02014-04-03 21:56:01 +0000241} // namespace voe
242} // namespace webrtc