Avoid divide-by-zero on each note on.
[calfbox.git] / reverb.c
1 /*
2 Calf Box, an open source musical instrument.
3 Copyright (C) 2010-2011 Krzysztof Foltman
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include "config.h"
20 #include "config-api.h"
21 #include "dspmath.h"
22 #include "module.h"
23 #include "onepole-float.h"
24 #include <glib.h>
25 #include <malloc.h>
26 #include <math.h>
27 #include <memory.h>
28 #include <sndfile.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31
32 // The reverb structure is based on this article:
33 // http://www.spinsemi.com/knowledge_base/effects.html#Reverberation
34
35 #define DELAY_BUFFER 1024
36 #define ALLPASS_BUFFER 2048
37
38 struct allpass_param
39 {
40     int delay;
41     float diffusion;
42 };
43
44 struct cbox_reverb_leg_params
45 {
46     int delay_length;
47     int allpass_units;
48     struct allpass_param allpasses[0];
49 };
50
51 struct cbox_reverb_leg
52 {
53     struct cbox_reverb_leg_params *params;
54     float (*allpass_storage)[ALLPASS_BUFFER];
55     float delay_storage[DELAY_BUFFER];
56     struct cbox_onepolef_state filter_state;
57     float buffer[CBOX_BLOCK_SIZE];
58 };
59
60 static struct cbox_reverb_leg_params *leg_params_new(int delay_length, int allpasses, const struct allpass_param *allpass_params)
61 {
62     struct cbox_reverb_leg_params *p = malloc(sizeof(struct cbox_reverb_leg_params) + sizeof(struct allpass_param) * allpasses);
63     p->delay_length = delay_length;
64     p->allpass_units = allpasses;
65     
66     if (allpass_params)
67     {
68         for (int i = 0; i < allpasses; i++)
69             memcpy(&p->allpasses[i], &allpass_params[i], sizeof(struct allpass_param));
70     }
71
72     return p;
73 }
74
75 static void cbox_reverb_leg_reset(struct cbox_reverb_leg *leg)
76 {
77     cbox_onepolef_reset(&leg->filter_state);
78     int i;
79     for (int a = 0; a < leg->params->allpass_units; a++)
80         for (i = 0; i < ALLPASS_BUFFER; i++)
81             leg->allpass_storage[a][i] = 0.f;
82     for (i = 0; i < DELAY_BUFFER; i++)
83         leg->delay_storage[i] = 0.f;
84 }
85
86 static void cbox_reverb_leg_init(struct cbox_reverb_leg *leg)
87 {
88     leg->allpass_storage = malloc(leg->params->allpass_units * ALLPASS_BUFFER * sizeof(float));
89     cbox_reverb_leg_reset(leg);
90 }
91
92 static void cbox_reverb_leg_cleanup(struct cbox_reverb_leg *leg)
93 {
94     free(leg->params);
95     free(leg->allpass_storage);
96 }
97
98 #define MODULE_PARAMS reverb_params
99
100 struct reverb_params
101 {
102     float decay_time;
103     float wetamt;
104     float dryamt;
105     float lowpass, highpass;
106 };
107
108 struct reverb_state
109 {
110     struct cbox_reverb_leg *legs;
111     int leg_count;
112     int total_time;
113 };
114
115 struct reverb_module
116 {
117     struct cbox_module module;
118
119     struct cbox_onepolef_coeffs filter_coeffs[2];
120     struct reverb_params *params, *old_params;
121     struct reverb_state *state;
122     float gain;
123     int pos;
124 };
125
126 gboolean reverb_process_cmd(struct cbox_command_target *ct, struct cbox_command_target *fb, struct cbox_osc_command *cmd, GError **error)
127 {
128     struct reverb_module *m = (struct reverb_module *)ct->user_data;
129     
130     EFFECT_PARAM("/wet_amt", "f", wetamt, double, dB2gain_simple, -100, 100) else
131     EFFECT_PARAM("/dry_amt", "f", dryamt, double, dB2gain_simple, -100, 100) else
132     EFFECT_PARAM("/decay_time", "f", decay_time, double, , 500, 5000) else
133     EFFECT_PARAM("/lowpass", "f", lowpass, double, , 30, 20000) else
134     EFFECT_PARAM("/highpass", "f", highpass, double, , 30, 20000) else
135     if (!strcmp(cmd->command, "/status") && !strcmp(cmd->arg_types, ""))
136     {
137         if (!cbox_check_fb_channel(fb, cmd->command, error))
138             return FALSE;
139         return cbox_execute_on(fb, NULL, "/wet_amt", "f", error, gain2dB_simple(m->params->wetamt)) &&
140             cbox_execute_on(fb, NULL, "/dry_amt", "f", error, gain2dB_simple(m->params->dryamt)) &&
141             cbox_execute_on(fb, NULL, "/decay_time", "f", error, m->params->decay_time) &&
142             cbox_execute_on(fb, NULL, "/lowpass", "f", error, m->params->lowpass) &&
143             cbox_execute_on(fb, NULL, "/highpass", "f", error, m->params->highpass) && 
144             CBOX_OBJECT_DEFAULT_STATUS(&m->module, fb, error);
145     }
146     else
147         return cbox_object_default_process_cmd(ct, fb, cmd, error);
148     return TRUE;
149 }
150
151 void reverb_process_event(struct cbox_module *module, const uint8_t *data, uint32_t len)
152 {
153     // struct reverb_module *m = (struct reverb_module *)module;
154 }
155
156 static void cbox_reverb_process_leg(struct reverb_module *m, int u)
157 {
158     int pos;
159     int dv;
160     float *storage;
161     
162     struct reverb_state *state = m->state;
163     struct cbox_reverb_leg *b = &state->legs[u];
164     int uprev = u ? (u - 1) : (state->leg_count - 1);
165     struct cbox_reverb_leg *bprev = &state->legs[uprev];    
166     
167     float gain = m->gain;
168     pos = m->pos;
169     storage = bprev->delay_storage;
170     float *buf = b->buffer;
171     for (int i = 0; i < CBOX_BLOCK_SIZE; i++)
172     {
173         buf[i] += cbox_onepolef_process_sample(&b->filter_state, &m->filter_coeffs[u&1], storage[pos & (DELAY_BUFFER - 1)] * gain);
174         pos++;
175     }
176
177     int units = b->params->allpass_units;
178     for (int a = 0; a < units; a++)
179     {
180         pos = m->pos;
181         storage = b->allpass_storage[a];
182         dv = b->params->allpasses[a].delay;
183         float w = b->params->allpasses[a].diffusion;
184         for (int i = 0; i < CBOX_BLOCK_SIZE; i++)
185         {
186             float dry = buf[i];
187             float out = dry;
188         
189             float delayed = storage[pos & (ALLPASS_BUFFER - 1)];
190             
191             float feedback = sanef(out - w * delayed);
192             
193             buf[i] = sanef(feedback * w + delayed);
194             
195             storage[(pos + dv) & (ALLPASS_BUFFER - 1)] = feedback;
196             pos++;
197         }
198     }
199     pos = m->pos;
200     storage = b->delay_storage;
201     dv = b->params->delay_length - (u == 0 ? CBOX_BLOCK_SIZE : 0);
202     for (int i = 0; i < CBOX_BLOCK_SIZE; i++)
203     {
204         storage[(pos + dv) & (DELAY_BUFFER - 1)] = buf[i];
205         pos++;
206     }
207 }
208
209 void reverb_process_block(struct cbox_module *module, cbox_sample_t **inputs, cbox_sample_t **outputs)
210 {
211     struct reverb_module *m = (struct reverb_module *)module;
212     struct reverb_params *p = m->params;
213     
214     float dryamt = p->dryamt;
215     float wetamt = p->wetamt;
216     struct reverb_state *s = m->state;
217
218     if (p != m->old_params)
219     {
220         float tpdsr = 2.f * M_PI * m->module.srate_inv;
221         cbox_onepolef_set_lowpass(&m->filter_coeffs[0], p->lowpass * tpdsr);
222         cbox_onepolef_set_highpass(&m->filter_coeffs[1], p->highpass * tpdsr);
223         float rv = p->decay_time * m->module.srate / 1000;
224         m->gain = pow(0.001, s->total_time / (rv * s->leg_count / 2));
225         m->old_params = p;
226     }
227
228     int mid = s->leg_count >> 1;
229     memcpy(s->legs[0].buffer, inputs[0], CBOX_BLOCK_SIZE * sizeof(float));
230     memcpy(s->legs[mid].buffer, inputs[1], CBOX_BLOCK_SIZE * sizeof(float));
231     for (int u = 1; u < mid; u++)
232     {
233         for (int i = 0; i < CBOX_BLOCK_SIZE; i++)
234             s->legs[u].buffer[i] = 0.f;
235         for (int i = 0; i < CBOX_BLOCK_SIZE; i++)
236             s->legs[u + mid].buffer[i] = 0.f;
237     }
238         
239     for (int u = 0; u < s->leg_count; u++)
240         cbox_reverb_process_leg(m, u);
241
242     for (int i = 0; i < CBOX_BLOCK_SIZE; i++)
243         outputs[0][i] = inputs[0][i] * dryamt + s->legs[mid - 1].buffer[i] * wetamt;
244     for (int i = 0; i < CBOX_BLOCK_SIZE; i++)
245         outputs[1][i] = inputs[1][i] * dryamt + s->legs[s->leg_count - 1].buffer[i] * wetamt;
246     m->pos += CBOX_BLOCK_SIZE;
247 }
248
249 static void reverb_destroyfunc(struct cbox_module *module_)
250 {
251     struct reverb_module *m = (struct reverb_module *)module_;
252     free(m->params);
253     for (int i = 0; i < m->state->leg_count; i++)
254         cbox_reverb_leg_cleanup(&m->state->legs[i]);
255     free(m->state->legs);
256     free(m->state);
257 }
258
259 static struct reverb_state *create_reverb_state(int leg_count, ...)
260 {
261     struct reverb_state *state = malloc(sizeof(struct reverb_state));
262     state->leg_count = leg_count;
263     state->legs = malloc(state->leg_count * sizeof(struct cbox_reverb_leg));
264     va_list va;
265     va_start(va, leg_count);
266     state->total_time = 0;
267     for (int u = 0; u < state->leg_count; u++)
268     {
269         int delay_length = va_arg(va, int);
270         int allpasses = va_arg(va, int);
271         state->total_time += delay_length;
272         state->legs[u].params = leg_params_new(delay_length, allpasses, NULL);
273         for (int i = 0; i < allpasses; i++)
274         {
275             struct allpass_param *ap = &state->legs[u].params->allpasses[i];
276             ap->delay = va_arg(va, int);
277             ap->diffusion = va_arg(va, double);
278             state->total_time += ap->delay * ap->diffusion; // very rough approximation
279         }
280     }
281     va_end(va);
282     for (int u = 0; u < state->leg_count; u++)
283         cbox_reverb_leg_init(&state->legs[u]);
284     return state;
285 }
286
287 MODULE_CREATE_FUNCTION(reverb)
288 {
289     static int inited = 0;
290     if (!inited)
291     {
292         inited = 1;
293     }
294     
295     struct reverb_module *m = malloc(sizeof(struct reverb_module));
296     CALL_MODULE_INIT(m, 2, 2, reverb);
297     m->module.process_event = reverb_process_event;
298     m->module.process_block = reverb_process_block;
299     m->pos = 0;
300     m->old_params = NULL;
301     m->params = malloc(sizeof(struct reverb_params));
302     m->params->decay_time = cbox_config_get_float(cfg_section, "decay_time", 1000);
303     m->params->dryamt = cbox_config_get_gain_db(cfg_section, "dry_gain", 0.f);
304     m->params->wetamt = cbox_config_get_gain_db(cfg_section, "wet_gain", -6.f);
305     
306     m->state = create_reverb_state(4, 
307         133, 3, 
308             731, 0.45,
309             873, 0.5,
310             1215, 0.55,
311         461, 3,
312             1054, 0.5,
313             1519, 0.5,
314             973, 0.5,
315         251, 3, 
316             617, 0.45,
317             941, 0.5,
318             1277, 0.55,
319         379, 3,
320             1119, 0.5,
321             1477, 0.5,
322             933, 0.5);
323
324 #if 0
325     m->state = create_reverb_state(2, 
326         133, 6, 
327             1573, 0.35,
328             587, 0.35,
329             921, 0.45,
330             605, 0.5,
331             1051, 0.45,
332             397, 0.5,
333         251, 6, 
334             1561, 0.35,
335             594, 0.35,
336             927, 0.55,
337             611, 0.5,
338             1147, 0.55,
339             393, 0.5);
340 #endif
341     
342     m->params->lowpass = cbox_config_get_float(cfg_section, "lowpass", 8000.f);
343     m->params->highpass = cbox_config_get_float(cfg_section, "highpass", 35.f);
344     
345     return &m->module;
346 }
347
348 struct cbox_module_keyrange_metadata reverb_keyranges[] = {
349 };
350
351 struct cbox_module_livecontroller_metadata reverb_controllers[] = {
352 };
353
354 DEFINE_MODULE(reverb, 2, 2)
355