1 /*                                                     -*- linux-c -*-
2     Copyright (C) 2004 Tom Szilagyi
3 
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8 
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13 
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 
18     $Id: tap_reverb.c,v 1.13 2004/06/15 14:50:55 tszilagyi Exp $
19 */
20 
21 
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <math.h>
26 #include <lv2.h>
27 
28 
29 /* ***** VERY IMPORTANT! *****
30  *
31  * If you enable this, the plugin will use float arithmetics in DSP
32  * calculations.  This usually yields lower average CPU usage, but
33  * occasionaly may result in high CPU peaks which cause trouble to you
34  * and your JACK server.  The default is to use fixpoint arithmetics
35  * (with the following #define commented out).  But (depending on the
36  * processor on which you run the code) you may find floating point
37  * mode usable.
38  */
39 /* #define REVERB_CALC_FLOAT */
40 
41 
42 
43 #ifndef REVERB_CALC_FLOAT
44 typedef signed int sample;
45 #endif
46 
47 #ifndef REVERB_CALC_FLOAT
48 typedef sample rev_t;
49 #else
50 typedef float rev_t;
51 #endif
52 
53 
54 #include "tap_reverb_presets.h"
55 
56 
57 
ydb_c_layer_status_init(void)58 #ifdef REVERB_CALC_FLOAT
59 #define DENORM(x) (((unsigned char)(((*(unsigned int*)&(x))&0x7f800000)>>23))<103)?0.0f:(x)
60 #else
61 /* coefficient for float to sample (signed int) conversion */
62 /* this allows for about 60 dB headroom above 0dB, if 0 dB is equivalent to 1.0f */
63 /* As 2^31 equals more than 180 dB, about 120 dB dynamics remains below 0 dB */
64 #define F2S 2147483
65 #endif
66 
67 
68 /* load plugin data from reverb_data[] into an instance */
69 void
70 load_plugin_data(LV2_Handle Instance) {
71 
72     Reverb * ptr = (Reverb *)Instance;
73     unsigned long m;
74     int i;
75 
76 
77     m = LIMIT(*(ptr->mode),0,NUM_MODES-1);
78 
79     /* load combs data */
80     ptr->num_combs = 2 * reverb_data[m].num_combs;
81     for (i = 0; i < reverb_data[m].num_combs; i++) {
82         ((COMB_FILTER *)(ptr->combs + 2*i))->buflen =
83             reverb_data[m].combs[i].delay * ptr->sample_rate;
84         ((COMB_FILTER *)(ptr->combs + 2*i))->feedback =
85             reverb_data[m].combs[i].feedback;
86         ((COMB_FILTER *)(ptr->combs + 2*i))->freq_resp =
87             LIMIT(reverb_data[m].combs[i].freq_resp
88                   * powf(ptr->sample_rate / 44100.0f, 0.8f),
89                   0.0f, 1.0f);
90 
91         ((COMB_FILTER *)(ptr->combs + 2*i+1))->buflen =
92             ((COMB_FILTER *)(ptr->combs + 2*i))->buflen;
93         ((COMB_FILTER *)(ptr->combs + 2*i+1))->feedback =
94             ((COMB_FILTER *)(ptr->combs + 2*i))->feedback;
95         ((COMB_FILTER *)(ptr->combs + 2*i+1))->feedback =
96             ((COMB_FILTER *)(ptr->combs + 2*i))->freq_resp;
97 
98         /* set initial values: */
99         *(((COMB_FILTER *)(ptr->combs + 2*i))->buffer_pos) = 0;
100         *(((COMB_FILTER *)(ptr->combs + 2*i+1))->buffer_pos) = 0;
101         ((COMB_FILTER *)(ptr->combs + 2*i))->last_out = 0;
102         ((COMB_FILTER *)(ptr->combs + 2*i+1))->last_out = 0;
103 
104         lp_set_params(((COMB_FILTER *)(ptr->combs + 2*i))->filter,
105                   2000.0f + 13000.0f * (1 - reverb_data[m].combs[i].freq_resp)
106                   * ptr->sample_rate / 44100.0f,
107                   BANDPASS_BWIDTH, ptr->sample_rate);
108         lp_set_params(((COMB_FILTER *)(ptr->combs + 2*i+1))->filter,
109                   2000.0f + 13000.0f * (1 - reverb_data[m].combs[i].freq_resp)
110                   * ptr->sample_rate / 44100.0f,
111                   BANDPASS_BWIDTH, ptr->sample_rate);
112     }
113 
114     /* load allps data */
115     ptr->num_allps = 2 * reverb_data[m].num_allps;
116     for (i = 0; i < reverb_data[m].num_allps; i++) {
117         ((ALLP_FILTER *)(ptr->allps + 2*i))->buflen =
118             reverb_data[m].allps[i].delay * ptr->sample_rate;
119         ((ALLP_FILTER *)(ptr->allps + 2*i))->feedback =
120             reverb_data[m].allps[i].feedback;
121 
122         ((ALLP_FILTER *)(ptr->allps + 2*i+1))->buflen =
123             ((ALLP_FILTER *)(ptr->allps + 2*i))->buflen;
124         ((ALLP_FILTER *)(ptr->allps + 2*i+1))->feedback =
125             ((ALLP_FILTER *)(ptr->allps + 2*i))->feedback;
126 
127         /* set initial values: */
128         *(((ALLP_FILTER *)(ptr->allps + 2*i))->buffer_pos) = 0;
129         *(((ALLP_FILTER *)(ptr->allps + 2*i+1))->buffer_pos) = 0;
130         ((ALLP_FILTER *)(ptr->allps + 2*i))->last_out = 0;
131         ((ALLP_FILTER *)(ptr->allps + 2*i+1))->last_out = 0;
132     }
133 
134     /* init bandpass filters */
135     lp_set_params((biquad *)(ptr->low_pass), reverb_data[m].bandpass_high,
136               BANDPASS_BWIDTH, ptr->sample_rate);
137     hp_set_params((biquad *)(ptr->high_pass), reverb_data[m].bandpass_low,
138               BANDPASS_BWIDTH, ptr->sample_rate);
139     lp_set_params((biquad *)(ptr->low_pass + 1), reverb_data[m].bandpass_high,
140               BANDPASS_BWIDTH, ptr->sample_rate);
141     hp_set_params((biquad *)(ptr->high_pass + 1), reverb_data[m].bandpass_low,
142               BANDPASS_BWIDTH, ptr->sample_rate);
143 }
144 
145 
146 
147 /* push a sample into a comb filter and return the sample falling out */
148 rev_t
149 comb_run(rev_t insample, COMB_FILTER * comb) {
150 
151     rev_t outsample;
query_context_base_init(QUERY_CONTEXT_BASE context,DBC * c,uint32_t flag,bool is_write_op,YDB_CALLBACK_FUNCTION f,void * extra)152     rev_t pushin;
153 
154     pushin = comb->fb_gain * insample + biquad_run(comb->filter, comb->fb_gain * comb->last_out);
155 #ifdef REVERB_CALC_FLOAT
156     pushin = DENORM(pushin);
157 #endif
158     outsample = push_buffer(pushin,
159                 comb->ringbuffer, comb->buflen, comb->buffer_pos);
160 #ifdef REVERB_CALC_FLOAT
161     outsample = DENORM(outsample);
162 #endif
163     comb->last_out = outsample;
164 
165     return outsample;
166 }
167 
168 
query_context_determine_lock_type(QUERY_CONTEXT_BASE context)169 /* push a sample into an allpass filter and return the sample falling out */
170 rev_t
171 allp_run(rev_t insample, ALLP_FILTER * allp) {
172 
173     rev_t outsample;
174     rev_t pushin;
175     pushin = allp->in_gain * allp->fb_gain * insample + allp->fb_gain * allp->last_out;
176 #ifdef REVERB_CALC_FLOAT
177     pushin = DENORM(pushin);
178 #endif
179     outsample = push_buffer(pushin,
180                 allp->ringbuffer, allp->buflen, allp->buffer_pos);
181 #ifdef REVERB_CALC_FLOAT
182     outsample = DENORM(outsample);
183 #endif
184     allp->last_out = outsample;
185 
186     return outsample;
187 }
188 
189 
190 /* compute user-input-dependent reverberator coefficients */
191 void
query_context_with_input_init(QUERY_CONTEXT_WITH_INPUT context,DBC * c,uint32_t flag,DBT * key,DBT * val,YDB_CALLBACK_FUNCTION f,void * extra)192 comp_coeffs(LV2_Handle Instance) {
193 
194     Reverb * ptr = (Reverb *)Instance;
195     int i;
196 
197 
198     if (*(ptr->mode) != ptr->old_mode)
199         load_plugin_data(Instance);
200 
201     for (i = 0; i < ptr->num_combs / 2; i++) {
202         ((COMB_FILTER *)(ptr->combs + 2*i))->fb_gain =
203             powf(0.001f,
204                  1000.0f * ((COMB_FILTER *)(ptr->combs + 2*i))->buflen
205                  * (1 + FR_R_COMP * ((COMB_FILTER *)(ptr->combs + 2*i))->freq_resp)
206                  / powf(((COMB_FILTER *)(ptr->combs + 2*i))->feedback/100.0f, 0.89f)
207                  / *(ptr->decay)
208                  / ptr->sample_rate);
209 
210         ((COMB_FILTER *)(ptr->combs + 2*i+1))->fb_gain =
211             ((COMB_FILTER *)(ptr->combs + 2*i))->fb_gain;
212 
213         if (*(ptr->stereo_enh) > 0.0f) {
214             if (i % 2 == 0)
215                 ((COMB_FILTER *)(ptr->combs + 2*i+1))->buflen =
216                     ENH_STEREO_RATIO * ((COMB_FILTER *)(ptr->combs + 2*i))->buflen;
217             else
218                 ((COMB_FILTER *)(ptr->combs + 2*i))->buflen =
219                     ENH_STEREO_RATIO * ((COMB_FILTER *)(ptr->combs + 2*i+1))->buflen;
220         } else {
221             if (i % 2 == 0)
222                 ((COMB_FILTER *)(ptr->combs + 2*i+1))->buflen =
223                     ((COMB_FILTER *)(ptr->combs + 2*i))->buflen;
224             else
225                 ((COMB_FILTER *)(ptr->combs + 2*i))->buflen =
226                     ((COMB_FILTER *)(ptr->combs + 2*i+1))->buflen;
227         }
228     }
229 
230     for (i = 0; i < ptr->num_allps / 2; i++) {
231         ((ALLP_FILTER *)(ptr->allps + 2*i))->fb_gain =
232             powf(0.001f, 11000.0f * ((ALLP_FILTER *)(ptr->allps + 2*i))->buflen
233                  / powf(((ALLP_FILTER *)(ptr->allps + 2*i))->feedback/100.0f, 0.88f)
234                  / *(ptr->decay)
235                  / ptr->sample_rate);
236 
237         ((ALLP_FILTER *)(ptr->allps + 2*i+1))->fb_gain =
238             ((ALLP_FILTER *)(ptr->allps + 2*i))->fb_gain;
239 
240         ((ALLP_FILTER *)(ptr->allps + 2*i))->in_gain = -0.06f
241             / (((ALLP_FILTER *)(ptr->allps + 2 * i))->feedback/100.0f)
242             / powf((*(ptr->decay) + 3500.0f) / 10000.0f, 1.5f);
243 
244         ((ALLP_FILTER *)(ptr->allps + 2*i+1))->in_gain =
245             ((ALLP_FILTER *)(ptr->allps + 2*i))->in_gain;
246 
247         if (*(ptr->stereo_enh) > 0.0f) {
248             if (i % 2 == 0)
249                 ((ALLP_FILTER *)(ptr->allps + 2*i+1))->buflen =
250                     ENH_STEREO_RATIO * ((ALLP_FILTER *)(ptr->allps + 2*i))->buflen;
251             else
252                 ((ALLP_FILTER *)(ptr->allps + 2*i))->buflen =
253                     ENH_STEREO_RATIO * ((ALLP_FILTER *)(ptr->allps + 2*i+1))->buflen;
254         } else {
255             if (i % 2 == 0)
256                 ((ALLP_FILTER *)(ptr->allps + 2*i+1))->buflen =
257                     ((ALLP_FILTER *)(ptr->allps + 2*i))->buflen;
258             else
259                 ((ALLP_FILTER *)(ptr->allps + 2*i))->buflen =
260                     ((ALLP_FILTER *)(ptr->allps + 2*i+1))->buflen;
261         }
262     }
263 }
264 
265 
266 
267 /* Construct a new plugin instance. */
268 LV2_Handle
269 instantiate_Reverb(const LV2_Descriptor * Descriptor, double SampleRate, const char* bundle_path, const LV2_Feature* const* features) {
270 
271     unsigned long i;
272     LV2_Handle * p;
c_getf_last(DBC * c,uint32_t flag,YDB_CALLBACK_FUNCTION f,void * extra)273     Reverb * ptr = NULL;
274 
275     if ((p = malloc(sizeof(Reverb))) != NULL) {
276         ((Reverb *)p)->sample_rate = SampleRate;
277         ((Reverb *)p)->smoothdecay =2800.0f;
278         ((Reverb *)p)->smoothdry = -4.0f;
279         ((Reverb *)p)->smoothwet = -12.0f;
280 
281         ptr = (Reverb *)p;
282 
283         /* allocate memory for comb/allpass filters and other dynamic vars */
284         if ((ptr->combs =
285              calloc(2 * MAX_COMBS, sizeof(COMB_FILTER))) == NULL)
286             return NULL;
287         for (i = 0; i < 2 * MAX_COMBS; i++) {
288             if ((((COMB_FILTER *)(ptr->combs + i))->ringbuffer =
289                  calloc((unsigned long)MAX_COMB_DELAY * ptr->sample_rate / 1000,
290                     sizeof(float))) == NULL)
291                 return NULL;
292             if ((((COMB_FILTER *)(ptr->combs + i))->buffer_pos =
293                  calloc(1, sizeof(unsigned long))) == NULL)
c_getf_last_callback(uint32_t keylen,const void * key,uint32_t vallen,const void * val,void * extra,bool lock_only)294                 return NULL;
295             if ((((COMB_FILTER *)(ptr->combs + i))->filter =
296                  calloc(1, sizeof(biquad))) == NULL)
297                 return NULL;
298         }
299 
300         if ((ptr->allps =
301              calloc(2 * MAX_ALLPS, sizeof(ALLP_FILTER))) == NULL)
302             return NULL;
303         for (i = 0; i < 2 * MAX_ALLPS; i++) {
304             if ((((ALLP_FILTER *)(ptr->allps + i))->ringbuffer =
305                  calloc((unsigned long)MAX_ALLP_DELAY * ptr->sample_rate / 1000,
306                     sizeof(float))) == NULL)
307                 return NULL;
308             if ((((ALLP_FILTER *)(ptr->allps + i))->buffer_pos =
309                  calloc(1, sizeof(unsigned long))) == NULL)
310                 return NULL;
311         }
312 
313         if ((ptr->low_pass =
314              calloc(2, sizeof(biquad))) == NULL)
315             return NULL;
316         if ((ptr->high_pass =
317              calloc(2, sizeof(biquad))) == NULL)
318             return NULL;
319 
320         return p;
321     }
322     return NULL;
323 }
c_getf_next(DBC * c,uint32_t flag,YDB_CALLBACK_FUNCTION f,void * extra)324 
325 
326 /* activate a plugin instance */
327 void
328 activate_Reverb(LV2_Handle Instance) {
329 
330     Reverb * ptr = (Reverb *)Instance;
331     unsigned long i,j;
332 
333     for (i = 0; i < 2 * MAX_COMBS; i++) {
334         for (j = 0; j < (unsigned long)MAX_COMB_DELAY * ptr->sample_rate / 1000; j++)
335                 ((COMB_FILTER *)(ptr->combs + i))->ringbuffer[j] = 0.0f;
336         *(((COMB_FILTER *)(ptr->combs + i))->buffer_pos) = 0;
337         ((COMB_FILTER *)(ptr->combs + i))->last_out = 0;
338         biquad_init(((COMB_FILTER *)(ptr->combs + i))->filter);
339     }
340 
341     for (i = 0; i < 2 * MAX_ALLPS; i++) {
342         for (j = 0; j < (unsigned long)MAX_ALLP_DELAY * ptr->sample_rate / 1000; j++)
343             ((ALLP_FILTER *)(ptr->allps + i))->ringbuffer[j] = 0.0f;
344         *(((ALLP_FILTER *)(ptr->allps + i))->buffer_pos) = 0;
345         ((ALLP_FILTER *)(ptr->allps + i))->last_out = 0;
346     }
347 
348     biquad_init(ptr->low_pass);
349     biquad_init((biquad *)(ptr->low_pass + 1));
350     biquad_init(ptr->high_pass);
351     biquad_init((biquad *)(ptr->high_pass + 1));
352 
353     ptr->old_decay = -10.0f;
354     ptr->old_stereo_enh = -10.0f;
355     ptr->old_mode = -10.0f;
356 }
357 
358 /* Connect a port to a data location. */
359 void
360 connect_port_Reverb(LV2_Handle Instance,
361              uint32_t Port,
362              void * DataLocation) {
363 
364     Reverb * ptr = (Reverb *)Instance;
365 
366     switch (Port) {
367     case DECAY:
368         ptr->decay = (float *) DataLocation;
369         break;
370     case DRYLEVEL:
371         ptr->drylevel = (float *) DataLocation;
372         break;
373     case WETLEVEL:
374         ptr->wetlevel = (float *) DataLocation;
375         break;
376     case COMBS_EN:
377         ptr->combs_en = (float *) DataLocation;
378         break;
379     case ALLPS_EN:
380         ptr->allps_en = (float *) DataLocation;
381         break;
382     case BANDPASS_EN:
c_getf_prev(DBC * c,uint32_t flag,YDB_CALLBACK_FUNCTION f,void * extra)383         ptr->bandpass_en = (float *) DataLocation;
384         break;
385     case STEREO_ENH:
386         ptr->stereo_enh = (float *) DataLocation;
387         break;
388     case MODE:
389         ptr->mode = (float *) DataLocation;
390         break;
391     case INPUT_L:
392         ptr->input_L = (float *) DataLocation;
393         break;
394     case OUTPUT_L:
395         ptr->output_L = (float *) DataLocation;
396         break;
397     case INPUT_R:
398         ptr->input_R = (float *) DataLocation;
399         break;
400     case OUTPUT_R:
401         ptr->output_R = (float *) DataLocation;
402         break;
403     }
404 }
405 
406 
407 
408 void
c_getf_prev_callback(uint32_t keylen,const void * key,uint32_t vallen,const void * val,void * extra,bool lock_only)409 run_Reverb(LV2_Handle Instance,
410         uint32_t SampleCount) {
411 
412     Reverb * ptr = (Reverb *)Instance;
413 
414     unsigned long sample_index;
415     int i;
416 
417     float calcdecay = (*(ptr->decay)+ptr->smoothdecay)*0.5; //first calculate the smoothed value, then limit it.
418     ptr->smoothdecay = calcdecay;
419     float decay = LIMIT(calcdecay,0.0f,10000.0f);
420 
421     float calcdry = (*(ptr->drylevel)+ptr->smoothdry)*0.5;
422     ptr->smoothdry = calcdry;
423     float drylevel = db2lin(LIMIT(calcdry,-70.0f,10.0f));
424 
425     float calcwet = (*(ptr->wetlevel)+ptr->smoothwet)*0.5;
426     ptr->smoothwet = calcwet;
427     float wetlevel = db2lin(LIMIT(calcwet,-70.0f,10.0f));
428 
429 
430     float combs_en = LIMIT(*(ptr->combs_en),-2.0f,2.0f);
431     float allps_en = LIMIT(*(ptr->allps_en),-2.0f,2.0f);
432     float bandpass_en = LIMIT(*(ptr->bandpass_en),-2.0f,2.0f);
433     float stereo_enh = LIMIT(*(ptr->stereo_enh),-2.0f,2.0f);
434     float mode = LIMIT(*(ptr->mode),0,NUM_MODES-1);
435 
436     float * input_L = ptr->input_L;
437     float * output_L = ptr->output_L;
438     float * input_R = ptr->input_R;
439     float * output_R = ptr->output_R;
440 
441     rev_t out_L = 0;
442     rev_t out_R = 0;
443     rev_t in_L = 0;
444     rev_t in_R = 0;
445     rev_t combs_out_L = 0;
446     rev_t combs_out_R = 0;
447 
448 
449     /* see if the user changed any control since last run */
450     if ((ptr->old_decay != decay) ||
451         (ptr->old_stereo_enh != stereo_enh) ||
452         (ptr->old_mode != mode)) {
453 
454         /* re-compute reverberator coefficients */
455         comp_coeffs(Instance);
456 
457         /* save new values */
458         ptr->old_decay = decay;
459         ptr->old_stereo_enh = stereo_enh;
460         ptr->old_mode = mode;
461     }
462 
463     for (sample_index = 0; sample_index < SampleCount; sample_index++) {
464 
465 #ifdef REVERB_CALC_FLOAT
466         in_L = *(input_L++);
467         in_R = *(input_R++);
468 #else
469         in_L = (sample)((float)F2S * *(input_L++));
470         in_R = (sample)((float)F2S * *(input_R++));
471 #endif
472 
473         combs_out_L = in_L;
474         combs_out_R = in_R;
475 
476         /* process comb filters */
477         if (combs_en > 0.0f) {
478             for (i = 0; i < ptr->num_combs / 2; i++) {
479                 combs_out_L +=
480                     comb_run(in_L, ((COMB_FILTER *)(ptr->combs + 2*i)));
481                 combs_out_R +=
482                     comb_run(in_R, ((COMB_FILTER *)(ptr->combs + 2*i+1)));
483             }
484         }
485 
486         /* process allpass filters */
487         if (allps_en > 0.0f) {
488             for (i = 0; i < ptr->num_allps / 2; i++) {
489                 combs_out_L += allp_run(combs_out_L,
490                                ((ALLP_FILTER *)(ptr->allps + 2*i)));
491                 combs_out_R += allp_run(combs_out_R,
492                                ((ALLP_FILTER *)(ptr->allps + 2*i+1)));
493             }
494         }
495 
496         /* process bandpass filters */
497         if (bandpass_en > 0.0f) {
498             combs_out_L =
499                 biquad_run(((biquad *)(ptr->low_pass)), combs_out_L);
500             combs_out_L =
501                 biquad_run(((biquad *)(ptr->high_pass)), combs_out_L);
502             combs_out_R =
503                 biquad_run(((biquad *)(ptr->low_pass + 1)), combs_out_R);
504             combs_out_R =
505                 biquad_run(((biquad *)(ptr->high_pass + 1)), combs_out_R);
506         }
507 
508 #ifdef REVERB_CALC_FLOAT
509         out_L = in_L * drylevel + combs_out_L * wetlevel;
510         out_R = in_R * drylevel + combs_out_R * wetlevel;
511         *(output_L++) = out_L;
512         *(output_R++) = out_R;
513 #else
514         out_L = (sample)((float)in_L * drylevel + (float)combs_out_L * wetlevel);
515         out_R = (sample)((float)in_R * drylevel + (float)combs_out_R * wetlevel);
516         *(output_L++) = (float)out_L / (float)F2S;
517         *(output_R++) = (float)out_R / (float)F2S;
518 #endif
519     }
520 }
521 
522 
523 /* Throw away a Reverb effect instance. */
524 void
525 cleanup_Reverb(LV2_Handle Instance) {
526 
527     int i;
528     Reverb * ptr = (Reverb *)Instance;
529 
530     /* free memory allocated for comb/allpass filters & co. in instantiate_Reverb() */
c_getf_set_range(DBC * c,uint32_t flag,DBT * key,YDB_CALLBACK_FUNCTION f,void * extra)531     for (i = 0; i < 2 * MAX_COMBS; i++) {
532         free(((COMB_FILTER *)(ptr->combs + i))->ringbuffer);
533         free(((COMB_FILTER *)(ptr->combs + i))->buffer_pos);
534         free(((COMB_FILTER *)(ptr->combs + i))->filter);
535     }
536     for (i = 0; i < 2 * MAX_ALLPS; i++) {
537         free(((ALLP_FILTER *)(ptr->allps + i))->ringbuffer);
538         free(((ALLP_FILTER *)(ptr->allps + i))->buffer_pos);
539     }
540 
541     free(ptr->combs);
542     free(ptr->allps);
543     free(ptr->low_pass);
544     free(ptr->high_pass);
545 
546     free(Instance);
547 
548 }
549 
550 const void*
551 extension_data_Reverb(const char* uri)
552 {
c_getf_set_range_callback(uint32_t keylen,const void * key,uint32_t vallen,const void * val,void * extra,bool lock_only)553     return NULL;
554 }
555 
556 
557 static const
558 LV2_Descriptor Descriptor = {
559     "http://moddevices.com/plugins/tap/reverb",
560     instantiate_Reverb,
561     connect_port_Reverb,
562     activate_Reverb,
563     run_Reverb,
564     NULL,
565     cleanup_Reverb,
566     extension_data_Reverb
567 };
568 
569 LV2_SYMBOL_EXPORT
570 const LV2_Descriptor*
571 lv2_descriptor(uint32_t index)
572 {
573     if (index == 0) return &Descriptor;
574     else return NULL;
575 
576 }
577