diff --git a/fluidsynth/src/rvoice/fluid_rev.c b/fluidsynth/src/rvoice/fluid_rev.c index 1ff59ef4..ae076300 100644 --- a/fluidsynth/src/rvoice/fluid_rev.c +++ b/fluidsynth/src/rvoice/fluid_rev.c @@ -72,18 +72,25 @@ struct _fluid_allpass { }; void fluid_allpass_setbuffer(fluid_allpass* allpass, fluid_real_t *buf, int size); +void fluid_allpass_release(fluid_comb* comb); 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); void -fluid_allpass_setbuffer(fluid_allpass* allpass, fluid_real_t *buf, int size) +fluid_allpass_setbuffer(fluid_allpass* allpass, int size) { allpass->bufidx = 0; - allpass->buffer = buf; + allpass->buffer = FLUID_ARRAY(fluid_real_t,size); allpass->bufsize = size; } +void +fluid_allpass_release(fluid_allpass* allpass) +{ + FLUID_FREE(allpass->buffer); +} + void fluid_allpass_init(fluid_allpass* allpass) { @@ -144,7 +151,8 @@ struct _fluid_comb { int bufidx; }; -void fluid_comb_setbuffer(fluid_comb* comb, fluid_real_t *buf, int size); +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); @@ -152,14 +160,20 @@ 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, fluid_real_t *buf, int size) +fluid_comb_setbuffer(fluid_comb* comb, int size) { comb->filterstore = 0; comb->bufidx = 0; - comb->buffer = buf; + 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) { @@ -244,29 +258,29 @@ fluid_comb_getfeedback(fluid_comb* comb) The values were obtained by listening tests. */ #define combtuningL1 1116 -#define combtuningR1 1116 + stereospread +#define combtuningR1 (1116 + stereospread) #define combtuningL2 1188 -#define combtuningR2 1188 + stereospread +#define combtuningR2 (1188 + stereospread) #define combtuningL3 1277 -#define combtuningR3 1277 + stereospread +#define combtuningR3 (1277 + stereospread) #define combtuningL4 1356 -#define combtuningR4 1356 + stereospread +#define combtuningR4 (1356 + stereospread) #define combtuningL5 1422 -#define combtuningR5 1422 + stereospread +#define combtuningR5 (1422 + stereospread) #define combtuningL6 1491 -#define combtuningR6 1491 + stereospread +#define combtuningR6 (1491 + stereospread) #define combtuningL7 1557 -#define combtuningR7 1557 + stereospread +#define combtuningR7 (1557 + stereospread) #define combtuningL8 1617 -#define combtuningR8 1617 + stereospread +#define combtuningR8 (1617 + stereospread) #define allpasstuningL1 556 -#define allpasstuningR1 556 + stereospread +#define allpasstuningR1 (556 + stereospread) #define allpasstuningL2 441 -#define allpasstuningR2 441 + stereospread +#define allpasstuningR2 (441 + stereospread) #define allpasstuningL3 341 -#define allpasstuningR3 341 + stereospread +#define allpasstuningR3 (341 + stereospread) #define allpasstuningL4 225 -#define allpasstuningR4 225 + stereospread +#define allpasstuningR4 (225 + stereospread) struct _fluid_revmodel_t { fluid_real_t roomsize; @@ -285,39 +299,14 @@ struct _fluid_revmodel_t { /* Allpass filters */ fluid_allpass allpassL[numallpasses]; fluid_allpass allpassR[numallpasses]; - /* Buffers for the combs */ - fluid_real_t bufcombL1[combtuningL1]; - fluid_real_t bufcombR1[combtuningR1]; - fluid_real_t bufcombL2[combtuningL2]; - fluid_real_t bufcombR2[combtuningR2]; - fluid_real_t bufcombL3[combtuningL3]; - fluid_real_t bufcombR3[combtuningR3]; - fluid_real_t bufcombL4[combtuningL4]; - fluid_real_t bufcombR4[combtuningR4]; - fluid_real_t bufcombL5[combtuningL5]; - fluid_real_t bufcombR5[combtuningR5]; - fluid_real_t bufcombL6[combtuningL6]; - fluid_real_t bufcombR6[combtuningR6]; - fluid_real_t bufcombL7[combtuningL7]; - fluid_real_t bufcombR7[combtuningR7]; - fluid_real_t bufcombL8[combtuningL8]; - fluid_real_t bufcombR8[combtuningR8]; - /* Buffers for the allpasses */ - fluid_real_t bufallpassL1[allpasstuningL1]; - fluid_real_t bufallpassR1[allpasstuningR1]; - fluid_real_t bufallpassL2[allpasstuningL2]; - fluid_real_t bufallpassR2[allpasstuningR2]; - fluid_real_t bufallpassL3[allpasstuningL3]; - fluid_real_t bufallpassR3[allpasstuningR3]; - fluid_real_t bufallpassL4[allpasstuningL4]; - fluid_real_t bufallpassR4[allpasstuningR4]; }; 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, int sample_rate); fluid_revmodel_t* -new_fluid_revmodel() +new_fluid_revmodel(int sample_rate) { fluid_revmodel_t* rev; rev = FLUID_NEW(fluid_revmodel_t); @@ -325,31 +314,8 @@ new_fluid_revmodel() return NULL; } - /* Tie the components to their buffers */ - fluid_comb_setbuffer(&rev->combL[0], rev->bufcombL1, combtuningL1); - fluid_comb_setbuffer(&rev->combR[0], rev->bufcombR1, combtuningR1); - fluid_comb_setbuffer(&rev->combL[1], rev->bufcombL2, combtuningL2); - fluid_comb_setbuffer(&rev->combR[1], rev->bufcombR2, combtuningR2); - fluid_comb_setbuffer(&rev->combL[2], rev->bufcombL3, combtuningL3); - fluid_comb_setbuffer(&rev->combR[2], rev->bufcombR3, combtuningR3); - fluid_comb_setbuffer(&rev->combL[3], rev->bufcombL4, combtuningL4); - fluid_comb_setbuffer(&rev->combR[3], rev->bufcombR4, combtuningR4); - fluid_comb_setbuffer(&rev->combL[4], rev->bufcombL5, combtuningL5); - fluid_comb_setbuffer(&rev->combR[4], rev->bufcombR5, combtuningR5); - fluid_comb_setbuffer(&rev->combL[5], rev->bufcombL6, combtuningL6); - fluid_comb_setbuffer(&rev->combR[5], rev->bufcombR6, combtuningR6); - fluid_comb_setbuffer(&rev->combL[6], rev->bufcombL7, combtuningL7); - fluid_comb_setbuffer(&rev->combR[6], rev->bufcombR7, combtuningR7); - fluid_comb_setbuffer(&rev->combL[7], rev->bufcombL8, combtuningL8); - fluid_comb_setbuffer(&rev->combR[7], rev->bufcombR8, combtuningR8); - fluid_allpass_setbuffer(&rev->allpassL[0], rev->bufallpassL1, allpasstuningL1); - fluid_allpass_setbuffer(&rev->allpassR[0], rev->bufallpassR1, allpasstuningR1); - fluid_allpass_setbuffer(&rev->allpassL[1], rev->bufallpassL2, allpasstuningL2); - fluid_allpass_setbuffer(&rev->allpassR[1], rev->bufallpassR2, allpasstuningR2); - fluid_allpass_setbuffer(&rev->allpassL[2], rev->bufallpassL3, allpasstuningL3); - fluid_allpass_setbuffer(&rev->allpassR[2], rev->bufallpassR3, allpasstuningR3); - fluid_allpass_setbuffer(&rev->allpassL[3], rev->bufallpassL4, allpasstuningL4); - fluid_allpass_setbuffer(&rev->allpassR[3], rev->bufallpassR4, allpasstuningR4); + 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); @@ -360,28 +326,63 @@ new_fluid_revmodel() fluid_allpass_setfeedback(&rev->allpassL[3], 0.5f); fluid_allpass_setfeedback(&rev->allpassR[3], 0.5f); - /* set values manually, since calling set functions causes update - and all values should be initialized for an update */ - rev->roomsize = initialroom * scaleroom + offsetroom; - rev->damp = initialdamp * scaledamp; - rev->wet = initialwet * scalewet; - rev->width = initialwidth; rev->gain = fixedgain; + fluid_revmodel_set(rev,FLUID_REVMODEL_SET_ALL,initialroom,initialdamp,initialwidth,initialwet); - /* now its okay to update reverb */ - fluid_revmodel_update(rev); - - /* Clear all buffers */ - fluid_revmodel_init(rev); 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, int 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) { @@ -417,7 +418,7 @@ fluid_revmodel_processreplace(fluid_revmodel_t* rev, fluid_real_t *in, * 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 * in[k] + DC_OFFSET) * rev->gain; + input = (2.0f * in[k] + DC_OFFSET) * rev->gain; /* Accumulate comb filters in parallel */ for (i = 0; i < numcombs; i++) { @@ -455,7 +456,7 @@ fluid_revmodel_processmix(fluid_revmodel_t* rev, fluid_real_t *in, * 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 * in[k] + DC_OFFSET) * rev->gain; + input = (2.0f * in[k] + DC_OFFSET) * rev->gain; /* Accumulate comb filters in parallel */ for (i = 0; i < numcombs; i++) { @@ -484,8 +485,8 @@ fluid_revmodel_update(fluid_revmodel_t* rev) /* Recalculate internal values after parameter change */ int i; - rev->wet1 = rev->wet * (rev->width / 2 + 0.5f); - rev->wet2 = rev->wet * ((1 - rev->width) / 2); + 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); @@ -529,3 +530,17 @@ fluid_revmodel_set(fluid_revmodel_t* rev, int set, float roomsize, fluid_revmodel_update (rev); } + +void +fluid_revmodel_samplerate_change(fluid_revmodel_t* rev, int 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); +} diff --git a/fluidsynth/src/rvoice/fluid_rev.h b/fluidsynth/src/rvoice/fluid_rev.h index 8244038f..80660b31 100644 --- a/fluidsynth/src/rvoice/fluid_rev.h +++ b/fluidsynth/src/rvoice/fluid_rev.h @@ -54,7 +54,7 @@ typedef struct _fluid_revmodel_presets_t { /* * reverb */ -fluid_revmodel_t* new_fluid_revmodel(void); +fluid_revmodel_t* new_fluid_revmodel(int sample_rate); void delete_fluid_revmodel(fluid_revmodel_t* rev); void fluid_revmodel_processmix(fluid_revmodel_t* rev, fluid_real_t *in, @@ -68,4 +68,6 @@ void fluid_revmodel_reset(fluid_revmodel_t* rev); void fluid_revmodel_set(fluid_revmodel_t* rev, int set, float roomsize, float damping, float width, float level); +void fluid_revmodel_samplerate_change(fluid_revmodel_t* rev, int sample_rate); + #endif /* _FLUID_REV_H */ diff --git a/fluidsynth/src/rvoice/fluid_rvoice_event.c b/fluidsynth/src/rvoice/fluid_rvoice_event.c index f36a3a9f..db4bb58b 100644 --- a/fluidsynth/src/rvoice/fluid_rvoice_event.c +++ b/fluidsynth/src/rvoice/fluid_rvoice_event.c @@ -220,7 +220,7 @@ finished_voice_callback(void* userdata, fluid_rvoice_t* rvoice) } fluid_rvoice_eventhandler_t* new_fluid_rvoice_eventhandler( - int is_threadsafe, int queuesize, int finished_voices_size, int bufs, int fx_bufs) + int is_threadsafe, int queuesize, int finished_voices_size, int bufs, int fx_bufs, int sample_rate) { fluid_rvoice_eventhandler_t* eventhandler = FLUID_NEW(fluid_rvoice_eventhandler_t); if (eventhandler == NULL) { @@ -242,7 +242,7 @@ fluid_rvoice_eventhandler_t* new_fluid_rvoice_eventhandler( if (eventhandler->queue == NULL) goto error_recovery; - eventhandler->mixer = new_fluid_rvoice_mixer(bufs, fx_bufs); + eventhandler->mixer = new_fluid_rvoice_mixer(bufs, fx_bufs, sample_rate); if (eventhandler->mixer == NULL) goto error_recovery; fluid_rvoice_mixer_set_finished_voices_callback(eventhandler->mixer, diff --git a/fluidsynth/src/rvoice/fluid_rvoice_mixer.c b/fluidsynth/src/rvoice/fluid_rvoice_mixer.c index 670f55cf..c21ea518 100644 --- a/fluidsynth/src/rvoice/fluid_rvoice_mixer.c +++ b/fluidsynth/src/rvoice/fluid_rvoice_mixer.c @@ -519,6 +519,8 @@ fluid_rvoice_mixer_set_samplerate(fluid_rvoice_mixer_t* mixer, fluid_real_t samp if (mixer->fx.chorus) delete_fluid_chorus(mixer->fx.chorus); mixer->fx.chorus = new_fluid_chorus(samplerate); + if (mixer->fx.reverb) + fluid_revmodel_samplerate_change(mixer->fx.reverb, samplerate); for (i=0; i < mixer->active_voices; i++) fluid_rvoice_set_output_rate(mixer->rvoices[i], samplerate); } @@ -529,7 +531,7 @@ fluid_rvoice_mixer_set_samplerate(fluid_rvoice_mixer_t* mixer, fluid_real_t samp * @param fx_buf_count number of stereo effect buffers */ fluid_rvoice_mixer_t* -new_fluid_rvoice_mixer(int buf_count, int fx_buf_count) +new_fluid_rvoice_mixer(int buf_count, int fx_buf_count, int sample_rate) { fluid_rvoice_mixer_t* mixer = FLUID_NEW(fluid_rvoice_mixer_t); if (mixer == NULL) { @@ -542,8 +544,8 @@ new_fluid_rvoice_mixer(int buf_count, int fx_buf_count) mixer->buffers.buf_blocks = FLUID_MIXER_MAX_BUFFERS_DEFAULT; /* allocate the reverb module */ - mixer->fx.reverb = new_fluid_revmodel(); - mixer->fx.chorus = new_fluid_chorus(44100); /* FIXME: Hardcoded sample rate */ + mixer->fx.reverb = new_fluid_revmodel(sample_rate); + mixer->fx.chorus = new_fluid_chorus(sample_rate); if (mixer->fx.reverb == NULL) { FLUID_LOG(FLUID_ERR, "Out of memory"); delete_fluid_rvoice_mixer(mixer); diff --git a/fluidsynth/src/rvoice/fluid_rvoice_mixer.h b/fluidsynth/src/rvoice/fluid_rvoice_mixer.h index 74befb4f..5180afb9 100644 --- a/fluidsynth/src/rvoice/fluid_rvoice_mixer.h +++ b/fluidsynth/src/rvoice/fluid_rvoice_mixer.h @@ -41,7 +41,7 @@ int fluid_rvoice_mixer_render(fluid_rvoice_mixer_t* mixer, int blockcount); int fluid_rvoice_mixer_get_bufs(fluid_rvoice_mixer_t* mixer, fluid_real_t*** left, fluid_real_t*** right); -fluid_rvoice_mixer_t* new_fluid_rvoice_mixer(int buf_count, int fx_buf_count); +fluid_rvoice_mixer_t* new_fluid_rvoice_mixer(int buf_count, int fx_buf_count, int sample_rate); void delete_fluid_rvoice_mixer(fluid_rvoice_mixer_t*); diff --git a/fluidsynth/src/synth/fluid_synth.c b/fluidsynth/src/synth/fluid_synth.c index 163eebf9..071fb0a4 100644 --- a/fluidsynth/src/synth/fluid_synth.c +++ b/fluidsynth/src/synth/fluid_synth.c @@ -665,7 +665,7 @@ new_fluid_synth(fluid_settings_t *settings) /* In an overflow situation, a new voice takes about 50 spaces in the queue! */ synth->eventhandler = new_fluid_rvoice_eventhandler(i, synth->polyphony*64, synth->polyphony, - nbuf, synth->effects_channels); + nbuf, synth->effects_channels, (int)synth->sample_rate); if (synth->eventhandler == NULL) goto error_recovery;