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)