OpenShot Audio Library | OpenShotAudio 0.4.0
Loading...
Searching...
No Matches
juce_GenericInterpolator.h
1/*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
10 The code included in this file is provided under the terms of the ISC license
11 http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12 To use, copy, modify, and/or distribute this software for any purpose with or
13 without fee is hereby granted provided that the above copyright notice and
14 this permission notice appear in all copies.
15
16 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18 DISCLAIMED.
19
20 ==============================================================================
21*/
22
23namespace juce
24{
25
39template <class InterpolatorTraits, int memorySize>
40class JUCE_API GenericInterpolator
41{
42 static auto processReplacingCallback()
43 {
44 return [] (auto, auto newValue) { return newValue; };
45 }
46
47 static auto processAddingCallback (float gain)
48 {
49 return [gain] (auto oldValue, auto newValue) { return oldValue + gain * newValue; };
50 }
51
52public:
53 GenericInterpolator() noexcept { reset(); }
54
55 GenericInterpolator (GenericInterpolator&&) noexcept = default;
56 GenericInterpolator& operator= (GenericInterpolator&&) noexcept = default;
57
63 static constexpr float getBaseLatency() noexcept
64 {
65 return InterpolatorTraits::algorithmicLatency;
66 }
67
72 void reset() noexcept
73 {
74 indexBuffer = 0;
75 subSamplePos = 1.0;
76 std::fill (std::begin (lastInputSamples), std::end (lastInputSamples), 0.0f);
77 }
78
89 int process (double speedRatio,
90 const float* inputSamples,
91 float* outputSamples,
92 int numOutputSamplesToProduce) noexcept
93 {
94 return interpolateImpl (speedRatio,
95 inputSamples,
96 outputSamples,
97 numOutputSamplesToProduce,
98 processReplacingCallback());
99 }
100
116 int process (double speedRatio,
117 const float* inputSamples,
118 float* outputSamples,
119 int numOutputSamplesToProduce,
120 int numInputSamplesAvailable,
121 int wrapAround) noexcept
122 {
123 return interpolateImpl (speedRatio,
124 inputSamples,
125 outputSamples,
126 numOutputSamplesToProduce,
127 numInputSamplesAvailable,
128 wrapAround,
129 processReplacingCallback());
130 }
131
147 int processAdding (double speedRatio,
148 const float* inputSamples,
149 float* outputSamples,
150 int numOutputSamplesToProduce,
151 float gain) noexcept
152 {
153 return interpolateImpl (speedRatio,
154 inputSamples,
155 outputSamples,
156 numOutputSamplesToProduce,
157 processAddingCallback (gain));
158 }
159
180 int processAdding (double speedRatio,
181 const float* inputSamples,
182 float* outputSamples,
183 int numOutputSamplesToProduce,
184 int numInputSamplesAvailable,
185 int wrapAround,
186 float gain) noexcept
187 {
188 return interpolateImpl (speedRatio,
189 inputSamples,
190 outputSamples,
191 numOutputSamplesToProduce,
192 numInputSamplesAvailable,
193 wrapAround,
194 processAddingCallback (gain));
195 }
196
197private:
198 //==============================================================================
199 forcedinline void pushInterpolationSample (float newValue) noexcept
200 {
201 lastInputSamples[indexBuffer] = newValue;
202
203 if (++indexBuffer == memorySize)
204 indexBuffer = 0;
205 }
206
207 forcedinline void pushInterpolationSamples (const float* input,
208 int numOutputSamplesToProduce) noexcept
209 {
210 if (numOutputSamplesToProduce >= memorySize)
211 {
212 const auto* const offsetInput = input + (numOutputSamplesToProduce - memorySize);
213
214 for (int i = 0; i < memorySize; ++i)
215 pushInterpolationSample (offsetInput[i]);
216 }
217 else
218 {
219 for (int i = 0; i < numOutputSamplesToProduce; ++i)
220 pushInterpolationSample (input[i]);
221 }
222 }
223
224 forcedinline void pushInterpolationSamples (const float* input,
225 int numOutputSamplesToProduce,
226 int numInputSamplesAvailable,
227 int wrapAround) noexcept
228 {
229 if (numOutputSamplesToProduce >= memorySize)
230 {
231 if (numInputSamplesAvailable >= memorySize)
232 {
233 pushInterpolationSamples (input,
234 numOutputSamplesToProduce);
235 }
236 else
237 {
238 pushInterpolationSamples (input + ((numOutputSamplesToProduce - numInputSamplesAvailable) - 1),
239 numInputSamplesAvailable);
240
241 if (wrapAround > 0)
242 {
243 numOutputSamplesToProduce -= wrapAround;
244
245 pushInterpolationSamples (input + ((numOutputSamplesToProduce - (memorySize - numInputSamplesAvailable)) - 1),
246 memorySize - numInputSamplesAvailable);
247 }
248 else
249 {
250 for (int i = numInputSamplesAvailable; i < memorySize; ++i)
251 pushInterpolationSample (0.0f);
252 }
253 }
254 }
255 else
256 {
257 if (numOutputSamplesToProduce > numInputSamplesAvailable)
258 {
259 for (int i = 0; i < numInputSamplesAvailable; ++i)
260 pushInterpolationSample (input[i]);
261
262 const auto extraSamples = numOutputSamplesToProduce - numInputSamplesAvailable;
263
264 if (wrapAround > 0)
265 {
266 const auto* const offsetInput = input + (numInputSamplesAvailable - wrapAround);
267
268 for (int i = 0; i < extraSamples; ++i)
269 pushInterpolationSample (offsetInput[i]);
270 }
271 else
272 {
273 for (int i = 0; i < extraSamples; ++i)
274 pushInterpolationSample (0.0f);
275 }
276 }
277 else
278 {
279 for (int i = 0; i < numOutputSamplesToProduce; ++i)
280 pushInterpolationSample (input[i]);
281 }
282 }
283 }
284
285 //==============================================================================
286 template <typename Process>
287 int interpolateImpl (double speedRatio,
288 const float* input,
289 float* output,
290 int numOutputSamplesToProduce,
291 int numInputSamplesAvailable,
292 int wrap,
293 Process process)
294 {
295 auto originalIn = input;
296 bool exceeded = false;
297
298 const auto pushSample = [&]
299 {
300 if (exceeded)
301 {
302 pushInterpolationSample (0.0);
303 }
304 else
305 {
306 pushInterpolationSample (*input++);
307
308 if (--numInputSamplesAvailable <= 0)
309 {
310 if (wrap > 0)
311 {
312 input -= wrap;
313 numInputSamplesAvailable += wrap;
314 }
315 else
316 {
317 exceeded = true;
318 }
319 }
320 }
321 };
322
323 interpolateImpl (speedRatio,
324 output,
325 numOutputSamplesToProduce,
326 process,
327 pushSample);
328
329 if (wrap == 0)
330 return (int) (input - originalIn);
331
332 return ((int) (input - originalIn) + wrap) % wrap;
333 }
334
335 template <typename Process>
336 int interpolateImpl (double speedRatio,
337 const float* input,
338 float* output,
339 int numOutputSamplesToProduce,
340 Process process)
341 {
342 int numUsed = 0;
343
344 interpolateImpl (speedRatio,
345 output,
346 numOutputSamplesToProduce,
347 process,
348 [this, input, &numUsed] { pushInterpolationSample (input[numUsed++]); });
349
350 return numUsed;
351 }
352
353 template <typename Process, typename PushSample>
354 void interpolateImpl (double speedRatio,
355 float* output,
356 int numOutputSamplesToProduce,
357 Process process,
358 PushSample pushSample)
359 {
360 auto pos = subSamplePos;
361
362 for (auto i = 0; i < numOutputSamplesToProduce; ++i)
363 {
364 while (pos >= 1.0)
365 {
366 pushSample();
367 pos -= 1.0;
368 }
369
370 *output = process (*output, InterpolatorTraits::valueAtOffset (lastInputSamples, (float) pos, indexBuffer));
371 ++output;
372 pos += speedRatio;
373 }
374
375 subSamplePos = pos;
376 }
377
378 //==============================================================================
379 float lastInputSamples[(size_t) memorySize];
380 double subSamplePos = 1.0;
381 int indexBuffer = 0;
382
383 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (GenericInterpolator)
384};
385
386} // namespace juce
int process(double speedRatio, const float *inputSamples, float *outputSamples, int numOutputSamplesToProduce, int numInputSamplesAvailable, int wrapAround) noexcept
int process(double speedRatio, const float *inputSamples, float *outputSamples, int numOutputSamplesToProduce) noexcept
int processAdding(double speedRatio, const float *inputSamples, float *outputSamples, int numOutputSamplesToProduce, int numInputSamplesAvailable, int wrapAround, float gain) noexcept
int processAdding(double speedRatio, const float *inputSamples, float *outputSamples, int numOutputSamplesToProduce, float gain) noexcept
static constexpr float getBaseLatency() noexcept