blob: 17b876b6b2e0e05f58428dc07db239f57d20b32e [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
Yves Gerey988cc082018-10-23 12:03:01 +020013#include <stdint.h>
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000014#include <string.h>
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +000015
Mirko Bonadei317a1f02019-09-17 17:06:18 +020016#include <memory>
17
Alex Loiko3fc5a202018-10-02 14:09:46 +020018#include "absl/container/inlined_vector.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020019#include "common_audio/include/audio_util.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020020#include "common_audio/resampler/push_sinc_resampler.h"
21#include "rtc_base/checks.h"
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +000022
23namespace webrtc {
Tommif4fc0ff2016-05-26 22:40:09 +020024namespace {
25// These checks were factored out into a non-templatized function
26// due to problems with clang on Windows in debug builds.
27// For some reason having the DCHECKs inline in the template code
28// caused the compiler to generate code that threw off the linker.
Tommi90edc652016-05-26 23:48:16 +020029// TODO(tommi): Re-enable when we've figured out what the problem is.
30// http://crbug.com/615050
Yves Gerey665174f2018-06-19 15:03:05 +020031void CheckValidInitParams(int src_sample_rate_hz,
32 int dst_sample_rate_hz,
Tommif4fc0ff2016-05-26 22:40:09 +020033 size_t num_channels) {
Tommi90edc652016-05-26 23:48:16 +020034// The below checks are temporarily disabled on WEBRTC_WIN due to problems
35// with clang debug builds.
kwiberg5377bc72016-10-04 13:46:56 -070036#if !defined(WEBRTC_WIN) && defined(__clang__)
Tommif4fc0ff2016-05-26 22:40:09 +020037 RTC_DCHECK_GT(src_sample_rate_hz, 0);
38 RTC_DCHECK_GT(dst_sample_rate_hz, 0);
kwibergaf476c72016-11-28 15:21:39 -080039 RTC_DCHECK_GT(num_channels, 0);
Tommi0ad72ea2016-05-26 23:07:40 +020040#endif
Tommif4fc0ff2016-05-26 22:40:09 +020041}
42
Tommic47f0092016-05-26 22:55:35 +020043void CheckExpectedBufferSizes(size_t src_length,
44 size_t dst_capacity,
45 size_t num_channels,
46 int src_sample_rate,
Tommif4fc0ff2016-05-26 22:40:09 +020047 int dst_sample_rate) {
Tommi90edc652016-05-26 23:48:16 +020048// The below checks are temporarily disabled on WEBRTC_WIN due to problems
49// with clang debug builds.
50// TODO(tommi): Re-enable when we've figured out what the problem is.
51// http://crbug.com/615050
kwiberg5377bc72016-10-04 13:46:56 -070052#if !defined(WEBRTC_WIN) && defined(__clang__)
Tommif4fc0ff2016-05-26 22:40:09 +020053 const size_t src_size_10ms = src_sample_rate * num_channels / 100;
54 const size_t dst_size_10ms = dst_sample_rate * num_channels / 100;
kwiberg5377bc72016-10-04 13:46:56 -070055 RTC_DCHECK_EQ(src_length, src_size_10ms);
56 RTC_DCHECK_GE(dst_capacity, dst_size_10ms);
Tommi0ad72ea2016-05-26 23:07:40 +020057#endif
Tommif4fc0ff2016-05-26 22:40:09 +020058}
oprypin67fdb802017-03-09 06:25:06 -080059} // namespace
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +000060
andrew@webrtc.orgf5a33f12014-04-19 00:32:07 +000061template <typename T>
62PushResampler<T>::PushResampler()
Yves Gerey665174f2018-06-19 15:03:05 +020063 : src_sample_rate_hz_(0), dst_sample_rate_hz_(0), num_channels_(0) {}
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +000064
andrew@webrtc.orgf5a33f12014-04-19 00:32:07 +000065template <typename T>
Yves Gerey665174f2018-06-19 15:03:05 +020066PushResampler<T>::~PushResampler() {}
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +000067
andrew@webrtc.orgf5a33f12014-04-19 00:32:07 +000068template <typename T>
69int PushResampler<T>::InitializeIfNeeded(int src_sample_rate_hz,
70 int dst_sample_rate_hz,
Peter Kasting69558702016-01-12 16:26:35 -080071 size_t num_channels) {
Tommif4fc0ff2016-05-26 22:40:09 +020072 CheckValidInitParams(src_sample_rate_hz, dst_sample_rate_hz, num_channels);
73
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +000074 if (src_sample_rate_hz == src_sample_rate_hz_ &&
75 dst_sample_rate_hz == dst_sample_rate_hz_ &&
Tommif4fc0ff2016-05-26 22:40:09 +020076 num_channels == num_channels_) {
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +000077 // No-op if settings haven't changed.
78 return 0;
Tommif4fc0ff2016-05-26 22:40:09 +020079 }
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +000080
Alex Loiko3fc5a202018-10-02 14:09:46 +020081 if (src_sample_rate_hz <= 0 || dst_sample_rate_hz <= 0 || num_channels <= 0) {
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +000082 return -1;
Tommif4fc0ff2016-05-26 22:40:09 +020083 }
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +000084
85 src_sample_rate_hz_ = src_sample_rate_hz;
86 dst_sample_rate_hz_ = dst_sample_rate_hz;
87 num_channels_ = num_channels;
88
Peter Kastingdce40cf2015-08-24 14:52:23 -070089 const size_t src_size_10ms_mono =
90 static_cast<size_t>(src_sample_rate_hz / 100);
91 const size_t dst_size_10ms_mono =
92 static_cast<size_t>(dst_sample_rate_hz / 100);
Alex Loiko3fc5a202018-10-02 14:09:46 +020093 channel_resamplers_.clear();
94 for (size_t i = 0; i < num_channels; ++i) {
95 channel_resamplers_.push_back(ChannelResampler());
96 auto channel_resampler = channel_resamplers_.rbegin();
Mirko Bonadei317a1f02019-09-17 17:06:18 +020097 channel_resampler->resampler = std::make_unique<PushSincResampler>(
Alex Loiko3fc5a202018-10-02 14:09:46 +020098 src_size_10ms_mono, dst_size_10ms_mono);
99 channel_resampler->source.resize(src_size_10ms_mono);
100 channel_resampler->destination.resize(dst_size_10ms_mono);
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +0000101 }
102
103 return 0;
104}
105
andrew@webrtc.orgf5a33f12014-04-19 00:32:07 +0000106template <typename T>
Yves Gerey665174f2018-06-19 15:03:05 +0200107int PushResampler<T>::Resample(const T* src,
108 size_t src_length,
109 T* dst,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700110 size_t dst_capacity) {
Tommic47f0092016-05-26 22:55:35 +0200111 CheckExpectedBufferSizes(src_length, dst_capacity, num_channels_,
112 src_sample_rate_hz_, dst_sample_rate_hz_);
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +0000113
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +0000114 if (src_sample_rate_hz_ == dst_sample_rate_hz_) {
115 // The old resampler provides this memcpy facility in the case of matching
116 // sample rates, so reproduce it here for the sinc resampler.
andrew@webrtc.orgf5a33f12014-04-19 00:32:07 +0000117 memcpy(dst, src, src_length * sizeof(T));
Peter Kastingdce40cf2015-08-24 14:52:23 -0700118 return static_cast<int>(src_length);
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +0000119 }
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +0000120
Alex Loiko3fc5a202018-10-02 14:09:46 +0200121 const size_t src_length_mono = src_length / num_channels_;
122 const size_t dst_capacity_mono = dst_capacity / num_channels_;
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +0000123
Alex Loiko3fc5a202018-10-02 14:09:46 +0200124 absl::InlinedVector<T*, 8> source_pointers;
125 for (auto& resampler : channel_resamplers_) {
126 source_pointers.push_back(resampler.source.data());
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +0000127 }
Alex Loiko3fc5a202018-10-02 14:09:46 +0200128
129 Deinterleave(src, src_length_mono, num_channels_, source_pointers.data());
130
131 size_t dst_length_mono = 0;
132
133 for (auto& resampler : channel_resamplers_) {
134 dst_length_mono = resampler.resampler->Resample(
135 resampler.source.data(), src_length_mono, resampler.destination.data(),
136 dst_capacity_mono);
137 }
138
139 absl::InlinedVector<T*, 8> destination_pointers;
140 for (auto& resampler : channel_resamplers_) {
141 destination_pointers.push_back(resampler.destination.data());
142 }
143
144 Interleave(destination_pointers.data(), dst_length_mono, num_channels_, dst);
145 return static_cast<int>(dst_length_mono * num_channels_);
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +0000146}
147
andrew@webrtc.orgf5a33f12014-04-19 00:32:07 +0000148// Explictly generate required instantiations.
149template class PushResampler<int16_t>;
150template class PushResampler<float>;
151
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +0000152} // namespace webrtc