LMMS
Loading...
Searching...
No Matches
juce_ResamplingAudioSource.cpp
Go to the documentation of this file.
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
27 const bool deleteInputWhenDeleted,
28 const int channels)
29 : input (inputSource, deleteInputWhenDeleted),
30 numChannels (channels)
31{
32 jassert (input != nullptr);
34}
35
37
38void ResamplingAudioSource::setResamplingRatio (const double samplesInPerOutputSample)
39{
40 jassert (samplesInPerOutputSample > 0);
41
43 ratio = jmax (0.0, samplesInPerOutputSample);
44}
45
46void ResamplingAudioSource::prepareToPlay (int samplesPerBlockExpected, double sampleRate)
47{
49
50 auto scaledBlockSize = roundToInt (samplesPerBlockExpected * ratio);
51 input->prepareToPlay (scaledBlockSize, sampleRate * ratio);
52
53 buffer.setSize (numChannels, scaledBlockSize + 32);
54
56 srcBuffers.calloc (numChannels);
57 destBuffers.calloc (numChannels);
59
61}
62
64{
65 const ScopedLock sl (callbackLock);
66
67 buffer.clear();
68 bufferPos = 0;
69 sampsInBuffer = 0;
70 subSampleOffset = 0.0;
72}
73
75{
76 input->releaseResources();
77 buffer.setSize (numChannels, 0);
78}
79
81{
82 const ScopedLock sl (callbackLock);
83
84 double localRatio;
85
86 {
87 const SpinLock::ScopedLockType ratioSl (ratioLock);
88 localRatio = ratio;
89 }
90
91 if (lastRatio != localRatio)
92 {
93 createLowPass (localRatio);
94 lastRatio = localRatio;
95 }
96
97 const int sampsNeeded = roundToInt (info.numSamples * localRatio) + 3;
98
99 int bufferSize = buffer.getNumSamples();
100
101 if (bufferSize < sampsNeeded + 8)
102 {
103 bufferPos %= bufferSize;
104 bufferSize = sampsNeeded + 32;
105 buffer.setSize (buffer.getNumChannels(), bufferSize, true, true);
106 }
107
108 bufferPos %= bufferSize;
109
110 int endOfBufferPos = bufferPos + sampsInBuffer;
111 const int channelsToProcess = jmin (numChannels, info.buffer->getNumChannels());
112
113 while (sampsNeeded > sampsInBuffer)
114 {
115 endOfBufferPos %= bufferSize;
116
117 int numToDo = jmin (sampsNeeded - sampsInBuffer,
118 bufferSize - endOfBufferPos);
119
120 AudioSourceChannelInfo readInfo (&buffer, endOfBufferPos, numToDo);
121 input->getNextAudioBlock (readInfo);
122
123 if (localRatio > 1.0001)
124 {
125 // for down-sampling, pre-apply the filter..
126
127 for (int i = channelsToProcess; --i >= 0;)
128 applyFilter (buffer.getWritePointer (i, endOfBufferPos), numToDo, filterStates[i]);
129 }
130
131 sampsInBuffer += numToDo;
132 endOfBufferPos += numToDo;
133 }
134
135 for (int channel = 0; channel < channelsToProcess; ++channel)
136 {
137 destBuffers[channel] = info.buffer->getWritePointer (channel, info.startSample);
138 srcBuffers[channel] = buffer.getReadPointer (channel);
139 }
140
141 int nextPos = (bufferPos + 1) % bufferSize;
142
143 for (int m = info.numSamples; --m >= 0;)
144 {
145 jassert (sampsInBuffer > 0 && nextPos != endOfBufferPos);
146
147 const float alpha = (float) subSampleOffset;
148
149 for (int channel = 0; channel < channelsToProcess; ++channel)
150 *destBuffers[channel]++ = srcBuffers[channel][bufferPos]
151 + alpha * (srcBuffers[channel][nextPos] - srcBuffers[channel][bufferPos]);
152
153 subSampleOffset += localRatio;
154
155 while (subSampleOffset >= 1.0)
156 {
157 if (++bufferPos >= bufferSize)
158 bufferPos = 0;
159
161
162 nextPos = (bufferPos + 1) % bufferSize;
163 subSampleOffset -= 1.0;
164 }
165 }
166
167 if (localRatio < 0.9999)
168 {
169 // for up-sampling, apply the filter after transposing..
170 for (int i = channelsToProcess; --i >= 0;)
171 applyFilter (info.buffer->getWritePointer (i, info.startSample), info.numSamples, filterStates[i]);
172 }
173 else if (localRatio <= 1.0001 && info.numSamples > 0)
174 {
175 // if the filter's not currently being applied, keep it stoked with the last couple of samples to avoid discontinuities
176 for (int i = channelsToProcess; --i >= 0;)
177 {
178 const float* const endOfBuffer = info.buffer->getReadPointer (i, info.startSample + info.numSamples - 1);
180
181 if (info.numSamples > 1)
182 {
183 fs.y2 = fs.x2 = *(endOfBuffer - 1);
184 }
185 else
186 {
187 fs.y2 = fs.y1;
188 fs.x2 = fs.x1;
189 }
190
191 fs.y1 = fs.x1 = *endOfBuffer;
192 }
193 }
194
195 jassert (sampsInBuffer >= 0);
196}
197
198void ResamplingAudioSource::createLowPass (const double frequencyRatio)
199{
200 const double proportionalRate = (frequencyRatio > 1.0) ? 0.5 / frequencyRatio
201 : 0.5 * frequencyRatio;
202
203 const double n = 1.0 / std::tan (MathConstants<double>::pi * jmax (0.001, proportionalRate));
204 const double nSquared = n * n;
205 const double c1 = 1.0 / (1.0 + MathConstants<double>::sqrt2 * n + nSquared);
206
208 c1 * 2.0f,
209 c1,
210 1.0,
211 c1 * 2.0 * (1.0 - nSquared),
212 c1 * (1.0 - MathConstants<double>::sqrt2 * n + nSquared));
213}
214
215void ResamplingAudioSource::setFilterCoefficients (double c1, double c2, double c3, double c4, double c5, double c6)
216{
217 const double a = 1.0 / c4;
218
219 c1 *= a;
220 c2 *= a;
221 c3 *= a;
222 c5 *= a;
223 c6 *= a;
224
225 coefficients[0] = c1;
226 coefficients[1] = c2;
227 coefficients[2] = c3;
228 coefficients[3] = c4;
229 coefficients[4] = c5;
230 coefficients[5] = c6;
231}
232
234{
235 if (filterStates != nullptr)
236 filterStates.clear ((size_t) numChannels);
237}
238
239void ResamplingAudioSource::applyFilter (float* samples, int num, FilterState& fs)
240{
241 while (--num >= 0)
242 {
243 const double in = *samples;
244
245 double out = coefficients[0] * in
246 + coefficients[1] * fs.x1
247 + coefficients[2] * fs.x2
248 - coefficients[4] * fs.y1
249 - coefficients[5] * fs.y2;
250
251 #if JUCE_INTEL
252 if (! (out < -1.0e-8 || out > 1.0e-8))
253 out = 0;
254 #endif
255
256 fs.x2 = fs.x1;
257 fs.x1 = in;
258 fs.y2 = fs.y1;
259 fs.y1 = out;
260
261 *samples++ = (float) out;
262 }
263}
264
265} // namespace juce
Type jmin(const Type a, const Type b)
Definition MathsFunctions.h:60
Type jmax(const Type a, const Type b)
Definition MathsFunctions.h:48
uint8_t a
Definition Spc_Cpu.h:141
AudioSource()=default
OptionalScopedPointer< AudioSource > input
Definition juce_ResamplingAudioSource.h:78
HeapBlock< FilterState > filterStates
Definition juce_ResamplingAudioSource.h:98
void releaseResources() override
Definition juce_ResamplingAudioSource.cpp:74
AudioBuffer< float > buffer
Definition juce_ResamplingAudioSource.h:80
double subSampleOffset
Definition juce_ResamplingAudioSource.h:82
void setFilterCoefficients(double c1, double c2, double c3, double c4, double c5, double c6)
Definition juce_ResamplingAudioSource.cpp:215
double coefficients[6]
Definition juce_ResamplingAudioSource.h:83
int bufferPos
Definition juce_ResamplingAudioSource.h:81
const int numChannels
Definition juce_ResamplingAudioSource.h:86
void getNextAudioBlock(const AudioSourceChannelInfo &) override
Definition juce_ResamplingAudioSource.cpp:80
void prepareToPlay(int samplesPerBlockExpected, double sampleRate) override
Definition juce_ResamplingAudioSource.cpp:46
HeapBlock< const float * > srcBuffers
Definition juce_ResamplingAudioSource.h:88
double lastRatio
Definition juce_ResamplingAudioSource.h:79
void flushBuffers()
Definition juce_ResamplingAudioSource.cpp:63
int sampsInBuffer
Definition juce_ResamplingAudioSource.h:81
CriticalSection callbackLock
Definition juce_ResamplingAudioSource.h:85
void resetFilters()
Definition juce_ResamplingAudioSource.cpp:233
void applyFilter(float *samples, int num, FilterState &fs)
Definition juce_ResamplingAudioSource.cpp:239
~ResamplingAudioSource() override
Definition juce_ResamplingAudioSource.cpp:36
SpinLock ratioLock
Definition juce_ResamplingAudioSource.h:84
void setResamplingRatio(double samplesInPerOutputSample)
Definition juce_ResamplingAudioSource.cpp:38
ResamplingAudioSource(AudioSource *inputSource, bool deleteInputWhenDeleted, int numChannels=2)
Definition juce_ResamplingAudioSource.cpp:26
HeapBlock< float * > destBuffers
Definition juce_ResamplingAudioSource.h:87
void createLowPass(double proportionalRate)
Definition juce_ResamplingAudioSource.cpp:198
double ratio
Definition juce_ResamplingAudioSource.h:79
GenericScopedLock< SpinLock > ScopedLockType
Definition juce_SpinLock.h:73
unsigned * m
Definition inflate.c:1559
register unsigned i
Definition inflate.c:1575
static void c2(register WDL_FFT_COMPLEX *a)
Definition fft.c:270
static void c4(register WDL_FFT_COMPLEX *a)
Definition fft.c:283
struct backing_store_struct * info
Definition jmemsys.h:183
#define jassert(expression)
float in
Definition lilv_test.c:1460
float out
Definition lilv_test.c:1461
Definition carla_juce.cpp:31
CriticalSection::ScopedLockType ScopedLock
Definition juce_CriticalSection.h:186
constexpr Type jmax(Type a, Type b)
Definition juce_MathsFunctions.h:94
int roundToInt(const FloatType value) noexcept
Definition juce_MathsFunctions.h:465
void zeromem(void *memory, size_t numBytes) noexcept
Definition juce_Memory.h:28
Definition juce_AudioSource.h:33
static constexpr FloatType sqrt2
Definition juce_MathsFunctions.h:394
static constexpr FloatType pi
Definition juce_MathsFunctions.h:382
Definition juce_ResamplingAudioSource.h:94
double y1
Definition juce_ResamplingAudioSource.h:95
double x1
Definition juce_ResamplingAudioSource.h:95
double y2
Definition juce_ResamplingAudioSource.h:95
double x2
Definition juce_ResamplingAudioSource.h:95
int n
Definition crypt.c:458