diff --git a/CMakeLists.txt b/CMakeLists.txt index 09a68ed6..b12c6098 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -79,7 +79,6 @@ set(COMMON_SOURCES sources/Synth.cpp sources/FilePool.cpp sources/Region.cpp - sources/StereoBuffer.cpp sources/Parser.cpp ) diff --git a/sources/Buffer.h b/sources/Buffer.h index b5f38956..cbf80982 100644 --- a/sources/Buffer.h +++ b/sources/Buffer.h @@ -4,7 +4,7 @@ #include #include -template +template class Buffer { public: diff --git a/sources/FilePool.h b/sources/FilePool.h index b9c86e26..e961cfb4 100644 --- a/sources/FilePool.h +++ b/sources/FilePool.h @@ -46,7 +46,7 @@ public: auto preloadedSize = std::min(returnedValue.end, static_cast(config::preloadSize)); returnedValue.preloadedData = std::make_shared>(preloadedSize); sndFile.readf(tempReadBuffer.data(), preloadedSize); - returnedValue.preloadedData->readInterleaved(tempReadBuffer.data(), preloadedSize); + returnedValue.preloadedData->readInterleaved(tempReadBuffer.data(), preloadedSize); preloadedData[filename] = returnedValue.preloadedData; // char buffer [2048] ; // sndFile.command(SFC_GET_LOG_INFO, buffer, sizeof(buffer)) ; diff --git a/sources/Globals.h b/sources/Globals.h index 51d8c59d..19611c3e 100644 --- a/sources/Globals.h +++ b/sources/Globals.h @@ -21,10 +21,14 @@ namespace config } // namespace sfz enum class SIMD { scalar, sse, neon }; -namespace config +namespace SIMDConfig { inline constexpr unsigned int defaultAlignment { 16 }; - inline constexpr SIMD vectorOperation { SIMD::scalar }; +#if HAVE_X86INTRIN_H || HAVE_INTRIN_H + inline constexpr SIMD supported { SIMD::sse }; +#else + inline constexpr SIMD supported {SIMD::scalar}; +#endif } // namespace config #if HAVE_X86INTRIN_H diff --git a/sources/Region.h b/sources/Region.h index 43281d83..6967a640 100644 --- a/sources/Region.h +++ b/sources/Region.h @@ -7,6 +7,7 @@ #include "EGDescription.h" #include "Defaults.h" #include "CCMap.h" + namespace sfz { struct Region diff --git a/sources/StereoBuffer.cpp b/sources/StereoBuffer.cpp deleted file mode 100644 index 0627a96e..00000000 --- a/sources/StereoBuffer.cpp +++ /dev/null @@ -1,58 +0,0 @@ -#include "StereoBuffer.h" - -template<> -template<> -void StereoBuffer::readInterleaved(float* input, int numFrames) noexcept -{ - ASSERT(this->numFrames >= numFrames); - const int residualFrames = numFrames & (2 * TypeAlignment - 1); - const int lastAligned = numFrames - residualFrames; - float* in = input; - auto [lOut, rOut] = getChannels(); - const float* end = input + 2 * lastAligned; - while (in < end) - { - auto register0 = _mm_loadu_ps(in); - in += 4; - auto register1 = _mm_loadu_ps(in); - in += 4; - auto register2 = register0; - // register 2 holds the copy of register 0 that is going to get erased by the first operation - // Remember that the bit mask reads from the end; 10 00 10 00 means - // "take 0 from a, take 2 from a, take 0 from b, take 2 from b" - register0 = _mm_shuffle_ps(register0, register1, 0b10001000); - register1 = _mm_shuffle_ps(register2, register1, 0b11011101); - _mm_store_ps(lOut, register0); - _mm_store_ps(rOut, register1); - lOut += 4; - rOut += 4; - } - end = input + numChannels * numFrames; - while (in < end) - { - *lOut = *in; - in++; - *rOut = *in; - in++; - lOut += 1; - rOut += 1; - } -} - -template<> -template<> -void StereoBuffer::fill(float value) noexcept -{ - const __m128 mmValue = _mm_set_ps1(value); - auto [lBegin, rBegin] = getChannels(); - auto [lEnd, rEnd] = alignedEnds(); - auto mmLeft = reinterpret_cast<__m128*>(lBegin); - auto mmRight = reinterpret_cast<__m128*>(rBegin); - while(mmLeft < reinterpret_cast<__m128*>(lEnd)) // we should only need to test a single channel - { - _mm_store_ps(reinterpret_cast(mmLeft), mmValue); - _mm_store_ps(reinterpret_cast(mmRight), mmValue); - mmLeft++; - mmRight++; - } -} \ No newline at end of file diff --git a/sources/StereoBuffer.h b/sources/StereoBuffer.h index 962763a6..bffc935a 100644 --- a/sources/StereoBuffer.h +++ b/sources/StereoBuffer.h @@ -8,7 +8,7 @@ enum class Channel {left, right}; -template +template class StereoBuffer { public: @@ -70,6 +70,61 @@ public: } } + template <> + void readInterleaved(float *input, int numFrames) noexcept + { + ASSERT(this->numFrames >= numFrames); + const int residualFrames = numFrames & (2 * TypeAlignment - 1); + const int lastAligned = numFrames - residualFrames; + float *in = input; + auto [lOut, rOut] = getChannels(); + const float *end = input + 2 * lastAligned; + while (in < end) + { + auto register0 = _mm_loadu_ps(in); + in += 4; + auto register1 = _mm_loadu_ps(in); + in += 4; + auto register2 = register0; + // register 2 holds the copy of register 0 that is going to get erased by the first operation + // Remember that the bit mask reads from the end; 10 00 10 00 means + // "take 0 from a, take 2 from a, take 0 from b, take 2 from b" + register0 = _mm_shuffle_ps(register0, register1, 0b10001000); + register1 = _mm_shuffle_ps(register2, register1, 0b11011101); + _mm_store_ps(lOut, register0); + _mm_store_ps(rOut, register1); + lOut += 4; + rOut += 4; + } + end = input + numChannels * numFrames; + while (in < end) + { + *lOut = *in; + in++; + *rOut = *in; + in++; + lOut += 1; + rOut += 1; + } + } + + template<> + void fill(float value) noexcept + { + const __m128 mmValue = _mm_set_ps1(value); + auto [lBegin, rBegin] = getChannels(); + auto [lEnd, rEnd] = alignedEnds(); + auto mmLeft = reinterpret_cast<__m128 *>(lBegin); + auto mmRight = reinterpret_cast<__m128 *>(rBegin); + while (mmLeft < reinterpret_cast<__m128 *>(lEnd)) // we should only need to test a single channel + { + _mm_store_ps(reinterpret_cast(mmLeft), mmValue); + _mm_store_ps(reinterpret_cast(mmRight), mmValue); + mmLeft++; + mmRight++; + } + } + Type* getChannel(Channel channel) noexcept { switch(channel)