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);
198void 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),
215void 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;
233void ResamplingAudioSource::resetFilters()
235 if (filterStates !=
nullptr)
236 filterStates.
clear ((
size_t) numChannels);
239void 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 setSize(int newNumChannels, int newNumSamples, bool keepExistingContent=false, bool clearExtraSpace=false, bool avoidReallocating=false)
Changes the buffer's size or number of channels.
Type * getWritePointer(int channelNumber) noexcept
Returns a writeable pointer to one of the buffer's channels.
int getNumChannels() const noexcept
Returns the number of channels of audio data that this buffer contains.
int getNumSamples() const noexcept
Returns the number of samples allocated in each of the buffer's channels.
void clear() noexcept
Clears all the samples in all channels.
const Type * getReadPointer(int channelNumber) const noexcept
Returns a pointer to an array of read-only samples in one of the buffer's channels.
Base class for objects that can produce a continuous stream of audio.
Automatically locks and unlocks a mutex object.
void clear(SizeType numElements) noexcept
This fills the block with zeros, up to the number of elements specified.
void calloc(SizeType newNumElements, const size_t elementSize=sizeof(ElementType))
Allocates a specified amount of memory and clears it.
void releaseResources() override
Allows the source to release anything it no longer needs after playback has stopped.
void getNextAudioBlock(const AudioSourceChannelInfo &) override
Called repeatedly to fetch subsequent blocks of audio data.
void prepareToPlay(int samplesPerBlockExpected, double sampleRate) override
Tells the source to prepare for playing.
void flushBuffers()
Clears any buffers and filters that the resampler is using.
~ResamplingAudioSource() override
Destructor.
void setResamplingRatio(double samplesInPerOutputSample)
Changes the resampling ratio.
ResamplingAudioSource(AudioSource *inputSource, bool deleteInputWhenDeleted, int numChannels=2)
Creates a ResamplingAudioSource for a given input source.
Used by AudioSource::getNextAudioBlock().
int numSamples
The number of samples in the buffer which the callback is expected to fill with data.
AudioBuffer< float > * buffer
The destination buffer to fill with audio data.
int startSample
The first sample in the buffer from which the callback is expected to write data.
Commonly used mathematical constants.