LMMS
Loading...
Searching...
No Matches
HilbertTransform.h
Go to the documentation of this file.
1/*
2 * HilbertTransform.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 * Full credit for the Hilbert IIR coefficients and general usage goes to:
25 *
26 * Copyright (c) 2024 Geraint Luff / Signalsmith Audio Ltd.
27 * Released under the 0BSD (Zero-Clause BSD) License.
28 *
29 * https://github.com/Signalsmith-Audio/hilbert-iir/blob/main/hilbert.h
30 * -------------------------------------------------------------------------
31 */
32
33#ifndef LMMS_HILBERT_TRANSFORM_H
34#define LMMS_HILBERT_TRANSFORM_H
35#include <cmath>
36
37#ifdef __SSE2__
38 #include <emmintrin.h>
39#endif
40
41namespace lmms
42{
43
44template<int Channels>
46{
47 static constexpr int order = 12;
48
49 alignas(16) static constexpr float baseCoeffsR[order] = {
50 -0.000224352093802f, 0.0107500557815f, -0.0456795873917f,
51 0.11282500582f, -0.208067578452f, 0.28717837501f,
52 -0.254675294431f, 0.0481081835026f, 0.227861357867f,
53 -0.365411839137f, 0.280729061131f, -0.0935061787728f
54 };
55 alignas(16) static constexpr float baseCoeffsI[order] = {
56 0.00543499018201f, -0.0173890685681f, 0.0229166931429f,
57 0.00278413661237f, -0.104628958675f, 0.33619239719f,
58 -0.683033899655f, 0.954061589374f, -0.891273574569f,
59 0.525088317271f, -0.155131206606f, 0.00512245855404f
60 };
61 alignas(16) static constexpr float basePolesR[order] = {
62 -0.00495335976478f, -0.017859491302f, -0.0413714373155f,
63 -0.0882148408885f, -0.17922965812f, -0.338261800753f,
64 -0.557688699732f, -0.735157736148f, -0.719057381172f,
65 -0.517871025209f, -0.280197469471f, -0.0852751354531f
66 };
67 alignas(16) static constexpr float basePolesI[order] = {
68 0.0092579876872f, 0.0273493725543f, 0.0744756910287f,
69 0.178349677457f, 0.39601340223f, 0.829229533354f,
70 1.61298538328f, 2.79987398682f, 4.16396166128f,
71 5.29724826804f, 5.99598602388f, 6.3048492377f
72 };
73 static constexpr float baseDirect = 0.000262057212648f;
74
75 alignas(16) float coeffsR[order];
76 alignas(16) float coeffsI[order];
77 alignas(16) float polesR[order];
78 alignas(16) float polesI[order];
79 alignas(16) float stateR[Channels][order];
80 alignas(16) float stateI[Channels][order];
81 float direct;
82
83 HilbertIIRFloat(float sampleRate = 48000.0f, float passbandGain = 2.0f)
84 {
85 const float freqFactor = std::fmin(0.46f, 20000.0f / sampleRate);
86 const float coeffScale = freqFactor * passbandGain;
87 direct = baseDirect * 2.0f * passbandGain * freqFactor;
88 for (int i = 0; i < order; ++i)
89 {
90 coeffsR[i] = baseCoeffsR[i] * coeffScale;
91 coeffsI[i] = baseCoeffsI[i] * coeffScale;
92 const float a = basePolesR[i] * freqFactor;
93 const float b = basePolesI[i] * freqFactor;
94 const float ea = std::exp(a);
95 polesR[i] = ea * std::cos(b);
96 polesI[i] = ea * std::sin(b);
97 }
98 reset();
99 }
100
101 inline void reset()
102 {
103 for (int ch = 0; ch < Channels; ++ch)
104 {
105 for (int i = 0; i < order; ++i)
106 {
107 stateR[ch][i] = stateI[ch][i] = 0.0f;
108 }
109 }
110 }
111
112 inline void processReal(float x, int channel, float *out)
113 {
114 float *sR = stateR[channel], *sI = stateI[channel];
115#ifdef __SSE2__
116 const __m128 vx = _mm_set1_ps(x);
117 __m128 sumR = _mm_setzero_ps(), sumI = _mm_setzero_ps();
118 for (int i = 0; i < order; i += 4)
119 {
120 __m128 vr = _mm_load_ps(&sR[i]);
121 __m128 vi = _mm_load_ps(&sI[i]);
122 __m128 vpr = _mm_load_ps(&polesR[i]);
123 __m128 vpi = _mm_load_ps(&polesI[i]);
124 __m128 vcr = _mm_load_ps(&coeffsR[i]);
125 __m128 vci = _mm_load_ps(&coeffsI[i]);
126
127 __m128 rpr = _mm_mul_ps(vr, vpr);
128 __m128 impi = _mm_mul_ps(vi, vpi);
129 __m128 xcr = _mm_mul_ps(vx, vcr);
130 __m128 nr = _mm_add_ps(_mm_sub_ps(rpr, impi), xcr);
131
132 __m128 rpi = _mm_mul_ps(vr, vpi);
133 __m128 impr = _mm_mul_ps(vi, vpr);
134 __m128 xci = _mm_mul_ps(vx, vci);
135 __m128 ni = _mm_add_ps(_mm_add_ps(rpi, impr), xci);
136
137 _mm_store_ps(&sR[i], nr);
138 _mm_store_ps(&sI[i], ni);
139
140 sumR = _mm_add_ps(sumR, nr);
141 sumI = _mm_add_ps(sumI, ni);
142 }
143 float tmpR[4], tmpI[4];
144 _mm_storeu_ps(tmpR, sumR);
145 _mm_storeu_ps(tmpI, sumI);
146 out[0] = x * direct + (tmpR[0] + tmpR[1] + tmpR[2] + tmpR[3]);
147 out[1] = (tmpI[0] + tmpI[1] + tmpI[2] + tmpI[3]);
148#else
149 float sumR = 0.0f, sumI = 0.0f;
150 for (int i = 0; i < order; ++i)
151 {
152 const float r = sR[i], im = sI[i], pr = polesR[i], pi = polesI[i];
153 const float nr = r * pr - im * pi + x * coeffsR[i];
154 const float ni = r * pi + im * pr + x * coeffsI[i];
155 sR[i] = nr; sI[i] = ni;
156 sumR += nr; sumI += ni;
157 }
158 out[0] = x * direct + sumR;
159 out[1] = sumI;
160#endif
161 }
162
163 inline void processComplex(const float *x, int channel, float *out)
164 {
165 const float xr = x[0], xi = x[1];
166 float *sR = stateR[channel], *sI = stateI[channel];
167#ifdef __SSE2__
168 const __m128 vxr = _mm_set1_ps(xr), vxi = _mm_set1_ps(xi);
169 __m128 sumR = _mm_setzero_ps(), sumI = _mm_setzero_ps();
170 for (int i = 0; i < order; i += 4)
171 {
172 __m128 vr = _mm_load_ps(&sR[i]);
173 __m128 vi = _mm_load_ps(&sI[i]);
174 __m128 vpr = _mm_load_ps(&polesR[i]);
175 __m128 vpi = _mm_load_ps(&polesI[i]);
176 __m128 vcr = _mm_load_ps(&coeffsR[i]);
177 __m128 vci = _mm_load_ps(&coeffsI[i]);
178
179 __m128 xrcr = _mm_mul_ps(vxr, vcr);
180 __m128 xici = _mm_mul_ps(vxi, vci);
181 __m128 xrci = _mm_mul_ps(vxr, vci);
182 __m128 xicr = _mm_mul_ps(vxi, vcr);
183
184 __m128 rpr = _mm_mul_ps(vr, vpr);
185 __m128 impi = _mm_mul_ps(vi, vpi);
186 __m128 rpi = _mm_mul_ps(vr, vpi);
187 __m128 impr = _mm_mul_ps(vi, vpr);
188
189 __m128 nr = _mm_add_ps(_mm_sub_ps(rpr, impi), _mm_sub_ps(xrcr, xici));
190 __m128 ni = _mm_add_ps(_mm_add_ps(rpi, impr), _mm_add_ps(xrci, xicr));
191
192 _mm_store_ps(&sR[i], nr);
193 _mm_store_ps(&sI[i], ni);
194
195 sumR = _mm_add_ps(sumR, nr);
196 sumI = _mm_add_ps(sumI, ni);
197 }
198 float tmpR[4], tmpI[4];
199 _mm_storeu_ps(tmpR, sumR);
200 _mm_storeu_ps(tmpI, sumI);
201 const float sr = tmpR[0] + tmpR[1] + tmpR[2] + tmpR[3];
202 const float si = tmpI[0] + tmpI[1] + tmpI[2] + tmpI[3];
203 out[0] = xr * direct + sr;
204 out[1] = xi * direct + si;
205#else
206 float sumR = 0.0f, sumI = 0.0f;
207 for (int i = 0; i < order; ++i)
208 {
209 const float r = sR[i], im = sI[i];
210 const float pr = polesR[i], pi = polesI[i], cr = coeffsR[i], ci = coeffsI[i];
211 const float xrcr = xr * cr, xici = xi * ci, xrci = xr * ci, xicr = xi * cr;
212 const float nr = r * pr - im * pi + (xrcr - xici);
213 const float ni = r * pi + im * pr + (xrci + xicr);
214 sR[i] = nr; sI[i] = ni;
215 sumR += nr; sumI += ni;
216 }
217 out[0] = xr * direct + sumR;
218 out[1] = xi * direct + sumI;
219#endif
220 }
221};
222
223} // namespace lmms
224
225#endif // LMMS_HILBERT_TRANSFORM_H
uint8_t a
Definition Spc_Cpu.h:141
register unsigned i
Definition inflate.c:1575
unsigned x[BMAX+1]
Definition inflate.c:1586
const double pi
Definition exprtk_benchmark.cpp:186
float out
Definition lilv_test.c:1461
Definition AudioAlsa.cpp:35
void reset()
Definition HilbertTransform.h:101
float stateR[Channels][order]
Definition HilbertTransform.h:79
HilbertIIRFloat(float sampleRate=48000.0f, float passbandGain=2.0f)
Definition HilbertTransform.h:83
float polesI[order]
Definition HilbertTransform.h:78
float polesR[order]
Definition HilbertTransform.h:77
float stateI[Channels][order]
Definition HilbertTransform.h:80
float direct
Definition HilbertTransform.h:81
static constexpr float baseCoeffsR[order]
Definition HilbertTransform.h:49
static constexpr float baseCoeffsI[order]
Definition HilbertTransform.h:55
static constexpr float basePolesI[order]
Definition HilbertTransform.h:67
static constexpr float basePolesR[order]
Definition HilbertTransform.h:61
void processReal(float x, int channel, float *out)
Definition HilbertTransform.h:112
static constexpr float baseDirect
Definition HilbertTransform.h:73
float coeffsR[order]
Definition HilbertTransform.h:75
void processComplex(const float *x, int channel, float *out)
Definition HilbertTransform.h:163
static constexpr int order
Definition HilbertTransform.h:47
float coeffsI[order]
Definition HilbertTransform.h:76
int r
Definition crypt.c:458
b
Definition crypt.c:628