libresidfp 0.9.1
Resampler.h
1/*
2 * This file is part of libsidplayfp, a SID player engine.
3 *
4 * Copyright 2011-2024 Leandro Nini <drfiemost@users.sourceforge.net>
5 * Copyright 2007-2010 Antti Lankila
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 */
21
22#ifndef RESAMPLER_H
23#define RESAMPLER_H
24
25#include <cmath>
26#include <cassert>
27
28#include "siddefs-fp.h"
29
30namespace reSIDfp
31{
32
38{
39private:
40#if defined(PADE_TANH)
41 // Padé approximation of tanh
42 static constexpr inline double sid_tanh(double x) noexcept
43 {
44 if (likely(x < 3.))
45 {
46 const double x2 = x * x;
47 const double num = x*(945. + x2*(105. + x2));
48 const double den = 945. + x2*(420. + x2*15.);
49 return num/den;
50 }
51 return 1.;
52 }
53#elif defined(LAMBERT_TANH)
54 // 7th-degree Lambert approximation of tanh
55 static constexpr inline double sid_tanh(double x) noexcept
56 {
57 if (likely(x < 4.))
58 {
59 const double x2 = x * x;
60 const double num = x*(135135. + x2*(17325. + x2*(378 + x2)));
61 const double den = 135135. + x2*(62370. + x2*(3150. + x2*28.));
62 return num/den;
63 }
64 return 1.;
65 }
66#else
67 static inline double sid_tanh(double x)
68 {
69 return std::tanh(x);
70 }
71#endif
72
73 template<int m>
74 static inline int clipper(int x)
75 {
76 assert(x >= 0);
77 constexpr int threshold = 28000;
78 if (likely(x < threshold))
79 return x;
80
81 constexpr double max_val = static_cast<double>(m);
82 constexpr double t = threshold / max_val;
83 constexpr double a = 1. - t;
84 constexpr double b = 1. / a;
85
86 double value = static_cast<double>(x - threshold) / max_val;
87 value = t + a * sid_tanh(b * value);
88 return static_cast<int>(value * max_val);
89 }
90
91 /*
92 * Soft Clipping implementation, splitted for test.
93 */
94 static inline int softClipImpl(int x)
95 {
96 return x < 0 ? -clipper<32768>(-x) : clipper<32767>(x);
97 }
98
99protected:
100 /*
101 * Soft Clipping into 16 bit range [-32768,32767]
102 */
103 static inline short softClip(int x) { return static_cast<short>(softClipImpl(x)); }
104
105 virtual int output() const = 0;
106
107 Resampler() {}
108
109public:
110 virtual ~Resampler() = default;
111
118 virtual bool input(int sample) = 0;
119
125 inline short getOutput(int scaleFactor) const
126 {
127 const int out = (scaleFactor * output()) / 2;
128 return softClip(out);
129 }
130
131 virtual void reset() = 0;
132};
133
134} // namespace reSIDfp
135
136#endif
Definition Resampler.h:38
virtual bool input(int sample)=0
short getOutput(int scaleFactor) const
Definition Resampler.h:125