update OpenAL-Soft to 1.24.3.

This commit is contained in:
Sasha Szpakowski
2025-05-03 12:51:37 -03:00
parent 375c6f88cd
commit 5e4f3241ac
322 changed files with 54386 additions and 12885 deletions
+108 -44
View File
@@ -7,12 +7,14 @@
#include <cmath>
#include <cstddef>
#include <limits>
#include <memory>
#include <stdexcept>
#include <vector>
#include "alnumbers.h"
#include "alnumeric.h"
#include "alspan.h"
#include "bsinc_defs.h"
#include "opthelpers.h"
#include "resampler_limits.h"
@@ -20,10 +22,6 @@ 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.
@@ -36,7 +34,7 @@ using std::cyl_bessel_i;
* compounding the rounding and precision error), but it's good enough.
*/
template<typename T, typename U>
U cyl_bessel_i(T nu, U x)
constexpr auto cyl_bessel_i(T nu, U x) -> U
{
if(nu != T{0})
throw std::runtime_error{"cyl_bessel_i: nu != 0"};
@@ -60,7 +58,6 @@ U cyl_bessel_i(T nu, U x)
} while(sum != last_sum);
return static_cast<U>(sum);
}
#endif
/* This is the normalized cardinal sine (sinc) function.
*
@@ -93,7 +90,7 @@ constexpr double Kaiser(const double beta, const double k, const double besseli_
{
if(!(k >= -1.0 && k <= 1.0))
return 0.0;
return cyl_bessel_i(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.
@@ -119,74 +116,139 @@ constexpr double CalcKaiserBeta(const double rejection)
struct BSincHeader {
double width{};
double beta{};
double scaleBase{};
double scaleLimit{};
std::array<uint,BSincScaleCount> a{};
std::array<double,BSincScaleCount> a{};
std::array<uint,BSincScaleCount> m{};
uint total_size{};
constexpr BSincHeader(uint Rejection, uint Order) noexcept
: width{CalcKaiserWidth(Rejection, Order)}, beta{CalcKaiserBeta(Rejection)}
, scaleBase{width / 2.0}
constexpr BSincHeader(uint rejection, uint order, uint maxScale) noexcept
: beta{CalcKaiserBeta(rejection)}, scaleBase{CalcKaiserWidth(rejection, order) / 2.0}
, scaleLimit{1.0 / maxScale}
{
uint num_points{Order+1};
const auto base_a = (order+1.0) / 2.0;
for(uint si{0};si < BSincScaleCount;++si)
{
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_};
const auto scale = lerpd(scaleBase, 1.0, (si+1u) / double{BSincScaleCount});
a[si] = std::min(base_a/scale, base_a*maxScale);
/* std::ceil() isn't constexpr until C++23, this should behave the
* same.
*/
auto a_ = static_cast<uint>(a[si]);
a_ += (static_cast<double>(a_) != a[si]);
m[si] = a_ * 2u;
a[si] = a_;
total_size += 4 * BSincPhaseCount * ((m+3) & ~3u);
total_size += 4u * BSincPhaseCount * ((m[si]+3u) & ~3u);
}
}
};
/* 11th and 23rd order filters (12 and 24-point respectively) with a 60dB drop
* at nyquist. Each filter will scale up the order when downsampling, to 23rd
* and 47th order respectively.
* at nyquist. Each filter will scale up to double size when downsampling, to
* 23rd and 47th order respectively.
*/
constexpr BSincHeader bsinc12_hdr{60, 11};
constexpr BSincHeader bsinc24_hdr{60, 23};
constexpr auto bsinc12_hdr = BSincHeader{60, 11, 2};
constexpr auto bsinc24_hdr = BSincHeader{60, 23, 2};
/* 47th order filter (48-point) with an 80dB drop at nyquist. The filter order
* doesn't increase when downsampling.
*/
constexpr auto bsinc48_hdr = BSincHeader{80, 47, 1};
template<const BSincHeader &hdr>
struct BSincFilterArray {
struct SIMDALIGN BSincFilterArray {
alignas(16) std::array<float, hdr.total_size> mTable{};
BSincFilterArray()
{
static constexpr uint BSincPointsMax{(hdr.a[0]*2u + 3u) & ~3u};
static constexpr auto BSincPointsMax = (hdr.m[0]+3u) & ~3u;
static_assert(BSincPointsMax <= MaxResamplerPadding, "MaxResamplerPadding is too small");
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();
auto filter = std::vector<filter_type>(BSincScaleCount);
const double besseli_0_beta{cyl_bessel_i(0, hdr.beta)};
static constexpr auto besseli_0_beta = ::cyl_bessel_i(0, hdr.beta);
/* Calculate the Kaiser-windowed Sinc filter coefficients for each
* scale and phase index.
*/
for(uint si{0};si < BSincScaleCount;++si)
{
const uint m{hdr.a[si] * 2};
const size_t o{(BSincPointsMax-m) / 2};
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};
const auto a = hdr.a[si];
const auto m = hdr.m[si];
const auto l = std::floor(m*0.5) - 1.0;
const auto o = size_t{BSincPointsMax-m} / 2u;
const auto scale = lerpd(hdr.scaleBase, 1.0, (si+1u) / double{BSincScaleCount});
/* Calculate an appropriate cutoff frequency. An explanation may be
* in order here.
*
* When up-sampling, or down-sampling by less than the max scaling
* factor (when scale >= scaleLimit), the filter order increases as
* the down-sampling factor is reduced, enabling a consistent
* filter response output.
*
* When down-sampling by more than the max scale factor, the filter
* order stays constant to avoid further increasing the processing
* cost, causing the transition width to increase. This would
* normally be compensated for by reducing the cutoff frequency,
* to keep the transition band under the nyquist frequency and
* avoid aliasing. However, this has the side-effect of attenuating
* more of the original high frequency content, which can be
* significant with more extreme down-sampling scales.
*
* To combat this, we can allow for some aliasing to keep the
* cutoff frequency higher than it would otherwise be. We can allow
* the transition band to "wrap around" the nyquist frequency, so
* the output would have some low-level aliasing that overlays with
* the attenuated frequencies in the transition band. This allows
* the cutoff frequency to remain fixed as the transition width
* increases, until the stop frequency aliases back to the cutoff
* frequency and the transition band becomes fully wrapped over
* itself, at which point the cutoff frequency will lower at half
* the rate the transition width increases.
*
* This has an additional benefit when dealing with typical output
* rates like 44 or 48khz. Since human hearing maxes out at 20khz,
* and these rates handle frequencies up to 22 or 24khz, this lets
* some aliasing get masked. For example, the bsinc24 filter with
* 48khz output has a cutoff of 20khz when down-sampling, and a
* 4khz transition band. When down-sampling by more extreme scales,
* the cutoff frequency can stay at 20khz while the transition
* width doubles before any aliasing noise may become audible.
*
* This is what we do here.
*
* 'max_cutoff` is the upper bound normalized cutoff frequency for
* this scale factor, that aligns with the same absolute frequency
* as nominal resample factors. When up-sampling (scale == 1), the
* cutoff can't be raised further than this, or else it would
* prematurely add audible aliasing noise.
*
* 'width' is the normalized transition width for this scale
* factor.
*
* '(scale - width)*0.5' calculates the cutoff frequency necessary
* for the transition band to fully wrap on itself around the
* nyquist frequency. If this is larger than max_cutoff, the
* transition band is not fully wrapped at this scale and the
* cutoff doesn't need adjustment.
*/
const auto max_cutoff = (0.5 - hdr.scaleBase)*scale;
const auto width = hdr.scaleBase * std::max(hdr.scaleLimit, scale);
const auto cutoff2 = std::min(max_cutoff, (scale - width)*0.5) * 2.0;
for(uint pi{0};pi < BSincPhaseCount;++pi)
{
const double phase{std::floor(l) + (pi/double{BSincPhaseCount})};
const auto phase = 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, besseli_0_beta) * cutoff *
Sinc(cutoff*x);
const auto x = static_cast<double>(i) - phase;
filter[si][pi][o+i] = Kaiser(hdr.beta, x/a, besseli_0_beta) * cutoff2 *
Sinc(cutoff2*x);
}
}
}
@@ -194,8 +256,8 @@ struct BSincFilterArray {
size_t idx{0};
for(size_t si{0};si < BSincScaleCount;++si)
{
const size_t m{((hdr.a[si]*2) + 3) & ~3u};
const size_t o{(BSincPointsMax-m) / 2};
const auto m = (hdr.m[si]+3_uz) & ~3_uz;
const auto o = size_t{BSincPointsMax-m} / 2u;
/* Write out each phase index's filter and phase delta for this
* quality scale.
@@ -279,11 +341,12 @@ struct BSincFilterArray {
}
[[nodiscard]] constexpr auto getHeader() const noexcept -> const BSincHeader& { return hdr; }
[[nodiscard]] constexpr auto getTable() const noexcept -> const float* { return mTable.data(); }
[[nodiscard]] constexpr auto getTable() const noexcept { return al::span{mTable}; }
};
const BSincFilterArray<bsinc12_hdr> bsinc12_filter{};
const BSincFilterArray<bsinc24_hdr> bsinc24_filter{};
const auto bsinc12_filter = BSincFilterArray<bsinc12_hdr>{};
const auto bsinc24_filter = BSincFilterArray<bsinc24_hdr>{};
const auto bsinc48_filter = BSincFilterArray<bsinc48_hdr>{};
template<typename T>
constexpr BSincTable GenerateBSincTable(const T &filter)
@@ -293,7 +356,7 @@ constexpr BSincTable GenerateBSincTable(const T &filter)
ret.scaleBase = static_cast<float>(hdr.scaleBase);
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.m[i] = (hdr.m[i]+3u) & ~3u;
ret.filterOffset[0] = 0;
for(size_t i{1};i < BSincScaleCount;++i)
ret.filterOffset[i] = ret.filterOffset[i-1] + ret.m[i-1]*4*BSincPhaseCount;
@@ -305,3 +368,4 @@ constexpr BSincTable GenerateBSincTable(const T &filter)
const BSincTable gBSinc12{GenerateBSincTable(bsinc12_filter)};
const BSincTable gBSinc24{GenerateBSincTable(bsinc24_filter)};
const BSincTable gBSinc48{GenerateBSincTable(bsinc48_filter)};