LMMS
Loading...
Searching...
No Matches
OversamplingHelpers.h
Go to the documentation of this file.
1/*
2 * OversamplingHelpers.h
3 *
4 * Copyright (c) 2025 Lost Robot <r94231/at/gmail/dot/com>
5 *
6 * This file is part of LMMS - https://lmms.io
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public
19 * License along with this program (see COPYING); if not, write to the
20 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301 USA.
22 *
23 */
24
25#ifndef LMMS_OVERSAMPLING_HELPERS_H
26#define LMMS_OVERSAMPLING_HELPERS_H
27
28#include <algorithm>
29#include <array>
30
31#include <hiir/PolyphaseIir2Designer.h>
32
33#ifdef __SSE2__
34#include <hiir/Downsampler2xSse.h>
35#include <hiir/Upsampler2xSse.h>
36#else
37#include <hiir/Downsampler2xFpu.h>
38#include <hiir/Upsampler2xFpu.h>
39#endif
40
41
42inline constexpr float HIIR_DEFAULT_PASSBAND = 19600;
43inline constexpr int HIIR_DEFAULT_MAX_COEFS = 8;
44
45namespace lmms
46{
47
48template<int MaxStages, int MaxCoefs = 8>
50{
51public:
52 void reset()
53 {
54 float bw = 0.5f - m_passband / m_sampleRate;
55
56 // Stage 1
57 double coefsFirst[s_firstCoefCount];
58 hiir::PolyphaseIir2Designer::compute_coefs_spec_order_tbw(coefsFirst, s_firstCoefCount, bw);
59 m_upsampleFirst.set_coefs(coefsFirst);
60 m_upsampleFirst.clear_buffers();
61 bw = (bw + 0.5f) * 0.5f;
62
63 // Stage 2
64 double coefsSecond[s_secondCoefCount];
65 hiir::PolyphaseIir2Designer::compute_coefs_spec_order_tbw(coefsSecond, s_secondCoefCount, bw);
66 m_upsampleSecond.set_coefs(coefsSecond);
67 m_upsampleSecond.clear_buffers();
68 bw = (bw + 0.5f) * 0.5f;
69
70 // Remaining stages
71 for (int i = 0; i < m_stages - 2; ++i)
72 {
73 double coefsRest[s_restCoefCount];
74 hiir::PolyphaseIir2Designer::compute_coefs_spec_order_tbw(coefsRest, s_restCoefCount, bw);
75 m_upsampleRest[i].set_coefs(coefsRest);
76 m_upsampleRest[i].clear_buffers();
77 bw = (bw + 0.5f) * 0.5f;
78 }
79 }
80
81 void setup(int stages, float sampleRate, float passband = HIIR_DEFAULT_PASSBAND)
82 {
83 assert(stages <= MaxStages);
84 m_stages = stages;
85 m_sampleRate = sampleRate;
86 m_passband = passband;
87 reset();
88 }
89
90 // expects `2 ^ m_stages` elements for the output
91 void processSample(float* outSamples, float inSample)
92 {
93 int total = 1 << m_stages;
94 outSamples[0] = inSample;
95 int gap1 = total / 2;
96
97 if (m_stages >= 1)
98 {
99 m_upsampleFirst.process_sample(outSamples[0], outSamples[gap1], outSamples[0]);
100 }
101
102 if (m_stages >= 2)
103 {
104 int gap2 = gap1 / 2;
105 m_upsampleSecond.process_sample(outSamples[0], outSamples[gap2], outSamples[0]);
106 m_upsampleSecond.process_sample(outSamples[gap1], outSamples[gap1 + gap2], outSamples[gap1]);
107 }
108
109 for (int i = 2; i < m_stages; ++i)
110 {
111 int count = 1 << i;
112 int gap = total / count;
113 for (int j = 0; j < count; ++j)
114 {
115 int temp = j * gap;
116 m_upsampleRest[i - 2].process_sample(outSamples[temp], outSamples[temp + gap / 2], outSamples[temp]);
117 }
118 }
119 }
120
121 int getStages() const { return m_stages; }
122 float getSampleRate() const { return m_sampleRate; }
123 float getPassband() const { return m_passband; }
124
125 void setStages(int stages) { m_stages = stages; reset(); }
126 void setSampleRate(float sampleRate) { m_sampleRate = sampleRate; reset(); }
127 void setPassband(float passband) { m_passband = passband; reset(); }
128
129private:
130 static constexpr int s_firstCoefCount = MaxCoefs;
131 static constexpr int s_secondCoefCount = std::max(MaxCoefs / 2, 2);
132 static constexpr int s_restCoefCount = std::max(MaxCoefs / 4, 2);
133#ifdef __SSE2__
134 hiir::Upsampler2xSse<s_firstCoefCount> m_upsampleFirst;
135 hiir::Upsampler2xSse<s_secondCoefCount> m_upsampleSecond;
136 std::array<hiir::Upsampler2xSse<s_restCoefCount>, MaxStages - 2> m_upsampleRest;
137#else
138 hiir::Upsampler2xFpu<s_firstCoefCount> m_upsampleFirst;
139 hiir::Upsampler2xFpu<s_secondCoefCount> m_upsampleSecond;
140 std::array<hiir::Upsampler2xFpu<s_restCoefCount>, MaxStages - 2> m_upsampleRest;
141#endif
142
143 int m_stages = 0;
144 float m_sampleRate = 44100;
146};
147
148
149template<int MaxStages, int MaxCoefs = 8>
151{
152public:
153 void reset()
154 {
155 float bw = 0.5f - m_passband / m_sampleRate;
156
157 // Stage 1
158 double coefsFirst[s_firstCoefCount];
159 hiir::PolyphaseIir2Designer::compute_coefs_spec_order_tbw(coefsFirst, s_firstCoefCount, bw);
160 m_downsampleFirst.set_coefs(coefsFirst);
161 m_downsampleFirst.clear_buffers();
162 bw = (bw + 0.5f) * 0.5f;
163
164 // Stage 2
165 double coefsSecond[s_secondCoefCount];
166 hiir::PolyphaseIir2Designer::compute_coefs_spec_order_tbw(coefsSecond, s_secondCoefCount, bw);
167 m_downsampleSecond.set_coefs(coefsSecond);
168 m_downsampleSecond.clear_buffers();
169 bw = (bw + 0.5f) * 0.5f;
170
171 // Remaining stages
172 for (int i = 0; i < m_stages - 2; ++i)
173 {
174 double coefsRest[s_restCoefCount];
175 hiir::PolyphaseIir2Designer::compute_coefs_spec_order_tbw(coefsRest, s_restCoefCount, bw);
176 m_downsampleRest[i].set_coefs(coefsRest);
177 m_downsampleRest[i].clear_buffers();
178 bw = (bw + 0.5f) * 0.5f;
179 }
180 }
181
182 void setup(int stages, float sampleRate, float passband = HIIR_DEFAULT_PASSBAND)
183 {
184 assert(stages <= MaxStages);
185 m_stages = stages;
186 m_sampleRate = sampleRate;
187 m_passband = passband;
188 reset();
189 }
190
191 // expects `2 ^ m_stages` elements for the input
192 float processSample(float* inSamples)
193 {
194 for (int i = m_stages - 1; i >= 2; --i)
195 {
196 for (int j = 0; j < 1 << i; ++j)
197 {
198 inSamples[j] = m_downsampleRest[i - 2].process_sample(&inSamples[j * 2]);
199 }
200 }
201
202 if (m_stages >= 2)
203 {
204 for (int j = 0; j < 2; ++j)
205 {
206 inSamples[j] = m_downsampleSecond.process_sample(&inSamples[j * 2]);
207 }
208 }
209
210 if (m_stages >= 1)
211 {
212 inSamples[0] = m_downsampleFirst.process_sample(&inSamples[0]);
213 }
214
215 return inSamples[0];
216 }
217
218 int getStages() const { return m_stages; }
219 float getSampleRate() const { return m_sampleRate; }
220 float getPassband() const { return m_passband; }
221
222 void setStages(int stages) { m_stages = stages; reset(); }
223 void setSampleRate(float sampleRate) { m_sampleRate = sampleRate; reset(); }
224 void setPassband(float passband) { m_passband = passband; reset(); }
225
226private:
227 static constexpr int s_firstCoefCount = MaxCoefs;
228 static constexpr int s_secondCoefCount = std::max(MaxCoefs / 2, 2);
229 static constexpr int s_restCoefCount = std::max(MaxCoefs / 4, 2);
230#ifdef __SSE2__
231 hiir::Downsampler2xSse<s_firstCoefCount> m_downsampleFirst;
232 hiir::Downsampler2xSse<s_secondCoefCount> m_downsampleSecond;
233 std::array<hiir::Downsampler2xSse<s_restCoefCount>, MaxStages - 2> m_downsampleRest;
234#else
235 hiir::Downsampler2xFpu<s_firstCoefCount> m_downsampleFirst;
236 hiir::Downsampler2xFpu<s_secondCoefCount> m_downsampleSecond;
237 std::array<hiir::Downsampler2xFpu<s_restCoefCount>, MaxStages - 2> m_downsampleRest;
238#endif
239
240 int m_stages = 0;
241 float m_sampleRate = 44100;
243};
244
245
246} // namespace lmms
247
248#endif // LMMS_OVERSAMPLING_HELPERS_H
249
constexpr int HIIR_DEFAULT_MAX_COEFS
Definition OversamplingHelpers.h:43
constexpr float HIIR_DEFAULT_PASSBAND
Definition OversamplingHelpers.h:42
assert(0)
Definition OversamplingHelpers.h:151
void setup(int stages, float sampleRate, float passband=HIIR_DEFAULT_PASSBAND)
Definition OversamplingHelpers.h:182
float m_passband
Definition OversamplingHelpers.h:242
static constexpr int s_firstCoefCount
Definition OversamplingHelpers.h:227
int getStages() const
Definition OversamplingHelpers.h:218
float m_sampleRate
Definition OversamplingHelpers.h:241
void reset()
Definition OversamplingHelpers.h:153
std::array< hiir::Downsampler2xFpu< s_restCoefCount >, MaxStages - 2 > m_downsampleRest
Definition OversamplingHelpers.h:237
hiir::Downsampler2xFpu< s_firstCoefCount > m_downsampleFirst
Definition OversamplingHelpers.h:235
float getPassband() const
Definition OversamplingHelpers.h:220
hiir::Downsampler2xFpu< s_secondCoefCount > m_downsampleSecond
Definition OversamplingHelpers.h:236
int m_stages
Definition OversamplingHelpers.h:240
float getSampleRate() const
Definition OversamplingHelpers.h:219
static constexpr int s_restCoefCount
Definition OversamplingHelpers.h:229
void setPassband(float passband)
Definition OversamplingHelpers.h:224
float processSample(float *inSamples)
Definition OversamplingHelpers.h:192
void setSampleRate(float sampleRate)
Definition OversamplingHelpers.h:223
static constexpr int s_secondCoefCount
Definition OversamplingHelpers.h:228
void setStages(int stages)
Definition OversamplingHelpers.h:222
Definition OversamplingHelpers.h:50
void setup(int stages, float sampleRate, float passband=HIIR_DEFAULT_PASSBAND)
Definition OversamplingHelpers.h:81
static constexpr int s_firstCoefCount
Definition OversamplingHelpers.h:130
float getPassband() const
Definition OversamplingHelpers.h:123
void setPassband(float passband)
Definition OversamplingHelpers.h:127
int getStages() const
Definition OversamplingHelpers.h:121
void processSample(float *outSamples, float inSample)
Definition OversamplingHelpers.h:91
void reset()
Definition OversamplingHelpers.h:52
float m_sampleRate
Definition OversamplingHelpers.h:144
float m_passband
Definition OversamplingHelpers.h:145
static constexpr int s_restCoefCount
Definition OversamplingHelpers.h:132
int m_stages
Definition OversamplingHelpers.h:143
hiir::Upsampler2xFpu< s_firstCoefCount > m_upsampleFirst
Definition OversamplingHelpers.h:138
static constexpr int s_secondCoefCount
Definition OversamplingHelpers.h:131
std::array< hiir::Upsampler2xFpu< s_restCoefCount >, MaxStages - 2 > m_upsampleRest
Definition OversamplingHelpers.h:140
hiir::Upsampler2xFpu< s_secondCoefCount > m_upsampleSecond
Definition OversamplingHelpers.h:139
float getSampleRate() const
Definition OversamplingHelpers.h:122
void setStages(int stages)
Definition OversamplingHelpers.h:125
void setSampleRate(float sampleRate)
Definition OversamplingHelpers.h:126
register unsigned j
Definition inflate.c:1576
register unsigned i
Definition inflate.c:1575
Definition AudioAlsa.cpp:35
_WDL_CSTRING_PREFIX void INT_PTR count
Definition wdlcstring.h:263