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/>.
20 #include "config-api.h"
23 #include "onepole-float.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
44 struct cbox_reverb_leg_params
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;
68 for (int i = 0; i < allpasses; i++)
69 memcpy(&p->allpasses[i], &allpass_params[i], sizeof(struct allpass_param));
75 static void cbox_reverb_leg_reset(struct cbox_reverb_leg *leg)
77 cbox_onepolef_reset(&leg->filter_state);
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)
95 free(leg->allpass_storage);
98 #define MODULE_PARAMS reverb_params
105 float lowpass, highpass;
110 struct cbox_reverb_leg *legs;
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;
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))
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);
147 return cbox_object_default_process_cmd(ct, fb, cmd, error);
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)
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;
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);
177 int units = b->params->allpass_units;
178 for (int a = 0; a < units; a++)
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++)
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;
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];
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));
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_;
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);
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));
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
282 for (int u = 0; u < state->leg_count; u++)
283 cbox_reverb_leg_init(&state->legs[u]);
287 MODULE_CREATE_FUNCTION(reverb)
289 static int inited = 0;
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;
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,
325 m->state = create_reverb_state(2,
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);
348 struct cbox_module_keyrange_metadata reverb_keyranges[] = {
351 struct cbox_module_livecontroller_metadata reverb_controllers[] = {
354 DEFINE_MODULE(reverb, 2, 2)