remix_resample.cc (3687B)
1 /* 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 11 #include "audio/remix_resample.h" 12 13 #include <array> 14 #include <cstdint> 15 16 #include "api/audio/audio_frame.h" 17 #include "api/audio/audio_view.h" 18 #include "audio/utility/audio_frame_operations.h" 19 #include "common_audio/resampler/include/push_resampler.h" 20 #include "rtc_base/checks.h" 21 22 namespace webrtc { 23 namespace voe { 24 25 void RemixAndResample(const AudioFrame& src_frame, 26 PushResampler<int16_t>* resampler, 27 AudioFrame* dst_frame) { 28 RemixAndResample(src_frame.data_view(), src_frame.sample_rate_hz_, resampler, 29 dst_frame); 30 dst_frame->timestamp_ = src_frame.timestamp_; 31 dst_frame->elapsed_time_ms_ = src_frame.elapsed_time_ms_; 32 dst_frame->ntp_time_ms_ = src_frame.ntp_time_ms_; 33 dst_frame->packet_infos_ = src_frame.packet_infos_; 34 } 35 36 void RemixAndResample(InterleavedView<const int16_t> src_data, 37 int sample_rate_hz, 38 PushResampler<int16_t>* resampler, 39 AudioFrame* dst_frame) { 40 // The `samples_per_channel_` members must have been set correctly based on 41 // the associated sample rate and the assumed 10ms buffer size. 42 // TODO(tommi): Remove the `sample_rate_hz` param. 43 RTC_DCHECK_EQ(SampleRateToDefaultChannelSize(sample_rate_hz), 44 src_data.samples_per_channel()); 45 RTC_DCHECK_EQ(SampleRateToDefaultChannelSize(dst_frame->sample_rate_hz_), 46 dst_frame->samples_per_channel()); 47 48 // Temporary buffer in case downmixing is required. 49 std::array<int16_t, AudioFrame::kMaxDataSizeSamples> downmixed_audio; 50 51 // Downmix before resampling. 52 if (src_data.num_channels() > dst_frame->num_channels_) { 53 RTC_DCHECK(src_data.num_channels() == 2 || src_data.num_channels() == 4) 54 << "num_channels: " << src_data.num_channels(); 55 RTC_DCHECK(dst_frame->num_channels_ == 1 || dst_frame->num_channels_ == 2) 56 << "dst_frame->num_channels_: " << dst_frame->num_channels_; 57 58 InterleavedView<int16_t> downmixed(downmixed_audio.data(), 59 src_data.samples_per_channel(), 60 dst_frame->num_channels_); 61 AudioFrameOperations::DownmixChannels(src_data, downmixed); 62 src_data = downmixed; 63 } 64 65 // TODO(yujo): for muted input frames, don't resample. Either 1) allow 66 // resampler to return output length without doing the resample, so we know 67 // how much to zero here; or 2) make resampler accept a hint that the input is 68 // zeroed. 69 70 // Stash away the originally requested number of channels. Then provide 71 // `dst_frame` as a target buffer with the same number of channels as the 72 // source. 73 auto original_dst_number_of_channels = dst_frame->num_channels_; 74 resampler->Resample(src_data, 75 dst_frame->mutable_data(dst_frame->samples_per_channel_, 76 src_data.num_channels())); 77 78 // Upmix after resampling. 79 if (src_data.num_channels() == 1 && original_dst_number_of_channels == 2) { 80 // The audio in dst_frame really is mono at this point; MonoToStereo will 81 // set this back to stereo. 82 RTC_DCHECK_EQ(dst_frame->num_channels_, 1); 83 AudioFrameOperations::UpmixChannels(2, dst_frame); 84 } 85 } 86 87 } // namespace voe 88 } // namespace webrtc