| @@ -39,10 +39,9 @@ AudioSampleBuffer::AudioSampleBuffer (const AudioSampleBuffer& other) noexcept | |||||
| size (other.size) | size (other.size) | ||||
| { | { | ||||
| allocateData(); | allocateData(); | ||||
| const size_t numBytes = sizeof (float) * (size_t) size; | |||||
| for (int i = 0; i < numChannels; ++i) | 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() | void AudioSampleBuffer::allocateData() | ||||
| @@ -130,10 +129,8 @@ AudioSampleBuffer& AudioSampleBuffer::operator= (const AudioSampleBuffer& other) | |||||
| { | { | ||||
| setSize (other.getNumChannels(), other.getNumSamples(), false, false, false); | setSize (other.getNumChannels(), other.getNumSamples(), false, false, false); | ||||
| const size_t numBytes = sizeof (float) * (size_t) size; | |||||
| for (int i = 0; i < numChannels; ++i) | for (int i = 0; i < numChannels; ++i) | ||||
| memcpy (channels[i], other.channels[i], numBytes); | |||||
| FloatVectorOperations::copy (channels[i], other.channels[i], size); | |||||
| } | } | ||||
| return *this; | return *this; | ||||
| @@ -154,15 +151,17 @@ void AudioSampleBuffer::setSize (const int newNumChannels, | |||||
| if (newNumSamples != size || newNumChannels != numChannels) | 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) | if (keepExistingContent) | ||||
| { | { | ||||
| HeapBlock <char, true> newData; | HeapBlock <char, true> newData; | ||||
| newData.allocate (newTotalBytes, clearExtraSpace); | 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** const newChannels = reinterpret_cast <float**> (newData.getData()); | ||||
| float* newChan = reinterpret_cast <float*> (newData + channelListSize); | float* newChan = reinterpret_cast <float*> (newData + channelListSize); | ||||
| @@ -170,12 +169,12 @@ void AudioSampleBuffer::setSize (const int newNumChannels, | |||||
| for (int j = 0; j < newNumChannels; ++j) | for (int j = 0; j < newNumChannels; ++j) | ||||
| { | { | ||||
| newChannels[j] = newChan; | newChannels[j] = newChan; | ||||
| newChan += newNumSamples; | |||||
| newChan += allocatedSamplesPerChannel; | |||||
| } | } | ||||
| const int numChansToCopy = jmin (numChannels, newNumChannels); | const int numChansToCopy = jmin (numChannels, newNumChannels); | ||||
| for (int i = 0; i < numChansToCopy; ++i) | for (int i = 0; i < numChansToCopy; ++i) | ||||
| memcpy (newChannels[i], channels[i], numBytesToCopy); | |||||
| FloatVectorOperations::copy (newChannels[i], channels[i], numSamplesToCopy); | |||||
| allocatedData.swapWith (newData); | allocatedData.swapWith (newData); | ||||
| allocatedBytes = newTotalBytes; | allocatedBytes = newTotalBytes; | ||||
| @@ -199,7 +198,7 @@ void AudioSampleBuffer::setSize (const int newNumChannels, | |||||
| for (int i = 0; i < newNumChannels; ++i) | for (int i = 0; i < newNumChannels; ++i) | ||||
| { | { | ||||
| channels[i] = chan; | channels[i] = chan; | ||||
| chan += newNumSamples; | |||||
| chan += allocatedSamplesPerChannel; | |||||
| } | } | ||||
| } | } | ||||
| @@ -212,7 +211,7 @@ void AudioSampleBuffer::setSize (const int newNumChannels, | |||||
| void AudioSampleBuffer::clear() noexcept | void AudioSampleBuffer::clear() noexcept | ||||
| { | { | ||||
| for (int i = 0; i < numChannels; ++i) | 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, | void AudioSampleBuffer::clear (const int startSample, | ||||
| @@ -221,7 +220,7 @@ void AudioSampleBuffer::clear (const int startSample, | |||||
| jassert (startSample >= 0 && startSample + numSamples <= size); | jassert (startSample >= 0 && startSample + numSamples <= size); | ||||
| for (int i = 0; i < numChannels; ++i) | 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, | void AudioSampleBuffer::clear (const int channel, | ||||
| @@ -231,7 +230,7 @@ void AudioSampleBuffer::clear (const int channel, | |||||
| jassert (isPositiveAndBelow (channel, numChannels)); | jassert (isPositiveAndBelow (channel, numChannels)); | ||||
| jassert (startSample >= 0 && startSample + numSamples <= size); | 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, | void AudioSampleBuffer::applyGain (const int channel, | ||||
| @@ -244,17 +243,12 @@ void AudioSampleBuffer::applyGain (const int channel, | |||||
| if (gain != 1.0f) | if (gain != 1.0f) | ||||
| { | { | ||||
| float* d = channels [channel] + startSample; | |||||
| float* const d = channels [channel] + startSample; | |||||
| if (gain == 0.0f) | if (gain == 0.0f) | ||||
| { | |||||
| zeromem (d, sizeof (float) * (size_t) numSamples); | |||||
| } | |||||
| FloatVectorOperations::clear (d, numSamples); | |||||
| else | 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) | 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) | if (gain != 1.0f) | ||||
| { | |||||
| while (--numSamples >= 0) | |||||
| *d++ += gain * *s++; | |||||
| } | |||||
| FloatVectorOperations::addWithMultiply (d, s, gain, numSamples); | |||||
| else | 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) | if (gain != 0.0f && numSamples > 0) | ||||
| { | { | ||||
| float* d = channels [destChannel] + destStartSample; | |||||
| float* const d = channels [destChannel] + destStartSample; | |||||
| if (gain != 1.0f) | if (gain != 1.0f) | ||||
| { | |||||
| while (--numSamples >= 0) | |||||
| *d++ += gain * *source++; | |||||
| } | |||||
| FloatVectorOperations::addWithMultiply (d, source, gain, numSamples); | |||||
| else | else | ||||
| { | |||||
| while (--numSamples >= 0) | |||||
| *d++ += *source++; | |||||
| } | |||||
| FloatVectorOperations::add (d, source, numSamples); | |||||
| } | } | ||||
| } | } | ||||
| @@ -378,11 +360,7 @@ void AudioSampleBuffer::addFromWithRamp (const int destChannel, | |||||
| if (startGain == endGain) | if (startGain == endGain) | ||||
| { | { | ||||
| addFrom (destChannel, | |||||
| destStartSample, | |||||
| source, | |||||
| numSamples, | |||||
| startGain); | |||||
| addFrom (destChannel, destStartSample, source, numSamples, startGain); | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| @@ -415,9 +393,9 @@ void AudioSampleBuffer::copyFrom (const int destChannel, | |||||
| if (numSamples > 0) | 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) | 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 != 1.0f) | ||||
| { | { | ||||
| if (gain == 0) | if (gain == 0) | ||||
| { | |||||
| zeromem (d, sizeof (float) * (size_t) numSamples); | |||||
| } | |||||
| FloatVectorOperations::clear (d, numSamples); | |||||
| else | else | ||||
| { | |||||
| while (--numSamples >= 0) | |||||
| *d++ = gain * *source++; | |||||
| } | |||||
| FloatVectorOperations::copyWithMultiply (d, source, gain, numSamples); | |||||
| } | } | ||||
| else | 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) | if (startGain == endGain) | ||||
| { | { | ||||
| copyFrom (destChannel, | |||||
| destStartSample, | |||||
| source, | |||||
| numSamples, | |||||
| startGain); | |||||
| copyFrom (destChannel, destStartSample, source, numSamples, startGain); | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| @@ -515,7 +484,8 @@ void AudioSampleBuffer::findMinMax (const int channel, | |||||
| jassert (isPositiveAndBelow (channel, numChannels)); | jassert (isPositiveAndBelow (channel, numChannels)); | ||||
| jassert (startSample >= 0 && startSample + numSamples <= size); | 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, | 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) | IIRFilter::IIRFilter (const IIRFilter& other) | ||||
| : active (other.active), v1 (0), v2 (0) | : active (other.active), v1 (0), v2 (0) | ||||
| { | { | ||||
| const ScopedLock sl (other.processLock); | |||||
| const SpinLock::ScopedLockType sl (other.processLock); | |||||
| memcpy (coefficients, other.coefficients, sizeof (coefficients)); | memcpy (coefficients, other.coefficients, sizeof (coefficients)); | ||||
| } | } | ||||
| @@ -49,7 +49,7 @@ IIRFilter::~IIRFilter() | |||||
| //============================================================================== | //============================================================================== | ||||
| void IIRFilter::reset() noexcept | void IIRFilter::reset() noexcept | ||||
| { | { | ||||
| const ScopedLock sl (processLock); | |||||
| const SpinLock::ScopedLockType sl (processLock); | |||||
| v1 = v2 = 0; | v1 = v2 = 0; | ||||
| } | } | ||||
| @@ -59,8 +59,8 @@ float IIRFilter::processSingleSampleRaw (const float in) noexcept | |||||
| JUCE_SNAP_TO_ZERO (out); | 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; | return out; | ||||
| } | } | ||||
| @@ -68,23 +68,29 @@ float IIRFilter::processSingleSampleRaw (const float in) noexcept | |||||
| void IIRFilter::processSamples (float* const samples, | void IIRFilter::processSamples (float* const samples, | ||||
| const int numSamples) noexcept | const int numSamples) noexcept | ||||
| { | { | ||||
| const ScopedLock sl (processLock); | |||||
| const SpinLock::ScopedLockType sl (processLock); | |||||
| if (active) | 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) | for (int i = 0; i < numSamples; ++i) | ||||
| { | { | ||||
| const float in = samples[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; | 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 | void IIRFilter::makeInactive() noexcept | ||||
| { | { | ||||
| const ScopedLock sl (processLock); | |||||
| const SpinLock::ScopedLockType sl (processLock); | |||||
| active = false; | active = false; | ||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| void IIRFilter::copyCoefficientsFrom (const IIRFilter& other) noexcept | void IIRFilter::copyCoefficientsFrom (const IIRFilter& other) noexcept | ||||
| { | { | ||||
| const ScopedLock sl (processLock); | |||||
| const SpinLock::ScopedLockType sl (processLock); | |||||
| memcpy (coefficients, other.coefficients, sizeof (coefficients)); | memcpy (coefficients, other.coefficients, sizeof (coefficients)); | ||||
| active = other.active; | active = other.active; | ||||
| @@ -219,14 +225,13 @@ void IIRFilter::setCoefficients (double c1, double c2, double c3, | |||||
| c5 *= a; | c5 *= a; | ||||
| c6 *= a; | c6 *= a; | ||||
| const ScopedLock sl (processLock); | |||||
| const SpinLock::ScopedLockType sl (processLock); | |||||
| coefficients[0] = (float) c1; | coefficients[0] = (float) c1; | ||||
| coefficients[1] = (float) c2; | coefficients[1] = (float) c2; | ||||
| coefficients[2] = (float) c3; | 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; | active = true; | ||||
| } | } | ||||
| @@ -131,13 +131,13 @@ public: | |||||
| protected: | protected: | ||||
| //============================================================================== | //============================================================================== | ||||
| CriticalSection processLock; | |||||
| SpinLock processLock; | |||||
| void setCoefficients (double c1, double c2, double c3, | void setCoefficients (double c1, double c2, double c3, | ||||
| double c4, double c5, double c6) noexcept; | double c4, double c5, double c6) noexcept; | ||||
| bool active; | bool active; | ||||
| float coefficients[6]; | |||||
| float coefficients[5]; | |||||
| float v1, v2; | float v1, v2; | ||||
| // (use the copyCoefficientsFrom() method instead of this operator) | // (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, | // 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. | // and your header search path must make it accessible to the module's files. | ||||
| #include "AppConfig.h" | #include "AppConfig.h" | ||||
| #include "juce_audio_basics.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 | namespace juce | ||||
| { | { | ||||
| // START_AUTOINCLUDE buffers/*.cpp, effects/*.cpp, midi/*.cpp, sources/*.cpp, synthesisers/*.cpp | // START_AUTOINCLUDE buffers/*.cpp, effects/*.cpp, midi/*.cpp, sources/*.cpp, synthesisers/*.cpp | ||||
| #include "buffers/juce_AudioDataConverters.cpp" | #include "buffers/juce_AudioDataConverters.cpp" | ||||
| #include "buffers/juce_AudioSampleBuffer.cpp" | #include "buffers/juce_AudioSampleBuffer.cpp" | ||||
| #include "buffers/juce_FloatVectorOperations.cpp" | |||||
| #include "effects/juce_IIRFilter.cpp" | #include "effects/juce_IIRFilter.cpp" | ||||
| #include "effects/juce_LagrangeInterpolator.cpp" | #include "effects/juce_LagrangeInterpolator.cpp" | ||||
| #include "midi/juce_MidiBuffer.cpp" | #include "midi/juce_MidiBuffer.cpp" | ||||
| @@ -39,6 +39,9 @@ namespace juce | |||||
| #ifndef __JUCE_AUDIOSAMPLEBUFFER_JUCEHEADER__ | #ifndef __JUCE_AUDIOSAMPLEBUFFER_JUCEHEADER__ | ||||
| #include "buffers/juce_AudioSampleBuffer.h" | #include "buffers/juce_AudioSampleBuffer.h" | ||||
| #endif | #endif | ||||
| #ifndef __JUCE_FLOATVECTOROPERATIONS_JUCEHEADER__ | |||||
| #include "buffers/juce_FloatVectorOperations.h" | |||||
| #endif | |||||
| #ifndef __JUCE_DECIBELS_JUCEHEADER__ | #ifndef __JUCE_DECIBELS_JUCEHEADER__ | ||||
| #include "effects/juce_Decibels.h" | #include "effects/juce_Decibels.h" | ||||
| #endif | #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> | template <typename SampleType> | ||||
| static void getStereoMinAndMax (SampleType* const* channels, const int numChannels, const int numSamples, | static void getStereoMinAndMax (SampleType* const* channels, const int numChannels, const int numSamples, | ||||
| SampleType& lmin, SampleType& lmax, SampleType& rmin, SampleType& rmax) | SampleType& lmin, SampleType& lmax, SampleType& rmin, SampleType& rmax) | ||||
| { | { | ||||
| SampleType bufMin, bufMax; | SampleType bufMin, bufMax; | ||||
| findMinAndMax (channels[0], numSamples, bufMin, bufMax); | |||||
| getChannelMinAndMax (channels[0], numSamples, bufMin, bufMax); | |||||
| lmax = jmax (lmax, bufMax); | lmax = jmax (lmax, bufMax); | ||||
| lmin = jmin (lmin, bufMin); | lmin = jmin (lmin, bufMin); | ||||
| if (numChannels > 1) | if (numChannels > 1) | ||||
| { | { | ||||
| findMinAndMax (channels[1], numSamples, bufMin, bufMax); | |||||
| getChannelMinAndMax (channels[1], numSamples, bufMin, bufMax); | |||||
| rmax = jmax (rmax, bufMax); | rmax = jmax (rmax, bufMax); | ||||
| rmin = jmin (rmin, bufMin); | rmin = jmin (rmin, bufMin); | ||||
| } | } | ||||
| @@ -562,7 +562,7 @@ protected: | |||||
| if (juceFilter->isSuspended()) | if (juceFilter->isSuspended()) | ||||
| { | { | ||||
| for (int i = 0; i < numOut; ++i) | for (int i = 0; i < numOut; ++i) | ||||
| zeromem (outputs [i], sizeof (float) * numSamples); | |||||
| FloatVectorOperations::clear (outputs [i], numSamples); | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| @@ -573,7 +573,7 @@ protected: | |||||
| channels[i] = outputs [i]; | channels[i] = outputs [i]; | ||||
| if (i < numIn && inputs != outputs) | if (i < numIn && inputs != outputs) | ||||
| memcpy (outputs [i], inputs[i], sizeof (float) * numSamples); | |||||
| FloatVectorOperations::copy (outputs [i], inputs[i], numSamples); | |||||
| } | } | ||||
| for (; i < numIn; ++i) | for (; i < numIn; ++i) | ||||
| @@ -813,9 +813,9 @@ private: | |||||
| for (int i = fNumOutputs; --i >= 0;) | for (int i = fNumOutputs; --i >= 0;) | ||||
| { | { | ||||
| if (i < fNumInputs) | if (i < fNumInputs) | ||||
| memcpy (outputs[i], inputs[i], numSamples * sizeof (float)); | |||||
| FloatVectorOperations::copy (outputs[i], inputs[i], numSamples); | |||||
| else | else | ||||
| zeromem (outputs[i], numSamples * sizeof (float)); | |||||
| FloatVectorOperations::clear (outputs[i], numSamples); | |||||
| } | } | ||||
| } | } | ||||
| @@ -526,7 +526,7 @@ public: | |||||
| if (filter->isSuspended()) | if (filter->isSuspended()) | ||||
| { | { | ||||
| for (int i = 0; i < numOut; ++i) | for (int i = 0; i < numOut; ++i) | ||||
| zeromem (outputs[i], sizeof (float) * (size_t) numSamples); | |||||
| FloatVectorOperations::clear (outputs[i], numSamples); | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| @@ -700,7 +700,7 @@ void AudioThumbnail::addBlock (const int64 startSample, const AudioSampleBuffer& | |||||
| { | { | ||||
| float low, high; | float low, high; | ||||
| const int start = i * samplesPerThumbSample; | 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); | dest[i].setFloat (low, high); | ||||
| } | } | ||||
| } | } | ||||