Add remaining files
[juce-lv2.git] / juce / source / src / audio / audio_sources / juce_ResamplingAudioSource.cpp
blobd4bc89e4ba81db7156036d818068c4eabc332ca1
1 /*
2 ==============================================================================
4 This file is part of the JUCE library - "Jules' Utility Class Extensions"
5 Copyright 2004-11 by Raw Material Software Ltd.
7 ------------------------------------------------------------------------------
9 JUCE can be redistributed and/or modified under the terms of the GNU General
10 Public License (Version 2), as published by the Free Software Foundation.
11 A copy of the license is included in the JUCE distribution, or can be found
12 online at www.gnu.org/licenses.
14 JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
18 ------------------------------------------------------------------------------
20 To release a closed-source product which uses JUCE, commercial licenses are
21 available: visit www.rawmaterialsoftware.com/juce for more information.
23 ==============================================================================
26 #include "../../core/juce_StandardHeader.h"
28 BEGIN_JUCE_NAMESPACE
30 #include "juce_ResamplingAudioSource.h"
33 //==============================================================================
34 ResamplingAudioSource::ResamplingAudioSource (AudioSource* const inputSource,
35 const bool deleteInputWhenDeleted,
36 const int numChannels_)
37 : input (inputSource, deleteInputWhenDeleted),
38 ratio (1.0),
39 lastRatio (1.0),
40 buffer (numChannels_, 0),
41 sampsInBuffer (0),
42 numChannels (numChannels_)
44 jassert (input != nullptr);
47 ResamplingAudioSource::~ResamplingAudioSource() {}
49 void ResamplingAudioSource::setResamplingRatio (const double samplesInPerOutputSample)
51 jassert (samplesInPerOutputSample > 0);
53 const SpinLock::ScopedLockType sl (ratioLock);
54 ratio = jmax (0.0, samplesInPerOutputSample);
57 void ResamplingAudioSource::prepareToPlay (int samplesPerBlockExpected,
58 double sampleRate)
60 const SpinLock::ScopedLockType sl (ratioLock);
62 input->prepareToPlay (samplesPerBlockExpected, sampleRate);
64 buffer.setSize (numChannels, roundToInt (samplesPerBlockExpected * ratio) + 32);
65 buffer.clear();
66 sampsInBuffer = 0;
67 bufferPos = 0;
68 subSampleOffset = 0.0;
70 filterStates.calloc (numChannels);
71 srcBuffers.calloc (numChannels);
72 destBuffers.calloc (numChannels);
73 createLowPass (ratio);
74 resetFilters();
77 void ResamplingAudioSource::releaseResources()
79 input->releaseResources();
80 buffer.setSize (numChannels, 0);
83 void ResamplingAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& info)
85 double localRatio;
88 const SpinLock::ScopedLockType sl (ratioLock);
89 localRatio = ratio;
92 if (lastRatio != localRatio)
94 createLowPass (localRatio);
95 lastRatio = localRatio;
98 const int sampsNeeded = roundToInt (info.numSamples * localRatio) + 2;
100 int bufferSize = buffer.getNumSamples();
102 if (bufferSize < sampsNeeded + 8)
104 bufferPos %= bufferSize;
105 bufferSize = sampsNeeded + 32;
106 buffer.setSize (buffer.getNumChannels(), bufferSize, true, true);
109 bufferPos %= bufferSize;
111 int endOfBufferPos = bufferPos + sampsInBuffer;
112 const int channelsToProcess = jmin (numChannels, info.buffer->getNumChannels());
114 while (sampsNeeded > sampsInBuffer)
116 endOfBufferPos %= bufferSize;
118 int numToDo = jmin (sampsNeeded - sampsInBuffer,
119 bufferSize - endOfBufferPos);
121 AudioSourceChannelInfo readInfo;
122 readInfo.buffer = &buffer;
123 readInfo.numSamples = numToDo;
124 readInfo.startSample = endOfBufferPos;
126 input->getNextAudioBlock (readInfo);
128 if (localRatio > 1.0001)
130 // for down-sampling, pre-apply the filter..
132 for (int i = channelsToProcess; --i >= 0;)
133 applyFilter (buffer.getSampleData (i, endOfBufferPos), numToDo, filterStates[i]);
136 sampsInBuffer += numToDo;
137 endOfBufferPos += numToDo;
140 for (int channel = 0; channel < channelsToProcess; ++channel)
142 destBuffers[channel] = info.buffer->getSampleData (channel, info.startSample);
143 srcBuffers[channel] = buffer.getSampleData (channel, 0);
146 int nextPos = (bufferPos + 1) % bufferSize;
147 for (int m = info.numSamples; --m >= 0;)
149 const float alpha = (float) subSampleOffset;
150 const float invAlpha = 1.0f - alpha;
152 for (int channel = 0; channel < channelsToProcess; ++channel)
153 *destBuffers[channel]++ = srcBuffers[channel][bufferPos] * invAlpha + srcBuffers[channel][nextPos] * alpha;
155 subSampleOffset += localRatio;
157 jassert (sampsInBuffer > 0);
159 while (subSampleOffset >= 1.0)
161 if (++bufferPos >= bufferSize)
162 bufferPos = 0;
164 --sampsInBuffer;
166 nextPos = (bufferPos + 1) % bufferSize;
167 subSampleOffset -= 1.0;
171 if (localRatio < 0.9999)
173 // for up-sampling, apply the filter after transposing..
174 for (int i = channelsToProcess; --i >= 0;)
175 applyFilter (info.buffer->getSampleData (i, info.startSample), info.numSamples, filterStates[i]);
177 else if (localRatio <= 1.0001)
179 // if the filter's not currently being applied, keep it stoked with the last couple of samples to avoid discontinuities
180 for (int i = channelsToProcess; --i >= 0;)
182 const float* const endOfBuffer = info.buffer->getSampleData (i, info.startSample + info.numSamples - 1);
183 FilterState& fs = filterStates[i];
185 if (info.numSamples > 1)
187 fs.y2 = fs.x2 = *(endOfBuffer - 1);
189 else
191 fs.y2 = fs.y1;
192 fs.x2 = fs.x1;
195 fs.y1 = fs.x1 = *endOfBuffer;
199 jassert (sampsInBuffer >= 0);
202 void ResamplingAudioSource::createLowPass (const double frequencyRatio)
204 const double proportionalRate = (frequencyRatio > 1.0) ? 0.5 / frequencyRatio
205 : 0.5 * frequencyRatio;
207 const double n = 1.0 / std::tan (double_Pi * jmax (0.001, proportionalRate));
208 const double nSquared = n * n;
209 const double c1 = 1.0 / (1.0 + std::sqrt (2.0) * n + nSquared);
211 setFilterCoefficients (c1,
212 c1 * 2.0f,
214 1.0,
215 c1 * 2.0 * (1.0 - nSquared),
216 c1 * (1.0 - std::sqrt (2.0) * n + nSquared));
219 void ResamplingAudioSource::setFilterCoefficients (double c1, double c2, double c3, double c4, double c5, double c6)
221 const double a = 1.0 / c4;
223 c1 *= a;
224 c2 *= a;
225 c3 *= a;
226 c5 *= a;
227 c6 *= a;
229 coefficients[0] = c1;
230 coefficients[1] = c2;
231 coefficients[2] = c3;
232 coefficients[3] = c4;
233 coefficients[4] = c5;
234 coefficients[5] = c6;
237 void ResamplingAudioSource::resetFilters()
239 filterStates.clear (numChannels);
242 void ResamplingAudioSource::applyFilter (float* samples, int num, FilterState& fs)
244 while (--num >= 0)
246 const double in = *samples;
248 double out = coefficients[0] * in
249 + coefficients[1] * fs.x1
250 + coefficients[2] * fs.x2
251 - coefficients[4] * fs.y1
252 - coefficients[5] * fs.y2;
254 #if JUCE_INTEL
255 if (! (out < -1.0e-8 || out > 1.0e-8))
256 out = 0;
257 #endif
259 fs.x2 = fs.x1;
260 fs.x1 = in;
261 fs.y2 = fs.y1;
262 fs.y1 = out;
264 *samples++ = (float) out;
268 END_JUCE_NAMESPACE