mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-14 18:46:34 +01:00
Import libfluidsynth into the Ardour codebase
This commit is contained in:
parent
ac8617017a
commit
ac05f05023
69 changed files with 29290 additions and 0 deletions
544
libs/fluidsynth/src/fluid_rev.c
Normal file
544
libs/fluidsynth/src/fluid_rev.c
Normal file
|
|
@ -0,0 +1,544 @@
|
|||
/*
|
||||
|
||||
Freeverb
|
||||
|
||||
Written by Jezar at Dreampoint, June 2000
|
||||
http://www.dreampoint.co.uk
|
||||
This code is public domain
|
||||
|
||||
Translated to C by Peter Hanappe, Mai 2001
|
||||
*/
|
||||
|
||||
#include "fluid_rev.h"
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
* REVERB
|
||||
*/
|
||||
|
||||
/* Denormalising:
|
||||
*
|
||||
* According to music-dsp thread 'Denormalise', Pentium processors
|
||||
* have a hardware 'feature', that is of interest here, related to
|
||||
* numeric underflow. We have a recursive filter. The output decays
|
||||
* exponentially, if the input stops. So the numbers get smaller and
|
||||
* smaller... At some point, they reach 'denormal' level. This will
|
||||
* lead to drastic spikes in the CPU load. The effect was reproduced
|
||||
* with the reverb - sometimes the average load over 10 s doubles!!.
|
||||
*
|
||||
* The 'undenormalise' macro fixes the problem: As soon as the number
|
||||
* is close enough to denormal level, the macro forces the number to
|
||||
* 0.0f. The original macro is:
|
||||
*
|
||||
* #define undenormalise(sample) if(((*(unsigned int*)&sample)&0x7f800000)==0) sample=0.0f
|
||||
*
|
||||
* This will zero out a number when it reaches the denormal level.
|
||||
* Advantage: Maximum dynamic range Disadvantage: We'll have to check
|
||||
* every sample, expensive. The alternative macro comes from a later
|
||||
* mail from Jon Watte. It will zap a number before it reaches
|
||||
* denormal level. Jon suggests to run it once per block instead of
|
||||
* every sample.
|
||||
*/
|
||||
|
||||
# if defined(WITH_FLOATX)
|
||||
# define zap_almost_zero(sample) (((*(unsigned int*)&(sample))&0x7f800000) < 0x08000000)?0.0f:(sample)
|
||||
# else
|
||||
/* 1e-20 was chosen as an arbitrary (small) threshold. */
|
||||
#define zap_almost_zero(sample) fabs(sample)<1e-10 ? 0 : sample;
|
||||
#endif
|
||||
|
||||
/* Denormalising part II:
|
||||
*
|
||||
* Another method fixes the problem cheaper: Use a small DC-offset in
|
||||
* the filter calculations. Now the signals converge not against 0,
|
||||
* but against the offset. The constant offset is invisible from the
|
||||
* outside world (i.e. it does not appear at the output. There is a
|
||||
* very small turn-on transient response, which should not cause
|
||||
* problems.
|
||||
*/
|
||||
|
||||
|
||||
//#define DC_OFFSET 0
|
||||
#define DC_OFFSET 1e-8
|
||||
//#define DC_OFFSET 0.001f
|
||||
typedef struct _fluid_allpass fluid_allpass;
|
||||
typedef struct _fluid_comb fluid_comb;
|
||||
|
||||
struct _fluid_allpass {
|
||||
fluid_real_t feedback;
|
||||
fluid_real_t *buffer;
|
||||
int bufsize;
|
||||
int bufidx;
|
||||
};
|
||||
|
||||
void fluid_allpass_init(fluid_allpass* allpass);
|
||||
void fluid_allpass_setfeedback(fluid_allpass* allpass, fluid_real_t val);
|
||||
fluid_real_t fluid_allpass_getfeedback(fluid_allpass* allpass);
|
||||
|
||||
static void
|
||||
fluid_allpass_setbuffer(fluid_allpass* allpass, int size)
|
||||
{
|
||||
allpass->bufidx = 0;
|
||||
allpass->buffer = FLUID_ARRAY(fluid_real_t,size);
|
||||
allpass->bufsize = size;
|
||||
}
|
||||
|
||||
static void
|
||||
fluid_allpass_release(fluid_allpass* allpass)
|
||||
{
|
||||
FLUID_FREE(allpass->buffer);
|
||||
}
|
||||
|
||||
void
|
||||
fluid_allpass_init(fluid_allpass* allpass)
|
||||
{
|
||||
int i;
|
||||
int len = allpass->bufsize;
|
||||
fluid_real_t* buf = allpass->buffer;
|
||||
for (i = 0; i < len; i++) {
|
||||
buf[i] = DC_OFFSET; /* this is not 100 % correct. */
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
fluid_allpass_setfeedback(fluid_allpass* allpass, fluid_real_t val)
|
||||
{
|
||||
allpass->feedback = val;
|
||||
}
|
||||
|
||||
fluid_real_t
|
||||
fluid_allpass_getfeedback(fluid_allpass* allpass)
|
||||
{
|
||||
return allpass->feedback;
|
||||
}
|
||||
|
||||
#define fluid_allpass_process(_allpass, _input) \
|
||||
{ \
|
||||
fluid_real_t output; \
|
||||
fluid_real_t bufout; \
|
||||
bufout = _allpass.buffer[_allpass.bufidx]; \
|
||||
output = bufout-_input; \
|
||||
_allpass.buffer[_allpass.bufidx] = _input + (bufout * _allpass.feedback); \
|
||||
if (++_allpass.bufidx >= _allpass.bufsize) { \
|
||||
_allpass.bufidx = 0; \
|
||||
} \
|
||||
_input = output; \
|
||||
}
|
||||
|
||||
/* fluid_real_t fluid_allpass_process(fluid_allpass* allpass, fluid_real_t input) */
|
||||
/* { */
|
||||
/* fluid_real_t output; */
|
||||
/* fluid_real_t bufout; */
|
||||
/* bufout = allpass->buffer[allpass->bufidx]; */
|
||||
/* undenormalise(bufout); */
|
||||
/* output = -input + bufout; */
|
||||
/* allpass->buffer[allpass->bufidx] = input + (bufout * allpass->feedback); */
|
||||
/* if (++allpass->bufidx >= allpass->bufsize) { */
|
||||
/* allpass->bufidx = 0; */
|
||||
/* } */
|
||||
/* return output; */
|
||||
/* } */
|
||||
|
||||
struct _fluid_comb {
|
||||
fluid_real_t feedback;
|
||||
fluid_real_t filterstore;
|
||||
fluid_real_t damp1;
|
||||
fluid_real_t damp2;
|
||||
fluid_real_t *buffer;
|
||||
int bufsize;
|
||||
int bufidx;
|
||||
};
|
||||
|
||||
void fluid_comb_setbuffer(fluid_comb* comb, int size);
|
||||
void fluid_comb_release(fluid_comb* comb);
|
||||
void fluid_comb_init(fluid_comb* comb);
|
||||
void fluid_comb_setdamp(fluid_comb* comb, fluid_real_t val);
|
||||
fluid_real_t fluid_comb_getdamp(fluid_comb* comb);
|
||||
void fluid_comb_setfeedback(fluid_comb* comb, fluid_real_t val);
|
||||
fluid_real_t fluid_comb_getfeedback(fluid_comb* comb);
|
||||
|
||||
void
|
||||
fluid_comb_setbuffer(fluid_comb* comb, int size)
|
||||
{
|
||||
comb->filterstore = 0;
|
||||
comb->bufidx = 0;
|
||||
comb->buffer = FLUID_ARRAY(fluid_real_t,size);
|
||||
comb->bufsize = size;
|
||||
}
|
||||
|
||||
void
|
||||
fluid_comb_release(fluid_comb* comb)
|
||||
{
|
||||
FLUID_FREE(comb->buffer);
|
||||
}
|
||||
|
||||
void
|
||||
fluid_comb_init(fluid_comb* comb)
|
||||
{
|
||||
int i;
|
||||
fluid_real_t* buf = comb->buffer;
|
||||
int len = comb->bufsize;
|
||||
for (i = 0; i < len; i++) {
|
||||
buf[i] = DC_OFFSET; /* This is not 100 % correct. */
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
fluid_comb_setdamp(fluid_comb* comb, fluid_real_t val)
|
||||
{
|
||||
comb->damp1 = val;
|
||||
comb->damp2 = 1 - val;
|
||||
}
|
||||
|
||||
fluid_real_t
|
||||
fluid_comb_getdamp(fluid_comb* comb)
|
||||
{
|
||||
return comb->damp1;
|
||||
}
|
||||
|
||||
void
|
||||
fluid_comb_setfeedback(fluid_comb* comb, fluid_real_t val)
|
||||
{
|
||||
comb->feedback = val;
|
||||
}
|
||||
|
||||
fluid_real_t
|
||||
fluid_comb_getfeedback(fluid_comb* comb)
|
||||
{
|
||||
return comb->feedback;
|
||||
}
|
||||
|
||||
#define fluid_comb_process(_comb, _input, _output) \
|
||||
{ \
|
||||
fluid_real_t _tmp = _comb.buffer[_comb.bufidx]; \
|
||||
_comb.filterstore = (_tmp * _comb.damp2) + (_comb.filterstore * _comb.damp1); \
|
||||
_comb.buffer[_comb.bufidx] = _input + (_comb.filterstore * _comb.feedback); \
|
||||
if (++_comb.bufidx >= _comb.bufsize) { \
|
||||
_comb.bufidx = 0; \
|
||||
} \
|
||||
_output += _tmp; \
|
||||
}
|
||||
|
||||
/* fluid_real_t fluid_comb_process(fluid_comb* comb, fluid_real_t input) */
|
||||
/* { */
|
||||
/* fluid_real_t output; */
|
||||
|
||||
/* output = comb->buffer[comb->bufidx]; */
|
||||
/* undenormalise(output); */
|
||||
/* comb->filterstore = (output * comb->damp2) + (comb->filterstore * comb->damp1); */
|
||||
/* undenormalise(comb->filterstore); */
|
||||
/* comb->buffer[comb->bufidx] = input + (comb->filterstore * comb->feedback); */
|
||||
/* if (++comb->bufidx >= comb->bufsize) { */
|
||||
/* comb->bufidx = 0; */
|
||||
/* } */
|
||||
|
||||
/* return output; */
|
||||
/* } */
|
||||
|
||||
#define numcombs 8
|
||||
#define numallpasses 4
|
||||
#define fixedgain 0.015f
|
||||
#define scalewet 3.0f
|
||||
#define scaledamp 1.0f
|
||||
#define scaleroom 0.28f
|
||||
#define offsetroom 0.7f
|
||||
#define initialroom 0.5f
|
||||
#define initialdamp 0.2f
|
||||
#define initialwet 1
|
||||
#define initialdry 0
|
||||
#define initialwidth 1
|
||||
#define stereospread 23
|
||||
|
||||
/*
|
||||
These values assume 44.1KHz sample rate
|
||||
they will probably be OK for 48KHz sample rate
|
||||
but would need scaling for 96KHz (or other) sample rates.
|
||||
The values were obtained by listening tests.
|
||||
*/
|
||||
#define combtuningL1 1116
|
||||
#define combtuningR1 (1116 + stereospread)
|
||||
#define combtuningL2 1188
|
||||
#define combtuningR2 (1188 + stereospread)
|
||||
#define combtuningL3 1277
|
||||
#define combtuningR3 (1277 + stereospread)
|
||||
#define combtuningL4 1356
|
||||
#define combtuningR4 (1356 + stereospread)
|
||||
#define combtuningL5 1422
|
||||
#define combtuningR5 (1422 + stereospread)
|
||||
#define combtuningL6 1491
|
||||
#define combtuningR6 (1491 + stereospread)
|
||||
#define combtuningL7 1557
|
||||
#define combtuningR7 (1557 + stereospread)
|
||||
#define combtuningL8 1617
|
||||
#define combtuningR8 (1617 + stereospread)
|
||||
#define allpasstuningL1 556
|
||||
#define allpasstuningR1 (556 + stereospread)
|
||||
#define allpasstuningL2 441
|
||||
#define allpasstuningR2 (441 + stereospread)
|
||||
#define allpasstuningL3 341
|
||||
#define allpasstuningR3 (341 + stereospread)
|
||||
#define allpasstuningL4 225
|
||||
#define allpasstuningR4 (225 + stereospread)
|
||||
|
||||
struct _fluid_revmodel_t {
|
||||
fluid_real_t roomsize;
|
||||
fluid_real_t damp;
|
||||
fluid_real_t wet, wet1, wet2;
|
||||
fluid_real_t width;
|
||||
fluid_real_t gain;
|
||||
/*
|
||||
The following are all declared inline
|
||||
to remove the need for dynamic allocation
|
||||
with its subsequent error-checking messiness
|
||||
*/
|
||||
/* Comb filters */
|
||||
fluid_comb combL[numcombs];
|
||||
fluid_comb combR[numcombs];
|
||||
/* Allpass filters */
|
||||
fluid_allpass allpassL[numallpasses];
|
||||
fluid_allpass allpassR[numallpasses];
|
||||
};
|
||||
|
||||
static void fluid_revmodel_update(fluid_revmodel_t* rev);
|
||||
static void fluid_revmodel_init(fluid_revmodel_t* rev);
|
||||
void fluid_set_revmodel_buffers(fluid_revmodel_t* rev, fluid_real_t sample_rate);
|
||||
|
||||
fluid_revmodel_t*
|
||||
new_fluid_revmodel(fluid_real_t sample_rate)
|
||||
{
|
||||
fluid_revmodel_t* rev;
|
||||
rev = FLUID_NEW(fluid_revmodel_t);
|
||||
if (rev == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fluid_set_revmodel_buffers(rev, sample_rate);
|
||||
|
||||
/* Set default values */
|
||||
fluid_allpass_setfeedback(&rev->allpassL[0], 0.5f);
|
||||
fluid_allpass_setfeedback(&rev->allpassR[0], 0.5f);
|
||||
fluid_allpass_setfeedback(&rev->allpassL[1], 0.5f);
|
||||
fluid_allpass_setfeedback(&rev->allpassR[1], 0.5f);
|
||||
fluid_allpass_setfeedback(&rev->allpassL[2], 0.5f);
|
||||
fluid_allpass_setfeedback(&rev->allpassR[2], 0.5f);
|
||||
fluid_allpass_setfeedback(&rev->allpassL[3], 0.5f);
|
||||
fluid_allpass_setfeedback(&rev->allpassR[3], 0.5f);
|
||||
|
||||
rev->gain = fixedgain;
|
||||
fluid_revmodel_set(rev,FLUID_REVMODEL_SET_ALL,initialroom,initialdamp,initialwidth,initialwet);
|
||||
|
||||
return rev;
|
||||
}
|
||||
|
||||
void
|
||||
delete_fluid_revmodel(fluid_revmodel_t* rev)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < numcombs;i++) {
|
||||
fluid_comb_release(&rev->combL[i]);
|
||||
fluid_comb_release(&rev->combR[i]);
|
||||
}
|
||||
for (i = 0; i < numallpasses; i++) {
|
||||
fluid_allpass_release(&rev->allpassL[i]);
|
||||
fluid_allpass_release(&rev->allpassR[i]);
|
||||
}
|
||||
|
||||
FLUID_FREE(rev);
|
||||
}
|
||||
|
||||
void
|
||||
fluid_set_revmodel_buffers(fluid_revmodel_t* rev, fluid_real_t sample_rate) {
|
||||
|
||||
float srfactor = sample_rate/44100.0f;
|
||||
|
||||
fluid_comb_setbuffer(&rev->combL[0], combtuningL1*srfactor);
|
||||
fluid_comb_setbuffer(&rev->combR[0], combtuningR1*srfactor);
|
||||
fluid_comb_setbuffer(&rev->combL[1], combtuningL2*srfactor);
|
||||
fluid_comb_setbuffer(&rev->combR[1], combtuningR2*srfactor);
|
||||
fluid_comb_setbuffer(&rev->combL[2], combtuningL3*srfactor);
|
||||
fluid_comb_setbuffer(&rev->combR[2], combtuningR3*srfactor);
|
||||
fluid_comb_setbuffer(&rev->combL[3], combtuningL4*srfactor);
|
||||
fluid_comb_setbuffer(&rev->combR[3], combtuningR4*srfactor);
|
||||
fluid_comb_setbuffer(&rev->combL[4], combtuningL5*srfactor);
|
||||
fluid_comb_setbuffer(&rev->combR[4], combtuningR5*srfactor);
|
||||
fluid_comb_setbuffer(&rev->combL[5], combtuningL6*srfactor);
|
||||
fluid_comb_setbuffer(&rev->combR[5], combtuningR6*srfactor);
|
||||
fluid_comb_setbuffer(&rev->combL[6], combtuningL7*srfactor);
|
||||
fluid_comb_setbuffer(&rev->combR[6], combtuningR7*srfactor);
|
||||
fluid_comb_setbuffer(&rev->combL[7], combtuningL8*srfactor);
|
||||
fluid_comb_setbuffer(&rev->combR[7], combtuningR8*srfactor);
|
||||
fluid_allpass_setbuffer(&rev->allpassL[0], allpasstuningL1*srfactor);
|
||||
fluid_allpass_setbuffer(&rev->allpassR[0], allpasstuningR1*srfactor);
|
||||
fluid_allpass_setbuffer(&rev->allpassL[1], allpasstuningL2*srfactor);
|
||||
fluid_allpass_setbuffer(&rev->allpassR[1], allpasstuningR2*srfactor);
|
||||
fluid_allpass_setbuffer(&rev->allpassL[2], allpasstuningL3*srfactor);
|
||||
fluid_allpass_setbuffer(&rev->allpassR[2], allpasstuningR3*srfactor);
|
||||
fluid_allpass_setbuffer(&rev->allpassL[3], allpasstuningL4*srfactor);
|
||||
fluid_allpass_setbuffer(&rev->allpassR[3], allpasstuningR4*srfactor);
|
||||
|
||||
/* Clear all buffers */
|
||||
fluid_revmodel_init(rev);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
fluid_revmodel_init(fluid_revmodel_t* rev)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < numcombs;i++) {
|
||||
fluid_comb_init(&rev->combL[i]);
|
||||
fluid_comb_init(&rev->combR[i]);
|
||||
}
|
||||
for (i = 0; i < numallpasses; i++) {
|
||||
fluid_allpass_init(&rev->allpassL[i]);
|
||||
fluid_allpass_init(&rev->allpassR[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
fluid_revmodel_reset(fluid_revmodel_t* rev)
|
||||
{
|
||||
fluid_revmodel_init(rev);
|
||||
}
|
||||
|
||||
void
|
||||
fluid_revmodel_processreplace(fluid_revmodel_t* rev, fluid_real_t *in,
|
||||
fluid_real_t *left_out, fluid_real_t *right_out)
|
||||
{
|
||||
int i, k = 0;
|
||||
fluid_real_t outL, outR, input;
|
||||
|
||||
for (k = 0; k < FLUID_BUFSIZE; k++) {
|
||||
|
||||
outL = outR = 0;
|
||||
|
||||
/* The original Freeverb code expects a stereo signal and 'input'
|
||||
* is set to the sum of the left and right input sample. Since
|
||||
* this code works on a mono signal, 'input' is set to twice the
|
||||
* input sample. */
|
||||
input = (2.0f * in[k] + DC_OFFSET) * rev->gain;
|
||||
|
||||
/* Accumulate comb filters in parallel */
|
||||
for (i = 0; i < numcombs; i++) {
|
||||
fluid_comb_process(rev->combL[i], input, outL);
|
||||
fluid_comb_process(rev->combR[i], input, outR);
|
||||
}
|
||||
/* Feed through allpasses in series */
|
||||
for (i = 0; i < numallpasses; i++) {
|
||||
fluid_allpass_process(rev->allpassL[i], outL);
|
||||
fluid_allpass_process(rev->allpassR[i], outR);
|
||||
}
|
||||
|
||||
/* Remove the DC offset */
|
||||
outL -= DC_OFFSET;
|
||||
outR -= DC_OFFSET;
|
||||
|
||||
/* Calculate output REPLACING anything already there */
|
||||
left_out[k] = outL * rev->wet1 + outR * rev->wet2;
|
||||
right_out[k] = outR * rev->wet1 + outL * rev->wet2;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
fluid_revmodel_processmix(fluid_revmodel_t* rev, fluid_real_t *in,
|
||||
fluid_real_t *left_out, fluid_real_t *right_out)
|
||||
{
|
||||
int i, k = 0;
|
||||
fluid_real_t outL, outR, input;
|
||||
|
||||
for (k = 0; k < FLUID_BUFSIZE; k++) {
|
||||
|
||||
outL = outR = 0;
|
||||
|
||||
/* The original Freeverb code expects a stereo signal and 'input'
|
||||
* is set to the sum of the left and right input sample. Since
|
||||
* this code works on a mono signal, 'input' is set to twice the
|
||||
* input sample. */
|
||||
input = (2.0f * in[k] + DC_OFFSET) * rev->gain;
|
||||
|
||||
/* Accumulate comb filters in parallel */
|
||||
for (i = 0; i < numcombs; i++) {
|
||||
fluid_comb_process(rev->combL[i], input, outL);
|
||||
fluid_comb_process(rev->combR[i], input, outR);
|
||||
}
|
||||
/* Feed through allpasses in series */
|
||||
for (i = 0; i < numallpasses; i++) {
|
||||
fluid_allpass_process(rev->allpassL[i], outL);
|
||||
fluid_allpass_process(rev->allpassR[i], outR);
|
||||
}
|
||||
|
||||
/* Remove the DC offset */
|
||||
outL -= DC_OFFSET;
|
||||
outR -= DC_OFFSET;
|
||||
|
||||
/* Calculate output MIXING with anything already there */
|
||||
left_out[k] += outL * rev->wet1 + outR * rev->wet2;
|
||||
right_out[k] += outR * rev->wet1 + outL * rev->wet2;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
fluid_revmodel_update(fluid_revmodel_t* rev)
|
||||
{
|
||||
/* Recalculate internal values after parameter change */
|
||||
int i;
|
||||
|
||||
rev->wet1 = rev->wet * (rev->width / 2.0f + 0.5f);
|
||||
rev->wet2 = rev->wet * ((1.0f - rev->width) / 2.0f);
|
||||
|
||||
for (i = 0; i < numcombs; i++) {
|
||||
fluid_comb_setfeedback(&rev->combL[i], rev->roomsize);
|
||||
fluid_comb_setfeedback(&rev->combR[i], rev->roomsize);
|
||||
}
|
||||
|
||||
for (i = 0; i < numcombs; i++) {
|
||||
fluid_comb_setdamp(&rev->combL[i], rev->damp);
|
||||
fluid_comb_setdamp(&rev->combR[i], rev->damp);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set one or more reverb parameters.
|
||||
* @param rev Reverb instance
|
||||
* @param set One or more flags from #fluid_revmodel_set_t indicating what
|
||||
* parameters to set (#FLUID_REVMODEL_SET_ALL to set all parameters)
|
||||
* @param roomsize Reverb room size
|
||||
* @param damping Reverb damping
|
||||
* @param width Reverb width
|
||||
* @param level Reverb level
|
||||
*/
|
||||
void
|
||||
fluid_revmodel_set(fluid_revmodel_t* rev, int set, float roomsize,
|
||||
float damping, float width, float level)
|
||||
{
|
||||
if (set & FLUID_REVMODEL_SET_ROOMSIZE)
|
||||
rev->roomsize = (roomsize * scaleroom) + offsetroom;
|
||||
|
||||
if (set & FLUID_REVMODEL_SET_DAMPING)
|
||||
rev->damp = damping * scaledamp;
|
||||
|
||||
if (set & FLUID_REVMODEL_SET_WIDTH)
|
||||
rev->width = width;
|
||||
|
||||
if (set & FLUID_REVMODEL_SET_LEVEL)
|
||||
{
|
||||
fluid_clip(level, 0.0f, 1.0f);
|
||||
rev->wet = level * scalewet;
|
||||
}
|
||||
|
||||
fluid_revmodel_update (rev);
|
||||
}
|
||||
|
||||
void
|
||||
fluid_revmodel_samplerate_change(fluid_revmodel_t* rev, fluid_real_t sample_rate) {
|
||||
int i;
|
||||
for (i = 0; i < numcombs;i++) {
|
||||
fluid_comb_release(&rev->combL[i]);
|
||||
fluid_comb_release(&rev->combR[i]);
|
||||
}
|
||||
for (i = 0; i < numallpasses; i++) {
|
||||
fluid_allpass_release(&rev->allpassL[i]);
|
||||
fluid_allpass_release(&rev->allpassR[i]);
|
||||
}
|
||||
fluid_set_revmodel_buffers(rev, sample_rate);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue