@@ -39,10 +39,9 @@ AudioSampleBuffer::AudioSampleBuffer (const AudioSampleBuffer& other) noexcept | |||
size (other.size) | |||
{ | |||
allocateData(); | |||
const size_t numBytes = sizeof (float) * (size_t) size; | |||
for (int i = 0; i < numChannels; ++i) | |||
memcpy (channels[i], other.channels[i], numBytes); | |||
FloatVectorOperations::copy (channels[i], other.channels[i], size); | |||
} | |||
void AudioSampleBuffer::allocateData() | |||
@@ -130,10 +129,8 @@ AudioSampleBuffer& AudioSampleBuffer::operator= (const AudioSampleBuffer& other) | |||
{ | |||
setSize (other.getNumChannels(), other.getNumSamples(), false, false, false); | |||
const size_t numBytes = sizeof (float) * (size_t) size; | |||
for (int i = 0; i < numChannels; ++i) | |||
memcpy (channels[i], other.channels[i], numBytes); | |||
FloatVectorOperations::copy (channels[i], other.channels[i], size); | |||
} | |||
return *this; | |||
@@ -154,15 +151,17 @@ void AudioSampleBuffer::setSize (const int newNumChannels, | |||
if (newNumSamples != size || newNumChannels != numChannels) | |||
{ | |||
const size_t channelListSize = sizeof (float*) * (size_t) (newNumChannels + 1); | |||
const size_t newTotalBytes = ((size_t) newNumChannels * (size_t) newNumSamples * sizeof (float)) + channelListSize + 32; | |||
const size_t allocatedSamplesPerChannel = (newNumSamples + 3) & ~3; | |||
const size_t channelListSize = ((sizeof (float*) * (size_t) (newNumChannels + 1)) + 15) & ~15; | |||
const size_t newTotalBytes = ((size_t) newNumChannels * (size_t) allocatedSamplesPerChannel * sizeof (float)) | |||
+ channelListSize + 32; | |||
if (keepExistingContent) | |||
{ | |||
HeapBlock <char, true> newData; | |||
newData.allocate (newTotalBytes, clearExtraSpace); | |||
const size_t numBytesToCopy = sizeof (float) * (size_t) jmin (newNumSamples, size); | |||
const size_t numSamplesToCopy = jmin (newNumSamples, size); | |||
float** const newChannels = reinterpret_cast <float**> (newData.getData()); | |||
float* newChan = reinterpret_cast <float*> (newData + channelListSize); | |||
@@ -170,12 +169,12 @@ void AudioSampleBuffer::setSize (const int newNumChannels, | |||
for (int j = 0; j < newNumChannels; ++j) | |||
{ | |||
newChannels[j] = newChan; | |||
newChan += newNumSamples; | |||
newChan += allocatedSamplesPerChannel; | |||
} | |||
const int numChansToCopy = jmin (numChannels, newNumChannels); | |||
for (int i = 0; i < numChansToCopy; ++i) | |||
memcpy (newChannels[i], channels[i], numBytesToCopy); | |||
FloatVectorOperations::copy (newChannels[i], channels[i], numSamplesToCopy); | |||
allocatedData.swapWith (newData); | |||
allocatedBytes = newTotalBytes; | |||
@@ -199,7 +198,7 @@ void AudioSampleBuffer::setSize (const int newNumChannels, | |||
for (int i = 0; i < newNumChannels; ++i) | |||
{ | |||
channels[i] = chan; | |||
chan += newNumSamples; | |||
chan += allocatedSamplesPerChannel; | |||
} | |||
} | |||
@@ -212,7 +211,7 @@ void AudioSampleBuffer::setSize (const int newNumChannels, | |||
void AudioSampleBuffer::clear() noexcept | |||
{ | |||
for (int i = 0; i < numChannels; ++i) | |||
zeromem (channels[i], sizeof (float) * (size_t) size); | |||
FloatVectorOperations::clear (channels[i], size); | |||
} | |||
void AudioSampleBuffer::clear (const int startSample, | |||
@@ -221,7 +220,7 @@ void AudioSampleBuffer::clear (const int startSample, | |||
jassert (startSample >= 0 && startSample + numSamples <= size); | |||
for (int i = 0; i < numChannels; ++i) | |||
zeromem (channels [i] + startSample, sizeof (float) * (size_t) numSamples); | |||
FloatVectorOperations::clear (channels[i] + startSample, numSamples); | |||
} | |||
void AudioSampleBuffer::clear (const int channel, | |||
@@ -231,7 +230,7 @@ void AudioSampleBuffer::clear (const int channel, | |||
jassert (isPositiveAndBelow (channel, numChannels)); | |||
jassert (startSample >= 0 && startSample + numSamples <= size); | |||
zeromem (channels [channel] + startSample, sizeof (float) * (size_t) numSamples); | |||
FloatVectorOperations::clear (channels [channel] + startSample, numSamples); | |||
} | |||
void AudioSampleBuffer::applyGain (const int channel, | |||
@@ -244,17 +243,12 @@ void AudioSampleBuffer::applyGain (const int channel, | |||
if (gain != 1.0f) | |||
{ | |||
float* d = channels [channel] + startSample; | |||
float* const d = channels [channel] + startSample; | |||
if (gain == 0.0f) | |||
{ | |||
zeromem (d, sizeof (float) * (size_t) numSamples); | |||
} | |||
FloatVectorOperations::clear (d, numSamples); | |||
else | |||
{ | |||
while (--numSamples >= 0) | |||
*d++ *= gain; | |||
} | |||
FloatVectorOperations::multiply (d, gain, numSamples); | |||
} | |||
} | |||
@@ -322,19 +316,13 @@ void AudioSampleBuffer::addFrom (const int destChannel, | |||
if (gain != 0.0f && numSamples > 0) | |||
{ | |||
float* d = channels [destChannel] + destStartSample; | |||
const float* s = source.channels [sourceChannel] + sourceStartSample; | |||
float* const d = channels [destChannel] + destStartSample; | |||
const float* const s = source.channels [sourceChannel] + sourceStartSample; | |||
if (gain != 1.0f) | |||
{ | |||
while (--numSamples >= 0) | |||
*d++ += gain * *s++; | |||
} | |||
FloatVectorOperations::addWithMultiply (d, s, gain, numSamples); | |||
else | |||
{ | |||
while (--numSamples >= 0) | |||
*d++ += *s++; | |||
} | |||
FloatVectorOperations::add (d, s, numSamples); | |||
} | |||
} | |||
@@ -350,18 +338,12 @@ void AudioSampleBuffer::addFrom (const int destChannel, | |||
if (gain != 0.0f && numSamples > 0) | |||
{ | |||
float* d = channels [destChannel] + destStartSample; | |||
float* const d = channels [destChannel] + destStartSample; | |||
if (gain != 1.0f) | |||
{ | |||
while (--numSamples >= 0) | |||
*d++ += gain * *source++; | |||
} | |||
FloatVectorOperations::addWithMultiply (d, source, gain, numSamples); | |||
else | |||
{ | |||
while (--numSamples >= 0) | |||
*d++ += *source++; | |||
} | |||
FloatVectorOperations::add (d, source, numSamples); | |||
} | |||
} | |||
@@ -378,11 +360,7 @@ void AudioSampleBuffer::addFromWithRamp (const int destChannel, | |||
if (startGain == endGain) | |||
{ | |||
addFrom (destChannel, | |||
destStartSample, | |||
source, | |||
numSamples, | |||
startGain); | |||
addFrom (destChannel, destStartSample, source, numSamples, startGain); | |||
} | |||
else | |||
{ | |||
@@ -415,9 +393,9 @@ void AudioSampleBuffer::copyFrom (const int destChannel, | |||
if (numSamples > 0) | |||
{ | |||
memcpy (channels [destChannel] + destStartSample, | |||
source.channels [sourceChannel] + sourceStartSample, | |||
sizeof (float) * (size_t) numSamples); | |||
FloatVectorOperations::copy (channels [destChannel] + destStartSample, | |||
source.channels [sourceChannel] + sourceStartSample, | |||
numSamples); | |||
} | |||
} | |||
@@ -432,9 +410,9 @@ void AudioSampleBuffer::copyFrom (const int destChannel, | |||
if (numSamples > 0) | |||
{ | |||
memcpy (channels [destChannel] + destStartSample, | |||
source, | |||
sizeof (float) * (size_t) numSamples); | |||
FloatVectorOperations::copy (channels [destChannel] + destStartSample, | |||
source, | |||
numSamples); | |||
} | |||
} | |||
@@ -455,18 +433,13 @@ void AudioSampleBuffer::copyFrom (const int destChannel, | |||
if (gain != 1.0f) | |||
{ | |||
if (gain == 0) | |||
{ | |||
zeromem (d, sizeof (float) * (size_t) numSamples); | |||
} | |||
FloatVectorOperations::clear (d, numSamples); | |||
else | |||
{ | |||
while (--numSamples >= 0) | |||
*d++ = gain * *source++; | |||
} | |||
FloatVectorOperations::copyWithMultiply (d, source, gain, numSamples); | |||
} | |||
else | |||
{ | |||
memcpy (d, source, sizeof (float) * (size_t) numSamples); | |||
FloatVectorOperations::copy (d, source, numSamples); | |||
} | |||
} | |||
} | |||
@@ -484,11 +457,7 @@ void AudioSampleBuffer::copyFromWithRamp (const int destChannel, | |||
if (startGain == endGain) | |||
{ | |||
copyFrom (destChannel, | |||
destStartSample, | |||
source, | |||
numSamples, | |||
startGain); | |||
copyFrom (destChannel, destStartSample, source, numSamples, startGain); | |||
} | |||
else | |||
{ | |||
@@ -515,7 +484,8 @@ void AudioSampleBuffer::findMinMax (const int channel, | |||
jassert (isPositiveAndBelow (channel, numChannels)); | |||
jassert (startSample >= 0 && startSample + numSamples <= size); | |||
findMinAndMax (channels [channel] + startSample, numSamples, minVal, maxVal); | |||
FloatVectorOperations::findMinAndMax (channels [channel] + startSample, | |||
numSamples, minVal, maxVal); | |||
} | |||
float AudioSampleBuffer::getMagnitude (const int channel, | |||
@@ -0,0 +1,234 @@ | |||
/* | |||
============================================================================== | |||
This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||
Copyright 2004-11 by Raw Material Software Ltd. | |||
------------------------------------------------------------------------------ | |||
JUCE can be redistributed and/or modified under the terms of the GNU General | |||
Public License (Version 2), as published by the Free Software Foundation. | |||
A copy of the license is included in the JUCE distribution, or can be found | |||
online at www.gnu.org/licenses. | |||
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY | |||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | |||
A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |||
------------------------------------------------------------------------------ | |||
To release a closed-source product which uses JUCE, commercial licenses are | |||
available: visit www.rawmaterialsoftware.com/juce for more information. | |||
============================================================================== | |||
*/ | |||
#if JUCE_USE_SSE_INTRINSICS | |||
namespace FloatVectorHelpers | |||
{ | |||
static bool sse2Present = false; | |||
static bool isSSE2Available() | |||
{ | |||
if (sse2Present) | |||
return true; | |||
sse2Present = SystemStats::hasSSE2(); | |||
return sse2Present; | |||
} | |||
inline static bool isAligned (const void* p) | |||
{ | |||
return (((pointer_sized_int) p) & 15) == 0; | |||
} | |||
} | |||
#define JUCE_BEGIN_SSE_OP \ | |||
if (FloatVectorHelpers::isSSE2Available()) \ | |||
{ \ | |||
const int numLongOps = num / 4; | |||
#define JUCE_FINISH_SSE_OP(normalOp) \ | |||
_mm_empty(); \ | |||
num &= 3; \ | |||
if (num == 0) return; \ | |||
} \ | |||
for (int i = 0; i < num; ++i) normalOp; | |||
#define JUCE_SSE_LOOP(sseOp, srcLoad, dstLoad, dstStore, locals, increment) \ | |||
for (int i = 0; i < numLongOps; ++i) \ | |||
{ \ | |||
locals (srcLoad, dstLoad); \ | |||
dstStore (dest, sseOp); \ | |||
increment; \ | |||
} | |||
#define JUCE_INCREMENT_SRC_DEST dest += 4; src += 4; | |||
#define JUCE_INCREMENT_DEST dest += 4; | |||
#define JUCE_LOAD_NONE(srcLoad, dstLoad) | |||
#define JUCE_LOAD_DEST(srcLoad, dstLoad) const __m128 d = dstLoad (dest); | |||
#define JUCE_LOAD_SRC(srcLoad, dstLoad) const __m128 s = srcLoad (src); | |||
#define JUCE_LOAD_SRC_DEST(srcLoad, dstLoad) const __m128 d = dstLoad (dest); const __m128 s = srcLoad (src); | |||
#define JUCE_PERFORM_SSE_OP_DEST(normalOp, sseOp) \ | |||
JUCE_BEGIN_SSE_OP \ | |||
if (FloatVectorHelpers::isAligned (dest)) JUCE_SSE_LOOP (sseOp, dummy, _mm_load_ps, _mm_store_ps, JUCE_LOAD_DEST, JUCE_INCREMENT_DEST) \ | |||
else JUCE_SSE_LOOP (sseOp, dummy, _mm_loadu_ps, _mm_storeu_ps, JUCE_LOAD_DEST, JUCE_INCREMENT_DEST) \ | |||
JUCE_FINISH_SSE_OP (normalOp) | |||
#define JUCE_PERFORM_SSE_OP_SRC_DEST(normalOp, sseOp, locals, increment) \ | |||
JUCE_BEGIN_SSE_OP \ | |||
if (FloatVectorHelpers::isAligned (dest)) \ | |||
{ \ | |||
if (FloatVectorHelpers::isAligned (src)) JUCE_SSE_LOOP (sseOp, _mm_load_ps, _mm_load_ps, _mm_store_ps, locals, increment) \ | |||
else JUCE_SSE_LOOP (sseOp, _mm_loadu_ps, _mm_load_ps, _mm_store_ps, locals, increment) \ | |||
}\ | |||
else \ | |||
{ \ | |||
if (FloatVectorHelpers::isAligned (src)) JUCE_SSE_LOOP (sseOp, _mm_load_ps, _mm_loadu_ps, _mm_storeu_ps, locals, increment) \ | |||
else JUCE_SSE_LOOP (sseOp, _mm_loadu_ps, _mm_loadu_ps, _mm_storeu_ps, locals, increment) \ | |||
} \ | |||
JUCE_FINISH_SSE_OP (normalOp) | |||
#else | |||
#define JUCE_PERFORM_SSE_OP_DEST(normalOp, unused1) for (int i = 0; i < num; ++i) normalOp; | |||
#define JUCE_PERFORM_SSE_OP_SRC_DEST(normalOp, sseOp, locals, increment) for (int i = 0; i < num; ++i) normalOp; | |||
#endif | |||
void FloatVectorOperations::clear (float* dest, const int num) noexcept | |||
{ | |||
zeromem (dest, num * sizeof (float)); | |||
} | |||
void FloatVectorOperations::copy (float* dest, const float* src, const int num) noexcept | |||
{ | |||
memcpy (dest, src, num * sizeof (float)); | |||
} | |||
void FloatVectorOperations::copyWithMultiply (float* dest, const float* src, float multiplier, int num) noexcept | |||
{ | |||
#if JUCE_USE_SSE_INTRINSICS | |||
const __m128 mult = _mm_load1_ps (&multiplier); | |||
#endif | |||
JUCE_PERFORM_SSE_OP_SRC_DEST (dest[i] = src[i] * multiplier, | |||
_mm_mul_ps (mult, s), | |||
JUCE_LOAD_SRC, JUCE_INCREMENT_SRC_DEST) | |||
} | |||
void FloatVectorOperations::add (float* dest, const float* src, int num) noexcept | |||
{ | |||
JUCE_PERFORM_SSE_OP_SRC_DEST (dest[i] += src[i], | |||
_mm_add_ps (d, s), | |||
JUCE_LOAD_SRC_DEST, JUCE_INCREMENT_SRC_DEST) | |||
} | |||
void FloatVectorOperations::add (float* dest, float amount, int num) noexcept | |||
{ | |||
#if JUCE_USE_SSE_INTRINSICS | |||
const __m128 amountToAdd = _mm_load1_ps (&amount); | |||
#endif | |||
JUCE_PERFORM_SSE_OP_DEST (dest[i] += amount, | |||
_mm_add_ps (d, amountToAdd)) | |||
} | |||
void FloatVectorOperations::addWithMultiply (float* dest, const float* src, float multiplier, int num) noexcept | |||
{ | |||
#if JUCE_USE_SSE_INTRINSICS | |||
const __m128 mult = _mm_load1_ps (&multiplier); | |||
#endif | |||
JUCE_PERFORM_SSE_OP_SRC_DEST (dest[i] += src[i] * multiplier, | |||
_mm_add_ps (d, _mm_mul_ps (mult, s)), | |||
JUCE_LOAD_SRC_DEST, JUCE_INCREMENT_SRC_DEST) | |||
} | |||
void FloatVectorOperations::multiply (float* dest, const float* src, int num) noexcept | |||
{ | |||
JUCE_PERFORM_SSE_OP_SRC_DEST (dest[i] *= src[i], | |||
_mm_mul_ps (d, s), | |||
JUCE_LOAD_SRC_DEST, JUCE_INCREMENT_SRC_DEST) | |||
} | |||
void FloatVectorOperations::multiply (float* dest, float multiplier, int num) noexcept | |||
{ | |||
#if JUCE_USE_SSE_INTRINSICS | |||
const __m128 mult = _mm_load1_ps (&multiplier); | |||
#endif | |||
JUCE_PERFORM_SSE_OP_DEST (dest[i] *= multiplier, | |||
_mm_mul_ps (d, mult)) | |||
} | |||
void FloatVectorOperations::convertFixedToFloat (float* dest, const int* src, float multiplier, int num) noexcept | |||
{ | |||
#if JUCE_USE_SSE_INTRINSICS | |||
const __m128 mult = _mm_load1_ps (&multiplier); | |||
#endif | |||
JUCE_PERFORM_SSE_OP_SRC_DEST (dest[i] = src[i] * multiplier, | |||
_mm_mul_ps (mult, _mm_movelh_ps (_mm_cvt_pi2ps (_mm_setzero_ps(), ((const __m64*) src)[0]), | |||
_mm_cvt_pi2ps (_mm_setzero_ps(), ((const __m64*) src)[1]))), | |||
JUCE_LOAD_NONE, JUCE_INCREMENT_SRC_DEST) | |||
} | |||
void FloatVectorOperations::findMinAndMax (const float* src, int num, float& minResult, float& maxResult) noexcept | |||
{ | |||
#if JUCE_USE_SSE_INTRINSICS | |||
const int numLongOps = num / 4; | |||
if (numLongOps > 1 && FloatVectorHelpers::isSSE2Available()) | |||
{ | |||
__m128 mn, mx; | |||
#define JUCE_MINMAX_SSE_LOOP(loadOp) \ | |||
mn = loadOp (src); \ | |||
mx = mn; \ | |||
src += 4; \ | |||
for (int i = 1; i < numLongOps; ++i) \ | |||
{ \ | |||
const __m128 s = loadOp (src); \ | |||
mn = _mm_min_ps (mn, s); \ | |||
mx = _mm_max_ps (mx, s); \ | |||
src += 4; \ | |||
} | |||
if (FloatVectorHelpers::isAligned (src)) { JUCE_MINMAX_SSE_LOOP (_mm_load_ps) } | |||
else { JUCE_MINMAX_SSE_LOOP (_mm_loadu_ps) } | |||
float localMin, localMax; | |||
{ | |||
float mns[4], mxs[4]; | |||
_mm_storeu_ps (mns, mn); | |||
_mm_storeu_ps (mxs, mx); | |||
_mm_empty(); | |||
localMin = jmin (mns[0], mns[1], mns[2], mns[3]); | |||
localMax = jmax (mxs[0], mxs[1], mxs[2], mxs[3]); | |||
} | |||
num &= 3; | |||
if (num != 0) | |||
{ | |||
for (int i = 0; i < num; ++i) | |||
{ | |||
const float s = src[i]; | |||
localMin = jmin (localMin, s); | |||
localMax = jmax (localMax, s); | |||
} | |||
} | |||
minResult = localMin; | |||
maxResult = localMax; | |||
return; | |||
} | |||
#endif | |||
juce::findMinAndMax (src, num, minResult, maxResult); | |||
} |
@@ -0,0 +1,69 @@ | |||
/* | |||
============================================================================== | |||
This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||
Copyright 2004-11 by Raw Material Software Ltd. | |||
------------------------------------------------------------------------------ | |||
JUCE can be redistributed and/or modified under the terms of the GNU General | |||
Public License (Version 2), as published by the Free Software Foundation. | |||
A copy of the license is included in the JUCE distribution, or can be found | |||
online at www.gnu.org/licenses. | |||
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY | |||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | |||
A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |||
------------------------------------------------------------------------------ | |||
To release a closed-source product which uses JUCE, commercial licenses are | |||
available: visit www.rawmaterialsoftware.com/juce for more information. | |||
============================================================================== | |||
*/ | |||
#ifndef __JUCE_FLOATVECTOROPERATIONS_JUCEHEADER__ | |||
#define __JUCE_FLOATVECTOROPERATIONS_JUCEHEADER__ | |||
//============================================================================== | |||
/** | |||
*/ | |||
class JUCE_API FloatVectorOperations | |||
{ | |||
public: | |||
//============================================================================== | |||
/** Clears a vector of floats. */ | |||
static void clear (float* dest, int numValues) noexcept; | |||
/** Copies a vector of floats. */ | |||
static void copy (float* dest, const float* src, int numValues) noexcept; | |||
/** Copies a vector of floats, multiplying each value by a given multiplier */ | |||
static void copyWithMultiply (float* dest, const float* src, float multiplier, int numValues) noexcept; | |||
/** Adds the source values to the destination values. */ | |||
static void add (float* dest, const float* src, int numValues) noexcept; | |||
/** Adds a fixed value to the destination values. */ | |||
static void add (float* dest, float amount, int numValues) noexcept; | |||
/** Multiplies each source value by the given multiplier, then adds it to the destination value. */ | |||
static void addWithMultiply (float* dest, const float* src, float multiplier, int numValues) noexcept; | |||
/** Multiplies the destination values by the source values. */ | |||
static void multiply (float* dest, const float* src, int numValues) noexcept; | |||
/** Multiplies each of the destination values by a fixed multiplier. */ | |||
static void multiply (float* dest, float multiplier, int numValues) noexcept; | |||
/** Converts a stream of integers to floats, multiplying each one by the given multiplier. */ | |||
static void convertFixedToFloat (float* dest, const int* src, float multiplier, int numValues) noexcept; | |||
/** Finds the miniumum and maximum values in the given array. */ | |||
static void findMinAndMax (const float* src, int numValues, float& minResult, float& maxResult) noexcept; | |||
}; | |||
#endif // __JUCE_FLOATVECTOROPERATIONS_JUCEHEADER__ |
@@ -38,7 +38,7 @@ IIRFilter::IIRFilter() | |||
IIRFilter::IIRFilter (const IIRFilter& other) | |||
: active (other.active), v1 (0), v2 (0) | |||
{ | |||
const ScopedLock sl (other.processLock); | |||
const SpinLock::ScopedLockType sl (other.processLock); | |||
memcpy (coefficients, other.coefficients, sizeof (coefficients)); | |||
} | |||
@@ -49,7 +49,7 @@ IIRFilter::~IIRFilter() | |||
//============================================================================== | |||
void IIRFilter::reset() noexcept | |||
{ | |||
const ScopedLock sl (processLock); | |||
const SpinLock::ScopedLockType sl (processLock); | |||
v1 = v2 = 0; | |||
} | |||
@@ -59,8 +59,8 @@ float IIRFilter::processSingleSampleRaw (const float in) noexcept | |||
JUCE_SNAP_TO_ZERO (out); | |||
v1 = coefficients[1] * in - coefficients[4] * out + v2; | |||
v2 = coefficients[2] * in - coefficients[5] * out; | |||
v1 = coefficients[1] * in - coefficients[3] * out + v2; | |||
v2 = coefficients[2] * in - coefficients[4] * out; | |||
return out; | |||
} | |||
@@ -68,23 +68,29 @@ float IIRFilter::processSingleSampleRaw (const float in) noexcept | |||
void IIRFilter::processSamples (float* const samples, | |||
const int numSamples) noexcept | |||
{ | |||
const ScopedLock sl (processLock); | |||
const SpinLock::ScopedLockType sl (processLock); | |||
if (active) | |||
{ | |||
const float c0 = coefficients[0]; | |||
const float c1 = coefficients[1]; | |||
const float c2 = coefficients[2]; | |||
const float c3 = coefficients[3]; | |||
const float c4 = coefficients[4]; | |||
float lv1 = v1, lv2 = v2; | |||
for (int i = 0; i < numSamples; ++i) | |||
{ | |||
const float in = samples[i]; | |||
float out = coefficients[0] * in + v1; | |||
JUCE_SNAP_TO_ZERO (out); | |||
v1 = coefficients[1] * in - coefficients[4] * out + v2; | |||
v2 = coefficients[2] * in - coefficients[5] * out; | |||
const float out = c0 * in + lv1; | |||
samples[i] = out; | |||
lv1 = c1 * in - c3 * out + lv2; | |||
lv2 = c2 * in - c4 * out; | |||
} | |||
JUCE_SNAP_TO_ZERO (lv1); v1 = lv1; | |||
JUCE_SNAP_TO_ZERO (lv2); v2 = lv2; | |||
} | |||
} | |||
@@ -194,14 +200,14 @@ void IIRFilter::makeBandPass (const double sampleRate, | |||
void IIRFilter::makeInactive() noexcept | |||
{ | |||
const ScopedLock sl (processLock); | |||
const SpinLock::ScopedLockType sl (processLock); | |||
active = false; | |||
} | |||
//============================================================================== | |||
void IIRFilter::copyCoefficientsFrom (const IIRFilter& other) noexcept | |||
{ | |||
const ScopedLock sl (processLock); | |||
const SpinLock::ScopedLockType sl (processLock); | |||
memcpy (coefficients, other.coefficients, sizeof (coefficients)); | |||
active = other.active; | |||
@@ -219,14 +225,13 @@ void IIRFilter::setCoefficients (double c1, double c2, double c3, | |||
c5 *= a; | |||
c6 *= a; | |||
const ScopedLock sl (processLock); | |||
const SpinLock::ScopedLockType sl (processLock); | |||
coefficients[0] = (float) c1; | |||
coefficients[1] = (float) c2; | |||
coefficients[2] = (float) c3; | |||
coefficients[3] = (float) c4; | |||
coefficients[4] = (float) c5; | |||
coefficients[5] = (float) c6; | |||
coefficients[3] = (float) c5; | |||
coefficients[4] = (float) c6; | |||
active = true; | |||
} | |||
@@ -131,13 +131,13 @@ public: | |||
protected: | |||
//============================================================================== | |||
CriticalSection processLock; | |||
SpinLock processLock; | |||
void setCoefficients (double c1, double c2, double c3, | |||
double c4, double c5, double c6) noexcept; | |||
bool active; | |||
float coefficients[6]; | |||
float coefficients[5]; | |||
float v1, v2; | |||
// (use the copyCoefficientsFrom() method instead of this operator) | |||
@@ -35,15 +35,27 @@ | |||
// Your project must contain an AppConfig.h file with your project-specific settings in it, | |||
// and your header search path must make it accessible to the module's files. | |||
#include "AppConfig.h" | |||
#include "juce_audio_basics.h" | |||
#ifndef JUCE_USE_SSE_INTRINSICS | |||
#define JUCE_USE_SSE_INTRINSICS 1 | |||
#endif | |||
#if ! JUCE_INTEL | |||
#define JUCE_USE_SSE_INTRINSICS 0 | |||
#endif | |||
#if JUCE_USE_SSE_INTRINSICS | |||
#include <emmintrin.h> | |||
#endif | |||
namespace juce | |||
{ | |||
// START_AUTOINCLUDE buffers/*.cpp, effects/*.cpp, midi/*.cpp, sources/*.cpp, synthesisers/*.cpp | |||
#include "buffers/juce_AudioDataConverters.cpp" | |||
#include "buffers/juce_AudioSampleBuffer.cpp" | |||
#include "buffers/juce_FloatVectorOperations.cpp" | |||
#include "effects/juce_IIRFilter.cpp" | |||
#include "effects/juce_LagrangeInterpolator.cpp" | |||
#include "midi/juce_MidiBuffer.cpp" | |||
@@ -39,6 +39,9 @@ namespace juce | |||
#ifndef __JUCE_AUDIOSAMPLEBUFFER_JUCEHEADER__ | |||
#include "buffers/juce_AudioSampleBuffer.h" | |||
#endif | |||
#ifndef __JUCE_FLOATVECTOROPERATIONS_JUCEHEADER__ | |||
#include "buffers/juce_FloatVectorOperations.h" | |||
#endif | |||
#ifndef __JUCE_DECIBELS_JUCEHEADER__ | |||
#include "effects/juce_Decibels.h" | |||
#endif | |||
@@ -160,18 +160,29 @@ void AudioFormatReader::read (AudioSampleBuffer* buffer, | |||
} | |||
} | |||
template <typename SampleType> | |||
static inline void getChannelMinAndMax (SampleType* channel, const int numSamples, SampleType& mn, SampleType& mx) | |||
{ | |||
findMinAndMax (channel, numSamples, mn, mx); | |||
} | |||
static inline void getChannelMinAndMax (float* channel, const int numSamples, float& mn, float& mx) | |||
{ | |||
FloatVectorOperations::findMinAndMax (channel, numSamples, mn, mx); | |||
} | |||
template <typename SampleType> | |||
static void getStereoMinAndMax (SampleType* const* channels, const int numChannels, const int numSamples, | |||
SampleType& lmin, SampleType& lmax, SampleType& rmin, SampleType& rmax) | |||
{ | |||
SampleType bufMin, bufMax; | |||
findMinAndMax (channels[0], numSamples, bufMin, bufMax); | |||
getChannelMinAndMax (channels[0], numSamples, bufMin, bufMax); | |||
lmax = jmax (lmax, bufMax); | |||
lmin = jmin (lmin, bufMin); | |||
if (numChannels > 1) | |||
{ | |||
findMinAndMax (channels[1], numSamples, bufMin, bufMax); | |||
getChannelMinAndMax (channels[1], numSamples, bufMin, bufMax); | |||
rmax = jmax (rmax, bufMax); | |||
rmin = jmin (rmin, bufMin); | |||
} | |||
@@ -562,7 +562,7 @@ protected: | |||
if (juceFilter->isSuspended()) | |||
{ | |||
for (int i = 0; i < numOut; ++i) | |||
zeromem (outputs [i], sizeof (float) * numSamples); | |||
FloatVectorOperations::clear (outputs [i], numSamples); | |||
} | |||
else | |||
{ | |||
@@ -573,7 +573,7 @@ protected: | |||
channels[i] = outputs [i]; | |||
if (i < numIn && inputs != outputs) | |||
memcpy (outputs [i], inputs[i], sizeof (float) * numSamples); | |||
FloatVectorOperations::copy (outputs [i], inputs[i], numSamples); | |||
} | |||
for (; i < numIn; ++i) | |||
@@ -813,9 +813,9 @@ private: | |||
for (int i = fNumOutputs; --i >= 0;) | |||
{ | |||
if (i < fNumInputs) | |||
memcpy (outputs[i], inputs[i], numSamples * sizeof (float)); | |||
FloatVectorOperations::copy (outputs[i], inputs[i], numSamples); | |||
else | |||
zeromem (outputs[i], numSamples * sizeof (float)); | |||
FloatVectorOperations::clear (outputs[i], numSamples); | |||
} | |||
} | |||
@@ -526,7 +526,7 @@ public: | |||
if (filter->isSuspended()) | |||
{ | |||
for (int i = 0; i < numOut; ++i) | |||
zeromem (outputs[i], sizeof (float) * (size_t) numSamples); | |||
FloatVectorOperations::clear (outputs[i], numSamples); | |||
} | |||
else | |||
{ | |||
@@ -700,7 +700,7 @@ void AudioThumbnail::addBlock (const int64 startSample, const AudioSampleBuffer& | |||
{ | |||
float low, high; | |||
const int start = i * samplesPerThumbSample; | |||
findMinAndMax (sourceData + start, jmin (samplesPerThumbSample, numSamples - start), low, high); | |||
FloatVectorOperations::findMinAndMax (sourceData + start, jmin (samplesPerThumbSample, numSamples - start), low, high); | |||
dest[i].setFloat (low, high); | |||
} | |||
} | |||