Cleanups and added writeInterleaved
This commit is contained in:
parent
d0264f3416
commit
4f998cad8f
30 changed files with 241 additions and 22 deletions
|
|
@ -134,7 +134,7 @@ add_executable(sfizz_tests ${TEST_SOURCES} ${COMMON_SOURCES})
|
|||
if(UNIX)
|
||||
target_link_libraries(sfizz_tests stdc++fs)
|
||||
endif(UNIX)
|
||||
target_link_libraries(sfizz_tests Catch2::Catch2 absl::strings)
|
||||
target_link_libraries(sfizz_tests Catch2::Catch2 absl::strings absl::flat_hash_map sndfile readerwriterqueue)
|
||||
target_include_directories(sfizz_tests SYSTEM PRIVATE sources)
|
||||
file(COPY "tests" DESTINATION ${CMAKE_BINARY_DIR})
|
||||
|
||||
|
|
@ -147,9 +147,17 @@ endif(UNIX)
|
|||
target_link_libraries(bench_fill absl::strings benchmark)
|
||||
|
||||
###############################
|
||||
add_executable(bench_read benchmarks/Stereo_Read_Interleaved.cpp ${COMMON_SOURCES})
|
||||
add_executable(bench_read benchmarks/Stereo_Read_Interleaved.cpp sources/StereoBufferSSE.cpp)
|
||||
# Per OS properties
|
||||
if(UNIX)
|
||||
target_link_libraries(bench_read stdc++fs)
|
||||
endif(UNIX)
|
||||
target_link_libraries(bench_read absl::strings benchmark)
|
||||
|
||||
###############################
|
||||
add_executable(bench_write benchmarks/Stereo_Write_Interleaved.cpp sources/StereoBufferSSE.cpp)
|
||||
# Per OS properties
|
||||
if(UNIX)
|
||||
target_link_libraries(bench_write stdc++fs)
|
||||
endif(UNIX)
|
||||
target_link_libraries(bench_write absl::strings benchmark)
|
||||
|
|
|
|||
53
benchmarks/Stereo_Write_Interleaved.cpp
Normal file
53
benchmarks/Stereo_Write_Interleaved.cpp
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
#include <benchmark/benchmark.h>
|
||||
#include "../sources/StereoBuffer.h"
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
|
||||
static void Interleaved_Write(benchmark::State& state) {
|
||||
StereoBuffer<float> buffer (state.range(0));
|
||||
std::vector<float> input (state.range(0) * 2);
|
||||
buffer.readInterleaved(input.data(), state.range(0));
|
||||
std::vector<float> output (state.range(0) * 2);
|
||||
std::iota(input.begin(), input.end(), 1.0f);
|
||||
for (auto _ : state) {
|
||||
buffer.writeInterleaved(output.data(), state.range(0));
|
||||
}
|
||||
}
|
||||
BENCHMARK(Interleaved_Write)->Range((8<<10) + 3, (8<<20) + 3);
|
||||
|
||||
static void Interleaved_Write_SSE(benchmark::State& state) {
|
||||
StereoBuffer<float> buffer (state.range(0));
|
||||
std::vector<float> input (state.range(0) * 2);
|
||||
buffer.readInterleaved<true>(input.data(), state.range(0));
|
||||
std::vector<float> output (state.range(0) * 2);
|
||||
std::iota(input.begin(), input.end(), 1.0f);
|
||||
for (auto _ : state) {
|
||||
buffer.writeInterleaved<true>(output.data(), state.range(0));
|
||||
}
|
||||
}
|
||||
BENCHMARK(Interleaved_Write_SSE)->Range((8<<10) + 3, (8<<20) + 3);
|
||||
|
||||
static void Unaligned_Interleaved_Write(benchmark::State& state) {
|
||||
StereoBuffer<float> buffer (state.range(0));
|
||||
std::vector<float> input (state.range(0) * 2);
|
||||
buffer.readInterleaved(input.data(), state.range(0));
|
||||
std::vector<float> output (state.range(0) * 2 + 1);
|
||||
std::iota(input.begin(), input.end(), 1.0f);
|
||||
for (auto _ : state) {
|
||||
buffer.writeInterleaved(output.data() + 1, state.range(0));
|
||||
}
|
||||
}
|
||||
BENCHMARK(Unaligned_Interleaved_Write)->Range((8<<10) + 3, (8<<20) + 3);
|
||||
|
||||
static void Unaligned_Interleaved_Write_SSE(benchmark::State& state) {
|
||||
StereoBuffer<float> buffer (state.range(0));
|
||||
std::vector<float> input (state.range(0) * 2);
|
||||
buffer.readInterleaved<true>(input.data(), state.range(0));
|
||||
std::vector<float> output (state.range(0) * 2 + 1);
|
||||
std::iota(input.begin(), input.end(), 1.0f);
|
||||
for (auto _ : state) {
|
||||
buffer.writeInterleaved<true>(output.data() + 1, state.range(0));
|
||||
}
|
||||
}
|
||||
BENCHMARK(Unaligned_Interleaved_Write_SSE)->Range((8<<10) + 3, (8<<20) + 3);
|
||||
BENCHMARK_MAIN();
|
||||
|
|
@ -33,6 +33,8 @@ public:
|
|||
normalEnd = normalData + alignedSize;
|
||||
if (auto endMisalignment = (alignedSize & TypeAlignmentMask); endMisalignment != 0)
|
||||
_alignedEnd = normalEnd + Alignment - endMisalignment;
|
||||
else
|
||||
_alignedEnd = normalEnd;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
#include "FilePool.h"
|
||||
#include <chrono>
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
std::optional<sfz::FilePool::FileInformation> sfz::FilePool::getFileInformation(std::string_view filename)
|
||||
{
|
||||
|
|
@ -38,9 +40,11 @@ void sfz::FilePool::enqueueLoading(Voice* voice, std::string_view sample, int nu
|
|||
void sfz::FilePool::loadingThread()
|
||||
{
|
||||
FileLoadingInformation fileToLoad;
|
||||
while (true)
|
||||
while (!quitThread)
|
||||
{
|
||||
loadingQueue.wait_dequeue(fileToLoad);
|
||||
if (!loadingQueue.wait_dequeue_timed(fileToLoad, 1ms))
|
||||
continue;
|
||||
|
||||
if (fileToLoad.voice == nullptr)
|
||||
{
|
||||
DBG("Background thread error: voice is null.");
|
||||
|
|
|
|||
|
|
@ -19,7 +19,13 @@ public:
|
|||
FilePool()
|
||||
: fileLoadingThread(std::thread(&FilePool::loadingThread, this))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
~FilePool()
|
||||
{
|
||||
quitThread = true;
|
||||
fileLoadingThread.join();
|
||||
}
|
||||
void setRootDirectory(const std::filesystem::path& directory) { rootDirectory = directory; }
|
||||
size_t getNumPreloadedSamples() { return preloadedData.size(); }
|
||||
|
|
@ -45,6 +51,7 @@ private:
|
|||
moodycamel::BlockingReaderWriterQueue<FileLoadingInformation> loadingQueue;
|
||||
void loadingThread();
|
||||
std::thread fileLoadingThread;
|
||||
bool quitThread { false };
|
||||
Buffer<float> tempReadBuffer { config::preloadSize * 2 };
|
||||
// std::map<std::string_view, std::shared_ptr<StereoBuffer<float>>> preloadedData;
|
||||
absl::flat_hash_map<std::string_view, std::shared_ptr<StereoBuffer<float>>> preloadedData;
|
||||
|
|
|
|||
48
sources/InterleavedStereoBuffer.h
Normal file
48
sources/InterleavedStereoBuffer.h
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
#include "Globals.h"
|
||||
template<class Type, unsigned int Alignment = SIMDConfig::defaultAlignment>
|
||||
class InterleavedStereoBuffer
|
||||
{
|
||||
public:
|
||||
static constexpr int numChannels { 2 };
|
||||
InterleavedStereoBuffer() = default;
|
||||
InterleavedStereoBuffer(int numFrames)
|
||||
{
|
||||
resize(numFrames);
|
||||
}
|
||||
|
||||
bool resize(int numFrames)
|
||||
{
|
||||
// should have a positive number of frames...
|
||||
ASSERT(numFrames >= 0);
|
||||
if (buffer.resize(static_cast<size_t>(2*numFrames)))
|
||||
{
|
||||
this->numFrames = numFrames;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
struct Frame
|
||||
{
|
||||
Type left;
|
||||
Type right;
|
||||
};
|
||||
|
||||
Frame& getFrame(int frameIndex)
|
||||
{
|
||||
return *static_cast<Frame*>(buffer.data() + 2 * frameIndex);
|
||||
}
|
||||
|
||||
int getNumFrames() const noexcept { return numFrames; }
|
||||
int getNumChannels() const noexcept { return numChannels; }
|
||||
bool empty() const noexcept { return numFrames == 0; }
|
||||
private:
|
||||
static constexpr auto TypeAlignment { Alignment / sizeof(Type) };
|
||||
static constexpr auto TypeAlignmentMask { TypeAlignment - 1 };
|
||||
static_assert(TypeAlignment * sizeof(Type) == Alignment, "The alignment does not appear to be divided by the size of the Type");
|
||||
int numFrames { 0 };
|
||||
int totalSize { 0 };
|
||||
int padding { 0 };
|
||||
Buffer<Type, Alignment> buffer {};
|
||||
Type trash { 0 };
|
||||
};
|
||||
|
|
@ -67,13 +67,13 @@ private:
|
|||
template<class Type>
|
||||
bool operator==(const Range<Type>& lhs, const Range<Type>& rhs)
|
||||
{
|
||||
return (lhs.start() == rhs.start()) && (lhs.end() == rhs.end());
|
||||
return (lhs.getStart() == rhs.getStart()) && (lhs.getEnd() == rhs.getEnd());
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
bool operator==(const Range<Type>& lhs, const std::pair<Type, Type>& rhs)
|
||||
{
|
||||
return (lhs.start() == rhs.first) && (lhs.end() == rhs.second);
|
||||
return (lhs.getStart() == rhs.first) && (lhs.getEnd() == rhs.second);
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
|
|
|
|||
|
|
@ -70,6 +70,20 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
template<bool useSIMD=false>
|
||||
void writeInterleaved(Type* output, int numFrames) noexcept
|
||||
{
|
||||
ASSERT(numFrames <= this->numFrames);
|
||||
auto [lIn, rIn] = getChannels();
|
||||
auto* out = output;
|
||||
auto* end = output + numChannels * numFrames;
|
||||
while (out < end)
|
||||
{
|
||||
*out++ = *lIn++;
|
||||
*out++ = *rIn++;
|
||||
}
|
||||
}
|
||||
|
||||
Type* getChannel(Channel channel) noexcept
|
||||
{
|
||||
switch(channel)
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ template <>
|
|||
template <>
|
||||
void StereoBuffer<float, 16>::readInterleaved<true>(float *input, int numFrames) noexcept
|
||||
{
|
||||
// The number of frames to read has to fit!
|
||||
ASSERT(this->numFrames >= numFrames);
|
||||
const int residualFrames = numFrames & (2 * TypeAlignment - 1);
|
||||
const int lastAligned = numFrames - residualFrames;
|
||||
|
|
@ -47,6 +48,7 @@ void StereoBuffer<float, 16>::fill<true>(float value) noexcept
|
|||
const __m128 mmValue = _mm_set_ps1(value);
|
||||
auto [lBegin, rBegin] = getChannels();
|
||||
auto [lEnd, rEnd] = alignedEnds();
|
||||
// Cast to m128 so that pointer arithmetics make sense
|
||||
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
|
||||
|
|
@ -56,4 +58,38 @@ void StereoBuffer<float, 16>::fill<true>(float value) noexcept
|
|||
mmLeft++;
|
||||
mmRight++;
|
||||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
template<>
|
||||
void StereoBuffer<float, 16>::writeInterleaved<true>(float* output, int numFrames) noexcept
|
||||
{
|
||||
ASSERT(numFrames <= this->numFrames);
|
||||
const int residualFrames = numFrames & (TypeAlignment - 1);
|
||||
const int lastAligned = numFrames - residualFrames;
|
||||
auto [lIn, rIn] = getChannels();
|
||||
auto* out = output;
|
||||
const auto* sseEnd = lIn + lastAligned;
|
||||
while (lIn < sseEnd)
|
||||
{
|
||||
const auto lInRegister = _mm_load_ps(lIn);
|
||||
const auto rInRegister = _mm_load_ps(rIn);
|
||||
|
||||
const auto outRegister1 = _mm_unpacklo_ps(lInRegister, rInRegister);
|
||||
_mm_storeu_ps(out, outRegister1);
|
||||
out += TypeAlignment;
|
||||
const auto outRegister2 = _mm_unpackhi_ps(lInRegister, rInRegister);
|
||||
_mm_storeu_ps(out, outRegister2);
|
||||
out += TypeAlignment;
|
||||
|
||||
lIn += TypeAlignment;
|
||||
rIn += TypeAlignment;
|
||||
}
|
||||
|
||||
const auto* end = output + numChannels * numFrames;
|
||||
while (out < end)
|
||||
{
|
||||
*out++ = *lIn++;
|
||||
*out++ = *rIn++;
|
||||
}
|
||||
}
|
||||
|
|
@ -32,11 +32,11 @@ TEST_CASE("[Buffer] Empty (uint8_t)")
|
|||
}
|
||||
|
||||
template<class Type>
|
||||
void checkBoundaries(Buffer<Type>& buffer, size_t expectedSize)
|
||||
void checkBoundaries(Buffer<Type>& buffer, int expectedSize)
|
||||
{
|
||||
REQUIRE(buffer.size() == expectedSize);
|
||||
REQUIRE(((size_t)buffer.data() & (config::defaultAlignment - 1)) == 0);
|
||||
REQUIRE(((size_t)buffer.alignedEnd() & (config::defaultAlignment - 1)) == 0);
|
||||
REQUIRE((int)buffer.size() == expectedSize);
|
||||
REQUIRE(((size_t)buffer.data() & (SIMDConfig::defaultAlignment - 1)) == 0);
|
||||
REQUIRE(((size_t)buffer.alignedEnd() & (SIMDConfig::defaultAlignment - 1)) == 0);
|
||||
REQUIRE(std::distance(buffer.begin(), buffer.end()) == expectedSize);
|
||||
REQUIRE(std::distance(buffer.begin(), buffer.alignedEnd()) >= expectedSize);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,18 +79,20 @@ TEST_CASE("[Files] Subdir include Win")
|
|||
REQUIRE( synth.getRegionView(0)->sample == "dummy_subdir.wav" );
|
||||
}
|
||||
|
||||
TEST_CASE("[Files] Recursive include")
|
||||
TEST_CASE("[Files] Recursive include (with include guard)")
|
||||
{
|
||||
sfz::Synth synth;
|
||||
synth.enableRecursiveIncludeGuard();
|
||||
synth.loadSfzFile(std::filesystem::current_path() / "tests/TestFiles/Includes/root_recursive.sfz");
|
||||
REQUIRE( synth.getNumRegions() == 2 );
|
||||
REQUIRE( synth.getRegionView(0)->sample == "dummy_recursive2.wav" );
|
||||
REQUIRE( synth.getRegionView(1)->sample == "dummy_recursive1.wav" );
|
||||
}
|
||||
|
||||
TEST_CASE("[Files] Include loops")
|
||||
TEST_CASE("[Files] Include loops (with include guard)")
|
||||
{
|
||||
sfz::Synth synth;
|
||||
synth.enableRecursiveIncludeGuard();
|
||||
synth.loadSfzFile(std::filesystem::current_path() / "tests/TestFiles/Includes/root_loop.sfz");
|
||||
REQUIRE( synth.getNumRegions() == 2 );
|
||||
REQUIRE( synth.getRegionView(0)->sample == "dummy_loop2.wav" );
|
||||
|
|
|
|||
|
|
@ -200,10 +200,10 @@ TEST_CASE("[AudioBuffer] fills")
|
|||
REQUIRE( real == expected );
|
||||
}
|
||||
|
||||
SECTION("Floats - 0.0 - SSE")
|
||||
SECTION("Floats - 0.0 - SIMD")
|
||||
{
|
||||
StereoBuffer<float> buffer(10);
|
||||
buffer.fill<SIMD::sse>(0.0f);
|
||||
buffer.fill<true>(0.0f);
|
||||
std::array<float, 10> expected;
|
||||
std::fill(expected.begin(), expected.end(), 0.0f);
|
||||
std::array<float, 10> real { 2.0f };
|
||||
|
|
@ -217,10 +217,10 @@ TEST_CASE("[AudioBuffer] fills")
|
|||
REQUIRE( real == expected );
|
||||
}
|
||||
|
||||
SECTION("Floats - 1.0 - SSE")
|
||||
SECTION("Floats - 1.0 - SIMD")
|
||||
{
|
||||
StereoBuffer<float> buffer(10);
|
||||
buffer.fill<SIMD::sse>(1.0f);
|
||||
buffer.fill<true>(1.0f);
|
||||
std::array<float, 10> expected { 1.0f };
|
||||
std::fill(expected.begin(), expected.end(), 1.0f);
|
||||
std::array<float, 10> real { 2.0f };
|
||||
|
|
@ -250,12 +250,12 @@ TEST_CASE("[StereoBuffer] Interleave read")
|
|||
REQUIRE( real == expected );
|
||||
}
|
||||
|
||||
TEST_CASE("[StereoBuffer] Interleave read -- SSE")
|
||||
TEST_CASE("[StereoBuffer] Interleave read -- SIMD")
|
||||
{
|
||||
StereoBuffer<float> buffer(8);
|
||||
std::array<float, 16> input = { 0.0f, 10.0f, 1.0f, 11.0f, 2.0f, 12.0f, 3.0f, 13.0f, 4.0f, 14.0f, 5.0f, 15.0f, 6.0f, 16.0f, 7.0f, 17.0f};
|
||||
std::array<float, 16> expected = { 0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f, 17.0f };
|
||||
buffer.readInterleaved<SIMD::sse>(input.data(), 8);
|
||||
buffer.readInterleaved<true>(input.data(), 8);
|
||||
std::array<float, 16> real { 0.0f };
|
||||
auto realIdx = 0;
|
||||
for (auto frameIdx = 0; frameIdx < buffer.getNumFrames(); ++frameIdx)
|
||||
|
|
@ -265,12 +265,12 @@ TEST_CASE("[StereoBuffer] Interleave read -- SSE")
|
|||
REQUIRE( real == expected );
|
||||
}
|
||||
|
||||
TEST_CASE("[StereoBuffer] Interleave read unaligned end -- SSE")
|
||||
TEST_CASE("[StereoBuffer] Interleave read unaligned end -- SIMD")
|
||||
{
|
||||
StereoBuffer<float> buffer(10);
|
||||
std::array<float, 20> input = { 0.0f, 10.0f, 1.0f, 11.0f, 2.0f, 12.0f, 3.0f, 13.0f, 4.0f, 14.0f, 5.0f, 15.0f, 6.0f, 16.0f, 7.0f, 17.0f, 8.0f, 18.0f, 9.0f, 19.0f};
|
||||
std::array<float, 20> expected = { 0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f, 17.0f, 18.0f, 19.0f};
|
||||
buffer.readInterleaved<SIMD::sse>(input.data(), 10);
|
||||
buffer.readInterleaved<true>(input.data(), 10);
|
||||
std::array<float, 20> real { 0.0f };
|
||||
auto realIdx = 0;
|
||||
for (auto frameIdx = 0; frameIdx < buffer.getNumFrames(); ++frameIdx)
|
||||
|
|
@ -280,7 +280,22 @@ TEST_CASE("[StereoBuffer] Interleave read unaligned end -- SSE")
|
|||
REQUIRE( real == expected );
|
||||
}
|
||||
|
||||
TEST_CASE("[StereoBuffer] SSE vs scalar")
|
||||
TEST_CASE("[StereoBuffer] small interleaved read unaligned end -- SIMD")
|
||||
{
|
||||
StereoBuffer<float> buffer(3);
|
||||
std::array<float, 20> input = { 0.0f, 10.0f, 1.0f, 11.0f, 2.0f, 12.0f};
|
||||
std::array<float, 20> expected = { 0.0f, 1.0f, 2.0f, 10.0f, 11.0f, 12.0f};
|
||||
buffer.readInterleaved<true>(input.data(), 3);
|
||||
std::array<float, 20> real { 0.0f };
|
||||
auto realIdx = 0;
|
||||
for (auto frameIdx = 0; frameIdx < buffer.getNumFrames(); ++frameIdx)
|
||||
real[realIdx++] = buffer(Channel::left, frameIdx);
|
||||
for (auto frameIdx = 0; frameIdx < buffer.getNumFrames(); ++frameIdx)
|
||||
real[realIdx++] = buffer(Channel::right, frameIdx);
|
||||
REQUIRE( real == expected );
|
||||
}
|
||||
|
||||
TEST_CASE("[StereoBuffer] SIMD vs scalar")
|
||||
{
|
||||
constexpr int numFrames { 91 };
|
||||
StereoBuffer<float> buffer(numFrames);
|
||||
|
|
@ -288,7 +303,7 @@ TEST_CASE("[StereoBuffer] SSE vs scalar")
|
|||
std::iota(input.begin(), input.end(), 0.0f);
|
||||
StereoBuffer<float> expectedBuffer (numFrames);
|
||||
expectedBuffer.readInterleaved(input.data(), 10);
|
||||
buffer.readInterleaved<SIMD::sse>(input.data(), 10);
|
||||
buffer.readInterleaved<true>(input.data(), 10);
|
||||
std::array<float, numFrames * 2> expectedArray { 0.0f };
|
||||
std::array<float, numFrames * 2> realArray { 0.0f };
|
||||
auto sampleIdx = 0;
|
||||
|
|
@ -312,4 +327,34 @@ TEST_CASE("[AudioBuffer] Fill a big Audiobuffer")
|
|||
std::vector<float> input (2*size);
|
||||
std::iota(input.begin(), input.end(), 1.0f);
|
||||
buffer.readInterleaved(input.data(), size);
|
||||
}
|
||||
|
||||
TEST_CASE("[StereoBuffer] Interleaved write -- Scalar")
|
||||
{
|
||||
StereoBuffer<float> buffer(10);
|
||||
std::array<float, 20> input = { 0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f, 17.0f, 18.0f, 19.0f};
|
||||
std::array<float, 20> output { 0.0f };
|
||||
buffer.readInterleaved<false>(input.data(), 10);
|
||||
buffer.writeInterleaved<false>(output.data(), 10);
|
||||
REQUIRE( output == input );
|
||||
}
|
||||
|
||||
TEST_CASE("[StereoBuffer] Interleaved write -- SIMD")
|
||||
{
|
||||
StereoBuffer<float> buffer(10);
|
||||
std::array<float, 20> input = { 0.0f, 10.0f, 1.0f, 11.0f, 2.0f, 12.0f, 3.0f, 13.0f, 4.0f, 14.0f, 5.0f, 15.0f, 6.0f, 16.0f, 7.0f, 17.0f, 8.0f, 18.0f, 9.0f, 19.0f};
|
||||
std::array<float, 20> output { 0.0f };
|
||||
buffer.readInterleaved<false>(input.data(), 10);
|
||||
buffer.writeInterleaved<true>(output.data(), 10);
|
||||
REQUIRE( output == input );
|
||||
}
|
||||
|
||||
TEST_CASE("[StereoBuffer] Small interleaved write -- SIMD")
|
||||
{
|
||||
StereoBuffer<float> buffer(3);
|
||||
std::array<float, 20> input = { 0.0f, 10.0f, 1.0f, 11.0f, 2.0f, 12.0f};
|
||||
std::array<float, 20> output { 0.0f };
|
||||
buffer.readInterleaved<false>(input.data(), 3);
|
||||
buffer.writeInterleaved<true>(output.data(), 3);
|
||||
REQUIRE( output == input );
|
||||
}
|
||||
BIN
tests/TestFiles/36-CajonCenter-1.wav
Executable file
BIN
tests/TestFiles/36-CajonCenter-1.wav
Executable file
Binary file not shown.
BIN
tests/TestFiles/36-CajonCenter-2.wav
Executable file
BIN
tests/TestFiles/36-CajonCenter-2.wav
Executable file
Binary file not shown.
BIN
tests/TestFiles/36-CajonCenter-3.wav
Executable file
BIN
tests/TestFiles/36-CajonCenter-3.wav
Executable file
Binary file not shown.
BIN
tests/TestFiles/36-CajonCenter-4.wav
Executable file
BIN
tests/TestFiles/36-CajonCenter-4.wav
Executable file
Binary file not shown.
BIN
tests/TestFiles/36-CajonCenter-5.wav
Executable file
BIN
tests/TestFiles/36-CajonCenter-5.wav
Executable file
Binary file not shown.
BIN
tests/TestFiles/Includes/dummy.wav
Executable file
BIN
tests/TestFiles/Includes/dummy.wav
Executable file
Binary file not shown.
BIN
tests/TestFiles/Includes/dummy2.wav
Executable file
BIN
tests/TestFiles/Includes/dummy2.wav
Executable file
Binary file not shown.
BIN
tests/TestFiles/Includes/dummy_loop1.wav
Executable file
BIN
tests/TestFiles/Includes/dummy_loop1.wav
Executable file
Binary file not shown.
BIN
tests/TestFiles/Includes/dummy_loop2.wav
Executable file
BIN
tests/TestFiles/Includes/dummy_loop2.wav
Executable file
Binary file not shown.
BIN
tests/TestFiles/Includes/dummy_recursive1.wav
Executable file
BIN
tests/TestFiles/Includes/dummy_recursive1.wav
Executable file
Binary file not shown.
BIN
tests/TestFiles/Includes/dummy_recursive2.wav
Executable file
BIN
tests/TestFiles/Includes/dummy_recursive2.wav
Executable file
Binary file not shown.
BIN
tests/TestFiles/Includes/dummy_subdir.wav
Executable file
BIN
tests/TestFiles/Includes/dummy_subdir.wav
Executable file
Binary file not shown.
BIN
tests/TestFiles/Regions/dummy.1.wav
Normal file → Executable file
BIN
tests/TestFiles/Regions/dummy.1.wav
Normal file → Executable file
Binary file not shown.
BIN
tests/TestFiles/Regions/dummy.2.wav
Normal file → Executable file
BIN
tests/TestFiles/Regions/dummy.2.wav
Normal file → Executable file
Binary file not shown.
BIN
tests/TestFiles/Regions/dummy.wav
Normal file → Executable file
BIN
tests/TestFiles/Regions/dummy.wav
Normal file → Executable file
Binary file not shown.
BIN
tests/TestFiles/closedhat.wav
Executable file
BIN
tests/TestFiles/closedhat.wav
Executable file
Binary file not shown.
BIN
tests/TestFiles/kick.wav
Executable file
BIN
tests/TestFiles/kick.wav
Executable file
Binary file not shown.
BIN
tests/TestFiles/snare.wav
Executable file
BIN
tests/TestFiles/snare.wav
Executable file
Binary file not shown.
Loading…
Add table
Reference in a new issue