1 /* Reverb Library
2 * Verblib version 0.4 - 2021-01-23
3 *
4 * Philip Bennefall - philip@blastbay.com
5 *
6 * See the end of this file for licensing terms.
7 * This reverb is based on Freeverb, a public domain reverb written by Jezar at Dreampoint.
8 *
9 * IMPORTANT: The reverb currently only works with 1 or 2 channels, at sample rates of 22050 HZ and above.
10 * These restrictions may be lifted in a future version.
11 *
12 * USAGE
13 *
14 * This is a single-file library. To use it, do something like the following in one .c file.
15 * #define VERBLIB_IMPLEMENTATION
16 * #include "verblib.h"
17 *
18 * You can then #include this file in other parts of the program as you would with any other header file.
19 */
20 
21 #ifndef VERBLIB_H
22 #define VERBLIB_H
23 
24 #ifdef __cplusplus
25 extern "C" {
26 #endif
27 
28     /* COMPILE-TIME OPTIONS */
29 
30     /* The maximum sample rate that should be supported, specified as a multiple of 44100. */
31 #ifndef verblib_max_sample_rate_multiplier
32 #define verblib_max_sample_rate_multiplier 4
33 #endif
34 
35     /* The silence threshold which is used when calculating decay time. */
36 #ifndef verblib_silence_threshold
37 #define verblib_silence_threshold 80.0 /* In dB (absolute). */
38 #endif
39 
40     /* PUBLIC API */
41 
42     typedef struct verblib verblib;
43 
44     /* Initialize a verblib structure.
45     *
46     * Call this function to initialize the verblib structure.
47     * Returns nonzero (true) on success or 0 (false) on failure.
48     * The function will only fail if one or more of the parameters are invalid.
49     */
50     int verblib_initialize ( verblib* verb, unsigned long sample_rate, unsigned int channels );
51 
52     /* Run the reverb.
53     *
54     * Call this function continuously to generate your output.
55     * output_buffer may be the same pointer as input_buffer if in place processing is desired.
56     * frames specifies the number of sample frames that should be processed.
57     */
58     void verblib_process ( verblib* verb, const float* input_buffer, float* output_buffer, unsigned long frames );
59 
60     /* Set the size of the room, between 0.0 and 1.0. */
61     void verblib_set_room_size ( verblib* verb, float value );
62 
63     /* Get the size of the room. */
64     float verblib_get_room_size ( const verblib* verb );
65 
66     /* Set the amount of damping, between 0.0 and 1.0. */
67     void verblib_set_damping ( verblib* verb, float value );
68 
69     /* Get the amount of damping. */
70     float verblib_get_damping ( const verblib* verb );
71 
72     /* Set the stereo width of the reverb, between 0.0 and 1.0. */
73     void verblib_set_width ( verblib* verb, float value );
74 
75     /* Get the stereo width of the reverb. */
76     float verblib_get_width ( const verblib* verb );
77 
78     /* Set the volume of the wet signal, between 0.0 and 1.0. */
79     void verblib_set_wet ( verblib* verb, float value );
80 
81     /* Get the volume of the wet signal. */
82     float verblib_get_wet ( const verblib* verb );
83 
84     /* Set the volume of the dry signal, between 0.0 and 1.0. */
85     void verblib_set_dry ( verblib* verb, float value );
86 
87     /* Get the volume of the dry signal. */
88     float verblib_get_dry ( const verblib* verb );
89 
90     /* Set the mode of the reverb, where values below 0.5 mean normal and values above mean frozen. */
91     void verblib_set_mode ( verblib* verb, float value );
92 
93     /* Get the mode of the reverb. */
94     float verblib_get_mode ( const verblib* verb );
95 
96     /* Get the decay time in sample frames based on the current room size setting. */
97     /* If freeze mode is active, the decay time is infinite and this function returns 0. */
98     unsigned long verblib_get_decay_time_in_frames ( const verblib* verb );
99 
100     /* INTERNAL STRUCTURES */
101 
102     /* Allpass filter */
103     typedef struct verblib_allpass verblib_allpass;
104     struct verblib_allpass
105     {
106         float* buffer;
107         float feedback;
108         int  bufsize;
109         int  bufidx;
110     };
111 
112     /* Comb filter */
113     typedef struct verblib_comb verblib_comb;
114     struct verblib_comb
115     {
116         float* buffer;
117         float feedback;
118         float filterstore;
119         float damp1;
120         float damp2;
121         int  bufsize;
122         int  bufidx;
123     };
124 
125     /* Reverb model tuning values */
126 #define verblib_numcombs 8
127 #define verblib_numallpasses 4
128 #define verblib_muted 0.0f
129 #define verblib_fixedgain 0.015f
130 #define verblib_scalewet 3.0f
131 #define verblib_scaledry 2.0f
132 #define verblib_scaledamp 0.8f
133 #define verblib_scaleroom 0.28f
134 #define verblib_offsetroom 0.7f
135 #define verblib_initialroom 0.5f
136 #define verblib_initialdamp 0.25f
137 #define verblib_initialwet 1.0f/verblib_scalewet
138 #define verblib_initialdry 0.0f
139 #define verblib_initialwidth 1.0f
140 #define verblib_initialmode 0.0f
141 #define verblib_freezemode 0.5f
142 #define verblib_stereospread 23
143 
144     /*
145     * These values assume 44.1KHz sample rate, but will be verblib_scaled appropriately.
146     * The values were obtained by listening tests.
147     */
148 #define verblib_combtuningL1 1116
149 #define verblib_combtuningR1 (1116+verblib_stereospread)
150 #define verblib_combtuningL2 1188
151 #define verblib_combtuningR2 (1188+verblib_stereospread)
152 #define verblib_combtuningL3 1277
153 #define verblib_combtuningR3 (1277+verblib_stereospread)
154 #define verblib_combtuningL4 1356
155 #define verblib_combtuningR4 (1356+verblib_stereospread)
156 #define verblib_combtuningL5 1422
157 #define verblib_combtuningR5 (1422+verblib_stereospread)
158 #define verblib_combtuningL6 1491
159 #define verblib_combtuningR6 (1491+verblib_stereospread)
160 #define verblib_combtuningL7 1557
161 #define verblib_combtuningR7 (1557+verblib_stereospread)
162 #define verblib_combtuningL8 1617
163 #define verblib_combtuningR8 (1617+verblib_stereospread)
164 #define verblib_allpasstuningL1 556
165 #define verblib_allpasstuningR1 (556+verblib_stereospread)
166 #define verblib_allpasstuningL2 441
167 #define verblib_allpasstuningR2 (441+verblib_stereospread)
168 #define verblib_allpasstuningL3 341
169 #define verblib_allpasstuningR3 (341+verblib_stereospread)
170 #define verblib_allpasstuningL4 225
171 #define verblib_allpasstuningR4 (225+verblib_stereospread)
172 
173     /* The main reverb structure. This is the structure that you will create an instance of when using the reverb. */
174     struct verblib
175     {
176         unsigned int channels;
177         float gain;
178         float roomsize, roomsize1;
179         float damp, damp1;
180         float wet, wet1, wet2;
181         float dry;
182         float width;
183         float mode;
184 
185         /*
186         * The following are all declared inline
187         * to remove the need for dynamic allocation.
188         */
189 
190         /* Comb filters */
191         verblib_comb combL[verblib_numcombs];
192         verblib_comb combR[verblib_numcombs];
193 
194         /* Allpass filters */
195         verblib_allpass allpassL[verblib_numallpasses];
196         verblib_allpass allpassR[verblib_numallpasses];
197 
198         /* Buffers for the combs */
199         float bufcombL1[verblib_combtuningL1* verblib_max_sample_rate_multiplier];
200         float bufcombR1[verblib_combtuningR1* verblib_max_sample_rate_multiplier];
201         float bufcombL2[verblib_combtuningL2* verblib_max_sample_rate_multiplier];
202         float bufcombR2[verblib_combtuningR2* verblib_max_sample_rate_multiplier];
203         float bufcombL3[verblib_combtuningL3* verblib_max_sample_rate_multiplier];
204         float bufcombR3[verblib_combtuningR3* verblib_max_sample_rate_multiplier];
205         float bufcombL4[verblib_combtuningL4* verblib_max_sample_rate_multiplier];
206         float bufcombR4[verblib_combtuningR4* verblib_max_sample_rate_multiplier];
207         float bufcombL5[verblib_combtuningL5* verblib_max_sample_rate_multiplier];
208         float bufcombR5[verblib_combtuningR5* verblib_max_sample_rate_multiplier];
209         float bufcombL6[verblib_combtuningL6* verblib_max_sample_rate_multiplier];
210         float bufcombR6[verblib_combtuningR6* verblib_max_sample_rate_multiplier];
211         float bufcombL7[verblib_combtuningL7* verblib_max_sample_rate_multiplier];
212         float bufcombR7[verblib_combtuningR7* verblib_max_sample_rate_multiplier];
213         float bufcombL8[verblib_combtuningL8* verblib_max_sample_rate_multiplier];
214         float bufcombR8[verblib_combtuningR8* verblib_max_sample_rate_multiplier];
215 
216         /* Buffers for the allpasses */
217         float bufallpassL1[verblib_allpasstuningL1* verblib_max_sample_rate_multiplier];
218         float bufallpassR1[verblib_allpasstuningR1* verblib_max_sample_rate_multiplier];
219         float bufallpassL2[verblib_allpasstuningL2* verblib_max_sample_rate_multiplier];
220         float bufallpassR2[verblib_allpasstuningR2* verblib_max_sample_rate_multiplier];
221         float bufallpassL3[verblib_allpasstuningL3* verblib_max_sample_rate_multiplier];
222         float bufallpassR3[verblib_allpasstuningR3* verblib_max_sample_rate_multiplier];
223         float bufallpassL4[verblib_allpasstuningL4* verblib_max_sample_rate_multiplier];
224         float bufallpassR4[verblib_allpasstuningR4* verblib_max_sample_rate_multiplier];
225     };
226 
227 #ifdef __cplusplus
228 }
229 #endif
230 
231 #endif  /* VERBLIB_H */
232 
233 /* IMPLEMENTATION */
234 
235 #ifdef VERBLIB_IMPLEMENTATION
236 
237 #include <stddef.h>
238 #include <math.h>
239 
240 #ifdef _MSC_VER
241 #define VERBLIB_INLINE __forceinline
242 #else
243 #ifdef __GNUC__
244 #define VERBLIB_INLINE inline __attribute__((always_inline))
245 #else
246 #define VERBLIB_INLINE inline
247 #endif
248 #endif
249 
250 #define undenormalise(sample) sample+=1.0f; sample-=1.0f;
251 
252 /* Allpass filter */
verblib_allpass_initialize(verblib_allpass * allpass,float * buf,int size)253 static void verblib_allpass_initialize ( verblib_allpass* allpass, float* buf, int size )
254 {
255     allpass->buffer = buf;
256     allpass->bufsize = size;
257     allpass->bufidx = 0;
258 }
259 
verblib_allpass_process(verblib_allpass * allpass,float input)260 static VERBLIB_INLINE float verblib_allpass_process ( verblib_allpass* allpass, float input )
261 {
262     float output;
263     float bufout;
264 
265     bufout = allpass->buffer[allpass->bufidx];
266     undenormalise ( bufout );
267 
268     output = -input + bufout;
269     allpass->buffer[allpass->bufidx] = input + ( bufout * allpass->feedback );
270 
271     if ( ++allpass->bufidx >= allpass->bufsize )
272     {
273         allpass->bufidx = 0;
274     }
275 
276     return output;
277 }
278 
verblib_allpass_mute(verblib_allpass * allpass)279 static void verblib_allpass_mute ( verblib_allpass* allpass )
280 {
281     int i;
282     for ( i = 0; i < allpass->bufsize; i++ )
283     {
284         allpass->buffer[i] = 0.0f;
285     }
286 }
287 
288 /* Comb filter */
verblib_comb_initialize(verblib_comb * comb,float * buf,int size)289 static void verblib_comb_initialize ( verblib_comb* comb, float* buf, int size )
290 {
291     comb->buffer = buf;
292     comb->bufsize = size;
293     comb->filterstore = 0.0f;
294     comb->bufidx = 0;
295 }
296 
verblib_comb_mute(verblib_comb * comb)297 static void verblib_comb_mute ( verblib_comb* comb )
298 {
299     int i;
300     for ( i = 0; i < comb->bufsize; i++ )
301     {
302         comb->buffer[i] = 0.0f;
303     }
304 }
305 
verblib_comb_set_damp(verblib_comb * comb,float val)306 static void verblib_comb_set_damp ( verblib_comb* comb, float val )
307 {
308     comb->damp1 = val;
309     comb->damp2 = 1.0f - val;
310 }
311 
verblib_comb_process(verblib_comb * comb,float input)312 static VERBLIB_INLINE float verblib_comb_process ( verblib_comb* comb, float input )
313 {
314     float output;
315 
316     output = comb->buffer[comb->bufidx];
317     undenormalise ( output );
318 
319     comb->filterstore = ( output * comb->damp2 ) + ( comb->filterstore * comb->damp1 );
320     undenormalise ( comb->filterstore );
321 
322     comb->buffer[comb->bufidx] = input + ( comb->filterstore * comb->feedback );
323 
324     if ( ++comb->bufidx >= comb->bufsize )
325     {
326         comb->bufidx = 0;
327     }
328 
329     return output;
330 }
331 
verblib_update(verblib * verb)332 static void verblib_update ( verblib* verb )
333 {
334     /* Recalculate internal values after parameter change. */
335 
336     int i;
337 
338     verb->wet1 = verb->wet * ( verb->width / 2.0f + 0.5f );
339     verb->wet2 = verb->wet * ( ( 1.0f - verb->width ) / 2.0f );
340 
341     if ( verb->mode >= verblib_freezemode )
342     {
343         verb->roomsize1 = 1.0f;
344         verb->damp1 = 0.0f;
345         verb->gain = verblib_muted;
346     }
347     else
348     {
349         verb->roomsize1 = verb->roomsize;
350         verb->damp1 = verb->damp;
351         verb->gain = verblib_fixedgain;
352     }
353 
354     for ( i = 0; i < verblib_numcombs; i++ )
355     {
356         verb->combL[i].feedback = verb->roomsize1;
357         verb->combR[i].feedback = verb->roomsize1;
358         verblib_comb_set_damp ( &verb->combL[i], verb->damp1 );
359         verblib_comb_set_damp ( &verb->combR[i], verb->damp1 );
360     }
361 
362 }
363 
verblib_mute(verblib * verb)364 static void verblib_mute ( verblib* verb )
365 {
366     int i;
367     if ( verblib_get_mode ( verb ) >= verblib_freezemode )
368     {
369         return;
370     }
371 
372     for ( i = 0; i < verblib_numcombs; i++ )
373     {
374         verblib_comb_mute ( &verb->combL[i] );
375         verblib_comb_mute ( &verb->combR[i] );
376     }
377     for ( i = 0; i < verblib_numallpasses; i++ )
378     {
379         verblib_allpass_mute ( &verb->allpassL[i] );
380         verblib_allpass_mute ( &verb->allpassR[i] );
381     }
382 }
383 
verblib_get_verblib_scaled_buffer_size(unsigned long sample_rate,unsigned long value)384 static int verblib_get_verblib_scaled_buffer_size ( unsigned long sample_rate, unsigned long value )
385 {
386     long double result = ( long double ) sample_rate;
387     result /= 44100.0;
388     result = ( ( long double ) value ) * result;
389     if ( result < 1.0 )
390     {
391         result = 1.0;
392     }
393     return ( int ) result;
394 }
395 
verblib_initialize(verblib * verb,unsigned long sample_rate,unsigned int channels)396 int verblib_initialize ( verblib* verb, unsigned long sample_rate, unsigned int channels )
397 {
398     int i;
399 
400     if ( channels != 1 && channels != 2 )
401     {
402         return 0;    /* Currently supports only 1 or 2 channels. */
403     }
404     if ( sample_rate < 22050 )
405     {
406         return 0;    /* The minimum supported sample rate is 22050 HZ. */
407     }
408     else if ( sample_rate > 44100 * verblib_max_sample_rate_multiplier )
409     {
410         return 0; /* The sample rate is too high. */
411     }
412 
413     verb->channels = channels;
414 
415     /* Tie the components to their buffers. */
416     verblib_comb_initialize ( &verb->combL[0], verb->bufcombL1, verblib_get_verblib_scaled_buffer_size ( sample_rate, verblib_combtuningL1 ) );
417     verblib_comb_initialize ( &verb->combR[0], verb->bufcombR1, verblib_get_verblib_scaled_buffer_size ( sample_rate, verblib_combtuningR1 ) );
418     verblib_comb_initialize ( &verb->combL[1], verb->bufcombL2, verblib_get_verblib_scaled_buffer_size ( sample_rate, verblib_combtuningL2 ) );
419     verblib_comb_initialize ( &verb->combR[1], verb->bufcombR2, verblib_get_verblib_scaled_buffer_size ( sample_rate, verblib_combtuningR2 ) );
420     verblib_comb_initialize ( &verb->combL[2], verb->bufcombL3, verblib_get_verblib_scaled_buffer_size ( sample_rate, verblib_combtuningL3 ) );
421     verblib_comb_initialize ( &verb->combR[2], verb->bufcombR3, verblib_get_verblib_scaled_buffer_size ( sample_rate, verblib_combtuningR3 ) );
422     verblib_comb_initialize ( &verb->combL[3], verb->bufcombL4, verblib_get_verblib_scaled_buffer_size ( sample_rate, verblib_combtuningL4 ) );
423     verblib_comb_initialize ( &verb->combR[3], verb->bufcombR4, verblib_get_verblib_scaled_buffer_size ( sample_rate, verblib_combtuningR4 ) );
424     verblib_comb_initialize ( &verb->combL[4], verb->bufcombL5, verblib_get_verblib_scaled_buffer_size ( sample_rate, verblib_combtuningL5 ) );
425     verblib_comb_initialize ( &verb->combR[4], verb->bufcombR5, verblib_get_verblib_scaled_buffer_size ( sample_rate, verblib_combtuningR5 ) );
426     verblib_comb_initialize ( &verb->combL[5], verb->bufcombL6, verblib_get_verblib_scaled_buffer_size ( sample_rate, verblib_combtuningL6 ) );
427     verblib_comb_initialize ( &verb->combR[5], verb->bufcombR6, verblib_get_verblib_scaled_buffer_size ( sample_rate, verblib_combtuningR6 ) );
428     verblib_comb_initialize ( &verb->combL[6], verb->bufcombL7, verblib_get_verblib_scaled_buffer_size ( sample_rate, verblib_combtuningL7 ) );
429     verblib_comb_initialize ( &verb->combR[6], verb->bufcombR7, verblib_get_verblib_scaled_buffer_size ( sample_rate, verblib_combtuningR7 ) );
430     verblib_comb_initialize ( &verb->combL[7], verb->bufcombL8, verblib_get_verblib_scaled_buffer_size ( sample_rate, verblib_combtuningL8 ) );
431     verblib_comb_initialize ( &verb->combR[7], verb->bufcombR8, verblib_get_verblib_scaled_buffer_size ( sample_rate, verblib_combtuningR8 ) );
432 
433     verblib_allpass_initialize ( &verb->allpassL[0], verb->bufallpassL1, verblib_get_verblib_scaled_buffer_size ( sample_rate, verblib_allpasstuningL1 ) );
434     verblib_allpass_initialize ( &verb->allpassR[0], verb->bufallpassR1, verblib_get_verblib_scaled_buffer_size ( sample_rate, verblib_allpasstuningR1 ) );
435     verblib_allpass_initialize ( &verb->allpassL[1], verb->bufallpassL2, verblib_get_verblib_scaled_buffer_size ( sample_rate, verblib_allpasstuningL2 ) );
436     verblib_allpass_initialize ( &verb->allpassR[1], verb->bufallpassR2, verblib_get_verblib_scaled_buffer_size ( sample_rate, verblib_allpasstuningR2 ) );
437     verblib_allpass_initialize ( &verb->allpassL[2], verb->bufallpassL3, verblib_get_verblib_scaled_buffer_size ( sample_rate, verblib_allpasstuningL3 ) );
438     verblib_allpass_initialize ( &verb->allpassR[2], verb->bufallpassR3, verblib_get_verblib_scaled_buffer_size ( sample_rate, verblib_allpasstuningR3 ) );
439     verblib_allpass_initialize ( &verb->allpassL[3], verb->bufallpassL4, verblib_get_verblib_scaled_buffer_size ( sample_rate, verblib_allpasstuningL4 ) );
440     verblib_allpass_initialize ( &verb->allpassR[3], verb->bufallpassR4, verblib_get_verblib_scaled_buffer_size ( sample_rate, verblib_allpasstuningR4 ) );
441 
442     /* Set default values. */
443     for ( i = 0; i < verblib_numallpasses; i++ )
444     {
445         verb->allpassL[i].feedback = 0.5f;
446         verb->allpassR[i].feedback = 0.5f;
447     }
448 
449     verblib_set_wet ( verb, verblib_initialwet );
450     verblib_set_room_size ( verb, verblib_initialroom );
451     verblib_set_dry ( verb, verblib_initialdry );
452     verblib_set_damping ( verb, verblib_initialdamp );
453     verblib_set_width ( verb, verblib_initialwidth );
454     verblib_set_mode ( verb, verblib_initialmode );
455 
456     /* The buffers will be full of rubbish - so we MUST mute them. */
457     verblib_mute ( verb );
458 
459     return 1;
460 }
461 
verblib_process(verblib * verb,const float * input_buffer,float * output_buffer,unsigned long frames)462 void verblib_process ( verblib* verb, const float* input_buffer, float* output_buffer, unsigned long frames )
463 {
464     int i;
465     float outL, outR, input;
466 
467     if ( verb->channels == 1 )
468     {
469         while ( frames-- > 0 )
470         {
471             outL = 0.0f;
472             input = ( input_buffer[0] * 2.0f ) * verb->gain;
473 
474             /* Accumulate comb filters in parallel. */
475             for ( i = 0; i < verblib_numcombs; i++ )
476             {
477                 outL += verblib_comb_process ( &verb->combL[i], input );
478             }
479 
480             /* Feed through allpasses in series. */
481             for ( i = 0; i < verblib_numallpasses; i++ )
482             {
483                 outL = verblib_allpass_process ( &verb->allpassL[i], outL );
484             }
485 
486             /* Calculate output REPLACING anything already there. */
487             output_buffer[0] = outL * verb->wet1 + input_buffer[0] * verb->dry;
488 
489             /* Increment sample pointers. */
490             ++input_buffer;
491             ++output_buffer;
492         }
493     }
494     else if ( verb->channels == 2 )
495     {
496         while ( frames-- > 0 )
497         {
498             outL = outR = 0.0f;
499             input = ( input_buffer[0] + input_buffer[1] ) * verb->gain;
500 
501             /* Accumulate comb filters in parallel. */
502             for ( i = 0; i < verblib_numcombs; i++ )
503             {
504                 outL += verblib_comb_process ( &verb->combL[i], input );
505                 outR += verblib_comb_process ( &verb->combR[i], input );
506             }
507 
508             /* Feed through allpasses in series. */
509             for ( i = 0; i < verblib_numallpasses; i++ )
510             {
511                 outL = verblib_allpass_process ( &verb->allpassL[i], outL );
512                 outR = verblib_allpass_process ( &verb->allpassR[i], outR );
513             }
514 
515             /* Calculate output REPLACING anything already there. */
516             output_buffer[0] = outL * verb->wet1 + outR * verb->wet2 + input_buffer[0] * verb->dry;
517             output_buffer[1] = outR * verb->wet1 + outL * verb->wet2 + input_buffer[1] * verb->dry;
518 
519             /* Increment sample pointers. */
520             input_buffer += 2;
521             output_buffer += 2;
522         }
523     }
524 }
525 
verblib_set_room_size(verblib * verb,float value)526 void verblib_set_room_size ( verblib* verb, float value )
527 {
528     verb->roomsize = ( value * verblib_scaleroom ) + verblib_offsetroom;
529     verblib_update ( verb );
530 }
531 
verblib_get_room_size(const verblib * verb)532 float verblib_get_room_size ( const verblib* verb )
533 {
534     return ( verb->roomsize - verblib_offsetroom ) / verblib_scaleroom;
535 }
536 
verblib_set_damping(verblib * verb,float value)537 void verblib_set_damping ( verblib* verb, float value )
538 {
539     verb->damp = value * verblib_scaledamp;
540     verblib_update ( verb );
541 }
542 
verblib_get_damping(const verblib * verb)543 float verblib_get_damping ( const verblib* verb )
544 {
545     return verb->damp / verblib_scaledamp;
546 }
547 
verblib_set_wet(verblib * verb,float value)548 void verblib_set_wet ( verblib* verb, float value )
549 {
550     verb->wet = value * verblib_scalewet;
551     verblib_update ( verb );
552 }
553 
verblib_get_wet(const verblib * verb)554 float verblib_get_wet ( const verblib* verb )
555 {
556     return verb->wet / verblib_scalewet;
557 }
558 
verblib_set_dry(verblib * verb,float value)559 void verblib_set_dry ( verblib* verb, float value )
560 {
561     verb->dry = value * verblib_scaledry;
562 }
563 
verblib_get_dry(const verblib * verb)564 float verblib_get_dry ( const verblib* verb )
565 {
566     return verb->dry / verblib_scaledry;
567 }
568 
verblib_set_width(verblib * verb,float value)569 void verblib_set_width ( verblib* verb, float value )
570 {
571     verb->width = value;
572     verblib_update ( verb );
573 }
574 
verblib_get_width(const verblib * verb)575 float verblib_get_width ( const verblib* verb )
576 {
577     return verb->width;
578 }
579 
verblib_set_mode(verblib * verb,float value)580 void verblib_set_mode ( verblib* verb, float value )
581 {
582     verb->mode = value;
583     verblib_update ( verb );
584 }
585 
verblib_get_mode(const verblib * verb)586 float verblib_get_mode ( const verblib* verb )
587 {
588     if ( verb->mode >= verblib_freezemode )
589     {
590         return 1.0f;
591     }
592     return 0.0f;
593 }
594 
verblib_get_decay_time_in_frames(const verblib * verb)595 unsigned long verblib_get_decay_time_in_frames ( const verblib* verb )
596 {
597     double decay;
598 
599     if ( verb->mode >= verblib_freezemode )
600     {
601         return 0; /* Freeze mode creates an infinite decay. */
602     }
603 
604     decay = verblib_silence_threshold / fabs ( -20.0 * log ( 1.0 / verb->roomsize1 ) );
605     decay *= ( double ) ( verb->combR[7].bufsize * 2 );
606     return ( unsigned long ) decay;
607 }
608 
609 #endif /* VERBLIB_IMPLEMENTATION */
610 
611 /* REVISION HISTORY
612 *
613 * Version 0.4 - 2021-01-23
614 * Added a function called verblib_get_decay_time_in_frames.
615 *
616 * Version 0.3 - 2021-01-18
617 * Added support for sample rates of 22050 and above.
618 *
619 * Version 0.2 - 2021-01-17
620 * Added support for processing mono audio.
621 *
622 * Version 0.1 - 2021-01-17
623 * Initial release.
624 */
625 
626 /* LICENSE
627 
628 This software is available under 2 licenses -- choose whichever you prefer.
629 ------------------------------------------------------------------------------
630 ALTERNATIVE A - MIT No Attribution License
631 Copyright (c) 2021 Philip Bennefall
632 
633 Permission is hereby granted, free of charge, to any person obtaining a copy of
634 this software and associated documentation files (the "Software"), to deal in
635 the Software without restriction, including without limitation the rights to
636 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
637 of the Software, and to permit persons to whom the Software is furnished to do
638 so.
639 
640 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
641 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
642 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
643 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
644 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
645 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
646 SOFTWARE.
647 ------------------------------------------------------------------------------
648 ALTERNATIVE B - Public Domain (www.unlicense.org)
649 This is free and unencumbered software released into the public domain.
650 Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
651 software, either in source code form or as a compiled binary, for any purpose,
652 commercial or non-commercial, and by any means.
653 
654 In jurisdictions that recognize copyright laws, the author or authors of this
655 software dedicate any and all copyright interest in the software to the public
656 domain. We make this dedication for the benefit of the public at large and to
657 the detriment of our heirs and successors. We intend this dedication to be an
658 overt act of relinquishment in perpetuity of all present and future rights to
659 this software under copyright law.
660 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
661 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
662 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
663 AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
664 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
665 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
666 ------------------------------------------------------------------------------
667 */
668