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