-
Notifications
You must be signed in to change notification settings - Fork 52
/
ladspa-util.h
241 lines (186 loc) · 4.93 KB
/
ladspa-util.h
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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
/* Some misc util functions for audio DSP work, written by Steve Harris,
* December 2000
*
* steve@plugin.org.uk
*/
#ifndef LADSPA_UTIL_H
#define LADSPA_UTIL_H
#ifndef _USE_MATH_DEFINES
#define _USE_MATH_DEFINES
#endif
#include <math.h>
#include <stdint.h>
#include "config.h"
// 16.16 fixpoint
typedef union {
int32_t all;
struct {
#ifdef WORDS_BIGENDIAN
int16_t in;
uint16_t fr;
#else
uint16_t fr;
int16_t in;
#endif
} part;
} fixp16;
// 32.32 fixpoint
typedef union {
int64_t all;
struct {
#ifdef WORDS_BIGENDIAN
int32_t in;
uint32_t fr;
#else
uint32_t fr;
int32_t in;
#endif
} part;
} fixp32;
/* 32 bit "pointer cast" union */
typedef union {
float f;
int32_t i;
} ls_pcast32;
// Sometimes it doesn't get defined, even though it eists and C99 is declared
long int lrintf (float x);
// 1.0 / ln(2)
#define LN2R 1.442695041f
/* detet floating point denormal numbers by comparing them to the smallest
* normal, crap, but reliable */
#define DN_CHECK(x, l) if (fabs(x) < 1e-38) printf("DN: "l"\n")
// Denormalise floats, only actually needed for PIII and recent PowerPC
//#define FLUSH_TO_ZERO(fv) (((*(unsigned int*)&(fv))&0x7f800000)==0)?0.0f:(fv)
static inline float flush_to_zero(float f)
{
ls_pcast32 v;
v.f = f;
// original: return (v.i & 0x7f800000) == 0 ? 0.0f : f;
// version from Tim Blechmann
return (v.i & 0x7f800000) < 0x08000000 ? 0.0f : f;
}
static inline void round_to_zero(volatile float *f)
{
*f += 1e-18;
*f -= 1e-18;
}
/* A set of branchless clipping operations from Laurent de Soras */
static inline float f_max(float x, float a)
{
x -= a;
x += fabs(x);
x *= 0.5;
x += a;
return x;
}
static inline float f_min(float x, float b)
{
x = b - x;
x += fabs(x);
x *= 0.5;
x = b - x;
return x;
}
static inline float f_clamp(float x, float a, float b)
{
const float x1 = fabs(x - a);
const float x2 = fabs(x - b);
x = x1 + a + b;
x -= x2;
x *= 0.5;
return x;
}
// Limit a value to be l<=v<=u
#define LIMIT(v,l,u) ((v)<(l)?(l):((v)>(u)?(u):(v)))
// Truncate-to-zero modulo (ANSI C doesn't specify) will only work
// if -m < v < 2m
#define MOD(v,m) (v<0?v+m:(v>=m?v-m:v))
// Truncate-to-zero modulo (ANSI C doesn't specify) will only work
// if v > -m and v < m
#define NEG_MOD(v,m) ((v)<0?((v)+(m)):(v))
// Convert a value in dB's to a coefficent
#define DB_CO(g) ((g) > -90.0f ? powf(10.0f, (g) * 0.05f) : 0.0f)
#define CO_DB(v) (20.0f * log10f(v))
// Linearly interpolate [ = a * (1 - f) + b * f]
#define LIN_INTERP(f,a,b) ((a) + (f) * ((b) - (a)))
// Cubic interpolation function
static inline float cube_interp(const float fr, const float inm1, const float
in, const float inp1, const float inp2)
{
return in + 0.5f * fr * (inp1 - inm1 +
fr * (4.0f * inp1 + 2.0f * inm1 - 5.0f * in - inp2 +
fr * (3.0f * (in - inp1) - inm1 + inp2)));
}
/* fast sin^2 aproxiamtion, adapted from jan AT rpgfan's posting to the
* music-dsp list */
static inline float f_sin_sq(float angle)
{
const float asqr = angle * angle;
float result = -2.39e-08f;
result *= asqr;
result += 2.7526e-06f;
result *= asqr;
result -= 1.98409e-04f;
result *= asqr;
result += 8.3333315e-03f;
result *= asqr;
result -= 1.666666664e-01f;
result *= asqr;
result += 1.0f;
result *= angle;
return result * result;
}
#ifdef HAVE_LRINTF
#define f_round(f) lrintf(f)
#define f_abs(j) labs(j)
#else
// Round float to int using IEEE int* hack
static inline int f_round(float f)
{
ls_pcast32 p;
p.f = f;
p.f += (3<<22);
return p.i - 0x4b400000;
}
#define f_abs(j) abs(j)
#endif
// Truncate float to int
static inline int f_trunc(float f)
{
return f_round(floorf(f));
}
/* Andrew Simper's pow(2, x) aproximation from the music-dsp list */
#if 0
/* original */
static inline float f_pow2(float x)
{
long *px = (long*)(&x); // store address of float as long pointer
const float tx = (x-0.5f) + (3<<22); // temporary value for truncation
const long lx = *((long*)&tx) - 0x4b400000; // integer power of 2
const float dx = x-(float)(lx); // float remainder of power of 2
x = 1.0f + dx*(0.6960656421638072f + // cubic apporoximation of 2^x
dx*(0.224494337302845f + // for x in the range [0, 1]
dx*(0.07944023841053369f)));
*px += (lx<<23); // add integer power of 2 to exponent
return x;
}
#else
/* union version */
static inline float f_pow2(float x)
{
ls_pcast32 *px, tx, lx;
float dx;
px = (ls_pcast32 *)&x; // store address of float as long pointer
tx.f = (x-0.5f) + (3<<22); // temporary value for truncation
lx.i = tx.i - 0x4b400000; // integer power of 2
dx = x - (float)lx.i; // float remainder of power of 2
x = 1.0f + dx * (0.6960656421638072f + // cubic apporoximation of 2^x
dx * (0.224494337302845f + // for x in the range [0, 1]
dx * (0.07944023841053369f)));
(*px).i += (lx.i << 23); // add integer power of 2 to exponent
return (*px).f;
}
#endif
/* Fast exponentiation function, y = e^x */
#define f_exp(x) f_pow2(x * LN2R)
#endif