🍑 nectarine
Audio synthesis tools for C23
Toggle main menu visibility
Loading...
Searching...
No Matches
wavetable.h
1
#include <stdlib.h>
2
#include <math.h>
3
#include "vendor/prelude/hint.h"
4
5
// TODO: Anti-aliasing filter. Should probably be in its own header
6
// since it's not strictly for use in the wavetables and should also be
7
// useful for real-time signals. Putting the reading links here first
8
// though since it will be used to filter the mipmaps.
9
// https://ldesoras.fr/doc/articles/resampler-en.pdf
10
// https://www.kvraudio.com/forum/viewtopic.php?t=458831
11
// https://www.earlevel.com/main/2020/01/04/further-thoughts-on-wave-table-oscillators
12
// https://community.native-instruments.com/discussion/411/anti-aliasing-strategies-for-a-phase-distortion-oscillator
13
14
struct
nec_wt
{
19
size_t
mipmap_count
;
20
25
size_t
variant_count
;
26
28
size_t
sample_count
;
29
35
float
data
[];
36
};
37
38
// TODO: Why isn't this autovectorized?
39
[[nodiscard, gnu::const]]
40
static
inline
float
nec_trilerp(
41
float
c000,
42
float
c001,
43
float
c010,
44
float
c011,
45
float
c100,
46
float
c101,
47
float
c110,
48
float
c111,
49
float
x,
float
y,
float
z
50
) [[unsequenced]] {
51
assume(0 <= x && x <= 1);
52
assume(0 <= y && y <= 1);
53
assume(0 <= z && z <= 1);
54
const
auto
z1 = 1.f - z;
55
const
auto
c00 = c000 * z1 + c001 * z;
56
const
auto
c01 = c010 * z1 + c011 * z;
57
const
auto
c10 = c100 * z1 + c101 * z;
58
const
auto
c11 = c110 * z1 + c111 * z;
59
const
auto
y1 = 1.f - y;
60
const
auto
c0 = c00 * y1 + c01 * y;
61
const
auto
c1 = c10 * y1 + c11 * y;
62
return
c0 * (1.f - x) + c1 * x;
63
}
64
65
// TODO: Attributes, documentation
66
size_t
nec_init_wt(
67
void
*wt,
68
size_t
mipmap_count,
69
size_t
variant_count,
70
size_t
sample_count
71
) {
72
if
(!mipmap_count) mipmap_count = 16;
73
if
(!variant_count) variant_count = 1;
74
if
(!sample_count) sample_count = 2048;
75
const
size_t
size =
sizeof
(
struct
nec_wt
) + sizeof(float[
mipmap_count
][
variant_count
][
sample_count
]);
76
if
(!wt)
return
size;
77
struct
nec_wt
*it = wt;
78
*it = (
struct
nec_wt
){
mipmap_count
,
variant_count
,
sample_count
};
79
return
size;
80
}
81
82
[[nodiscard]]
83
struct
nec_wt
*nec_alloc_wt(
84
size_t
mipmap_count
,
85
size_t
variant_count
,
86
size_t
sample_count
87
) [[clang::allocating]] {
88
const
size_t
size = nec_init_wt(
nullptr
,
mipmap_count
,
variant_count
,
sample_count
);
89
struct
nec_wt
*wt = malloc(size);
90
if
(!wt)
return
nullptr
;
91
nec_init_wt(wt,
mipmap_count
,
variant_count
,
sample_count
);
92
return
wt;
93
}
94
95
[[nodiscard, gnu::const, gnu::nonnull]]
96
static
inline
float
nec_wt_get(
97
struct
nec_wt
wt[
const
restrict
static
1],
98
float
normalized_frequency,
99
float
variant,
100
float
phase
101
) [[unsequenced]] {
102
assume(0 <= normalized_frequency && normalized_frequency <= 1);
103
assume(0 <= variant && variant <= 1);
104
assume(0 <= phase && phase < 1);
105
106
// Mipmap indicies
107
const
auto
m = normalized_frequency * (wt->
mipmap_count
- 1);
108
const
auto
mi = floorf(m);
// Integer part of m
109
const
auto
mf = m - mi;
// Fractional part of m
110
const
auto
m0 = (size_t)(mi);
111
const
auto
m1 = 1 + m0;
112
113
// Variant indicies
114
const
auto
v = variant * (wt->
variant_count
- 1);
115
const
auto
vi = floorf(v);
// Integer part of v
116
const
auto
vf = v - vi;
// Fractional part of v
117
const
auto
v0 = (size_t)(vi);
118
const
auto
v1 = 1 + v0;
119
120
// Sample indicies
121
const
auto
s = phase * wt->
sample_count
;
122
const
auto
si = floorf(s);
// Integer part of s
123
const
auto
sf = s - si;
// Fractional part of s
124
const
auto
s0 = (size_t)(si);
125
const
auto
s1 = (1 + s0) % wt->
sample_count
;
126
127
float (*w)[wt->
mipmap_count
][wt->
variant_count
][wt->
sample_count
] = (typeof(w))(&wt->
data
);
128
return
nec_trilerp(
129
(*w)[m0][v0][s0],
130
(*w)[m0][v0][s1],
131
(*w)[m0][v1][s0],
132
(*w)[m0][v1][s1],
133
(*w)[m1][v0][s0],
134
(*w)[m1][v0][s1],
135
(*w)[m1][v1][s0],
136
(*w)[m1][v1][s1],
137
mf, vf, sf
138
);
139
}
nec_wt
Definition
wavetable.h:14
nec_wt::variant_count
size_t variant_count
How many different wave shape variants exist in this wavetable that can be morphed between.
Definition
wavetable.h:25
nec_wt::sample_count
size_t sample_count
How many samples each wave shape variant is made of.
Definition
wavetable.h:28
nec_wt::mipmap_count
size_t mipmap_count
How many mip-map levels there are in this wavetable.
Definition
wavetable.h:19
nec_wt::data
float data[]
The actual wavetable data.
Definition
wavetable.h:35
wavetable.h
Generated by
1.17.0