push_resampler.cc (4618B)
1 /* 2 * Copyright (c) 2013 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 "common_audio/resampler/include/push_resampler.h" 12 13 #include <cstdint> 14 #include <cstring> 15 #include <memory> 16 17 #include "api/audio/audio_view.h" 18 #include "common_audio/include/audio_util.h" 19 #include "common_audio/resampler/push_sinc_resampler.h" 20 #include "rtc_base/checks.h" 21 22 namespace webrtc { 23 24 namespace { 25 // Maximum concurrent number of channels for `PushResampler<>`. 26 // Note that this may be different from what the maximum is for audio codecs. 27 constexpr int kMaxNumberOfChannels = 8; 28 } // namespace 29 30 template <typename T> 31 PushResampler<T>::PushResampler() = default; 32 33 template <typename T> 34 PushResampler<T>::PushResampler(size_t src_samples_per_channel, 35 size_t dst_samples_per_channel, 36 size_t num_channels) { 37 EnsureInitialized(src_samples_per_channel, dst_samples_per_channel, 38 num_channels); 39 } 40 41 template <typename T> 42 PushResampler<T>::~PushResampler() = default; 43 44 template <typename T> 45 void PushResampler<T>::EnsureInitialized(size_t src_samples_per_channel, 46 size_t dst_samples_per_channel, 47 size_t num_channels) { 48 RTC_DCHECK_GT(src_samples_per_channel, 0); 49 RTC_DCHECK_GT(dst_samples_per_channel, 0); 50 RTC_DCHECK_GT(num_channels, 0); 51 RTC_DCHECK_LE(src_samples_per_channel, kMaxSamplesPerChannel10ms); 52 RTC_DCHECK_LE(dst_samples_per_channel, kMaxSamplesPerChannel10ms); 53 RTC_DCHECK_LE(num_channels, kMaxNumberOfChannels); 54 55 if (src_samples_per_channel == SamplesPerChannel(source_view_) && 56 dst_samples_per_channel == SamplesPerChannel(destination_view_) && 57 num_channels == NumChannels(source_view_)) { 58 // No-op if settings haven't changed. 59 return; 60 } 61 62 // Allocate two buffers for all source and destination channels. 63 // Then organize source and destination views together with an array of 64 // resamplers for each channel in the deinterlaved buffers. 65 source_.reset(new T[src_samples_per_channel * num_channels]); 66 destination_.reset(new T[dst_samples_per_channel * num_channels]); 67 source_view_ = DeinterleavedView<T>(source_.get(), src_samples_per_channel, 68 num_channels); 69 destination_view_ = DeinterleavedView<T>( 70 destination_.get(), dst_samples_per_channel, num_channels); 71 resamplers_.resize(num_channels); 72 for (size_t i = 0; i < num_channels; ++i) { 73 resamplers_[i] = std::make_unique<PushSincResampler>( 74 src_samples_per_channel, dst_samples_per_channel); 75 } 76 } 77 78 template <typename T> 79 void PushResampler<T>::Resample(InterleavedView<const T> src, 80 InterleavedView<T> dst) { 81 EnsureInitialized(SamplesPerChannel(src), SamplesPerChannel(dst), 82 NumChannels(src)); 83 84 RTC_DCHECK_EQ(NumChannels(src), NumChannels(source_view_)); 85 RTC_DCHECK_EQ(NumChannels(dst), NumChannels(destination_view_)); 86 RTC_DCHECK_EQ(SamplesPerChannel(src), SamplesPerChannel(source_view_)); 87 RTC_DCHECK_EQ(SamplesPerChannel(dst), SamplesPerChannel(destination_view_)); 88 89 if (SamplesPerChannel(src) == SamplesPerChannel(dst)) { 90 // The old resampler provides this memcpy facility in the case of matching 91 // sample rates, so reproduce it here for the sinc resampler. 92 CopySamples(dst, src); 93 return; 94 } 95 96 Deinterleave(src, source_view_); 97 98 for (size_t i = 0; i < resamplers_.size(); ++i) { 99 size_t dst_length_mono = 100 resamplers_[i]->Resample(source_view_[i], destination_view_[i]); 101 RTC_DCHECK_EQ(dst_length_mono, SamplesPerChannel(dst)); 102 } 103 104 Interleave<T>(destination_view_, dst); 105 } 106 107 template <typename T> 108 void PushResampler<T>::Resample(MonoView<const T> src, MonoView<T> dst) { 109 RTC_DCHECK_EQ(resamplers_.size(), 1); 110 RTC_DCHECK_EQ(SamplesPerChannel(src), SamplesPerChannel(source_view_)); 111 RTC_DCHECK_EQ(SamplesPerChannel(dst), SamplesPerChannel(destination_view_)); 112 113 if (SamplesPerChannel(src) == SamplesPerChannel(dst)) { 114 CopySamples(dst, src); 115 } else { 116 resamplers_[0]->Resample(src, dst); 117 } 118 } 119 120 // Explictly generate required instantiations. 121 template class PushResampler<int16_t>; 122 template class PushResampler<float>; 123 124 } // namespace webrtc