1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker *
4*d9f75844SAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker */
10*d9f75844SAndroid Build Coastguard Worker
11*d9f75844SAndroid Build Coastguard Worker #include "modules/audio_mixer/frame_combiner.h"
12*d9f75844SAndroid Build Coastguard Worker
13*d9f75844SAndroid Build Coastguard Worker #include <algorithm>
14*d9f75844SAndroid Build Coastguard Worker #include <array>
15*d9f75844SAndroid Build Coastguard Worker #include <cstdint>
16*d9f75844SAndroid Build Coastguard Worker #include <iterator>
17*d9f75844SAndroid Build Coastguard Worker #include <memory>
18*d9f75844SAndroid Build Coastguard Worker #include <string>
19*d9f75844SAndroid Build Coastguard Worker #include <utility>
20*d9f75844SAndroid Build Coastguard Worker #include <vector>
21*d9f75844SAndroid Build Coastguard Worker
22*d9f75844SAndroid Build Coastguard Worker #include "api/array_view.h"
23*d9f75844SAndroid Build Coastguard Worker #include "api/rtp_packet_info.h"
24*d9f75844SAndroid Build Coastguard Worker #include "api/rtp_packet_infos.h"
25*d9f75844SAndroid Build Coastguard Worker #include "common_audio/include/audio_util.h"
26*d9f75844SAndroid Build Coastguard Worker #include "modules/audio_mixer/audio_frame_manipulator.h"
27*d9f75844SAndroid Build Coastguard Worker #include "modules/audio_mixer/audio_mixer_impl.h"
28*d9f75844SAndroid Build Coastguard Worker #include "modules/audio_processing/include/audio_frame_view.h"
29*d9f75844SAndroid Build Coastguard Worker #include "modules/audio_processing/include/audio_processing.h"
30*d9f75844SAndroid Build Coastguard Worker #include "modules/audio_processing/logging/apm_data_dumper.h"
31*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/arraysize.h"
32*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/checks.h"
33*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/numerics/safe_conversions.h"
34*d9f75844SAndroid Build Coastguard Worker #include "system_wrappers/include/metrics.h"
35*d9f75844SAndroid Build Coastguard Worker
36*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
37*d9f75844SAndroid Build Coastguard Worker namespace {
38*d9f75844SAndroid Build Coastguard Worker
39*d9f75844SAndroid Build Coastguard Worker using MixingBuffer =
40*d9f75844SAndroid Build Coastguard Worker std::array<std::array<float, FrameCombiner::kMaximumChannelSize>,
41*d9f75844SAndroid Build Coastguard Worker FrameCombiner::kMaximumNumberOfChannels>;
42*d9f75844SAndroid Build Coastguard Worker
SetAudioFrameFields(rtc::ArrayView<const AudioFrame * const> mix_list,size_t number_of_channels,int sample_rate,size_t number_of_streams,AudioFrame * audio_frame_for_mixing)43*d9f75844SAndroid Build Coastguard Worker void SetAudioFrameFields(rtc::ArrayView<const AudioFrame* const> mix_list,
44*d9f75844SAndroid Build Coastguard Worker size_t number_of_channels,
45*d9f75844SAndroid Build Coastguard Worker int sample_rate,
46*d9f75844SAndroid Build Coastguard Worker size_t number_of_streams,
47*d9f75844SAndroid Build Coastguard Worker AudioFrame* audio_frame_for_mixing) {
48*d9f75844SAndroid Build Coastguard Worker const size_t samples_per_channel = static_cast<size_t>(
49*d9f75844SAndroid Build Coastguard Worker (sample_rate * webrtc::AudioMixerImpl::kFrameDurationInMs) / 1000);
50*d9f75844SAndroid Build Coastguard Worker
51*d9f75844SAndroid Build Coastguard Worker // TODO(minyue): Issue bugs.webrtc.org/3390.
52*d9f75844SAndroid Build Coastguard Worker // Audio frame timestamp. The 'timestamp_' field is set to dummy
53*d9f75844SAndroid Build Coastguard Worker // value '0', because it is only supported in the one channel case and
54*d9f75844SAndroid Build Coastguard Worker // is then updated in the helper functions.
55*d9f75844SAndroid Build Coastguard Worker audio_frame_for_mixing->UpdateFrame(
56*d9f75844SAndroid Build Coastguard Worker 0, nullptr, samples_per_channel, sample_rate, AudioFrame::kUndefined,
57*d9f75844SAndroid Build Coastguard Worker AudioFrame::kVadUnknown, number_of_channels);
58*d9f75844SAndroid Build Coastguard Worker
59*d9f75844SAndroid Build Coastguard Worker if (mix_list.empty()) {
60*d9f75844SAndroid Build Coastguard Worker audio_frame_for_mixing->elapsed_time_ms_ = -1;
61*d9f75844SAndroid Build Coastguard Worker } else {
62*d9f75844SAndroid Build Coastguard Worker audio_frame_for_mixing->timestamp_ = mix_list[0]->timestamp_;
63*d9f75844SAndroid Build Coastguard Worker audio_frame_for_mixing->elapsed_time_ms_ = mix_list[0]->elapsed_time_ms_;
64*d9f75844SAndroid Build Coastguard Worker audio_frame_for_mixing->ntp_time_ms_ = mix_list[0]->ntp_time_ms_;
65*d9f75844SAndroid Build Coastguard Worker std::vector<RtpPacketInfo> packet_infos;
66*d9f75844SAndroid Build Coastguard Worker for (const auto& frame : mix_list) {
67*d9f75844SAndroid Build Coastguard Worker audio_frame_for_mixing->timestamp_ =
68*d9f75844SAndroid Build Coastguard Worker std::min(audio_frame_for_mixing->timestamp_, frame->timestamp_);
69*d9f75844SAndroid Build Coastguard Worker audio_frame_for_mixing->ntp_time_ms_ =
70*d9f75844SAndroid Build Coastguard Worker std::min(audio_frame_for_mixing->ntp_time_ms_, frame->ntp_time_ms_);
71*d9f75844SAndroid Build Coastguard Worker audio_frame_for_mixing->elapsed_time_ms_ = std::max(
72*d9f75844SAndroid Build Coastguard Worker audio_frame_for_mixing->elapsed_time_ms_, frame->elapsed_time_ms_);
73*d9f75844SAndroid Build Coastguard Worker packet_infos.insert(packet_infos.end(), frame->packet_infos_.begin(),
74*d9f75844SAndroid Build Coastguard Worker frame->packet_infos_.end());
75*d9f75844SAndroid Build Coastguard Worker }
76*d9f75844SAndroid Build Coastguard Worker audio_frame_for_mixing->packet_infos_ =
77*d9f75844SAndroid Build Coastguard Worker RtpPacketInfos(std::move(packet_infos));
78*d9f75844SAndroid Build Coastguard Worker }
79*d9f75844SAndroid Build Coastguard Worker }
80*d9f75844SAndroid Build Coastguard Worker
MixFewFramesWithNoLimiter(rtc::ArrayView<const AudioFrame * const> mix_list,AudioFrame * audio_frame_for_mixing)81*d9f75844SAndroid Build Coastguard Worker void MixFewFramesWithNoLimiter(rtc::ArrayView<const AudioFrame* const> mix_list,
82*d9f75844SAndroid Build Coastguard Worker AudioFrame* audio_frame_for_mixing) {
83*d9f75844SAndroid Build Coastguard Worker if (mix_list.empty()) {
84*d9f75844SAndroid Build Coastguard Worker audio_frame_for_mixing->Mute();
85*d9f75844SAndroid Build Coastguard Worker return;
86*d9f75844SAndroid Build Coastguard Worker }
87*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_LE(mix_list.size(), 1);
88*d9f75844SAndroid Build Coastguard Worker std::copy(mix_list[0]->data(),
89*d9f75844SAndroid Build Coastguard Worker mix_list[0]->data() +
90*d9f75844SAndroid Build Coastguard Worker mix_list[0]->num_channels_ * mix_list[0]->samples_per_channel_,
91*d9f75844SAndroid Build Coastguard Worker audio_frame_for_mixing->mutable_data());
92*d9f75844SAndroid Build Coastguard Worker }
93*d9f75844SAndroid Build Coastguard Worker
MixToFloatFrame(rtc::ArrayView<const AudioFrame * const> mix_list,size_t samples_per_channel,size_t number_of_channels,MixingBuffer * mixing_buffer)94*d9f75844SAndroid Build Coastguard Worker void MixToFloatFrame(rtc::ArrayView<const AudioFrame* const> mix_list,
95*d9f75844SAndroid Build Coastguard Worker size_t samples_per_channel,
96*d9f75844SAndroid Build Coastguard Worker size_t number_of_channels,
97*d9f75844SAndroid Build Coastguard Worker MixingBuffer* mixing_buffer) {
98*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_LE(samples_per_channel, FrameCombiner::kMaximumChannelSize);
99*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_LE(number_of_channels, FrameCombiner::kMaximumNumberOfChannels);
100*d9f75844SAndroid Build Coastguard Worker // Clear the mixing buffer.
101*d9f75844SAndroid Build Coastguard Worker *mixing_buffer = {};
102*d9f75844SAndroid Build Coastguard Worker
103*d9f75844SAndroid Build Coastguard Worker // Convert to FloatS16 and mix.
104*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < mix_list.size(); ++i) {
105*d9f75844SAndroid Build Coastguard Worker const AudioFrame* const frame = mix_list[i];
106*d9f75844SAndroid Build Coastguard Worker const int16_t* const frame_data = frame->data();
107*d9f75844SAndroid Build Coastguard Worker for (size_t j = 0; j < std::min(number_of_channels,
108*d9f75844SAndroid Build Coastguard Worker FrameCombiner::kMaximumNumberOfChannels);
109*d9f75844SAndroid Build Coastguard Worker ++j) {
110*d9f75844SAndroid Build Coastguard Worker for (size_t k = 0; k < std::min(samples_per_channel,
111*d9f75844SAndroid Build Coastguard Worker FrameCombiner::kMaximumChannelSize);
112*d9f75844SAndroid Build Coastguard Worker ++k) {
113*d9f75844SAndroid Build Coastguard Worker (*mixing_buffer)[j][k] += frame_data[number_of_channels * k + j];
114*d9f75844SAndroid Build Coastguard Worker }
115*d9f75844SAndroid Build Coastguard Worker }
116*d9f75844SAndroid Build Coastguard Worker }
117*d9f75844SAndroid Build Coastguard Worker }
118*d9f75844SAndroid Build Coastguard Worker
RunLimiter(AudioFrameView<float> mixing_buffer_view,Limiter * limiter)119*d9f75844SAndroid Build Coastguard Worker void RunLimiter(AudioFrameView<float> mixing_buffer_view, Limiter* limiter) {
120*d9f75844SAndroid Build Coastguard Worker const size_t sample_rate = mixing_buffer_view.samples_per_channel() * 1000 /
121*d9f75844SAndroid Build Coastguard Worker AudioMixerImpl::kFrameDurationInMs;
122*d9f75844SAndroid Build Coastguard Worker // TODO(alessiob): Avoid calling SetSampleRate every time.
123*d9f75844SAndroid Build Coastguard Worker limiter->SetSampleRate(sample_rate);
124*d9f75844SAndroid Build Coastguard Worker limiter->Process(mixing_buffer_view);
125*d9f75844SAndroid Build Coastguard Worker }
126*d9f75844SAndroid Build Coastguard Worker
127*d9f75844SAndroid Build Coastguard Worker // Both interleaves and rounds.
InterleaveToAudioFrame(AudioFrameView<const float> mixing_buffer_view,AudioFrame * audio_frame_for_mixing)128*d9f75844SAndroid Build Coastguard Worker void InterleaveToAudioFrame(AudioFrameView<const float> mixing_buffer_view,
129*d9f75844SAndroid Build Coastguard Worker AudioFrame* audio_frame_for_mixing) {
130*d9f75844SAndroid Build Coastguard Worker const size_t number_of_channels = mixing_buffer_view.num_channels();
131*d9f75844SAndroid Build Coastguard Worker const size_t samples_per_channel = mixing_buffer_view.samples_per_channel();
132*d9f75844SAndroid Build Coastguard Worker int16_t* const mixing_data = audio_frame_for_mixing->mutable_data();
133*d9f75844SAndroid Build Coastguard Worker // Put data in the result frame.
134*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < number_of_channels; ++i) {
135*d9f75844SAndroid Build Coastguard Worker for (size_t j = 0; j < samples_per_channel; ++j) {
136*d9f75844SAndroid Build Coastguard Worker mixing_data[number_of_channels * j + i] =
137*d9f75844SAndroid Build Coastguard Worker FloatS16ToS16(mixing_buffer_view.channel(i)[j]);
138*d9f75844SAndroid Build Coastguard Worker }
139*d9f75844SAndroid Build Coastguard Worker }
140*d9f75844SAndroid Build Coastguard Worker }
141*d9f75844SAndroid Build Coastguard Worker } // namespace
142*d9f75844SAndroid Build Coastguard Worker
143*d9f75844SAndroid Build Coastguard Worker constexpr size_t FrameCombiner::kMaximumNumberOfChannels;
144*d9f75844SAndroid Build Coastguard Worker constexpr size_t FrameCombiner::kMaximumChannelSize;
145*d9f75844SAndroid Build Coastguard Worker
FrameCombiner(bool use_limiter)146*d9f75844SAndroid Build Coastguard Worker FrameCombiner::FrameCombiner(bool use_limiter)
147*d9f75844SAndroid Build Coastguard Worker : data_dumper_(new ApmDataDumper(0)),
148*d9f75844SAndroid Build Coastguard Worker mixing_buffer_(
149*d9f75844SAndroid Build Coastguard Worker std::make_unique<std::array<std::array<float, kMaximumChannelSize>,
150*d9f75844SAndroid Build Coastguard Worker kMaximumNumberOfChannels>>()),
151*d9f75844SAndroid Build Coastguard Worker limiter_(static_cast<size_t>(48000), data_dumper_.get(), "AudioMixer"),
152*d9f75844SAndroid Build Coastguard Worker use_limiter_(use_limiter) {
153*d9f75844SAndroid Build Coastguard Worker static_assert(kMaximumChannelSize * kMaximumNumberOfChannels <=
154*d9f75844SAndroid Build Coastguard Worker AudioFrame::kMaxDataSizeSamples,
155*d9f75844SAndroid Build Coastguard Worker "");
156*d9f75844SAndroid Build Coastguard Worker }
157*d9f75844SAndroid Build Coastguard Worker
158*d9f75844SAndroid Build Coastguard Worker FrameCombiner::~FrameCombiner() = default;
159*d9f75844SAndroid Build Coastguard Worker
Combine(rtc::ArrayView<AudioFrame * const> mix_list,size_t number_of_channels,int sample_rate,size_t number_of_streams,AudioFrame * audio_frame_for_mixing)160*d9f75844SAndroid Build Coastguard Worker void FrameCombiner::Combine(rtc::ArrayView<AudioFrame* const> mix_list,
161*d9f75844SAndroid Build Coastguard Worker size_t number_of_channels,
162*d9f75844SAndroid Build Coastguard Worker int sample_rate,
163*d9f75844SAndroid Build Coastguard Worker size_t number_of_streams,
164*d9f75844SAndroid Build Coastguard Worker AudioFrame* audio_frame_for_mixing) {
165*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(audio_frame_for_mixing);
166*d9f75844SAndroid Build Coastguard Worker
167*d9f75844SAndroid Build Coastguard Worker SetAudioFrameFields(mix_list, number_of_channels, sample_rate,
168*d9f75844SAndroid Build Coastguard Worker number_of_streams, audio_frame_for_mixing);
169*d9f75844SAndroid Build Coastguard Worker
170*d9f75844SAndroid Build Coastguard Worker const size_t samples_per_channel = static_cast<size_t>(
171*d9f75844SAndroid Build Coastguard Worker (sample_rate * webrtc::AudioMixerImpl::kFrameDurationInMs) / 1000);
172*d9f75844SAndroid Build Coastguard Worker
173*d9f75844SAndroid Build Coastguard Worker for (const auto* frame : mix_list) {
174*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_EQ(samples_per_channel, frame->samples_per_channel_);
175*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_EQ(sample_rate, frame->sample_rate_hz_);
176*d9f75844SAndroid Build Coastguard Worker }
177*d9f75844SAndroid Build Coastguard Worker
178*d9f75844SAndroid Build Coastguard Worker // The 'num_channels_' field of frames in 'mix_list' could be
179*d9f75844SAndroid Build Coastguard Worker // different from 'number_of_channels'.
180*d9f75844SAndroid Build Coastguard Worker for (auto* frame : mix_list) {
181*d9f75844SAndroid Build Coastguard Worker RemixFrame(number_of_channels, frame);
182*d9f75844SAndroid Build Coastguard Worker }
183*d9f75844SAndroid Build Coastguard Worker
184*d9f75844SAndroid Build Coastguard Worker if (number_of_streams <= 1) {
185*d9f75844SAndroid Build Coastguard Worker MixFewFramesWithNoLimiter(mix_list, audio_frame_for_mixing);
186*d9f75844SAndroid Build Coastguard Worker return;
187*d9f75844SAndroid Build Coastguard Worker }
188*d9f75844SAndroid Build Coastguard Worker
189*d9f75844SAndroid Build Coastguard Worker MixToFloatFrame(mix_list, samples_per_channel, number_of_channels,
190*d9f75844SAndroid Build Coastguard Worker mixing_buffer_.get());
191*d9f75844SAndroid Build Coastguard Worker
192*d9f75844SAndroid Build Coastguard Worker const size_t output_number_of_channels =
193*d9f75844SAndroid Build Coastguard Worker std::min(number_of_channels, kMaximumNumberOfChannels);
194*d9f75844SAndroid Build Coastguard Worker const size_t output_samples_per_channel =
195*d9f75844SAndroid Build Coastguard Worker std::min(samples_per_channel, kMaximumChannelSize);
196*d9f75844SAndroid Build Coastguard Worker
197*d9f75844SAndroid Build Coastguard Worker // Put float data in an AudioFrameView.
198*d9f75844SAndroid Build Coastguard Worker std::array<float*, kMaximumNumberOfChannels> channel_pointers{};
199*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < output_number_of_channels; ++i) {
200*d9f75844SAndroid Build Coastguard Worker channel_pointers[i] = &(*mixing_buffer_.get())[i][0];
201*d9f75844SAndroid Build Coastguard Worker }
202*d9f75844SAndroid Build Coastguard Worker AudioFrameView<float> mixing_buffer_view(&channel_pointers[0],
203*d9f75844SAndroid Build Coastguard Worker output_number_of_channels,
204*d9f75844SAndroid Build Coastguard Worker output_samples_per_channel);
205*d9f75844SAndroid Build Coastguard Worker
206*d9f75844SAndroid Build Coastguard Worker if (use_limiter_) {
207*d9f75844SAndroid Build Coastguard Worker RunLimiter(mixing_buffer_view, &limiter_);
208*d9f75844SAndroid Build Coastguard Worker }
209*d9f75844SAndroid Build Coastguard Worker
210*d9f75844SAndroid Build Coastguard Worker InterleaveToAudioFrame(mixing_buffer_view, audio_frame_for_mixing);
211*d9f75844SAndroid Build Coastguard Worker }
212*d9f75844SAndroid Build Coastguard Worker
213*d9f75844SAndroid Build Coastguard Worker } // namespace webrtc
214