blob: 318d97b72c28ad50f3b0337aaf3b3fd855a542c8 [file] [log] [blame]
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +00001/*
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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "common_audio/resampler/include/push_resampler.h"
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +000012
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000013#include <string.h>
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +000014
Alex Loiko3fc5a202018-10-02 14:09:46 +020015#include "absl/container/inlined_vector.h"
16#include "absl/memory/memory.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020017#include "common_audio/include/audio_util.h"
18#include "common_audio/resampler/include/resampler.h"
19#include "common_audio/resampler/push_sinc_resampler.h"
20#include "rtc_base/checks.h"
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +000021
22namespace webrtc {
Tommif4fc0ff2016-05-26 22:40:09 +020023namespace {
24// These checks were factored out into a non-templatized function
25// due to problems with clang on Windows in debug builds.
26// For some reason having the DCHECKs inline in the template code
27// caused the compiler to generate code that threw off the linker.
Tommi90edc652016-05-26 23:48:16 +020028// TODO(tommi): Re-enable when we've figured out what the problem is.
29// http://crbug.com/615050
Yves Gerey665174f2018-06-19 15:03:05 +020030void CheckValidInitParams(int src_sample_rate_hz,
31 int dst_sample_rate_hz,
Tommif4fc0ff2016-05-26 22:40:09 +020032 size_t num_channels) {
Tommi90edc652016-05-26 23:48:16 +020033// The below checks are temporarily disabled on WEBRTC_WIN due to problems
34// with clang debug builds.
kwiberg5377bc72016-10-04 13:46:56 -070035#if !defined(WEBRTC_WIN) && defined(__clang__)
Tommif4fc0ff2016-05-26 22:40:09 +020036 RTC_DCHECK_GT(src_sample_rate_hz, 0);
37 RTC_DCHECK_GT(dst_sample_rate_hz, 0);
kwibergaf476c72016-11-28 15:21:39 -080038 RTC_DCHECK_GT(num_channels, 0);
Tommi0ad72ea2016-05-26 23:07:40 +020039#endif
Tommif4fc0ff2016-05-26 22:40:09 +020040}
41
Tommic47f0092016-05-26 22:55:35 +020042void CheckExpectedBufferSizes(size_t src_length,
43 size_t dst_capacity,
44 size_t num_channels,
45 int src_sample_rate,
Tommif4fc0ff2016-05-26 22:40:09 +020046 int dst_sample_rate) {
Tommi90edc652016-05-26 23:48:16 +020047// The below checks are temporarily disabled on WEBRTC_WIN due to problems
48// with clang debug builds.
49// TODO(tommi): Re-enable when we've figured out what the problem is.
50// http://crbug.com/615050
kwiberg5377bc72016-10-04 13:46:56 -070051#if !defined(WEBRTC_WIN) && defined(__clang__)
Tommif4fc0ff2016-05-26 22:40:09 +020052 const size_t src_size_10ms = src_sample_rate * num_channels / 100;
53 const size_t dst_size_10ms = dst_sample_rate * num_channels / 100;
kwiberg5377bc72016-10-04 13:46:56 -070054 RTC_DCHECK_EQ(src_length, src_size_10ms);
55 RTC_DCHECK_GE(dst_capacity, dst_size_10ms);
Tommi0ad72ea2016-05-26 23:07:40 +020056#endif
Tommif4fc0ff2016-05-26 22:40:09 +020057}
oprypin67fdb802017-03-09 06:25:06 -080058} // namespace
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +000059
andrew@webrtc.orgf5a33f12014-04-19 00:32:07 +000060template <typename T>
61PushResampler<T>::PushResampler()
Yves Gerey665174f2018-06-19 15:03:05 +020062 : src_sample_rate_hz_(0), dst_sample_rate_hz_(0), num_channels_(0) {}
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +000063
andrew@webrtc.orgf5a33f12014-04-19 00:32:07 +000064template <typename T>
Yves Gerey665174f2018-06-19 15:03:05 +020065PushResampler<T>::~PushResampler() {}
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +000066
andrew@webrtc.orgf5a33f12014-04-19 00:32:07 +000067template <typename T>
68int PushResampler<T>::InitializeIfNeeded(int src_sample_rate_hz,
69 int dst_sample_rate_hz,
Peter Kasting69558702016-01-12 16:26:35 -080070 size_t num_channels) {
Tommif4fc0ff2016-05-26 22:40:09 +020071 CheckValidInitParams(src_sample_rate_hz, dst_sample_rate_hz, num_channels);
72
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +000073 if (src_sample_rate_hz == src_sample_rate_hz_ &&
74 dst_sample_rate_hz == dst_sample_rate_hz_ &&
Tommif4fc0ff2016-05-26 22:40:09 +020075 num_channels == num_channels_) {
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +000076 // No-op if settings haven't changed.
77 return 0;
Tommif4fc0ff2016-05-26 22:40:09 +020078 }
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +000079
Alex Loiko3fc5a202018-10-02 14:09:46 +020080 if (src_sample_rate_hz <= 0 || dst_sample_rate_hz <= 0 || num_channels <= 0) {
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +000081 return -1;
Tommif4fc0ff2016-05-26 22:40:09 +020082 }
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +000083
84 src_sample_rate_hz_ = src_sample_rate_hz;
85 dst_sample_rate_hz_ = dst_sample_rate_hz;
86 num_channels_ = num_channels;
87
Peter Kastingdce40cf2015-08-24 14:52:23 -070088 const size_t src_size_10ms_mono =
89 static_cast<size_t>(src_sample_rate_hz / 100);
90 const size_t dst_size_10ms_mono =
91 static_cast<size_t>(dst_sample_rate_hz / 100);
Alex Loiko3fc5a202018-10-02 14:09:46 +020092 channel_resamplers_.clear();
93 for (size_t i = 0; i < num_channels; ++i) {
94 channel_resamplers_.push_back(ChannelResampler());
95 auto channel_resampler = channel_resamplers_.rbegin();
96 channel_resampler->resampler = absl::make_unique<PushSincResampler>(
97 src_size_10ms_mono, dst_size_10ms_mono);
98 channel_resampler->source.resize(src_size_10ms_mono);
99 channel_resampler->destination.resize(dst_size_10ms_mono);
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +0000100 }
101
102 return 0;
103}
104
andrew@webrtc.orgf5a33f12014-04-19 00:32:07 +0000105template <typename T>
Yves Gerey665174f2018-06-19 15:03:05 +0200106int PushResampler<T>::Resample(const T* src,
107 size_t src_length,
108 T* dst,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700109 size_t dst_capacity) {
Tommic47f0092016-05-26 22:55:35 +0200110 CheckExpectedBufferSizes(src_length, dst_capacity, num_channels_,
111 src_sample_rate_hz_, dst_sample_rate_hz_);
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +0000112
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +0000113 if (src_sample_rate_hz_ == dst_sample_rate_hz_) {
114 // The old resampler provides this memcpy facility in the case of matching
115 // sample rates, so reproduce it here for the sinc resampler.
andrew@webrtc.orgf5a33f12014-04-19 00:32:07 +0000116 memcpy(dst, src, src_length * sizeof(T));
Peter Kastingdce40cf2015-08-24 14:52:23 -0700117 return static_cast<int>(src_length);
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +0000118 }
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +0000119
Alex Loiko3fc5a202018-10-02 14:09:46 +0200120 const size_t src_length_mono = src_length / num_channels_;
121 const size_t dst_capacity_mono = dst_capacity / num_channels_;
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +0000122
Alex Loiko3fc5a202018-10-02 14:09:46 +0200123 absl::InlinedVector<T*, 8> source_pointers;
124 for (auto& resampler : channel_resamplers_) {
125 source_pointers.push_back(resampler.source.data());
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +0000126 }
Alex Loiko3fc5a202018-10-02 14:09:46 +0200127
128 Deinterleave(src, src_length_mono, num_channels_, source_pointers.data());
129
130 size_t dst_length_mono = 0;
131
132 for (auto& resampler : channel_resamplers_) {
133 dst_length_mono = resampler.resampler->Resample(
134 resampler.source.data(), src_length_mono, resampler.destination.data(),
135 dst_capacity_mono);
136 }
137
138 absl::InlinedVector<T*, 8> destination_pointers;
139 for (auto& resampler : channel_resamplers_) {
140 destination_pointers.push_back(resampler.destination.data());
141 }
142
143 Interleave(destination_pointers.data(), dst_length_mono, num_channels_, dst);
144 return static_cast<int>(dst_length_mono * num_channels_);
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +0000145}
146
andrew@webrtc.orgf5a33f12014-04-19 00:32:07 +0000147// Explictly generate required instantiations.
148template class PushResampler<int16_t>;
149template class PushResampler<float>;
150
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +0000151} // namespace webrtc