xybrid/xybrid/nodelib/resampler.h

40 lines
1.4 KiB
C++

#pragma once
#include <cmath>
#include <cstddef>
#include <array>
#include "data/audioframe.h"
#include "data/sample.h"
namespace Xybrid::NodeLib {
const constexpr size_t LUT_LEVELS = 16;
const constexpr size_t LUT_TAPS = 8;
const constexpr ptrdiff_t LUT_HTAPS = LUT_TAPS/2-1;//static_cast<ptrdiff_t>(LUT_TAPS - (LUT_TAPS+0.5)/2);
const constexpr size_t LUT_STEPS = 1024;
extern const std::array<std::array<std::array<double, LUT_TAPS>, LUT_LEVELS>, LUT_STEPS> resamplerLUT;
inline Data::AudioFrame resamp(Data::Sample* smp, double pos, double rate [[maybe_unused]]) {
auto loop = smp->loopStart >= 0;
auto len = static_cast<ptrdiff_t>(smp->length());
auto ls = static_cast<ptrdiff_t>(smp->loopStart);
auto le = static_cast<ptrdiff_t>(smp->loopEnd);
auto ll = le - ls;
double ip = std::floor(pos);
auto& pt = NodeLib::resamplerLUT[static_cast<size_t>((pos - ip)*NodeLib::LUT_STEPS) % NodeLib::LUT_STEPS][static_cast<size_t>(std::clamp(std::floor(rate - 0.00001), 0.0, (LUT_LEVELS-1)*1.0))];
Data::AudioFrame out(0.0);
auto ii = static_cast<ptrdiff_t>(ip) - LUT_HTAPS;
for (size_t i = 0; i < 8; i++) {
if (loop && ii >= le) ii = ((ii - ls) % ll) + ls;
else if (ii >= len) return out; // we can early-out here
if (ii >= 0) out += (*smp)[static_cast<size_t>(ii)] * pt[i];
ii++;
}
return out;
}
}