blob: d0112240554d555797834328a29572ac7971255c [file] [log] [blame]
andrew@webrtc.org076fc122013-02-15 03:54:22 +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 */
andrew@webrtc.orga8ef8112013-02-13 23:00:49 +000010
andrew@webrtc.org076fc122013-02-15 03:54:22 +000011// Modified from the Chromium original here:
12// src/media/base/sinc_resampler.h
andrew@webrtc.orga8ef8112013-02-13 23:00:49 +000013
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020014#ifndef COMMON_AUDIO_RESAMPLER_SINC_RESAMPLER_H_
15#define COMMON_AUDIO_RESAMPLER_SINC_RESAMPLER_H_
andrew@webrtc.orga8ef8112013-02-13 23:00:49 +000016
kwibergc2b785d2016-02-24 05:22:32 -080017#include <memory>
18
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020019#include "rtc_base/constructormagic.h"
20#include "rtc_base/gtest_prod_util.h"
21#include "system_wrappers/include/aligned_malloc.h"
Mirko Bonadei71207422017-09-15 13:58:09 +020022#include "typedefs.h" // NOLINT(build/include)
andrew@webrtc.org076fc122013-02-15 03:54:22 +000023
24namespace webrtc {
25
andrew@webrtc.orgc6a37552013-05-08 20:35:43 +000026// Callback class for providing more data into the resampler. Expects |frames|
27// of data to be rendered into |destination|; zero padded if not enough frames
28// are available to satisfy the request.
andrew@webrtc.org076fc122013-02-15 03:54:22 +000029class SincResamplerCallback {
30 public:
31 virtual ~SincResamplerCallback() {}
Peter Kastingdce40cf2015-08-24 14:52:23 -070032 virtual void Run(size_t frames, float* destination) = 0;
andrew@webrtc.org076fc122013-02-15 03:54:22 +000033};
andrew@webrtc.orga8ef8112013-02-13 23:00:49 +000034
35// SincResampler is a high-quality single-channel sample-rate converter.
andrew@webrtc.org076fc122013-02-15 03:54:22 +000036class SincResampler {
andrew@webrtc.orga8ef8112013-02-13 23:00:49 +000037 public:
Peter Kastingf045e4d2015-06-10 21:15:38 -070038 // The kernel size can be adjusted for quality (higher is better) at the
39 // expense of performance. Must be a multiple of 32.
40 // TODO(dalecurtis): Test performance to see if we can jack this up to 64+.
Peter Kastingdce40cf2015-08-24 14:52:23 -070041 static const size_t kKernelSize = 32;
andrew@webrtc.orgc6a37552013-05-08 20:35:43 +000042
Peter Kastingf045e4d2015-06-10 21:15:38 -070043 // Default request size. Affects how often and for how much SincResampler
44 // calls back for input. Must be greater than kKernelSize.
Peter Kastingdce40cf2015-08-24 14:52:23 -070045 static const size_t kDefaultRequestSize = 512;
andrew@webrtc.orgc6a37552013-05-08 20:35:43 +000046
Peter Kastingf045e4d2015-06-10 21:15:38 -070047 // The kernel offset count is used for interpolation and is the number of
48 // sub-sample kernel shifts. Can be adjusted for quality (higher is better)
49 // at the expense of allocating more memory.
Peter Kastingdce40cf2015-08-24 14:52:23 -070050 static const size_t kKernelOffsetCount = 32;
51 static const size_t kKernelStorageSize =
52 kKernelSize * (kKernelOffsetCount + 1);
andrew@webrtc.orgc6a37552013-05-08 20:35:43 +000053
andrew@webrtc.orga8ef8112013-02-13 23:00:49 +000054 // Constructs a SincResampler with the specified |read_cb|, which is used to
andrew@webrtc.orgb86fbaf2013-07-25 22:04:30 +000055 // acquire audio data for resampling. |io_sample_rate_ratio| is the ratio
56 // of input / output sample rates. |request_frames| controls the size in
57 // frames of the buffer requested by each |read_cb| call. The value must be
58 // greater than kKernelSize. Specify kDefaultRequestSize if there are no
59 // request size constraints.
andrew@webrtc.org076fc122013-02-15 03:54:22 +000060 SincResampler(double io_sample_rate_ratio,
Peter Kastingdce40cf2015-08-24 14:52:23 -070061 size_t request_frames,
andrew@webrtc.org076fc122013-02-15 03:54:22 +000062 SincResamplerCallback* read_cb);
andrew@webrtc.orga8ef8112013-02-13 23:00:49 +000063 virtual ~SincResampler();
64
65 // Resample |frames| of data from |read_cb_| into |destination|.
Peter Kastingdce40cf2015-08-24 14:52:23 -070066 void Resample(size_t frames, float* destination);
andrew@webrtc.orga8ef8112013-02-13 23:00:49 +000067
68 // The maximum size in frames that guarantees Resample() will only make a
69 // single call to |read_cb_| for more data.
Peter Kastingdce40cf2015-08-24 14:52:23 -070070 size_t ChunkSize() const;
andrew@webrtc.orga8ef8112013-02-13 23:00:49 +000071
Peter Kastingdce40cf2015-08-24 14:52:23 -070072 size_t request_frames() const { return request_frames_; }
andrew@webrtc.org8fc05fe2013-04-26 14:56:51 +000073
andrew@webrtc.orgc6a37552013-05-08 20:35:43 +000074 // Flush all buffered data and reset internal indices. Not thread safe, do
75 // not call while Resample() is in progress.
andrew@webrtc.orga8ef8112013-02-13 23:00:49 +000076 void Flush();
77
andrew@webrtc.orgc6a37552013-05-08 20:35:43 +000078 // Update |io_sample_rate_ratio_|. SetRatio() will cause a reconstruction of
79 // the kernels used for resampling. Not thread safe, do not call while
80 // Resample() is in progress.
81 //
andrew@webrtc.orgb86fbaf2013-07-25 22:04:30 +000082 // TODO(ajm): Use this in PushSincResampler rather than reconstructing
83 // SincResampler. We would also need a way to update |request_frames_|.
andrew@webrtc.orgc6a37552013-05-08 20:35:43 +000084 void SetRatio(double io_sample_rate_ratio);
85
86 float* get_kernel_for_testing() { return kernel_storage_.get(); }
87
andrew@webrtc.orga8ef8112013-02-13 23:00:49 +000088 private:
89 FRIEND_TEST_ALL_PREFIXES(SincResamplerTest, Convolve);
90 FRIEND_TEST_ALL_PREFIXES(SincResamplerTest, ConvolveBenchmark);
91
92 void InitializeKernel();
andrew@webrtc.orgb86fbaf2013-07-25 22:04:30 +000093 void UpdateRegions(bool second_load);
94
95 // Selects runtime specific CPU features like SSE. Must be called before
96 // using SincResampler.
97 // TODO(ajm): Currently managed by the class internally. See the note with
98 // |convolve_proc_| below.
99 void InitializeCPUSpecificFeatures();
andrew@webrtc.orga8ef8112013-02-13 23:00:49 +0000100
101 // Compute convolution of |k1| and |k2| over |input_ptr|, resultant sums are
andrew@webrtc.org00073aa2014-02-27 04:12:34 +0000102 // linearly interpolated using |kernel_interpolation_factor|. On x86 and ARM
103 // the underlying implementation is chosen at run time.
andrew@webrtc.orga8ef8112013-02-13 23:00:49 +0000104 static float Convolve_C(const float* input_ptr, const float* k1,
105 const float* k2, double kernel_interpolation_factor);
andrew@webrtc.orgc6a37552013-05-08 20:35:43 +0000106#if defined(WEBRTC_ARCH_X86_FAMILY)
andrew@webrtc.orga8ef8112013-02-13 23:00:49 +0000107 static float Convolve_SSE(const float* input_ptr, const float* k1,
108 const float* k2,
109 double kernel_interpolation_factor);
paskoe305d952016-05-17 10:56:40 -0700110#elif defined(WEBRTC_HAS_NEON)
andrew@webrtc.orga8ef8112013-02-13 23:00:49 +0000111 static float Convolve_NEON(const float* input_ptr, const float* k1,
112 const float* k2,
113 double kernel_interpolation_factor);
andrew@webrtc.orgc6a37552013-05-08 20:35:43 +0000114#endif
andrew@webrtc.orga8ef8112013-02-13 23:00:49 +0000115
116 // The ratio of input / output sample rates.
117 double io_sample_rate_ratio_;
118
119 // An index on the source input buffer with sub-sample precision. It must be
120 // double precision to avoid drift.
121 double virtual_source_idx_;
122
123 // The buffer is primed once at the very beginning of processing.
124 bool buffer_primed_;
125
126 // Source of data for resampling.
andrew@webrtc.org076fc122013-02-15 03:54:22 +0000127 SincResamplerCallback* read_cb_;
128
andrew@webrtc.orgb86fbaf2013-07-25 22:04:30 +0000129 // The size (in samples) to request from each |read_cb_| execution.
Peter Kastingdce40cf2015-08-24 14:52:23 -0700130 const size_t request_frames_;
andrew@webrtc.orgb86fbaf2013-07-25 22:04:30 +0000131
132 // The number of source frames processed per pass.
Peter Kastingdce40cf2015-08-24 14:52:23 -0700133 size_t block_size_;
andrew@webrtc.org076fc122013-02-15 03:54:22 +0000134
andrew@webrtc.orgb86fbaf2013-07-25 22:04:30 +0000135 // The size (in samples) of the internal buffer used by the resampler.
Peter Kastingdce40cf2015-08-24 14:52:23 -0700136 const size_t input_buffer_size_;
andrew@webrtc.orga8ef8112013-02-13 23:00:49 +0000137
138 // Contains kKernelOffsetCount kernels back-to-back, each of size kKernelSize.
139 // The kernel offsets are sub-sample shifts of a windowed sinc shifted from
140 // 0.0 to 1.0 sample.
kwibergc2b785d2016-02-24 05:22:32 -0800141 std::unique_ptr<float[], AlignedFreeDeleter> kernel_storage_;
142 std::unique_ptr<float[], AlignedFreeDeleter> kernel_pre_sinc_storage_;
143 std::unique_ptr<float[], AlignedFreeDeleter> kernel_window_storage_;
andrew@webrtc.orga8ef8112013-02-13 23:00:49 +0000144
145 // Data from the source is copied into this buffer for each processing pass.
kwibergc2b785d2016-02-24 05:22:32 -0800146 std::unique_ptr<float[], AlignedFreeDeleter> input_buffer_;
andrew@webrtc.orga8ef8112013-02-13 23:00:49 +0000147
andrew@webrtc.orgc6a37552013-05-08 20:35:43 +0000148 // Stores the runtime selection of which Convolve function to use.
andrew@webrtc.orgb86fbaf2013-07-25 22:04:30 +0000149 // TODO(ajm): Move to using a global static which must only be initialized
150 // once by the user. We're not doing this initially, because we don't have
151 // e.g. a LazyInstance helper in webrtc.
kjellanderbdf30722017-09-08 11:00:21 -0700152#if defined(WEBRTC_CPU_DETECTION)
andrew@webrtc.orgc6a37552013-05-08 20:35:43 +0000153 typedef float (*ConvolveProc)(const float*, const float*, const float*,
154 double);
andrew@webrtc.orgb86fbaf2013-07-25 22:04:30 +0000155 ConvolveProc convolve_proc_;
andrew@webrtc.orgc6a37552013-05-08 20:35:43 +0000156#endif
157
andrew@webrtc.orga8ef8112013-02-13 23:00:49 +0000158 // Pointers to the various regions inside |input_buffer_|. See the diagram at
159 // the top of the .cc file for more information.
andrew@webrtc.orgb86fbaf2013-07-25 22:04:30 +0000160 float* r0_;
andrew@webrtc.orga8ef8112013-02-13 23:00:49 +0000161 float* const r1_;
162 float* const r2_;
andrew@webrtc.orgb86fbaf2013-07-25 22:04:30 +0000163 float* r3_;
164 float* r4_;
andrew@webrtc.orga8ef8112013-02-13 23:00:49 +0000165
henrikg3c089d72015-09-16 05:37:44 -0700166 RTC_DISALLOW_COPY_AND_ASSIGN(SincResampler);
andrew@webrtc.orga8ef8112013-02-13 23:00:49 +0000167};
168
andrew@webrtc.org076fc122013-02-15 03:54:22 +0000169} // namespace webrtc
andrew@webrtc.orga8ef8112013-02-13 23:00:49 +0000170
Mirko Bonadei92ea95e2017-09-15 06:47:31 +0200171#endif // COMMON_AUDIO_RESAMPLER_SINC_RESAMPLER_H_