/* * Resampler.h * ----------- * Purpose: Holds the tables for all available resamplers. * Notes : (currently none) * Authors: OpenMPT Devs * The OpenMPT source code is released under the BSD license. Read LICENSE for more details. */ #pragma once #include "openmpt/all/BuildSettings.hpp" #include "WindowedFIR.h" #include "Mixer.h" #include "MixerSettings.h" #include "Paula.h" OPENMPT_NAMESPACE_BEGIN #ifdef LIBOPENMPT_BUILD // All these optimizations are not applicable to the tracker // because cutoff and firtype are configurable there. // Cache resampler tables across resampler object creation. // A C++11-style function-static singleton is holding the cached values. #define MPT_RESAMPLER_TABLES_CACHED // Prime the tables cache when the library is loaded. // Caching gets triggered via a global object that primes the cache during // construction. // This is only really useful with MPT_RESAMPLER_TABLES_CACHED. //#define MPT_RESAMPLER_TABLES_CACHED_ONSTARTUP #endif // LIBOPENMPT_BUILD #define SINC_WIDTH 8 #define SINC_PHASES_BITS 12 #define SINC_PHASES (1<<SINC_PHASES_BITS) #ifdef MPT_INTMIXER typedef int16 SINC_TYPE; #define SINC_QUANTSHIFT 15 #else typedef mixsample_t SINC_TYPE; #endif // MPT_INTMIXER #define SINC_MASK (SINC_PHASES-1) static_assert((SINC_MASK & 0xffff) == SINC_MASK); // exceeding fractional freq class CResamplerSettings { public: ResamplingMode SrcMode = Resampling::Default(); double gdWFIRCutoff = 0.97; uint8 gbWFIRType = WFIR_KAISER4T; Resampling::AmigaFilter emulateAmiga = Resampling::AmigaFilter::Off; public: constexpr CResamplerSettings() = default; bool operator == (const CResamplerSettings &cmp) const { #if MPT_COMPILER_CLANG #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wfloat-equal" #endif // MPT_COMPILER_CLANG return SrcMode == cmp.SrcMode && gdWFIRCutoff == cmp.gdWFIRCutoff && gbWFIRType == cmp.gbWFIRType && emulateAmiga == cmp.emulateAmiga; #if MPT_COMPILER_CLANG #pragma clang diagnostic pop #endif // MPT_COMPILER_CLANG } bool operator != (const CResamplerSettings &cmp) const { return !(*this == cmp); } }; class CResampler { public: CResamplerSettings m_Settings; CWindowedFIR m_WindowedFIR; static const int16 FastSincTable[256 * 4]; #ifdef MODPLUG_TRACKER static bool StaticTablesInitialized; #define RESAMPLER_TABLE static #else // no global data which has to be initialized by hand in the library #define RESAMPLER_TABLE #endif // MODPLUG_TRACKER RESAMPLER_TABLE SINC_TYPE gKaiserSinc[SINC_PHASES * 8]; // Upsampling RESAMPLER_TABLE SINC_TYPE gDownsample13x[SINC_PHASES * 8]; // Downsample 1.333x RESAMPLER_TABLE SINC_TYPE gDownsample2x[SINC_PHASES * 8]; // Downsample 2x RESAMPLER_TABLE Paula::BlepTables blepTables; // Amiga BLEP resampler #ifndef MPT_INTMIXER RESAMPLER_TABLE mixsample_t FastSincTablef[256 * 4]; // Cubic spline LUT RESAMPLER_TABLE mixsample_t LinearTablef[256]; // Linear interpolation LUT #endif // !defined(MPT_INTMIXER) #undef RESAMPLER_TABLE private: CResamplerSettings m_OldSettings; public: CResampler(bool fresh_generate=false) { if(fresh_generate) { InitializeTablesFromScratch(true); } else { InitializeTables(); } } void InitializeTables() { #if defined(MPT_RESAMPLER_TABLES_CACHED) InitializeTablesFromCache(); #else InitializeTablesFromScratch(true); #endif } void UpdateTables() { InitializeTablesFromScratch(false); } private: void InitFloatmixerTables(); void InitializeTablesFromScratch(bool force=false); #ifdef MPT_RESAMPLER_TABLES_CACHED void InitializeTablesFromCache(); #endif }; OPENMPT_NAMESPACE_END