Add methods to get oversampler factor given in/out rates

This commit is contained in:
Jean Pierre Cimalando 2021-02-24 03:27:46 +01:00
parent 7d885bd297
commit 1818f2e927
6 changed files with 75 additions and 2 deletions

View file

@ -152,6 +152,7 @@ static void generate_cpp_prologue(int argc, char *argv[])
printf( printf(
"#pragma once\n" "#pragma once\n"
"#include \"OversamplerHelpers.h\"\n" "#include \"OversamplerHelpers.h\"\n"
"#include \"MathHelpers\"\n"
"\n" "\n"
"namespace sfz {\n" "namespace sfz {\n"
); );
@ -209,6 +210,14 @@ static void generate_cpp_upsampler(const Stage *stages, int num_stages)
printf("\t\t" "}\n"); printf("\t\t" "}\n");
printf("\t" "}\n"); printf("\t" "}\n");
printf("\t" "static unsigned conversionFactor(double sourceRate, double targetRate)\n");
printf("\t" "{\n");
printf("\t\t" "int factor = static_cast<int>(std::ceil(targetRate / sourceRate));\n");
printf("\t\t" "factor = (factor > 1) ? factor : 1;\n");
printf("\t\t" "factor = (factor < 128) ? factor : 128;\n");
printf("\t\t" "return nextPow2(factor);\n");
printf("\t" "}\n");
printf("\t" "static bool canProcess(int factor)\n"); printf("\t" "static bool canProcess(int factor)\n");
printf("\t" "{\n"); printf("\t" "{\n");
printf("\t\t" "switch (factor) {\n"); printf("\t\t" "switch (factor) {\n");
@ -322,6 +331,14 @@ static void generate_cpp_downsampler(const Stage *stages, int num_stages)
printf("\t\t" "}\n"); printf("\t\t" "}\n");
printf("\t" "}\n"); printf("\t" "}\n");
printf("\t" "static unsigned conversionFactor(double sourceRate, double targetRate)\n");
printf("\t" "{\n");
printf("\t\t" "int factor = static_cast<int>(std::ceil(targetRate / sourceRate));\n");
printf("\t\t" "factor = (factor > 1) ? factor : 1;\n");
printf("\t\t" "factor = (factor < 128) ? factor : 128;\n");
printf("\t\t" "return nextPow2(factor);\n");
printf("\t" "}\n");
printf("\t" "static bool canProcess(int factor)\n"); printf("\t" "static bool canProcess(int factor)\n");
printf("\t" "{\n"); printf("\t" "{\n");
printf("\t\t" "switch (factor) {\n"); printf("\t\t" "switch (factor) {\n");

View file

@ -263,8 +263,8 @@ add_library(sfizz::internal ALIAS sfizz_internal)
target_sources(sfizz_internal PRIVATE ${SFIZZ_HEADERS} ${SFIZZ_SOURCES} ${FAUST_FILES}) target_sources(sfizz_internal PRIVATE ${SFIZZ_HEADERS} ${SFIZZ_SOURCES} ${FAUST_FILES})
target_include_directories(sfizz_internal PUBLIC "." "sfizz") target_include_directories(sfizz_internal PUBLIC "." "sfizz")
target_link_libraries(sfizz_internal target_link_libraries(sfizz_internal
PUBLIC absl::strings absl::span sfizz::filesystem sfizz::atomic_queue sfizz::spin_mutex sfizz::bit_array sfizz::simde PUBLIC absl::strings absl::span sfizz::filesystem sfizz::atomic_queue sfizz::spin_mutex sfizz::bit_array sfizz::simde sfizz::hiir
PRIVATE sfizz::parser sfizz::messaging absl::flat_hash_map Threads::Threads st_audiofile sfizz::pugixml sfizz::spline sfizz::tunings sfizz::hiir sfizz::kissfft sfizz::cephes sfizz::cpuid sfizz::threadpool sfizz::jsl sfizz::atomic) PRIVATE sfizz::parser sfizz::messaging absl::flat_hash_map Threads::Threads st_audiofile sfizz::pugixml sfizz::spline sfizz::tunings sfizz::kissfft sfizz::cephes sfizz::cpuid sfizz::threadpool sfizz::jsl sfizz::atomic)
if(SFIZZ_USE_SNDFILE) if(SFIZZ_USE_SNDFILE)
target_compile_definitions(sfizz_internal PUBLIC "SFIZZ_USE_SNDFILE=1") target_compile_definitions(sfizz_internal PUBLIC "SFIZZ_USE_SNDFILE=1")
target_link_libraries(sfizz_internal PUBLIC st_audiofile) target_link_libraries(sfizz_internal PUBLIC st_audiofile)

View file

@ -296,6 +296,25 @@ constexpr long int lroundPositive(T value)
return static_cast<int>(0.5f + value); // NOLINT return static_cast<int>(0.5f + value); // NOLINT
} }
/**
* @brief Compute the next power of 2
*
* @param v An integer
* @return The next power of 2, inclusive from @p v
*/
inline uint32_t nextPow2(uint32_t v)
{
// Bit Twiddling Hacks
v--;
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
v++;
return v;
}
/** /**
@brief Wrap a normalized phase into the domain [0;1[ @brief Wrap a normalized phase into the domain [0;1[
*/ */

View file

@ -11,6 +11,7 @@
#pragma once #pragma once
#include "OversamplerHelpers.h" #include "OversamplerHelpers.h"
#include "MathHelpers.h"
namespace sfz { namespace sfz {
@ -94,6 +95,13 @@ public:
return factor * spl; return factor * spl;
} }
} }
static unsigned conversionFactor(double sourceRate, double targetRate)
{
int factor = static_cast<int>(std::ceil(targetRate / sourceRate));
factor = (factor > 1) ? factor : 1;
factor = (factor < 128) ? factor : 128;
return nextPow2(factor);
}
static bool canProcess(int factor) static bool canProcess(int factor)
{ {
switch (factor) { switch (factor) {
@ -293,6 +301,13 @@ public:
return factor * spl; return factor * spl;
} }
} }
static unsigned conversionFactor(double sourceRate, double targetRate)
{
int factor = static_cast<int>(std::ceil(targetRate / sourceRate));
factor = (factor > 1) ? factor : 1;
factor = (factor < 128) ? factor : 128;
return nextPow2(factor);
}
static bool canProcess(int factor) static bool canProcess(int factor)
{ {
switch (factor) { switch (factor) {

View file

@ -41,6 +41,7 @@ set(SFIZZ_TEST_SOURCES
ModulationsT.cpp ModulationsT.cpp
LFOT.cpp LFOT.cpp
MessagingT.cpp MessagingT.cpp
OversamplerT.cpp
DataHelpers.h DataHelpers.h
DataHelpers.cpp DataHelpers.cpp
) )

21
tests/OversamplerT.cpp Normal file
View file

@ -0,0 +1,21 @@
// SPDX-License-Identifier: BSD-2-Clause
// This code is part of the sfizz library and is licensed under a BSD 2-clause
// license. You should have receive a LICENSE.md file along with the code.
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
#include "sfizz/OversamplerHelpers.h"
#include "catch2/catch.hpp"
TEST_CASE("[Oversampler] Conversion factor")
{
REQUIRE(sfz::Upsampler::conversionFactor(44100.0, 44100.0) == 1);
REQUIRE(sfz::Upsampler::conversionFactor(44100.0, 44101.0) == 2);
REQUIRE(sfz::Upsampler::conversionFactor(44100.0, 88200.0) == 2);
REQUIRE(sfz::Upsampler::conversionFactor(44100.0, 88201.0) == 4);
REQUIRE(sfz::Upsampler::conversionFactor(44100.0, 176400.0) == 4);
REQUIRE(sfz::Upsampler::conversionFactor(44100.0, 176401.0) == 8);
// low and high limits
REQUIRE(sfz::Upsampler::conversionFactor(44100.0, 1.0) == 1);
REQUIRE(sfz::Upsampler::conversionFactor(44100.0, 1e10) == 128);
}