27 const bool deleteInputWhenDeleted,
29 : input (inputSource, deleteInputWhenDeleted),
35 numChannels (channels)
37 jassert (input !=
nullptr);
38 zeromem (coefficients,
sizeof (coefficients));
45 jassert (samplesInPerOutputSample > 0);
48 ratio = jmax (0.0, samplesInPerOutputSample);
55 auto scaledBlockSize = roundToInt (samplesPerBlockExpected * ratio);
56 input->prepareToPlay (scaledBlockSize, sampleRate * ratio);
58 buffer.
setSize (numChannels, scaledBlockSize + 32);
60 filterStates.
calloc (numChannels);
61 srcBuffers.
calloc (numChannels);
62 destBuffers.
calloc (numChannels);
63 createLowPass (ratio);
73 subSampleOffset = 0.0;
79 input->releaseResources();
80 buffer.
setSize (numChannels, 0);
92 if (lastRatio != localRatio)
94 createLowPass (localRatio);
95 lastRatio = localRatio;
98 const int sampsNeeded = roundToInt (info.
numSamples * localRatio) + 3;
102 if (bufferSize < sampsNeeded + 8)
104 bufferPos %= bufferSize;
105 bufferSize = sampsNeeded + 32;
109 bufferPos %= bufferSize;
111 int endOfBufferPos = bufferPos + sampsInBuffer;
114 while (sampsNeeded > sampsInBuffer)
116 endOfBufferPos %= bufferSize;
118 int numToDo = jmin (sampsNeeded - sampsInBuffer,
119 bufferSize - endOfBufferPos);
122 input->getNextAudioBlock (readInfo);
124 if (localRatio > 1.0001)
128 for (
int i = channelsToProcess; --i >= 0;)
129 applyFilter (buffer.
getWritePointer (i, endOfBufferPos), numToDo, filterStates[i]);
132 sampsInBuffer += numToDo;
133 endOfBufferPos += numToDo;
136 for (
int channel = 0; channel < channelsToProcess; ++channel)
142 int nextPos = (bufferPos + 1) % bufferSize;
146 jassert (sampsInBuffer > 0 && nextPos != endOfBufferPos);
148 const float alpha = (float) subSampleOffset;
150 for (
int channel = 0; channel < channelsToProcess; ++channel)
151 *destBuffers[channel]++ = srcBuffers[channel][bufferPos]
152 + alpha * (srcBuffers[channel][nextPos] - srcBuffers[channel][bufferPos]);
154 subSampleOffset += localRatio;
156 while (subSampleOffset >= 1.0)
158 if (++bufferPos >= bufferSize)
163 nextPos = (bufferPos + 1) % bufferSize;
164 subSampleOffset -= 1.0;
168 if (localRatio < 0.9999)
171 for (
int i = channelsToProcess; --i >= 0;)
174 else if (localRatio <= 1.0001 && info.numSamples > 0)
177 for (
int i = channelsToProcess; --i >= 0;)
180 FilterState& fs = filterStates[i];
184 fs.y2 = fs.x2 = *(endOfBuffer - 1);
192 fs.y1 = fs.x1 = *endOfBuffer;
196 jassert (sampsInBuffer >= 0);
199 void ResamplingAudioSource::createLowPass (
const double frequencyRatio)
201 const double proportionalRate = (frequencyRatio > 1.0) ? 0.5 / frequencyRatio
202 : 0.5 * frequencyRatio;
205 const double nSquared = n * n;
208 setFilterCoefficients (c1,
212 c1 * 2.0 * (1.0 - nSquared),
216 void ResamplingAudioSource::setFilterCoefficients (
double c1,
double c2,
double c3,
double c4,
double c5,
double c6)
218 const double a = 1.0 / c4;
226 coefficients[0] = c1;
227 coefficients[1] = c2;
228 coefficients[2] = c3;
229 coefficients[3] = c4;
230 coefficients[4] = c5;
231 coefficients[5] = c6;
234 void ResamplingAudioSource::resetFilters()
236 if (filterStates !=
nullptr)
237 filterStates.
clear ((
size_t) numChannels);
240 void ResamplingAudioSource::applyFilter (
float* samples,
int num, FilterState& fs)
244 const double in = *samples;
246 double out = coefficients[0] * in
247 + coefficients[1] * fs.x1
248 + coefficients[2] * fs.x2
249 - coefficients[4] * fs.y1
250 - coefficients[5] * fs.y2;
253 if (! (out < -1.0e-8 || out > 1.0e-8))
262 *samples++ = (float) out;