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