blob: ffd70d9ce82dd1c02bc008f311242c56446d3c1a [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
Yves Gerey988cc082018-10-23 12:03:01 +020017#include <stddef.h>
kwibergc2b785d2016-02-24 05:22:32 -080018#include <memory>
19
Steve Anton10542f22019-01-11 09:11:00 -080020#include "rtc_base/constructor_magic.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020021#include "rtc_base/gtest_prod_util.h"
Karl Wiberg29e7bee2018-03-22 14:11:52 +010022#include "rtc_base/memory/aligned_malloc.h"
Niels Möllera12c42a2018-07-25 16:05:48 +020023#include "rtc_base/system/arch.h"
andrew@webrtc.org076fc122013-02-15 03:54:22 +000024
25namespace webrtc {
26
andrew@webrtc.orgc6a37552013-05-08 20:35:43 +000027// Callback class for providing more data into the resampler. Expects |frames|
28// of data to be rendered into |destination|; zero padded if not enough frames
29// are available to satisfy the request.
andrew@webrtc.org076fc122013-02-15 03:54:22 +000030class SincResamplerCallback {
31 public:
32 virtual ~SincResamplerCallback() {}
Peter Kastingdce40cf2015-08-24 14:52:23 -070033 virtual void Run(size_t frames, float* destination) = 0;
andrew@webrtc.org076fc122013-02-15 03:54:22 +000034};
andrew@webrtc.orga8ef8112013-02-13 23:00:49 +000035
36// SincResampler is a high-quality single-channel sample-rate converter.
andrew@webrtc.org076fc122013-02-15 03:54:22 +000037class SincResampler {
andrew@webrtc.orga8ef8112013-02-13 23:00:49 +000038 public:
Peter Kastingf045e4d2015-06-10 21:15:38 -070039 // The kernel size can be adjusted for quality (higher is better) at the
40 // expense of performance. Must be a multiple of 32.
41 // TODO(dalecurtis): Test performance to see if we can jack this up to 64+.
Peter Kastingdce40cf2015-08-24 14:52:23 -070042 static const size_t kKernelSize = 32;
andrew@webrtc.orgc6a37552013-05-08 20:35:43 +000043
Peter Kastingf045e4d2015-06-10 21:15:38 -070044 // Default request size. Affects how often and for how much SincResampler
45 // calls back for input. Must be greater than kKernelSize.
Peter Kastingdce40cf2015-08-24 14:52:23 -070046 static const size_t kDefaultRequestSize = 512;
andrew@webrtc.orgc6a37552013-05-08 20:35:43 +000047
Peter Kastingf045e4d2015-06-10 21:15:38 -070048 // The kernel offset count is used for interpolation and is the number of
49 // sub-sample kernel shifts. Can be adjusted for quality (higher is better)
50 // at the expense of allocating more memory.
Peter Kastingdce40cf2015-08-24 14:52:23 -070051 static const size_t kKernelOffsetCount = 32;
52 static const size_t kKernelStorageSize =
53 kKernelSize * (kKernelOffsetCount + 1);
andrew@webrtc.orgc6a37552013-05-08 20:35:43 +000054
andrew@webrtc.orga8ef8112013-02-13 23:00:49 +000055 // Constructs a SincResampler with the specified |read_cb|, which is used to
andrew@webrtc.orgb86fbaf2013-07-25 22:04:30 +000056 // acquire audio data for resampling. |io_sample_rate_ratio| is the ratio
57 // of input / output sample rates. |request_frames| controls the size in
58 // frames of the buffer requested by each |read_cb| call. The value must be
59 // greater than kKernelSize. Specify kDefaultRequestSize if there are no
60 // request size constraints.
andrew@webrtc.org076fc122013-02-15 03:54:22 +000061 SincResampler(double io_sample_rate_ratio,
Peter Kastingdce40cf2015-08-24 14:52:23 -070062 size_t request_frames,
andrew@webrtc.org076fc122013-02-15 03:54:22 +000063 SincResamplerCallback* read_cb);
andrew@webrtc.orga8ef8112013-02-13 23:00:49 +000064 virtual ~SincResampler();
65
66 // Resample |frames| of data from |read_cb_| into |destination|.
Peter Kastingdce40cf2015-08-24 14:52:23 -070067 void Resample(size_t frames, float* destination);
andrew@webrtc.orga8ef8112013-02-13 23:00:49 +000068
69 // The maximum size in frames that guarantees Resample() will only make a
70 // single call to |read_cb_| for more data.
Peter Kastingdce40cf2015-08-24 14:52:23 -070071 size_t ChunkSize() const;
andrew@webrtc.orga8ef8112013-02-13 23:00:49 +000072
Peter Kastingdce40cf2015-08-24 14:52:23 -070073 size_t request_frames() const { return request_frames_; }
andrew@webrtc.org8fc05fe2013-04-26 14:56:51 +000074
andrew@webrtc.orgc6a37552013-05-08 20:35:43 +000075 // Flush all buffered data and reset internal indices. Not thread safe, do
76 // not call while Resample() is in progress.
andrew@webrtc.orga8ef8112013-02-13 23:00:49 +000077 void Flush();
78
andrew@webrtc.orgc6a37552013-05-08 20:35:43 +000079 // Update |io_sample_rate_ratio_|. SetRatio() will cause a reconstruction of
80 // the kernels used for resampling. Not thread safe, do not call while
81 // Resample() is in progress.
82 //
andrew@webrtc.orgb86fbaf2013-07-25 22:04:30 +000083 // TODO(ajm): Use this in PushSincResampler rather than reconstructing
84 // SincResampler. We would also need a way to update |request_frames_|.
andrew@webrtc.orgc6a37552013-05-08 20:35:43 +000085 void SetRatio(double io_sample_rate_ratio);
86
87 float* get_kernel_for_testing() { return kernel_storage_.get(); }
88
andrew@webrtc.orga8ef8112013-02-13 23:00:49 +000089 private:
90 FRIEND_TEST_ALL_PREFIXES(SincResamplerTest, Convolve);
91 FRIEND_TEST_ALL_PREFIXES(SincResamplerTest, ConvolveBenchmark);
92
93 void InitializeKernel();
andrew@webrtc.orgb86fbaf2013-07-25 22:04:30 +000094 void UpdateRegions(bool second_load);
95
96 // Selects runtime specific CPU features like SSE. Must be called before
97 // using SincResampler.
98 // TODO(ajm): Currently managed by the class internally. See the note with
99 // |convolve_proc_| below.
100 void InitializeCPUSpecificFeatures();
andrew@webrtc.orga8ef8112013-02-13 23:00:49 +0000101
102 // Compute convolution of |k1| and |k2| over |input_ptr|, resultant sums are
andrew@webrtc.org00073aa2014-02-27 04:12:34 +0000103 // linearly interpolated using |kernel_interpolation_factor|. On x86 and ARM
104 // the underlying implementation is chosen at run time.
Yves Gerey665174f2018-06-19 15:03:05 +0200105 static float Convolve_C(const float* input_ptr,
106 const float* k1,
107 const float* k2,
108 double kernel_interpolation_factor);
andrew@webrtc.orgc6a37552013-05-08 20:35:43 +0000109#if defined(WEBRTC_ARCH_X86_FAMILY)
Yves Gerey665174f2018-06-19 15:03:05 +0200110 static float Convolve_SSE(const float* input_ptr,
111 const float* k1,
andrew@webrtc.orga8ef8112013-02-13 23:00:49 +0000112 const float* k2,
113 double kernel_interpolation_factor);
paskoe305d952016-05-17 10:56:40 -0700114#elif defined(WEBRTC_HAS_NEON)
Yves Gerey665174f2018-06-19 15:03:05 +0200115 static float Convolve_NEON(const float* input_ptr,
116 const float* k1,
andrew@webrtc.orga8ef8112013-02-13 23:00:49 +0000117 const float* k2,
118 double kernel_interpolation_factor);
andrew@webrtc.orgc6a37552013-05-08 20:35:43 +0000119#endif
andrew@webrtc.orga8ef8112013-02-13 23:00:49 +0000120
121 // The ratio of input / output sample rates.
122 double io_sample_rate_ratio_;
123
124 // An index on the source input buffer with sub-sample precision. It must be
125 // double precision to avoid drift.
126 double virtual_source_idx_;
127
128 // The buffer is primed once at the very beginning of processing.
129 bool buffer_primed_;
130
131 // Source of data for resampling.
andrew@webrtc.org076fc122013-02-15 03:54:22 +0000132 SincResamplerCallback* read_cb_;
133
andrew@webrtc.orgb86fbaf2013-07-25 22:04:30 +0000134 // The size (in samples) to request from each |read_cb_| execution.
Peter Kastingdce40cf2015-08-24 14:52:23 -0700135 const size_t request_frames_;
andrew@webrtc.orgb86fbaf2013-07-25 22:04:30 +0000136
137 // The number of source frames processed per pass.
Peter Kastingdce40cf2015-08-24 14:52:23 -0700138 size_t block_size_;
andrew@webrtc.org076fc122013-02-15 03:54:22 +0000139
andrew@webrtc.orgb86fbaf2013-07-25 22:04:30 +0000140 // The size (in samples) of the internal buffer used by the resampler.
Peter Kastingdce40cf2015-08-24 14:52:23 -0700141 const size_t input_buffer_size_;
andrew@webrtc.orga8ef8112013-02-13 23:00:49 +0000142
143 // Contains kKernelOffsetCount kernels back-to-back, each of size kKernelSize.
144 // The kernel offsets are sub-sample shifts of a windowed sinc shifted from
145 // 0.0 to 1.0 sample.
kwibergc2b785d2016-02-24 05:22:32 -0800146 std::unique_ptr<float[], AlignedFreeDeleter> kernel_storage_;
147 std::unique_ptr<float[], AlignedFreeDeleter> kernel_pre_sinc_storage_;
148 std::unique_ptr<float[], AlignedFreeDeleter> kernel_window_storage_;
andrew@webrtc.orga8ef8112013-02-13 23:00:49 +0000149
150 // Data from the source is copied into this buffer for each processing pass.
kwibergc2b785d2016-02-24 05:22:32 -0800151 std::unique_ptr<float[], AlignedFreeDeleter> input_buffer_;
andrew@webrtc.orga8ef8112013-02-13 23:00:49 +0000152
Yves Gerey665174f2018-06-19 15:03:05 +0200153// Stores the runtime selection of which Convolve function to use.
154// TODO(ajm): Move to using a global static which must only be initialized
155// once by the user. We're not doing this initially, because we don't have
156// e.g. a LazyInstance helper in webrtc.
Fredrik Solenberg500e75b2018-05-23 11:49:01 +0200157#if defined(WEBRTC_ARCH_X86_FAMILY) && !defined(__SSE2__)
Yves Gerey665174f2018-06-19 15:03:05 +0200158 typedef float (*ConvolveProc)(const float*,
159 const float*,
160 const float*,
andrew@webrtc.orgc6a37552013-05-08 20:35:43 +0000161 double);
andrew@webrtc.orgb86fbaf2013-07-25 22:04:30 +0000162 ConvolveProc convolve_proc_;
andrew@webrtc.orgc6a37552013-05-08 20:35:43 +0000163#endif
164
andrew@webrtc.orga8ef8112013-02-13 23:00:49 +0000165 // Pointers to the various regions inside |input_buffer_|. See the diagram at
166 // the top of the .cc file for more information.
andrew@webrtc.orgb86fbaf2013-07-25 22:04:30 +0000167 float* r0_;
andrew@webrtc.orga8ef8112013-02-13 23:00:49 +0000168 float* const r1_;
169 float* const r2_;
andrew@webrtc.orgb86fbaf2013-07-25 22:04:30 +0000170 float* r3_;
171 float* r4_;
andrew@webrtc.orga8ef8112013-02-13 23:00:49 +0000172
henrikg3c089d72015-09-16 05:37:44 -0700173 RTC_DISALLOW_COPY_AND_ASSIGN(SincResampler);
andrew@webrtc.orga8ef8112013-02-13 23:00:49 +0000174};
175
andrew@webrtc.org076fc122013-02-15 03:54:22 +0000176} // namespace webrtc
andrew@webrtc.orga8ef8112013-02-13 23:00:49 +0000177
Mirko Bonadei92ea95e2017-09-15 06:47:31 +0200178#endif // COMMON_AUDIO_RESAMPLER_SINC_RESAMPLER_H_