Merge pull request #1 from atsampson/master
[calfbox.git] / reverb.c
blobd490d3cb47bd4d92c0ac99758e1352e852e45978
1 /*
2 Calf Box, an open source musical instrument.
3 Copyright (C) 2010-2011 Krzysztof Foltman
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.
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.
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/>.
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>
32 // The reverb structure is based on this article:
33 // http://www.spinsemi.com/knowledge_base/effects.html#Reverberation
35 #define DELAY_BUFFER 1024
36 #define ALLPASS_BUFFER 2048
38 struct allpass_param
40 int delay;
41 float diffusion;
44 struct cbox_reverb_leg_params
46 int delay_length;
47 int allpass_units;
48 struct allpass_param allpasses[0];
51 struct cbox_reverb_leg
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];
60 static struct cbox_reverb_leg_params *leg_params_new(int delay_length, int allpasses, const struct allpass_param *allpass_params)
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;
66 if (allpass_params)
68 for (int i = 0; i < allpasses; i++)
69 memcpy(&p->allpasses[i], &allpass_params[i], sizeof(struct allpass_param));
72 return p;
75 static void cbox_reverb_leg_reset(struct cbox_reverb_leg *leg)
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;
86 static void cbox_reverb_leg_init(struct cbox_reverb_leg *leg)
88 leg->allpass_storage = malloc(leg->params->allpass_units * ALLPASS_BUFFER * sizeof(float));
89 cbox_reverb_leg_reset(leg);
92 static void cbox_reverb_leg_cleanup(struct cbox_reverb_leg *leg)
94 free(leg->params);
95 free(leg->allpass_storage);
98 #define MODULE_PARAMS reverb_params
100 struct reverb_params
102 float decay_time;
103 float wetamt;
104 float dryamt;
105 float lowpass, highpass;
108 struct reverb_state
110 struct cbox_reverb_leg *legs;
111 int leg_count;
112 int total_time;
115 struct reverb_module
117 struct cbox_module module;
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;
126 gboolean reverb_process_cmd(struct cbox_command_target *ct, struct cbox_command_target *fb, struct cbox_osc_command *cmd, GError **error)
128 struct reverb_module *m = (struct reverb_module *)ct->user_data;
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, ""))
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);
146 else
147 return cbox_object_default_process_cmd(ct, fb, cmd, error);
148 return TRUE;
151 void reverb_process_event(struct cbox_module *module, const uint8_t *data, uint32_t len)
153 // struct reverb_module *m = (struct reverb_module *)module;
156 static void cbox_reverb_process_leg(struct reverb_module *m, int u)
158 int pos;
159 int dv;
160 float *storage;
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];
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++)
173 buf[i] += cbox_onepolef_process_sample(&b->filter_state, &m->filter_coeffs[u&1], storage[pos & (DELAY_BUFFER - 1)] * gain);
174 pos++;
177 int units = b->params->allpass_units;
178 for (int a = 0; a < units; a++)
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++)
186 float dry = buf[i];
187 float out = dry;
189 float delayed = storage[pos & (ALLPASS_BUFFER - 1)];
191 float feedback = sanef(out - w * delayed);
193 buf[i] = sanef(feedback * w + delayed);
195 storage[(pos + dv) & (ALLPASS_BUFFER - 1)] = feedback;
196 pos++;
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++)
204 storage[(pos + dv) & (DELAY_BUFFER - 1)] = buf[i];
205 pos++;
209 void reverb_process_block(struct cbox_module *module, cbox_sample_t **inputs, cbox_sample_t **outputs)
211 struct reverb_module *m = (struct reverb_module *)module;
212 struct reverb_params *p = m->params;
214 float dryamt = p->dryamt;
215 float wetamt = p->wetamt;
216 struct reverb_state *s = m->state;
218 if (p != m->old_params)
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;
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++)
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;
239 for (int u = 0; u < s->leg_count; u++)
240 cbox_reverb_process_leg(m, u);
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;
249 static void reverb_destroyfunc(struct cbox_module *module_)
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);
259 static struct reverb_state *create_reverb_state(int leg_count, ...)
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++)
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++)
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
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;
287 MODULE_CREATE_FUNCTION(reverb)
289 static int inited = 0;
290 if (!inited)
292 inited = 1;
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);
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);
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
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);
345 return &m->module;
348 struct cbox_module_keyrange_metadata reverb_keyranges[] = {
351 struct cbox_module_livecontroller_metadata reverb_controllers[] = {
354 DEFINE_MODULE(reverb, 2, 2)