27 const bool deleteInputWhenDeleted,
29 : input (inputSource, deleteInputWhenDeleted),
30 numChannels (channels)
32 jassert (input !=
nullptr);
33 zeromem (coefficients,
sizeof (coefficients));
40 jassert (samplesInPerOutputSample > 0);
43 ratio = jmax (0.0, samplesInPerOutputSample);
50 auto scaledBlockSize = roundToInt (samplesPerBlockExpected * ratio);
51 input->prepareToPlay (scaledBlockSize, sampleRate * ratio);
53 buffer.
setSize (numChannels, scaledBlockSize + 32);
55 filterStates.
calloc (numChannels);
56 srcBuffers.
calloc (numChannels);
57 destBuffers.
calloc (numChannels);
58 createLowPass (ratio);
70 subSampleOffset = 0.0;
76 input->releaseResources();
77 buffer.
setSize (numChannels, 0);
91 if (lastRatio != localRatio)
93 createLowPass (localRatio);
94 lastRatio = localRatio;
97 const int sampsNeeded = roundToInt (info.
numSamples * localRatio) + 3;
101 if (bufferSize < sampsNeeded + 8)
103 bufferPos %= bufferSize;
104 bufferSize = sampsNeeded + 32;
108 bufferPos %= bufferSize;
110 int endOfBufferPos = bufferPos + sampsInBuffer;
113 while (sampsNeeded > sampsInBuffer)
115 endOfBufferPos %= bufferSize;
117 int numToDo = jmin (sampsNeeded - sampsInBuffer,
118 bufferSize - endOfBufferPos);
121 input->getNextAudioBlock (readInfo);
123 if (localRatio > 1.0001)
127 for (
int i = channelsToProcess; --i >= 0;)
128 applyFilter (buffer.
getWritePointer (i, endOfBufferPos), numToDo, filterStates[i]);
131 sampsInBuffer += numToDo;
132 endOfBufferPos += numToDo;
135 for (
int channel = 0; channel < channelsToProcess; ++channel)
141 int nextPos = (bufferPos + 1) % bufferSize;
145 jassert (sampsInBuffer > 0 && nextPos != endOfBufferPos);
147 const float alpha = (float) subSampleOffset;
149 for (
int channel = 0; channel < channelsToProcess; ++channel)
150 *destBuffers[channel]++ = srcBuffers[channel][bufferPos]
151 + alpha * (srcBuffers[channel][nextPos] - srcBuffers[channel][bufferPos]);
153 subSampleOffset += localRatio;
155 while (subSampleOffset >= 1.0)
157 if (++bufferPos >= bufferSize)
162 nextPos = (bufferPos + 1) % bufferSize;
163 subSampleOffset -= 1.0;
167 if (localRatio < 0.9999)
170 for (
int i = channelsToProcess; --i >= 0;)
173 else if (localRatio <= 1.0001 && info.numSamples > 0)
176 for (
int i = channelsToProcess; --i >= 0;)
179 FilterState& fs = filterStates[i];
183 fs.y2 = fs.x2 = *(endOfBuffer - 1);
191 fs.y1 = fs.x1 = *endOfBuffer;
195 jassert (sampsInBuffer >= 0);
198 void ResamplingAudioSource::createLowPass (
const double frequencyRatio)
200 const double proportionalRate = (frequencyRatio > 1.0) ? 0.5 / frequencyRatio
201 : 0.5 * frequencyRatio;
204 const double nSquared = n * n;
207 setFilterCoefficients (c1,
211 c1 * 2.0 * (1.0 - nSquared),
215 void ResamplingAudioSource::setFilterCoefficients (
double c1,
double c2,
double c3,
double c4,
double c5,
double c6)
217 const double a = 1.0 / c4;
225 coefficients[0] = c1;
226 coefficients[1] = c2;
227 coefficients[2] = c3;
228 coefficients[3] = c4;
229 coefficients[4] = c5;
230 coefficients[5] = c6;
233 void ResamplingAudioSource::resetFilters()
235 if (filterStates !=
nullptr)
236 filterStates.
clear ((
size_t) numChannels);
239 void ResamplingAudioSource::applyFilter (
float* samples,
int num, FilterState& fs)
243 const double in = *samples;
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;
252 if (! (out < -1.0e-8 || out > 1.0e-8))
261 *samples++ = (float) out;
void prepareToPlay(int samplesPerBlockExpected, double sampleRate) override
void getNextAudioBlock(const AudioSourceChannelInfo &) override
void setSize(int newNumChannels, int newNumSamples, bool keepExistingContent=false, bool clearExtraSpace=false, bool avoidReallocating=false)
void releaseResources() override
const Type * getReadPointer(int channelNumber) const noexcept
void calloc(SizeType newNumElements, const size_t elementSize=sizeof(ElementType))
int getNumChannels() const noexcept
~ResamplingAudioSource() override
void clear(SizeType numElements) noexcept
ResamplingAudioSource(AudioSource *inputSource, bool deleteInputWhenDeleted, int numChannels=2)
AudioBuffer< float > * buffer
void setResamplingRatio(double samplesInPerOutputSample)
Type * getWritePointer(int channelNumber) noexcept
int getNumSamples() const noexcept