🍑 nectarine
Audio synthesis tools for C23
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
14struct nec_wt {
20
26
29
35 float data[];
36};
37
38// TODO: Why isn't this autovectorized?
39[[nodiscard, gnu::const]]
40static 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
66size_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;
79 return size;
80}
81
82[[nodiscard]]
83struct 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]]
96static 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}
Definition wavetable.h:14
size_t variant_count
How many different wave shape variants exist in this wavetable that can be morphed between.
Definition wavetable.h:25
size_t sample_count
How many samples each wave shape variant is made of.
Definition wavetable.h:28
size_t mipmap_count
How many mip-map levels there are in this wavetable.
Definition wavetable.h:19
float data[]
The actual wavetable data.
Definition wavetable.h:35