aboutsummaryrefslogtreecommitdiff
path: root/Src/external_dependencies/openmpt-trunk/soundlib/Resampler.h
blob: 1f617c775a7695d2103ac827b28037e02e0855da (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/*
 * 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