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