Template issue (weird?)
This commit is contained in:
parent
2a87e873d6
commit
ea4e72e6f6
7 changed files with 65 additions and 64 deletions
|
|
@ -79,7 +79,6 @@ set(COMMON_SOURCES
|
||||||
sources/Synth.cpp
|
sources/Synth.cpp
|
||||||
sources/FilePool.cpp
|
sources/FilePool.cpp
|
||||||
sources/Region.cpp
|
sources/Region.cpp
|
||||||
sources/StereoBuffer.cpp
|
|
||||||
sources/Parser.cpp
|
sources/Parser.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
template<class Type, unsigned int Alignment = config::defaultAlignment>
|
template<class Type, unsigned int Alignment = SIMDConfig::defaultAlignment>
|
||||||
class Buffer
|
class Buffer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ public:
|
||||||
auto preloadedSize = std::min(returnedValue.end, static_cast<uint32_t>(config::preloadSize));
|
auto preloadedSize = std::min(returnedValue.end, static_cast<uint32_t>(config::preloadSize));
|
||||||
returnedValue.preloadedData = std::make_shared<StereoBuffer<float>>(preloadedSize);
|
returnedValue.preloadedData = std::make_shared<StereoBuffer<float>>(preloadedSize);
|
||||||
sndFile.readf(tempReadBuffer.data(), preloadedSize);
|
sndFile.readf(tempReadBuffer.data(), preloadedSize);
|
||||||
returnedValue.preloadedData->readInterleaved(tempReadBuffer.data(), preloadedSize);
|
returnedValue.preloadedData->readInterleaved<SIMDConfig::supported>(tempReadBuffer.data(), preloadedSize);
|
||||||
preloadedData[filename] = returnedValue.preloadedData;
|
preloadedData[filename] = returnedValue.preloadedData;
|
||||||
// char buffer [2048] ;
|
// char buffer [2048] ;
|
||||||
// sndFile.command(SFC_GET_LOG_INFO, buffer, sizeof(buffer)) ;
|
// sndFile.command(SFC_GET_LOG_INFO, buffer, sizeof(buffer)) ;
|
||||||
|
|
|
||||||
|
|
@ -21,10 +21,14 @@ namespace config
|
||||||
} // namespace sfz
|
} // namespace sfz
|
||||||
|
|
||||||
enum class SIMD { scalar, sse, neon };
|
enum class SIMD { scalar, sse, neon };
|
||||||
namespace config
|
namespace SIMDConfig
|
||||||
{
|
{
|
||||||
inline constexpr unsigned int defaultAlignment { 16 };
|
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
|
} // namespace config
|
||||||
|
|
||||||
#if HAVE_X86INTRIN_H
|
#if HAVE_X86INTRIN_H
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
#include "EGDescription.h"
|
#include "EGDescription.h"
|
||||||
#include "Defaults.h"
|
#include "Defaults.h"
|
||||||
#include "CCMap.h"
|
#include "CCMap.h"
|
||||||
|
|
||||||
namespace sfz
|
namespace sfz
|
||||||
{
|
{
|
||||||
struct Region
|
struct Region
|
||||||
|
|
|
||||||
|
|
@ -1,58 +0,0 @@
|
||||||
#include "StereoBuffer.h"
|
|
||||||
|
|
||||||
template<>
|
|
||||||
template<>
|
|
||||||
void StereoBuffer<float>::readInterleaved<SIMD::sse>(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<float, 16>::fill<SIMD::sse>(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<float*>(mmLeft), mmValue);
|
|
||||||
_mm_store_ps(reinterpret_cast<float*>(mmRight), mmValue);
|
|
||||||
mmLeft++;
|
|
||||||
mmRight++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
enum class Channel {left, right};
|
enum class Channel {left, right};
|
||||||
|
|
||||||
template<class Type, unsigned int Alignment = config::defaultAlignment>
|
template<class Type, unsigned int Alignment = SIMDConfig::defaultAlignment>
|
||||||
class StereoBuffer
|
class StereoBuffer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
@ -70,6 +70,61 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
void readInterleaved<SIMD::sse>(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<SIMD::sse>(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<float *>(mmLeft), mmValue);
|
||||||
|
_mm_store_ps(reinterpret_cast<float *>(mmRight), mmValue);
|
||||||
|
mmLeft++;
|
||||||
|
mmRight++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Type* getChannel(Channel channel) noexcept
|
Type* getChannel(Channel channel) noexcept
|
||||||
{
|
{
|
||||||
switch(channel)
|
switch(channel)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue