Cover flac since we're at it
This commit is contained in:
parent
8e4e6460d8
commit
121d795559
6 changed files with 93 additions and 73 deletions
|
|
@ -5,12 +5,33 @@
|
||||||
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
|
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
|
||||||
|
|
||||||
#include "AudioSpan.h"
|
#include "AudioSpan.h"
|
||||||
|
#include "absl/types/span.h"
|
||||||
#include "sfizz/Synth.h"
|
#include "sfizz/Synth.h"
|
||||||
#include "TestHelpers.h"
|
#include "TestHelpers.h"
|
||||||
#include "catch2/catch.hpp"
|
#include "catch2/catch.hpp"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <vector>
|
||||||
using namespace Catch::literals;
|
using namespace Catch::literals;
|
||||||
|
|
||||||
|
TEST_CASE("[AudioFiles] No leakage on right")
|
||||||
|
{
|
||||||
|
sfz::Synth synth;
|
||||||
|
sfz::AudioBuffer<float> buffer { 2, static_cast<unsigned>(synth.getSamplesPerBlock()) };
|
||||||
|
std::vector<float> zeros(synth.getSamplesPerBlock(), 0);
|
||||||
|
sfz::AudioSpan<float> span { buffer };
|
||||||
|
synth.loadSfzString(fs::current_path() / "tests/TestFiles/wavpack.sfz", R"(
|
||||||
|
<region> sample=kick.wav key=60 pan=-100
|
||||||
|
)");
|
||||||
|
synth.noteOn(0, 60, 127);
|
||||||
|
synth.renderBlock(buffer);
|
||||||
|
REQUIRE( numPlayingVoices(synth) == 1 );
|
||||||
|
REQUIRE( approxEqual(span.getConstSpan(1), absl::MakeConstSpan(zeros), 1e-2f) );
|
||||||
|
while (numPlayingVoices(synth) > 0) {
|
||||||
|
synth.renderBlock(buffer);
|
||||||
|
REQUIRE( approxEqual(span.getConstSpan(1), absl::MakeConstSpan(zeros), 1e-2f) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("[AudioFiles] WavPack file")
|
TEST_CASE("[AudioFiles] WavPack file")
|
||||||
{
|
{
|
||||||
sfz::Synth synth;
|
sfz::Synth synth;
|
||||||
|
|
@ -29,3 +50,22 @@ TEST_CASE("[AudioFiles] WavPack file")
|
||||||
REQUIRE( approxEqual(span.getConstSpan(0), span.getConstSpan(1)) );
|
REQUIRE( approxEqual(span.getConstSpan(0), span.getConstSpan(1)) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("[AudioFiles] Flac file")
|
||||||
|
{
|
||||||
|
sfz::Synth synth;
|
||||||
|
sfz::AudioBuffer<float> buffer { 2, static_cast<unsigned>(synth.getSamplesPerBlock()) };
|
||||||
|
sfz::AudioSpan<float> span { buffer };
|
||||||
|
synth.loadSfzString(fs::current_path() / "tests/TestFiles/wavpack.sfz", R"(
|
||||||
|
<region> sample=kick.wav key=60 pan=-100
|
||||||
|
<region> sample=kick.flac key=60 pan=100
|
||||||
|
)");
|
||||||
|
synth.noteOn(0, 60, 127);
|
||||||
|
synth.renderBlock(buffer);
|
||||||
|
REQUIRE( numPlayingVoices(synth) == 2 );
|
||||||
|
REQUIRE( approxEqual(span.getConstSpan(0), span.getConstSpan(1)) );
|
||||||
|
while (numPlayingVoices(synth) > 0) {
|
||||||
|
synth.renderBlock(buffer);
|
||||||
|
REQUIRE( approxEqual(span.getConstSpan(0), span.getConstSpan(1)) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
#include "sfizz/ModifierHelpers.h"
|
#include "sfizz/ModifierHelpers.h"
|
||||||
#include "sfizz/Buffer.h"
|
#include "sfizz/Buffer.h"
|
||||||
#include "catch2/catch.hpp"
|
#include "catch2/catch.hpp"
|
||||||
|
#include "TestHelpers.h"
|
||||||
#include <absl/algorithm/container.h>
|
#include <absl/algorithm/container.h>
|
||||||
#include <absl/types/span.h>
|
#include <absl/types/span.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
@ -14,20 +15,6 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
using namespace Catch::literals;
|
using namespace Catch::literals;
|
||||||
|
|
||||||
template <class Type>
|
|
||||||
inline bool approxEqual(absl::Span<const Type> lhs, absl::Span<const Type> rhs, Type eps = 1e-3)
|
|
||||||
{
|
|
||||||
if (lhs.size() != rhs.size())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < rhs.size(); ++i)
|
|
||||||
if (rhs[i] != Approx(lhs[i]).epsilon(eps)) {
|
|
||||||
std::cerr << lhs[i] << " != " << rhs[i] << " at index " << i << '\n';
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto idModifier = [](float x) { return x; };
|
const auto idModifier = [](float x) { return x; };
|
||||||
const auto twiceModifier = [](float x) { return 2 * x; };
|
const auto twiceModifier = [](float x) { return 2 * x; };
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
#include "sfizz/simd/Common.h"
|
#include "sfizz/simd/Common.h"
|
||||||
#include "sfizz/SIMDHelpers.h"
|
#include "sfizz/SIMDHelpers.h"
|
||||||
#include "sfizz/Panning.h"
|
#include "sfizz/Panning.h"
|
||||||
|
#include "TestHelpers.h"
|
||||||
#include "catch2/catch.hpp"
|
#include "catch2/catch.hpp"
|
||||||
#include <absl/algorithm/container.h>
|
#include <absl/algorithm/container.h>
|
||||||
#include <absl/types/span.h>
|
#include <absl/types/span.h>
|
||||||
|
|
@ -20,39 +21,9 @@ template <class T, std::size_t A = sfz::config::defaultAlignment>
|
||||||
using aligned_vector = std::vector<T, jsl::aligned_allocator<T, A>>;
|
using aligned_vector = std::vector<T, jsl::aligned_allocator<T, A>>;
|
||||||
|
|
||||||
constexpr int bigBufferSize { 4095 };
|
constexpr int bigBufferSize { 4095 };
|
||||||
constexpr int medBufferSize { 127 };
|
constexpr int medBufferSize { 1023 };
|
||||||
constexpr float fillValue { 1.3f };
|
constexpr float fillValue { 1.3f };
|
||||||
|
|
||||||
template <class Type>
|
|
||||||
inline bool approxEqualMargin(absl::Span<const Type> lhs, absl::Span<const Type> rhs, Type eps = 1e-3)
|
|
||||||
{
|
|
||||||
if (lhs.size() != rhs.size())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < rhs.size(); ++i)
|
|
||||||
if (rhs[i] != Approx(lhs[i]).margin(eps)) {
|
|
||||||
std::cerr << lhs[i] << " != " << rhs[i] << " at index " << i << '\n';
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Type>
|
|
||||||
inline bool approxEqual(absl::Span<const Type> lhs, absl::Span<const Type> rhs, Type eps = 1e-3)
|
|
||||||
{
|
|
||||||
if (lhs.size() != rhs.size())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < rhs.size(); ++i)
|
|
||||||
if (rhs[i] != Approx(lhs[i]).epsilon(eps)) {
|
|
||||||
std::cerr << lhs[i] << " != " << rhs[i] << " at index " << i << '\n';
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("[Helpers] willAlign, prevAligned and unaligned tests")
|
TEST_CASE("[Helpers] willAlign, prevAligned and unaligned tests")
|
||||||
{
|
{
|
||||||
aligned_vector<float, 32> array(16);
|
aligned_vector<float, 32> array(16);
|
||||||
|
|
@ -430,8 +401,8 @@ TEST_CASE("[Helpers] Linear Ramp (SIMD)")
|
||||||
TEST_CASE("[Helpers] Linear Ramp (SIMD vs scalar)")
|
TEST_CASE("[Helpers] Linear Ramp (SIMD vs scalar)")
|
||||||
{
|
{
|
||||||
const float start { 0.0f };
|
const float start { 0.0f };
|
||||||
std::vector<float> outputScalar(bigBufferSize);
|
std::vector<float> outputScalar(medBufferSize);
|
||||||
std::vector<float> outputSIMD(bigBufferSize);
|
std::vector<float> outputSIMD(medBufferSize);
|
||||||
sfz::setSIMDOpStatus<float>(sfz::SIMDOps::linearRamp, false);
|
sfz::setSIMDOpStatus<float>(sfz::SIMDOps::linearRamp, false);
|
||||||
sfz::linearRamp<float>(absl::MakeSpan(outputScalar), start, fillValue);
|
sfz::linearRamp<float>(absl::MakeSpan(outputScalar), start, fillValue);
|
||||||
sfz::setSIMDOpStatus<float>(sfz::SIMDOps::linearRamp, true);
|
sfz::setSIMDOpStatus<float>(sfz::SIMDOps::linearRamp, true);
|
||||||
|
|
@ -442,8 +413,8 @@ TEST_CASE("[Helpers] Linear Ramp (SIMD vs scalar)")
|
||||||
TEST_CASE("[Helpers] Linear Ramp unaligned (SIMD vs scalar)")
|
TEST_CASE("[Helpers] Linear Ramp unaligned (SIMD vs scalar)")
|
||||||
{
|
{
|
||||||
const float start { 0.0f };
|
const float start { 0.0f };
|
||||||
std::vector<float> outputScalar(bigBufferSize);
|
std::vector<float> outputScalar(medBufferSize);
|
||||||
std::vector<float> outputSIMD(bigBufferSize);
|
std::vector<float> outputSIMD(medBufferSize);
|
||||||
sfz::setSIMDOpStatus<float>(sfz::SIMDOps::linearRamp, false);
|
sfz::setSIMDOpStatus<float>(sfz::SIMDOps::linearRamp, false);
|
||||||
sfz::linearRamp<float>(absl::MakeSpan(outputScalar).subspan(1), start, fillValue);
|
sfz::linearRamp<float>(absl::MakeSpan(outputScalar).subspan(1), start, fillValue);
|
||||||
sfz::setSIMDOpStatus<float>(sfz::SIMDOps::linearRamp, true);
|
sfz::setSIMDOpStatus<float>(sfz::SIMDOps::linearRamp, true);
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
#include "sfizz/OnePoleFilter.h"
|
#include "sfizz/OnePoleFilter.h"
|
||||||
#include "sfizz/Smoothers.h"
|
#include "sfizz/Smoothers.h"
|
||||||
#include "catch2/catch.hpp"
|
#include "catch2/catch.hpp"
|
||||||
|
#include "TestHelpers.h"
|
||||||
// #include "cnpy.h"
|
// #include "cnpy.h"
|
||||||
// #include "ghc/fs_std.hpp"
|
// #include "ghc/fs_std.hpp"
|
||||||
#include <absl/types/span.h>
|
#include <absl/types/span.h>
|
||||||
|
|
@ -16,21 +17,6 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
using namespace Catch::literals;
|
using namespace Catch::literals;
|
||||||
|
|
||||||
template <class Type, size_t N>
|
|
||||||
inline bool approxEqual(const std::array<Type, N>& lhs, const std::array<Type, N>& rhs, Type epsilon = 1e-3)
|
|
||||||
{
|
|
||||||
if (lhs.size() != rhs.size())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < rhs.size(); ++i)
|
|
||||||
if (lhs[i] != Approx(rhs[i]).epsilon(epsilon)) {
|
|
||||||
std::cerr << lhs[i] << " != " << rhs[i] << " at index " << i << '\n';
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Type, size_t N>
|
template <class Type, size_t N>
|
||||||
void testFilter(const std::array<Type, N>& input, const std::array<Type, N>& expectedLow, const std::array<Type, N>& expectedHigh, Type gain)
|
void testFilter(const std::array<Type, N>& input, const std::array<Type, N>& expectedLow, const std::array<Type, N>& expectedHigh, Type gain)
|
||||||
{
|
{
|
||||||
|
|
@ -43,19 +29,19 @@ void testFilter(const std::array<Type, N>& input, const std::array<Type, N>& exp
|
||||||
sfz::OnePoleFilter<Type> filter;
|
sfz::OnePoleFilter<Type> filter;
|
||||||
filter.setGain(gain);
|
filter.setGain(gain);
|
||||||
filter.processLowpass(input, outputSpan);
|
filter.processLowpass(input, outputSpan);
|
||||||
REQUIRE(approxEqual(output, expectedLow));
|
REQUIRE(approxEqual(absl::MakeConstSpan(output), absl::MakeConstSpan(expectedLow)));
|
||||||
|
|
||||||
filter.reset();
|
filter.reset();
|
||||||
filter.processLowpass(input, outputSpan, gains);
|
filter.processLowpass(input, outputSpan, gains);
|
||||||
REQUIRE(approxEqual(output, expectedLow));
|
REQUIRE(approxEqual(absl::MakeConstSpan(output), absl::MakeConstSpan(expectedLow)));
|
||||||
|
|
||||||
filter.reset();
|
filter.reset();
|
||||||
filter.processHighpass(input, outputSpan);
|
filter.processHighpass(input, outputSpan);
|
||||||
REQUIRE(approxEqual(output, expectedHigh));
|
REQUIRE(approxEqual(absl::MakeConstSpan(output), absl::MakeConstSpan(expectedHigh)));
|
||||||
|
|
||||||
filter.reset();
|
filter.reset();
|
||||||
filter.processHighpass(input, outputSpan, gains);
|
filter.processHighpass(input, outputSpan, gains);
|
||||||
REQUIRE(approxEqual(output, expectedHigh));
|
REQUIRE(approxEqual(absl::MakeConstSpan(output), absl::MakeConstSpan(expectedHigh)));
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr std::array<float, 64> floatInput01 = {
|
constexpr std::array<float, 64> floatInput01 = {
|
||||||
|
|
|
||||||
BIN
tests/TestFiles/kick.flac
Executable file
BIN
tests/TestFiles/kick.flac
Executable file
Binary file not shown.
|
|
@ -12,6 +12,8 @@
|
||||||
#include "sfizz/Messaging.h"
|
#include "sfizz/Messaging.h"
|
||||||
#include "catch2/catch.hpp"
|
#include "catch2/catch.hpp"
|
||||||
#include "sfizz/modulations/ModKey.h"
|
#include "sfizz/modulations/ModKey.h"
|
||||||
|
#include <iostream>
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
class RegionCCView {
|
class RegionCCView {
|
||||||
public:
|
public:
|
||||||
|
|
@ -148,18 +150,52 @@ std::string createDefaultGraph(std::vector<std::string> lines, int numRegions =
|
||||||
std::string createModulationDotGraph(std::vector<std::string> lines);
|
std::string createModulationDotGraph(std::vector<std::string> lines);
|
||||||
|
|
||||||
template <class Type>
|
template <class Type>
|
||||||
inline bool approxEqual(absl::Span<const Type> lhs, absl::Span<const Type> rhs, Type eps = 1e-3)
|
bool approxEqual(absl::Span<const Type> lhs, absl::Span<const Type> rhs, Type eps = 1e-3)
|
||||||
{
|
{
|
||||||
if (lhs.size() != rhs.size())
|
if (lhs.size() != rhs.size())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
bool different = false;
|
||||||
for (size_t i = 0; i < rhs.size(); ++i)
|
for (size_t i = 0; i < rhs.size(); ++i)
|
||||||
if (rhs[i] != Approx(lhs[i]).epsilon(eps)) {
|
if (rhs[i] != Approx(lhs[i]).margin(eps)) {
|
||||||
std::cerr << lhs[i] << " != " << rhs[i] << " at index " << i << '\n';
|
std::cerr << lhs[i] << " != " << rhs[i] << " (delta " << std::abs(rhs[i] - lhs[i]) << ") at index " << i << '\n';
|
||||||
return false;
|
different = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
auto print_span = [](absl::Span<const Type> span) {
|
||||||
|
if (span.empty()) {
|
||||||
|
std::cerr << "{ }" << '\n';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cerr << "{ ";
|
||||||
|
if (span.size() < 16) {
|
||||||
|
for (unsigned i = 0; i < span.size() - 1; ++i) {
|
||||||
|
std::cerr << span[i] << ", ";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (unsigned i = 0; i < 8; ++i) {
|
||||||
|
std::cerr << span[i] << ", ";
|
||||||
|
}
|
||||||
|
std::cerr << "..., ";
|
||||||
|
for (unsigned i = span.size() - 8; i < span.size() - 1; ++i) {
|
||||||
|
std::cerr << span[i] << ", ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::cerr << span.back() << " }" << '\n';
|
||||||
|
};
|
||||||
|
|
||||||
|
if (different) {
|
||||||
|
std::cerr << std::setprecision(3) << std::fixed;
|
||||||
|
std::cerr << "Differences between spans" << '\n';
|
||||||
|
std::cerr << "lhs: ";
|
||||||
|
print_span(lhs);
|
||||||
|
std::cerr << "rhs: ";
|
||||||
|
print_span(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
return !different;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue