mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
New class FloatVectorOperations, with a bunch of SSE2-accelerated floating point functions.
This commit is contained in:
parent
f65a8148a6
commit
b0ee49d537
11 changed files with 400 additions and 96 deletions
|
|
@ -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,
|
||||
|
|
|
|||
234
modules/juce_audio_basics/buffers/juce_FloatVectorOperations.cpp
Normal file
234
modules/juce_audio_basics/buffers/juce_FloatVectorOperations.cpp
Normal file
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue