17 AudioSampleBuffer* destBuffer = bufferToFill.buffer;
18 const int len = std::min(bufferToFill.numSamples,
static_cast<int>(
m_sourceBuffer->getSize() -
m_pos));
21 for (
int channel = 0; channel < destBuffer->getNumChannels(); ++channel)
25 destBuffer->copyFrom(channel, bufferToFill.startSample,
m_sourceBuffer->data() +
m_pos, len);
26 if (len < bufferToFill.numSamples)
28 const int startClear = bufferToFill.startSample + len;
29 const int lenClear = bufferToFill.numSamples - len;
30 destBuffer->clear(startClear, lenClear);
35 destBuffer->clear(channel, bufferToFill.startSample, bufferToFill.numSamples);
39 m_pos +=
static_cast<size_t>(len);
53 : juce::Thread(
"ConvolutionComputationThread"), m_processor(processor)
68 if (!irFile.existsAsFile())
72 int numConvolvers = convolvers.size();
74 std::vector<FloatBuffer::Ptr> buffers;
76 juce::AudioFormatManager formatManager;
77 formatManager.registerBasicFormats();
78 std::unique_ptr<AudioFormatReader> reader(formatManager.createReaderFor(irFile));
79 double fileSampleRate = reader->sampleRate;
82 int fileChannels =
static_cast<int>(reader->numChannels);
83 if (fileChannels < 1 || fileChannels > 2)
86 bool isMono = fileChannels == 1;
87 for (
int i = 0; i < numConvolvers; ++i)
88 if (!threadShouldExit())
93 if (convolverSampleRate < 1.0)
96 for (
int i = 0; i < numConvolvers; ++i)
97 if (!threadShouldExit())
98 buffers[
static_cast<size_t>(i)] =
99 changeSampleRate(buffers[
static_cast<size_t>(i)], fileSampleRate, convolverSampleRate);
103 if (threadShouldExit())
110 if (threadShouldExit())
118 if (headBlockSize > 0 && tailBlockSize > 0)
119 for (
int i = 0; i < convolvers.size(); i++)
120 convolvers[i]->resetConvolver(buffers[
static_cast<size_t>(i)], headBlockSize, tailBlockSize);
124 int fileChannel)
const
126 if (!reader || reader->sampleRate < 0.0001)
129 const int fileChannels =
static_cast<int>(reader->numChannels);
130 const int fileLen =
static_cast<int>(reader->lengthInSamples);
132 if (
static_cast<int>(fileChannel) >= fileChannels)
136 AudioFormatReaderSource audioFormatReaderSource(reader,
false);
137 juce::AudioSampleBuffer importBuffer(fileChannels, 8192);
138 auto bufferPtr = buffer->data();
139 auto importBufferPtr = importBuffer.getReadPointer(fileChannel);
141 while (pos < fileLen)
143 if (threadShouldExit())
148 const int loading = std::min(importBuffer.getNumSamples(),
static_cast<int>(fileLen - pos));
149 AudioSourceChannelInfo info;
150 info.buffer = &importBuffer;
151 info.startSample = 0;
152 info.numSamples = loading;
153 audioFormatReaderSource.getNextAudioBlock(info);
154 ::memcpy(bufferPtr + pos, importBufferPtr,
155 static_cast<size_t>(
static_cast<unsigned int>(loading) *
sizeof(
float)));
156 pos +=
static_cast<int>(loading);
163 double inputSampleRate,
164 double outputSampleRate)
const
171 if (std::fabs(outputSampleRate - inputSampleRate) < 0.0000001)
176 jassert(inputSampleRate >= 1.0);
177 jassert(outputSampleRate >= 1.0);
179 const double samplesInPerOutputSample = inputSampleRate / outputSampleRate;
180 const int inputSampleCount =
static_cast<int>(inputBuffer->getSize());
181 const int outputSampleCount =
182 static_cast<int>(::ceil(
static_cast<double>(inputSampleCount) / samplesInPerOutputSample));
183 const int blockSize = 8192;
186 ResamplingAudioSource resamplingSource(&inputSource,
false, 1);
187 resamplingSource.setResamplingRatio(samplesInPerOutputSample);
188 resamplingSource.prepareToPlay(blockSize, outputSampleRate);
191 AudioSampleBuffer blockBuffer(1, blockSize);
193 while (processed < outputSampleCount)
195 if (threadShouldExit())
200 const int remaining = outputSampleCount - processed;
201 const int processing = std::min(blockSize, remaining);
203 juce::AudioSourceChannelInfo info;
204 info.buffer = &blockBuffer;
205 info.startSample = 0;
206 info.numSamples = processing;
207 resamplingSource.getNextAudioBlock(info);
208 ::memcpy(outputBuffer->data() + processed, blockBuffer.getReadPointer(0),
209 static_cast<size_t>(
static_cast<unsigned long>(processing) *
sizeof(
float)));
210 processed += processing;
213 resamplingSource.releaseResources();
220 size_t bufferSize = 0;
221 for (
size_t i = 0; i < buffers.size(); ++i)
223 if (buffers[i] !=
nullptr)
225 bufferSize = std::max(bufferSize, buffers[i]->getSize());
228 for (
size_t i = 0; i < buffers.size(); ++i)
230 if (threadShouldExit())
234 if (buffers[i] && buffers[i]->getSize() < bufferSize)
237 const size_t copySize = buffers[i]->getSize();
238 const size_t padSize = bufferSize - copySize;
239 ::memcpy(buffer->data(), buffers[i]->data(), copySize *
sizeof(
float));
240 ::memset(buffer->data() + copySize, 0, padSize *
sizeof(
float));
249 if (threadShouldExit())
252 auto buffer = buffers[0]->data();
253 auto len = buffers[0]->getSize();
256 for (
size_t i = 0; i < len; ++i)
257 rms += buffer[i] * buffer[i];
258 rms = std::sqrt(rms /
static_cast<float>(len));
260 const float idealRms = 1e-3f;
261 float gain = idealRms / rms;
262 for (
auto& buff : buffers)
264 for (
int i = 0; i < static_cast<int>(buff->getSize()); i++)
265 buff->data()[i] *= gain;
void run() override
Adds audio buffer to the convolvers, resamples it to the current sample rate, unifies buffer size and...
Definition ConvolutionComputationThread.cpp:60
void normaliseImpulseResponses(const std::vector< FloatBuffer::Ptr > &buffers) const
Definition ConvolutionComputationThread.cpp:246
FloatBuffer::Ptr importChannelFromAudioFile(AudioFormatReader *reader, int fileChannel) const
Definition ConvolutionComputationThread.cpp:123
ConvolutionComputationThread(ConvolutionReverb &processor)
Definition ConvolutionComputationThread.cpp:52
~ConvolutionComputationThread() override
Definition ConvolutionComputationThread.cpp:58
ConvolutionReverb & m_processor
Definition ConvolutionComputationThread.h:24
FloatBuffer::Ptr changeSampleRate(const FloatBuffer::Ptr &inputBuffer, double inputSampleRate, double outputSampleRate) const
Definition ConvolutionComputationThread.cpp:162
void unifyBufferSize(std::vector< FloatBuffer::Ptr > &buffers) const
Definition ConvolutionComputationThread.cpp:218
Audio processing class that uses multi-threading to convolve an input signal with an impulse response...
Definition ConvolutionReverb.h:9
size_t getConvolverTailBlockSize() const
Definition ConvolutionReverb.cpp:171
String getImpulseResponseFilePath() const
Definition ConvolutionReverb.cpp:177
size_t getConvolverHeadBlockSize() const
Definition ConvolutionReverb.cpp:165
const OwnedArray< IRConvolver > & getConvolvers() const
Definition ConvolutionReverb.cpp:142
double getSampleRate() const
Definition ConvolutionReverb.cpp:84
Definition IRConvolver.h:4
ReferenceCountedObjectPtr< FloatBuffer > Ptr
Definition IRConvolver.h:6
Definition ConvolutionComputationThread.cpp:4
FloatBufferSource & operator=(const FloatBufferSource &)
virtual void releaseResources()
Definition ConvolutionComputationThread.cpp:13
const FloatBuffer::Ptr & m_sourceBuffer
Definition ConvolutionComputationThread.cpp:43
size_t m_pos
Definition ConvolutionComputationThread.cpp:44
virtual void getNextAudioBlock(const AudioSourceChannelInfo &bufferToFill)
Definition ConvolutionComputationThread.cpp:15
FloatBufferSource(const FloatBuffer::Ptr &sourceBuffer)
Definition ConvolutionComputationThread.cpp:6
FloatBufferSource(const FloatBufferSource &)
virtual void prepareToPlay(int, double)
Definition ConvolutionComputationThread.cpp:11
Definition AirAbsorptionFilter.cpp:2