#include "fluidsynth_priv.h"
#include "fluid_phase.h"
#include "fluidsynth_priv.h"
#include "fluid_synth.h"
#include "fluid_voice.h"
static fluid_real_t interp_coeff_linear[FLUID_INTERP_MAX][2];
static fluid_real_t interp_coeff[FLUID_INTERP_MAX][4];
static fluid_real_t sinc_table7[FLUID_INTERP_MAX][7];
#define SINC_INTERP_ORDER 7
void fluid_dsp_float_config (void)
{
int i, i2;
double x, v;
double i_shifted;
for (i = 0; i < FLUID_INTERP_MAX; i++)
{
x = (double) i / (double) FLUID_INTERP_MAX;
interp_coeff[i][0] = (fluid_real_t)(x * (-0.5 + x * (1 - 0.5 * x)));
interp_coeff[i][1] = (fluid_real_t)(1.0 + x * x * (1.5 * x - 2.5));
interp_coeff[i][2] = (fluid_real_t)(x * (0.5 + x * (2.0 - 1.5 * x)));
interp_coeff[i][3] = (fluid_real_t)(0.5 * x * x * (x - 1.0));
interp_coeff_linear[i][0] = (fluid_real_t)(1.0 - x);
interp_coeff_linear[i][1] = (fluid_real_t)x;
}
for (i = 0; i < SINC_INTERP_ORDER; i++)
{
for (i2 = 0; i2 < FLUID_INTERP_MAX; i2++)
{
i_shifted = (double)i - ((double)SINC_INTERP_ORDER / 2.0)
+ (double)i2 / (double)FLUID_INTERP_MAX;
if (fabs (i_shifted) > 0.000001)
{
v = (fluid_real_t)sin (i_shifted * M_PI) / (M_PI * i_shifted);
v *= (fluid_real_t)0.5 * (1.0 + cos (2.0 * M_PI * i_shifted / (fluid_real_t)SINC_INTERP_ORDER));
}
else v = 1.0;
sinc_table7[FLUID_INTERP_MAX - i2 - 1][i] = v;
}
}
#if 0#endif
}
int
fluid_dsp_float_interpolate_none (fluid_voice_t *voice)
{
fluid_phase_t dsp_phase = voice->phase;
fluid_phase_t dsp_phase_incr;
short int *dsp_data = voice->sample->data;
fluid_real_t *dsp_buf = voice->dsp_buf;
fluid_real_t dsp_amp = voice->amp;
fluid_real_t dsp_amp_incr = voice->amp_incr;
unsigned int dsp_i = 0;
unsigned int dsp_phase_index;
unsigned int end_index;
int looping;
fluid_phase_set_float (dsp_phase_incr, voice->phase_incr);
looping = _SAMPLEMODE (voice) == FLUID_LOOP_DURING_RELEASE
|| (_SAMPLEMODE (voice) == FLUID_LOOP_UNTIL_RELEASE
&& voice->volenv_section < FLUID_VOICE_ENVRELEASE);
end_index = looping ? voice->loopend - 1 : voice->end;
while (1)
{
dsp_phase_index = fluid_phase_index_round (dsp_phase);
for ( ; dsp_i < FLUID_BUFSIZE && dsp_phase_index <= end_index; dsp_i++)
{
dsp_buf[dsp_i] = dsp_amp * dsp_data[dsp_phase_index];
fluid_phase_incr (dsp_phase, dsp_phase_incr);
dsp_phase_index = fluid_phase_index_round (dsp_phase);
dsp_amp += dsp_amp_incr;
}
if (!looping) break;
if (dsp_phase_index > end_index)
{
fluid_phase_sub_int (dsp_phase, voice->loopend - voice->loopstart);
voice->has_looped = 1;
}
if (dsp_i >= FLUID_BUFSIZE) break;
}
voice->phase = dsp_phase;
voice->amp = dsp_amp;
return (dsp_i);
}
int
fluid_dsp_float_interpolate_linear (fluid_voice_t *voice)
{
fluid_phase_t dsp_phase = voice->phase;
fluid_phase_t dsp_phase_incr;
short int *dsp_data = voice->sample->data;
fluid_real_t *dsp_buf = voice->dsp_buf;
fluid_real_t dsp_amp = voice->amp;
fluid_real_t dsp_amp_incr = voice->amp_incr;
unsigned int dsp_i = 0;
unsigned int dsp_phase_index;
unsigned int end_index;
short int point;
fluid_real_t *coeffs;
int looping;
fluid_phase_set_float (dsp_phase_incr, voice->phase_incr);
looping = _SAMPLEMODE (voice) == FLUID_LOOP_DURING_RELEASE
|| (_SAMPLEMODE (voice) == FLUID_LOOP_UNTIL_RELEASE
&& voice->volenv_section < FLUID_VOICE_ENVRELEASE);
end_index = (looping ? voice->loopend - 1 : voice->end) - 1;
if (looping) point = dsp_data[voice->loopstart];
else point = dsp_data[voice->end];
while (1)
{
dsp_phase_index = fluid_phase_index (dsp_phase);
for ( ; dsp_i < FLUID_BUFSIZE && dsp_phase_index <= end_index; dsp_i++)
{
coeffs = interp_coeff_linear[fluid_phase_fract_to_tablerow (dsp_phase)];
dsp_buf[dsp_i] = dsp_amp * (coeffs[0] * dsp_data[dsp_phase_index]
+ coeffs[1] * dsp_data[dsp_phase_index+1]);
fluid_phase_incr (dsp_phase, dsp_phase_incr);
dsp_phase_index = fluid_phase_index (dsp_phase);
dsp_amp += dsp_amp_incr;
}
if (dsp_i >= FLUID_BUFSIZE) break;
end_index++;
for (; dsp_phase_index <= end_index && dsp_i < FLUID_BUFSIZE; dsp_i++)
{
coeffs = interp_coeff_linear[fluid_phase_fract_to_tablerow (dsp_phase)];
dsp_buf[dsp_i] = dsp_amp * (coeffs[0] * dsp_data[dsp_phase_index]
+ coeffs[1] * point);
fluid_phase_incr (dsp_phase, dsp_phase_incr);
dsp_phase_index = fluid_phase_index (dsp_phase);
dsp_amp += dsp_amp_incr;
}
if (!looping) break;
if (dsp_phase_index > end_index)
{
fluid_phase_sub_int (dsp_phase, voice->loopend - voice->loopstart);
voice->has_looped = 1;
}
if (dsp_i >= FLUID_BUFSIZE) break;
end_index--;
}
voice->phase = dsp_phase;
voice->amp = dsp_amp;
return (dsp_i);
}
int
fluid_dsp_float_interpolate_4th_order (fluid_voice_t *voice)
{
fluid_phase_t dsp_phase = voice->phase;
fluid_phase_t dsp_phase_incr;
short int *dsp_data = voice->sample->data;
fluid_real_t *dsp_buf = voice->dsp_buf;
fluid_real_t dsp_amp = voice->amp;
fluid_real_t dsp_amp_incr = voice->amp_incr;
unsigned int dsp_i = 0;
unsigned int dsp_phase_index;
unsigned int start_index, end_index;
short int start_point, end_point1, end_point2;
fluid_real_t *coeffs;
int looping;
fluid_phase_set_float (dsp_phase_incr, voice->phase_incr);
looping = _SAMPLEMODE (voice) == FLUID_LOOP_DURING_RELEASE
|| (_SAMPLEMODE (voice) == FLUID_LOOP_UNTIL_RELEASE
&& voice->volenv_section < FLUID_VOICE_ENVRELEASE);
end_index = (looping ? voice->loopend - 1 : voice->end) - 2;
if (voice->has_looped)
{
start_index = voice->loopstart;
start_point = dsp_data[voice->loopend - 1];
}
else
{
start_index = voice->start;
start_point = dsp_data[voice->start];
}
if (looping)
{
end_point1 = dsp_data[voice->loopstart];
end_point2 = dsp_data[voice->loopstart + 1];
}
else
{
end_point1 = dsp_data[voice->end];
end_point2 = end_point1;
}
while (1)
{
dsp_phase_index = fluid_phase_index (dsp_phase);
for ( ; dsp_phase_index == start_index && dsp_i < FLUID_BUFSIZE; dsp_i++)
{
coeffs = interp_coeff[fluid_phase_fract_to_tablerow (dsp_phase)];
dsp_buf[dsp_i] = dsp_amp * (coeffs[0] * start_point
+ coeffs[1] * dsp_data[dsp_phase_index]
+ coeffs[2] * dsp_data[dsp_phase_index+1]
+ coeffs[3] * dsp_data[dsp_phase_index+2]);
fluid_phase_incr (dsp_phase, dsp_phase_incr);
dsp_phase_index = fluid_phase_index (dsp_phase);
dsp_amp += dsp_amp_incr;
}
for ( ; dsp_i < FLUID_BUFSIZE && dsp_phase_index <= end_index; dsp_i++)
{
coeffs = interp_coeff[fluid_phase_fract_to_tablerow (dsp_phase)];
dsp_buf[dsp_i] = dsp_amp * (coeffs[0] * dsp_data[dsp_phase_index-1]
+ coeffs[1] * dsp_data[dsp_phase_index]
+ coeffs[2] * dsp_data[dsp_phase_index+1]
+ coeffs[3] * dsp_data[dsp_phase_index+2]);
fluid_phase_incr (dsp_phase, dsp_phase_incr);
dsp_phase_index = fluid_phase_index (dsp_phase);
dsp_amp += dsp_amp_incr;
}
if (dsp_i >= FLUID_BUFSIZE) break;
end_index++;
for (; dsp_phase_index <= end_index && dsp_i < FLUID_BUFSIZE; dsp_i++)
{
coeffs = interp_coeff[fluid_phase_fract_to_tablerow (dsp_phase)];
dsp_buf[dsp_i] = dsp_amp * (coeffs[0] * dsp_data[dsp_phase_index-1]
+ coeffs[1] * dsp_data[dsp_phase_index]
+ coeffs[2] * dsp_data[dsp_phase_index+1]
+ coeffs[3] * end_point1);
fluid_phase_incr (dsp_phase, dsp_phase_incr);
dsp_phase_index = fluid_phase_index (dsp_phase);
dsp_amp += dsp_amp_incr;
}
end_index++;
for (; dsp_phase_index <= end_index && dsp_i < FLUID_BUFSIZE; dsp_i++)
{
coeffs = interp_coeff[fluid_phase_fract_to_tablerow (dsp_phase)];
dsp_buf[dsp_i] = dsp_amp * (coeffs[0] * dsp_data[dsp_phase_index-1]
+ coeffs[1] * dsp_data[dsp_phase_index]
+ coeffs[2] * end_point1
+ coeffs[3] * end_point2);
fluid_phase_incr (dsp_phase, dsp_phase_incr);
dsp_phase_index = fluid_phase_index (dsp_phase);
dsp_amp += dsp_amp_incr;
}
if (!looping) break;
if (dsp_phase_index > end_index)
{
fluid_phase_sub_int (dsp_phase, voice->loopend - voice->loopstart);
if (!voice->has_looped)
{
voice->has_looped = 1;
start_index = voice->loopstart;
start_point = dsp_data[voice->loopend - 1];
}
}
if (dsp_i >= FLUID_BUFSIZE) break;
end_index -= 2;
}
voice->phase = dsp_phase;
voice->amp = dsp_amp;
return (dsp_i);
}
int
fluid_dsp_float_interpolate_7th_order (fluid_voice_t *voice)
{
fluid_phase_t dsp_phase = voice->phase;
fluid_phase_t dsp_phase_incr;
short int *dsp_data = voice->sample->data;
fluid_real_t *dsp_buf = voice->dsp_buf;
fluid_real_t dsp_amp = voice->amp;
fluid_real_t dsp_amp_incr = voice->amp_incr;
unsigned int dsp_i = 0;
unsigned int dsp_phase_index;
unsigned int start_index, end_index;
short int start_points[3];
short int end_points[3];
fluid_real_t *coeffs;
int looping;
fluid_phase_set_float (dsp_phase_incr, voice->phase_incr);
fluid_phase_incr (dsp_phase, (fluid_phase_t)0x80000000);
looping = _SAMPLEMODE (voice) == FLUID_LOOP_DURING_RELEASE
|| (_SAMPLEMODE (voice) == FLUID_LOOP_UNTIL_RELEASE
&& voice->volenv_section < FLUID_VOICE_ENVRELEASE);
end_index = (looping ? voice->loopend - 1 : voice->end) - 3;
if (voice->has_looped)
{
start_index = voice->loopstart;
start_points[0] = dsp_data[voice->loopend - 1];
start_points[1] = dsp_data[voice->loopend - 2];
start_points[2] = dsp_data[voice->loopend - 3];
}
else
{
start_index = voice->start;
start_points[0] = dsp_data[voice->start];
start_points[1] = start_points[0];
start_points[2] = start_points[0];
}
if (looping)
{
end_points[0] = dsp_data[voice->loopstart];
end_points[1] = dsp_data[voice->loopstart + 1];
end_points[2] = dsp_data[voice->loopstart + 2];
}
else
{
end_points[0] = dsp_data[voice->end];
end_points[1] = end_points[0];
end_points[2] = end_points[0];
}
while (1)
{
dsp_phase_index = fluid_phase_index (dsp_phase);
for ( ; dsp_phase_index == start_index && dsp_i < FLUID_BUFSIZE; dsp_i++)
{
coeffs = sinc_table7[fluid_phase_fract_to_tablerow (dsp_phase)];
dsp_buf[dsp_i] = dsp_amp
* (coeffs[0] * (fluid_real_t)start_points[2]
+ coeffs[1] * (fluid_real_t)start_points[1]
+ coeffs[2] * (fluid_real_t)start_points[0]
+ coeffs[3] * (fluid_real_t)dsp_data[dsp_phase_index]
+ coeffs[4] * (fluid_real_t)dsp_data[dsp_phase_index+1]
+ coeffs[5] * (fluid_real_t)dsp_data[dsp_phase_index+2]
+ coeffs[6] * (fluid_real_t)dsp_data[dsp_phase_index+3]);
fluid_phase_incr (dsp_phase, dsp_phase_incr);
dsp_phase_index = fluid_phase_index (dsp_phase);
dsp_amp += dsp_amp_incr;
}
start_index++;
for ( ; dsp_phase_index == start_index && dsp_i < FLUID_BUFSIZE; dsp_i++)
{
coeffs = sinc_table7[fluid_phase_fract_to_tablerow (dsp_phase)];
dsp_buf[dsp_i] = dsp_amp
* (coeffs[0] * (fluid_real_t)start_points[1]
+ coeffs[1] * (fluid_real_t)start_points[0]
+ coeffs[2] * (fluid_real_t)dsp_data[dsp_phase_index-1]
+ coeffs[3] * (fluid_real_t)dsp_data[dsp_phase_index]
+ coeffs[4] * (fluid_real_t)dsp_data[dsp_phase_index+1]
+ coeffs[5] * (fluid_real_t)dsp_data[dsp_phase_index+2]
+ coeffs[6] * (fluid_real_t)dsp_data[dsp_phase_index+3]);
fluid_phase_incr (dsp_phase, dsp_phase_incr);
dsp_phase_index = fluid_phase_index (dsp_phase);
dsp_amp += dsp_amp_incr;
}
start_index++;
for ( ; dsp_phase_index == start_index && dsp_i < FLUID_BUFSIZE; dsp_i++)
{
coeffs = sinc_table7[fluid_phase_fract_to_tablerow (dsp_phase)];
dsp_buf[dsp_i] = dsp_amp
* (coeffs[0] * (fluid_real_t)start_points[0]
+ coeffs[1] * (fluid_real_t)dsp_data[dsp_phase_index-2]
+ coeffs[2] * (fluid_real_t)dsp_data[dsp_phase_index-1]
+ coeffs[3] * (fluid_real_t)dsp_data[dsp_phase_index]
+ coeffs[4] * (fluid_real_t)dsp_data[dsp_phase_index+1]
+ coeffs[5] * (fluid_real_t)dsp_data[dsp_phase_index+2]
+ coeffs[6] * (fluid_real_t)dsp_data[dsp_phase_index+3]);
fluid_phase_incr (dsp_phase, dsp_phase_incr);
dsp_phase_index = fluid_phase_index (dsp_phase);
dsp_amp += dsp_amp_incr;
}
start_index -= 2;
for ( ; dsp_i < FLUID_BUFSIZE && dsp_phase_index <= end_index; dsp_i++)
{
coeffs = sinc_table7[fluid_phase_fract_to_tablerow (dsp_phase)];
dsp_buf[dsp_i] = dsp_amp
* (coeffs[0] * (fluid_real_t)dsp_data[dsp_phase_index-3]
+ coeffs[1] * (fluid_real_t)dsp_data[dsp_phase_index-2]
+ coeffs[2] * (fluid_real_t)dsp_data[dsp_phase_index-1]
+ coeffs[3] * (fluid_real_t)dsp_data[dsp_phase_index]
+ coeffs[4] * (fluid_real_t)dsp_data[dsp_phase_index+1]
+ coeffs[5] * (fluid_real_t)dsp_data[dsp_phase_index+2]
+ coeffs[6] * (fluid_real_t)dsp_data[dsp_phase_index+3]);
fluid_phase_incr (dsp_phase, dsp_phase_incr);
dsp_phase_index = fluid_phase_index (dsp_phase);
dsp_amp += dsp_amp_incr;
}
if (dsp_i >= FLUID_BUFSIZE) break;
end_index++;
for (; dsp_phase_index <= end_index && dsp_i < FLUID_BUFSIZE; dsp_i++)
{
coeffs = sinc_table7[fluid_phase_fract_to_tablerow (dsp_phase)];
dsp_buf[dsp_i] = dsp_amp
* (coeffs[0] * (fluid_real_t)dsp_data[dsp_phase_index-3]
+ coeffs[1] * (fluid_real_t)dsp_data[dsp_phase_index-2]
+ coeffs[2] * (fluid_real_t)dsp_data[dsp_phase_index-1]
+ coeffs[3] * (fluid_real_t)dsp_data[dsp_phase_index]
+ coeffs[4] * (fluid_real_t)dsp_data[dsp_phase_index+1]
+ coeffs[5] * (fluid_real_t)dsp_data[dsp_phase_index+2]
+ coeffs[6] * (fluid_real_t)end_points[0]);
fluid_phase_incr (dsp_phase, dsp_phase_incr);
dsp_phase_index = fluid_phase_index (dsp_phase);
dsp_amp += dsp_amp_incr;
}
end_index++;
for (; dsp_phase_index <= end_index && dsp_i < FLUID_BUFSIZE; dsp_i++)
{
coeffs = sinc_table7[fluid_phase_fract_to_tablerow (dsp_phase)];
dsp_buf[dsp_i] = dsp_amp
* (coeffs[0] * (fluid_real_t)dsp_data[dsp_phase_index-3]
+ coeffs[1] * (fluid_real_t)dsp_data[dsp_phase_index-2]
+ coeffs[2] * (fluid_real_t)dsp_data[dsp_phase_index-1]
+ coeffs[3] * (fluid_real_t)dsp_data[dsp_phase_index]
+ coeffs[4] * (fluid_real_t)dsp_data[dsp_phase_index+1]
+ coeffs[5] * (fluid_real_t)end_points[0]
+ coeffs[6] * (fluid_real_t)end_points[1]);
fluid_phase_incr (dsp_phase, dsp_phase_incr);
dsp_phase_index = fluid_phase_index (dsp_phase);
dsp_amp += dsp_amp_incr;
}
end_index++;
for (; dsp_phase_index <= end_index && dsp_i < FLUID_BUFSIZE; dsp_i++)
{
coeffs = sinc_table7[fluid_phase_fract_to_tablerow (dsp_phase)];
dsp_buf[dsp_i] = dsp_amp
* (coeffs[0] * (fluid_real_t)dsp_data[dsp_phase_index-3]
+ coeffs[1] * (fluid_real_t)dsp_data[dsp_phase_index-2]
+ coeffs[2] * (fluid_real_t)dsp_data[dsp_phase_index-1]
+ coeffs[3] * (fluid_real_t)dsp_data[dsp_phase_index]
+ coeffs[4] * (fluid_real_t)end_points[0]
+ coeffs[5] * (fluid_real_t)end_points[1]
+ coeffs[6] * (fluid_real_t)end_points[2]);
fluid_phase_incr (dsp_phase, dsp_phase_incr);
dsp_phase_index = fluid_phase_index (dsp_phase);
dsp_amp += dsp_amp_incr;
}
if (!looping) break;
if (dsp_phase_index > end_index)
{
fluid_phase_sub_int (dsp_phase, voice->loopend - voice->loopstart);
if (!voice->has_looped)
{
voice->has_looped = 1;
start_index = voice->loopstart;
start_points[0] = dsp_data[voice->loopend - 1];
start_points[1] = dsp_data[voice->loopend - 2];
start_points[2] = dsp_data[voice->loopend - 3];
}
}
if (dsp_i >= FLUID_BUFSIZE) break;
end_index -= 3;
}
fluid_phase_decr (dsp_phase, (fluid_phase_t)0x80000000);
voice->phase = dsp_phase;
voice->amp = dsp_amp;
return (dsp_i);
}