mirror of
https://github.com/love2d/megasource.git
synced 2026-08-19 12:14:41 +02:00
update OpenAL-Soft to 1.24.3.
This commit is contained in:
@@ -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)};
|
||||
|
||||
Reference in New Issue
Block a user