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