1 /* 2 * Resampler.h 3 * ----------- 4 * Purpose: Holds the tables for all available resamplers. 5 * Notes : (currently none) 6 * Authors: OpenMPT Devs 7 * The OpenMPT source code is released under the BSD license. Read LICENSE for more details. 8 */ 9 10 #pragma once 11 12 #include "openmpt/all/BuildSettings.hpp" 13 14 15 #include "WindowedFIR.h" 16 #include "Mixer.h" 17 #include "MixerSettings.h" 18 #include "Paula.h" 19 20 21 OPENMPT_NAMESPACE_BEGIN 22 23 24 #ifdef LIBOPENMPT_BUILD 25 // All these optimizations are not applicable to the tracker 26 // because cutoff and firtype are configurable there. 27 28 // Cache resampler tables across resampler object creation. 29 // A C++11-style function-static singleton is holding the cached values. 30 #define MPT_RESAMPLER_TABLES_CACHED 31 32 // Prime the tables cache when the library is loaded. 33 // Caching gets triggered via a global object that primes the cache during 34 // construction. 35 // This is only really useful with MPT_RESAMPLER_TABLES_CACHED. 36 //#define MPT_RESAMPLER_TABLES_CACHED_ONSTARTUP 37 38 #endif // LIBOPENMPT_BUILD 39 40 41 #define SINC_WIDTH 8 42 43 #define SINC_PHASES_BITS 12 44 #define SINC_PHASES (1<<SINC_PHASES_BITS) 45 46 #ifdef MPT_INTMIXER 47 typedef int16 SINC_TYPE; 48 #define SINC_QUANTSHIFT 15 49 #else 50 typedef mixsample_t SINC_TYPE; 51 #endif // MPT_INTMIXER 52 53 #define SINC_MASK (SINC_PHASES-1) 54 static_assert((SINC_MASK & 0xffff) == SINC_MASK); // exceeding fractional freq 55 56 57 class CResamplerSettings 58 { 59 public: 60 ResamplingMode SrcMode = Resampling::Default(); 61 double gdWFIRCutoff = 0.97; 62 uint8 gbWFIRType = WFIR_KAISER4T; 63 Resampling::AmigaFilter emulateAmiga = Resampling::AmigaFilter::Off; 64 public: 65 constexpr CResamplerSettings() = default; 66 bool operator == (const CResamplerSettings &cmp) const 67 { 68 #if MPT_COMPILER_CLANG 69 #pragma clang diagnostic push 70 #pragma clang diagnostic ignored "-Wfloat-equal" 71 #endif // MPT_COMPILER_CLANG 72 return SrcMode == cmp.SrcMode && gdWFIRCutoff == cmp.gdWFIRCutoff && gbWFIRType == cmp.gbWFIRType && emulateAmiga == cmp.emulateAmiga; 73 #if MPT_COMPILER_CLANG 74 #pragma clang diagnostic pop 75 #endif // MPT_COMPILER_CLANG 76 } 77 bool operator != (const CResamplerSettings &cmp) const { return !(*this == cmp); } 78 }; 79 80 81 class CResampler 82 { 83 public: 84 CResamplerSettings m_Settings; 85 CWindowedFIR m_WindowedFIR; 86 static const int16 FastSincTable[256 * 4]; 87 88 #ifdef MODPLUG_TRACKER 89 static bool StaticTablesInitialized; 90 #define RESAMPLER_TABLE static 91 #else 92 // no global data which has to be initialized by hand in the library 93 #define RESAMPLER_TABLE 94 #endif // MODPLUG_TRACKER 95 96 RESAMPLER_TABLE SINC_TYPE gKaiserSinc[SINC_PHASES * 8]; // Upsampling 97 RESAMPLER_TABLE SINC_TYPE gDownsample13x[SINC_PHASES * 8]; // Downsample 1.333x 98 RESAMPLER_TABLE SINC_TYPE gDownsample2x[SINC_PHASES * 8]; // Downsample 2x 99 RESAMPLER_TABLE Paula::BlepTables blepTables; // Amiga BLEP resampler 100 101 #ifndef MPT_INTMIXER 102 RESAMPLER_TABLE mixsample_t FastSincTablef[256 * 4]; // Cubic spline LUT 103 RESAMPLER_TABLE mixsample_t LinearTablef[256]; // Linear interpolation LUT 104 #endif // !defined(MPT_INTMIXER) 105 106 #undef RESAMPLER_TABLE 107 108 private: 109 CResamplerSettings m_OldSettings; 110 public: 111 CResampler(bool fresh_generate=false) 112 { 113 if(fresh_generate) 114 { 115 InitializeTablesFromScratch(true); 116 } else 117 { 118 InitializeTables(); 119 } 120 } InitializeTables()121 void InitializeTables() 122 { 123 #if defined(MPT_RESAMPLER_TABLES_CACHED) 124 InitializeTablesFromCache(); 125 #else 126 InitializeTablesFromScratch(true); 127 #endif 128 } UpdateTables()129 void UpdateTables() 130 { 131 InitializeTablesFromScratch(false); 132 } 133 134 private: 135 void InitFloatmixerTables(); 136 void InitializeTablesFromScratch(bool force=false); 137 #ifdef MPT_RESAMPLER_TABLES_CACHED 138 void InitializeTablesFromCache(); 139 #endif 140 }; 141 142 143 OPENMPT_NAMESPACE_END 144