Update OpenAL-soft to 1.23.1-bc7cb17.

This commit is contained in:
Miku AuahDark
2024-03-20 11:06:03 +08:00
parent 4a512be715
commit 73a6fc9196
294 changed files with 44342 additions and 40077 deletions
+124 -112
View File
@@ -5,18 +5,62 @@
#include <array>
#include <cassert>
#include <cmath>
#include <cstddef>
#include <limits>
#include <memory>
#include <stdexcept>
#include "alnumbers.h"
#include "core/mixer/defs.h"
#include "alnumeric.h"
#include "bsinc_defs.h"
#include "resampler_limits.h"
namespace {
using uint = unsigned int;
#if __cpp_lib_math_special_functions >= 201603L
using std::cyl_bessel_i;
#else
/* The zero-order modified Bessel function of the first kind, used for the
* Kaiser window.
*
* I_0(x) = sum_{k=0}^inf (1 / k!)^2 (x / 2)^(2 k)
* = sum_{k=0}^inf ((x / 2)^k / k!)^2
*
* This implementation only handles nu = 0, and isn't the most precise (it
* starts with the largest value and accumulates successively smaller values,
* compounding the rounding and precision error), but it's good enough.
*/
template<typename T, typename U>
U cyl_bessel_i(T nu, U x)
{
if(nu != T{0})
throw std::runtime_error{"cyl_bessel_i: nu != 0"};
/* Start at k=1 since k=0 is trivial. */
const double x2{x/2.0};
double term{1.0};
double sum{1.0};
int k{1};
/* Let the integration converge until the term of the sum is no longer
* significant.
*/
double last_sum{};
do {
const double y{x2 / k};
++k;
last_sum = sum;
term *= y * y;
sum += term;
} while(sum != last_sum);
return static_cast<U>(sum);
}
#endif
/* This is the normalized cardinal sine (sinc) function.
*
@@ -31,35 +75,6 @@ constexpr double Sinc(const double x)
return std::sin(al::numbers::pi*x) / (al::numbers::pi*x);
}
/* The zero-order modified Bessel function of the first kind, used for the
* Kaiser window.
*
* I_0(x) = sum_{k=0}^inf (1 / k!)^2 (x / 2)^(2 k)
* = sum_{k=0}^inf ((x / 2)^k / k!)^2
*/
constexpr double BesselI_0(const double x) noexcept
{
/* Start at k=1 since k=0 is trivial. */
const double x2{x / 2.0};
double term{1.0};
double sum{1.0};
double last_sum{};
int k{1};
/* Let the integration converge until the term of the sum is no longer
* significant.
*/
do {
const double y{x2 / k};
++k;
last_sum = sum;
term *= y * y;
sum += term;
} while(sum != last_sum);
return sum;
}
/* Calculate a Kaiser window from the given beta value and a normalized k
* [-1, 1].
*
@@ -78,7 +93,7 @@ constexpr double Kaiser(const double beta, const double k, const double besseli_
{
if(!(k >= -1.0 && k <= 1.0))
return 0.0;
return BesselI_0(beta * std::sqrt(1.0 - k*k)) / besseli_0_beta;
return cyl_bessel_i(0, beta * std::sqrt(1.0 - k*k)) / besseli_0_beta;
}
/* Calculates the (normalized frequency) transition width of the Kaiser window.
@@ -97,7 +112,7 @@ constexpr double CalcKaiserBeta(const double rejection)
{
if(rejection > 50.0)
return 0.1102 * (rejection-8.7);
else if(rejection >= 21.0)
if(rejection >= 21.0)
return (0.5842 * std::pow(rejection-21.0, 0.4)) + (0.07886 * (rejection-21.0));
return 0.0;
}
@@ -107,24 +122,18 @@ struct BSincHeader {
double width{};
double beta{};
double scaleBase{};
double scaleRange{};
double besseli_0_beta{};
uint a[BSincScaleCount]{};
std::array<uint,BSincScaleCount> a{};
uint total_size{};
constexpr BSincHeader(uint Rejection, uint Order) noexcept
: width{CalcKaiserWidth(Rejection, Order)}, beta{CalcKaiserBeta(Rejection)}
, scaleBase{width / 2.0}
{
width = CalcKaiserWidth(Rejection, Order);
beta = CalcKaiserBeta(Rejection);
scaleBase = width / 2.0;
scaleRange = 1.0 - scaleBase;
besseli_0_beta = BesselI_0(beta);
uint num_points{Order+1};
for(uint si{0};si < BSincScaleCount;++si)
{
const double scale{scaleBase + (scaleRange * (si+1) / BSincScaleCount)};
const double scale{lerpd(scaleBase, 1.0, (si+1) / double{BSincScaleCount})};
const uint a_{std::min(static_cast<uint>(num_points / 2.0 / scale), num_points)};
const uint m{2 * a_};
@@ -142,37 +151,20 @@ constexpr BSincHeader bsinc12_hdr{60, 11};
constexpr BSincHeader bsinc24_hdr{60, 23};
/* NOTE: GCC 5 has an issue with BSincHeader objects being in an anonymous
* namespace while also being used as non-type template parameters.
*/
#if !defined(__clang__) && defined(__GNUC__) && __GNUC__ < 6
/* The number of sample points is double the a value (rounded up to a multiple
* of 4), and scale index 0 includes the doubling for downsampling. bsinc24 is
* currently the highest quality filter, and will use the most sample points.
*/
constexpr uint BSincPointsMax{(bsinc24_hdr.a[0]*2 + 3) & ~3u};
static_assert(BSincPointsMax <= MaxResamplerPadding, "MaxResamplerPadding is too small");
template<size_t total_size>
struct BSincFilterArray {
alignas(16) std::array<float, total_size> mTable;
const BSincHeader &hdr;
BSincFilterArray(const BSincHeader &hdr_) : hdr{hdr_}
{
#else
template<const BSincHeader &hdr>
struct BSincFilterArray {
alignas(16) std::array<float, hdr.total_size> mTable{};
BSincFilterArray()
{
constexpr uint BSincPointsMax{(hdr.a[0]*2 + 3) & ~3u};
static constexpr uint BSincPointsMax{(hdr.a[0]*2u + 3u) & ~3u};
static_assert(BSincPointsMax <= MaxResamplerPadding, "MaxResamplerPadding is too small");
#endif
using filter_type = double[BSincPhaseCount+1][BSincPointsMax];
auto filter = std::make_unique<filter_type[]>(BSincScaleCount);
using filter_type = std::array<std::array<double,BSincPointsMax>,BSincPhaseCount>;
auto filterptr = std::make_unique<std::array<filter_type,BSincScaleCount>>();
const auto filter = filterptr->begin();
const double besseli_0_beta{cyl_bessel_i(0, hdr.beta)};
/* Calculate the Kaiser-windowed Sinc filter coefficients for each
* scale and phase index.
@@ -181,22 +173,19 @@ struct BSincFilterArray {
{
const uint m{hdr.a[si] * 2};
const size_t o{(BSincPointsMax-m) / 2};
const double scale{hdr.scaleBase + (hdr.scaleRange * (si+1) / BSincScaleCount)};
const double scale{lerpd(hdr.scaleBase, 1.0, (si+1) / double{BSincScaleCount})};
const double cutoff{scale - (hdr.scaleBase * std::max(1.0, scale*2.0))};
const auto a = static_cast<double>(hdr.a[si]);
const double l{a - 1.0/BSincPhaseCount};
/* Do one extra phase index so that the phase delta has a proper
* target for its last index.
*/
for(uint pi{0};pi <= BSincPhaseCount;++pi)
for(uint pi{0};pi < BSincPhaseCount;++pi)
{
const double phase{std::floor(l) + (pi/double{BSincPhaseCount})};
for(uint i{0};i < m;++i)
{
const double x{i - phase};
filter[si][pi][o+i] = Kaiser(hdr.beta, x/l, hdr.besseli_0_beta) * cutoff *
filter[si][pi][o+i] = Kaiser(hdr.beta, x/l, besseli_0_beta) * cutoff *
Sinc(cutoff*x);
}
}
@@ -219,59 +208,82 @@ struct BSincFilterArray {
/* Linear interpolation between phases is simplified by pre-
* calculating the delta (b - a) in: x = a + f (b - a)
*/
for(size_t i{0};i < m;++i)
if(pi < BSincPhaseCount-1)
{
const double phDelta{filter[si][pi+1][o+i] - filter[si][pi][o+i]};
mTable[idx++] = static_cast<float>(phDelta);
for(size_t i{0};i < m;++i)
{
const double phDelta{filter[si][pi+1][o+i] - filter[si][pi][o+i]};
mTable[idx++] = static_cast<float>(phDelta);
}
}
else
{
/* The delta target for the last phase index is the first
* phase index with the coefficients offset by one. The
* first delta targets 0, as it represents a coefficient
* for a sample that won't be part of the filter.
*/
mTable[idx++] = static_cast<float>(0.0 - filter[si][pi][o]);
for(size_t i{1};i < m;++i)
{
const double phDelta{filter[si][0][o+i-1] - filter[si][pi][o+i]};
mTable[idx++] = static_cast<float>(phDelta);
}
}
}
/* Calculate and write out each phase index's filter quality scale
* deltas. The last scale index doesn't have any scale or scale-
* phase deltas.
/* Now write out each phase index's scale and phase+scale deltas,
* to complete the bilinear equation for the combination of phase
* and scale.
*/
if(si == BSincScaleCount-1)
if(si < BSincScaleCount-1)
{
for(size_t pi{0};pi < BSincPhaseCount;++pi)
{
for(size_t i{0};i < m;++i)
{
const double scDelta{filter[si+1][pi][o+i] - filter[si][pi][o+i]};
mTable[idx++] = static_cast<float>(scDelta);
}
if(pi < BSincPhaseCount-1)
{
for(size_t i{0};i < m;++i)
{
const double spDelta{(filter[si+1][pi+1][o+i]-filter[si+1][pi][o+i]) -
(filter[si][pi+1][o+i]-filter[si][pi][o+i])};
mTable[idx++] = static_cast<float>(spDelta);
}
}
else
{
mTable[idx++] = static_cast<float>((0.0 - filter[si+1][pi][o]) -
(0.0 - filter[si][pi][o]));
for(size_t i{1};i < m;++i)
{
const double spDelta{(filter[si+1][0][o+i-1] - filter[si+1][pi][o+i]) -
(filter[si][0][o+i-1] - filter[si][pi][o+i])};
mTable[idx++] = static_cast<float>(spDelta);
}
}
}
}
else
{
/* The last scale index doesn't have scale-related deltas. */
for(size_t i{0};i < BSincPhaseCount*m*2;++i)
mTable[idx++] = 0.0f;
}
else for(size_t pi{0};pi < BSincPhaseCount;++pi)
{
/* Linear interpolation between scales is also simplified.
*
* Given a difference in the number of points between scales,
* the destination points will be 0, thus: x = a + f (-a)
*/
for(size_t i{0};i < m;++i)
{
const double scDelta{filter[si+1][pi][o+i] - filter[si][pi][o+i]};
mTable[idx++] = static_cast<float>(scDelta);
}
/* This last simplification is done to complete the bilinear
* equation for the combination of phase and scale.
*/
for(size_t i{0};i < m;++i)
{
const double spDelta{(filter[si+1][pi+1][o+i] - filter[si+1][pi][o+i]) -
(filter[si][pi+1][o+i] - filter[si][pi][o+i])};
mTable[idx++] = static_cast<float>(spDelta);
}
}
}
assert(idx == hdr.total_size);
}
constexpr const BSincHeader &getHeader() const noexcept { return hdr; }
constexpr const float *getTable() const noexcept { return &mTable.front(); }
[[nodiscard]] constexpr auto getHeader() const noexcept -> const BSincHeader& { return hdr; }
[[nodiscard]] constexpr auto getTable() const noexcept -> const float* { return mTable.data(); }
};
#if !defined(__clang__) && defined(__GNUC__) && __GNUC__ < 6
const BSincFilterArray<bsinc12_hdr.total_size> bsinc12_filter{bsinc12_hdr};
const BSincFilterArray<bsinc24_hdr.total_size> bsinc24_filter{bsinc24_hdr};
#else
const BSincFilterArray<bsinc12_hdr> bsinc12_filter{};
const BSincFilterArray<bsinc24_hdr> bsinc24_filter{};
#endif
template<typename T>
constexpr BSincTable GenerateBSincTable(const T &filter)
@@ -279,7 +291,7 @@ constexpr BSincTable GenerateBSincTable(const T &filter)
BSincTable ret{};
const BSincHeader &hdr = filter.getHeader();
ret.scaleBase = static_cast<float>(hdr.scaleBase);
ret.scaleRange = static_cast<float>(1.0 / hdr.scaleRange);
ret.scaleRange = static_cast<float>(1.0 / (1.0 - hdr.scaleBase));
for(size_t i{0};i < BSincScaleCount;++i)
ret.m[i] = ((hdr.a[i]*2) + 3) & ~3u;
ret.filterOffset[0] = 0;
@@ -291,5 +303,5 @@ constexpr BSincTable GenerateBSincTable(const T &filter)
} // namespace
const BSincTable bsinc12{GenerateBSincTable(bsinc12_filter)};
const BSincTable bsinc24{GenerateBSincTable(bsinc24_filter)};
const BSincTable gBSinc12{GenerateBSincTable(bsinc12_filter)};
const BSincTable gBSinc24{GenerateBSincTable(bsinc24_filter)};