1 #ifndef WAVEGUIDE_NL_H
2 #define WAVEGUIDE_NL_H
3
4 #include <stdlib.h>
5 #include <string.h>
6
7 typedef struct {
8 int size;
9 float *buffer[2];
10 int ptr;
11 int delay;
12 float fc;
13 float lp[2];
14 float a1a;
15 float a1b;
16 float zm1[2];
17 } waveguide_nl;
18
waveguide_nl_new(int size,float fc,float da,float db)19 waveguide_nl *waveguide_nl_new(int size, float fc, float da, float db)
20 {
21 waveguide_nl *wg = malloc(sizeof(waveguide_nl));
22 wg->size = size;
23 wg->delay = size;
24 wg->buffer[0] = calloc(size, sizeof(float));
25 wg->buffer[1] = calloc(size, sizeof(float));
26 wg->ptr = 0;
27 wg->fc = fc;
28 wg->lp[0] = 0.0f;
29 wg->lp[1] = 0.0f;
30 wg->zm1[0] = 0.0f;
31 wg->zm1[1] = 0.0f;
32 wg->a1a = (1.0f - da) / (1.0f + da);
33 wg->a1b = (1.0f - db) / (1.0f + db);
34
35 return wg;
36 }
37
waveguide_nl_reset(waveguide_nl * wg)38 inline void waveguide_nl_reset(waveguide_nl *wg)
39 {
40 memset(wg->buffer[0], 0, wg->size * sizeof(float));
41 memset(wg->buffer[1], 0, wg->size * sizeof(float));
42 wg->lp[0] = 0.0f;
43 wg->lp[1] = 0.0f;
44 wg->zm1[0] = 0.0f;
45 wg->zm1[1] = 0.0f;
46 }
47
waveguide_nl_free(waveguide_nl * wg)48 inline void waveguide_nl_free(waveguide_nl *wg)
49 {
50 if (!wg) {
51 return;
52 }
53 free(wg->buffer[0]);
54 free(wg->buffer[1]);
55 free(wg);
56 }
57
waveguide_nl_set_delay(waveguide_nl * wg,int delay)58 inline void waveguide_nl_set_delay(waveguide_nl *wg, int delay)
59 {
60 if (delay > wg->size) {
61 wg->delay = wg->size;
62 } else if (delay < 1) {
63 wg->delay = 1;
64 } else {
65 wg->delay = delay;
66 }
67 }
68
waveguide_nl_set_fc(waveguide_nl * wg,float fc)69 inline void waveguide_nl_set_fc(waveguide_nl *wg, float fc)
70 {
71 wg->fc = fc;
72 }
73
waveguide_nl_set_ap(waveguide_nl * wg,float da,float db)74 inline void waveguide_nl_set_ap(waveguide_nl *wg, float da, float db)
75 {
76 wg->a1a = (1.0f - da) / (1.0f + da);
77 wg->a1b = (1.0f - db) / (1.0f + db);
78 }
79
waveguide_nl_process_lin(waveguide_nl * wg,float in0,float in1,float * out0,float * out1)80 inline void waveguide_nl_process_lin(waveguide_nl *wg, float in0, float in1, float *out0, float *out1)
81 {
82 float tmp;
83
84 *out0 = wg->buffer[0][(wg->ptr + wg->delay) % wg->size];
85 *out0 = wg->lp[0] * (wg->fc - 1.0f) + wg->fc * *out0;
86 wg->lp[0] = *out0;
87 tmp = *out0 * -(wg->a1a) + wg->zm1[0];
88 wg->zm1[0] = tmp * wg->a1a + *out0;
89 *out0 = tmp;
90
91 *out1 = wg->buffer[1][(wg->ptr + wg->delay) % wg->size];
92 *out1 = wg->lp[1] * (wg->fc - 1.0f) + wg->fc * *out1;
93 wg->lp[1] = *out1;
94 tmp = *out1 * -(wg->a1a) + wg->zm1[1];
95 wg->zm1[1] = tmp * wg->a1a + *out1;
96 *out1 = tmp;
97
98 wg->buffer[0][wg->ptr] = in0;
99 wg->buffer[1][wg->ptr] = in1;
100 wg->ptr--;
101 if (wg->ptr < 0) {
102 wg->ptr += wg->size;
103 }
104 }
105
waveguide_nl_process(waveguide_nl * wg,float in0,float in1,float * out0,float * out1)106 inline void waveguide_nl_process(waveguide_nl *wg, float in0, float in1, float *out0, float *out1)
107 {
108 float tmp;
109 float a1;
110 float b;
111
112 *out0 = wg->buffer[0][(wg->ptr + wg->delay) % wg->size];
113 *out0 = wg->lp[0] * (wg->fc - 1.0f) + wg->fc * *out0;
114 wg->lp[0] = *out0;
115 b = (*out0 + 1.0) * 6.0f;
116 if (b > 1.0f) {
117 b = 1.0f;
118 }
119
120 if (b < 0.0f) {
121 b = 0.0f;
122 }
123 a1 = b * wg->a1a + (1.0f - b) * wg->a1b;
124 tmp = *out0 * -a1 + wg->zm1[0];
125 wg->zm1[0] = tmp * a1 + *out0;
126 *out0 = tmp;
127
128 *out1 = wg->buffer[1][(wg->ptr + wg->delay) % wg->size];
129 *out1 = wg->lp[1] * (wg->fc - 1.0f) + wg->fc * *out1;
130 wg->lp[1] = *out1;
131 b = (*out1 + 1.0) * 6.0f;
132 if (b > 1.0f) {
133 b = 1.0f;
134 }
135
136 if (b < 0.0f) {
137 b = 0.0f;
138 }
139 a1 = b * wg->a1a + (1.0f - b) * wg->a1b;
140 tmp = *out1 * -a1 + wg->zm1[1];
141 wg->zm1[1] = tmp * a1 + *out1;
142 *out1 = tmp;
143
144 wg->buffer[0][wg->ptr] = in0;
145 wg->buffer[1][wg->ptr] = in1;
146 wg->ptr--;
147 if (wg->ptr < 0) {
148 wg->ptr += wg->size;
149 }
150 }
151
152 #endif
153