13
0
livetrax/libs/fluidsynth/src/fluid_rvoice_dsp.c

637 lines
26 KiB
C

/* FluidSynth - A Software Synthesizer
*
* Copyright (C) 2003 Peter Hanappe and others.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA
*/
#include "fluid_sys.h"
#include "fluid_phase.h"
#include "fluid_rvoice.h"
#include "fluid_rvoice_dsp_tables.c"
/* Purpose:
*
* Interpolates audio data (obtains values between the samples of the original
* waveform data).
*
* Variables loaded from the voice structure (assigned in fluid_rvoice_write()):
* - dsp_data: Pointer to the original waveform data
* - dsp_phase: The position in the original waveform data.
* This has an integer and a fractional part (between samples).
* - dsp_phase_incr: For each output sample, the position in the original
* waveform advances by dsp_phase_incr. This also has an integer
* part and a fractional part.
* If a sample is played at root pitch (no pitch change),
* dsp_phase_incr is integer=1 and fractional=0.
* - dsp_amp: The current amplitude envelope value.
* - dsp_amp_incr: The changing rate of the amplitude envelope.
*
* A couple of variables are used internally, their results are discarded:
* - dsp_i: Index through the output buffer
* - dsp_buf: Output buffer of floating point values (FLUID_BUFSIZE in length)
*/
/* Interpolation (find a value between two samples of the original waveform) */
static FLUID_INLINE fluid_real_t
fluid_rvoice_get_float_sample(const short int *dsp_msb, const char *dsp_lsb, unsigned int idx)
{
int32_t sample = fluid_rvoice_get_sample(dsp_msb, dsp_lsb, idx);
return (fluid_real_t)sample;
}
/* No interpolation. Just take the sample, which is closest to
* the playback pointer. Questionable quality, but very
* efficient. */
int
fluid_rvoice_dsp_interpolate_none(fluid_rvoice_dsp_t *voice, fluid_real_t *FLUID_RESTRICT dsp_buf, int looping)
{
fluid_phase_t dsp_phase = voice->phase;
fluid_phase_t dsp_phase_incr;
short int *dsp_data = voice->sample->data;
char *dsp_data24 = voice->sample->data24;
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;
/* Convert playback "speed" floating point value to phase index/fract */
fluid_phase_set_float(dsp_phase_incr, voice->phase_incr);
end_index = looping ? voice->loopend - 1 : voice->end;
while(1)
{
dsp_phase_index = fluid_phase_index_round(dsp_phase); /* round to nearest point */
/* interpolate sequence of sample points */
for(; dsp_i < FLUID_BUFSIZE && dsp_phase_index <= end_index; dsp_i++)
{
dsp_buf[dsp_i] = dsp_amp * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index);
/* increment phase and amplitude */
fluid_phase_incr(dsp_phase, dsp_phase_incr);
dsp_phase_index = fluid_phase_index_round(dsp_phase); /* round to nearest point */
dsp_amp += dsp_amp_incr;
}
/* break out if not looping (buffer may not be full) */
if(!looping)
{
break;
}
/* go back to loop start */
if(dsp_phase_index > end_index)
{
fluid_phase_sub_int(dsp_phase, voice->loopend - voice->loopstart);
voice->has_looped = 1;
}
/* break out if filled buffer */
if(dsp_i >= FLUID_BUFSIZE)
{
break;
}
}
voice->phase = dsp_phase;
voice->amp = dsp_amp;
return (dsp_i);
}
/* Straight line interpolation.
* Returns number of samples processed (usually FLUID_BUFSIZE but could be
* smaller if end of sample occurs).
*/
int
fluid_rvoice_dsp_interpolate_linear(fluid_rvoice_dsp_t *voice, fluid_real_t *FLUID_RESTRICT dsp_buf, int looping)
{
fluid_phase_t dsp_phase = voice->phase;
fluid_phase_t dsp_phase_incr;
short int *dsp_data = voice->sample->data;
char *dsp_data24 = voice->sample->data24;
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;
fluid_real_t point;
const fluid_real_t *FLUID_RESTRICT coeffs;
/* Convert playback "speed" floating point value to phase index/fract */
fluid_phase_set_float(dsp_phase_incr, voice->phase_incr);
/* last index before 2nd interpolation point must be specially handled */
end_index = (looping ? voice->loopend - 1 : voice->end) - 1;
/* 2nd interpolation point to use at end of loop or sample */
if(looping)
{
point = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopstart); /* loop start */
}
else
{
point = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->end); /* duplicate end for samples no longer looping */
}
while(1)
{
dsp_phase_index = fluid_phase_index(dsp_phase);
/* interpolate the sequence of sample points */
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] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index)
+ coeffs[1] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 1));
/* increment phase and amplitude */
fluid_phase_incr(dsp_phase, dsp_phase_incr);
dsp_phase_index = fluid_phase_index(dsp_phase);
dsp_amp += dsp_amp_incr;
}
/* break out if buffer filled */
if(dsp_i >= FLUID_BUFSIZE)
{
break;
}
end_index++; /* we're now interpolating the last point */
/* interpolate within last point */
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] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index)
+ coeffs[1] * point);
/* increment phase and amplitude */
fluid_phase_incr(dsp_phase, dsp_phase_incr);
dsp_phase_index = fluid_phase_index(dsp_phase);
dsp_amp += dsp_amp_incr; /* increment amplitude */
}
if(!looping)
{
break; /* break out if not looping (end of sample) */
}
/* go back to loop start (if past */
if(dsp_phase_index > end_index)
{
fluid_phase_sub_int(dsp_phase, voice->loopend - voice->loopstart);
voice->has_looped = 1;
}
/* break out if filled buffer */
if(dsp_i >= FLUID_BUFSIZE)
{
break;
}
end_index--; /* set end back to second to last sample point */
}
voice->phase = dsp_phase;
voice->amp = dsp_amp;
return (dsp_i);
}
/* 4th order (cubic) interpolation.
* Returns number of samples processed (usually FLUID_BUFSIZE but could be
* smaller if end of sample occurs).
*/
int
fluid_rvoice_dsp_interpolate_4th_order(fluid_rvoice_dsp_t *voice, fluid_real_t *FLUID_RESTRICT dsp_buf, int looping)
{
fluid_phase_t dsp_phase = voice->phase;
fluid_phase_t dsp_phase_incr;
short int *dsp_data = voice->sample->data;
char *dsp_data24 = voice->sample->data24;
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;
fluid_real_t start_point, end_point1, end_point2;
const fluid_real_t *FLUID_RESTRICT coeffs;
/* Convert playback "speed" floating point value to phase index/fract */
fluid_phase_set_float(dsp_phase_incr, voice->phase_incr);
/* last index before 4th interpolation point must be specially handled */
end_index = (looping ? voice->loopend - 1 : voice->end) - 2;
if(voice->has_looped) /* set start_index and start point if looped or not */
{
start_index = voice->loopstart;
start_point = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopend - 1); /* last point in loop (wrap around) */
}
else
{
start_index = voice->start;
start_point = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->start); /* just duplicate the point */
}
/* get points off the end (loop start if looping, duplicate point if end) */
if(looping)
{
end_point1 = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopstart);
end_point2 = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopstart + 1);
}
else
{
end_point1 = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->end);
end_point2 = end_point1;
}
while(1)
{
dsp_phase_index = fluid_phase_index(dsp_phase);
/* interpolate first sample point (start or loop start) if needed */
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] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index)
+ coeffs[2] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 1)
+ coeffs[3] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 2));
/* increment phase and amplitude */
fluid_phase_incr(dsp_phase, dsp_phase_incr);
dsp_phase_index = fluid_phase_index(dsp_phase);
dsp_amp += dsp_amp_incr;
}
/* interpolate the sequence of sample points */
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] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 1)
+ coeffs[1] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index)
+ coeffs[2] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 1)
+ coeffs[3] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 2));
/* increment phase and amplitude */
fluid_phase_incr(dsp_phase, dsp_phase_incr);
dsp_phase_index = fluid_phase_index(dsp_phase);
dsp_amp += dsp_amp_incr;
}
/* break out if buffer filled */
if(dsp_i >= FLUID_BUFSIZE)
{
break;
}
end_index++; /* we're now interpolating the 2nd to last point */
/* interpolate within 2nd to last point */
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] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 1)
+ coeffs[1] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index)
+ coeffs[2] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 1)
+ coeffs[3] * end_point1);
/* increment phase and amplitude */
fluid_phase_incr(dsp_phase, dsp_phase_incr);
dsp_phase_index = fluid_phase_index(dsp_phase);
dsp_amp += dsp_amp_incr;
}
end_index++; /* we're now interpolating the last point */
/* interpolate within the last point */
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] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 1)
+ coeffs[1] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index)
+ coeffs[2] * end_point1
+ coeffs[3] * end_point2);
/* increment phase and amplitude */
fluid_phase_incr(dsp_phase, dsp_phase_incr);
dsp_phase_index = fluid_phase_index(dsp_phase);
dsp_amp += dsp_amp_incr;
}
if(!looping)
{
break; /* break out if not looping (end of sample) */
}
/* go back to loop start */
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 = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopend - 1);
}
}
/* break out if filled buffer */
if(dsp_i >= FLUID_BUFSIZE)
{
break;
}
end_index -= 2; /* set end back to third to last sample point */
}
voice->phase = dsp_phase;
voice->amp = dsp_amp;
return (dsp_i);
}
/* 7th order interpolation.
* Returns number of samples processed (usually FLUID_BUFSIZE but could be
* smaller if end of sample occurs).
*/
int
fluid_rvoice_dsp_interpolate_7th_order(fluid_rvoice_dsp_t *voice, fluid_real_t *FLUID_RESTRICT dsp_buf, int looping)
{
fluid_phase_t dsp_phase = voice->phase;
fluid_phase_t dsp_phase_incr;
short int *dsp_data = voice->sample->data;
char *dsp_data24 = voice->sample->data24;
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;
fluid_real_t start_points[3], end_points[3];
const fluid_real_t *FLUID_RESTRICT coeffs;
/* Convert playback "speed" floating point value to phase index/fract */
fluid_phase_set_float(dsp_phase_incr, voice->phase_incr);
/* add 1/2 sample to dsp_phase since 7th order interpolation is centered on
* the 4th sample point */
fluid_phase_incr(dsp_phase, (fluid_phase_t)0x80000000);
/* last index before 7th interpolation point must be specially handled */
end_index = (looping ? voice->loopend - 1 : voice->end) - 3;
if(voice->has_looped) /* set start_index and start point if looped or not */
{
start_index = voice->loopstart;
start_points[0] = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopend - 1);
start_points[1] = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopend - 2);
start_points[2] = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopend - 3);
}
else
{
start_index = voice->start;
start_points[0] = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->start); /* just duplicate the start point */
start_points[1] = start_points[0];
start_points[2] = start_points[0];
}
/* get the 3 points off the end (loop start if looping, duplicate point if end) */
if(looping)
{
end_points[0] = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopstart);
end_points[1] = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopstart + 1);
end_points[2] = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopstart + 2);
}
else
{
end_points[0] = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->end);
end_points[1] = end_points[0];
end_points[2] = end_points[0];
}
while(1)
{
dsp_phase_index = fluid_phase_index(dsp_phase);
/* interpolate first sample point (start or loop start) if needed */
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] * start_points[2]
+ coeffs[1] * start_points[1]
+ coeffs[2] * start_points[0]
+ coeffs[3] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index)
+ coeffs[4] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 1)
+ coeffs[5] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 2)
+ coeffs[6] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 3));
/* increment phase and amplitude */
fluid_phase_incr(dsp_phase, dsp_phase_incr);
dsp_phase_index = fluid_phase_index(dsp_phase);
dsp_amp += dsp_amp_incr;
}
start_index++;
/* interpolate 2nd to first sample point (start or loop start) if needed */
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] * start_points[1]
+ coeffs[1] * start_points[0]
+ coeffs[2] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 1)
+ coeffs[3] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index)
+ coeffs[4] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 1)
+ coeffs[5] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 2)
+ coeffs[6] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 3));
/* increment phase and amplitude */
fluid_phase_incr(dsp_phase, dsp_phase_incr);
dsp_phase_index = fluid_phase_index(dsp_phase);
dsp_amp += dsp_amp_incr;
}
start_index++;
/* interpolate 3rd to first sample point (start or loop start) if needed */
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] * start_points[0]
+ coeffs[1] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 2)
+ coeffs[2] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 1)
+ coeffs[3] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index)
+ coeffs[4] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 1)
+ coeffs[5] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 2)
+ coeffs[6] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 3));
/* increment phase and amplitude */
fluid_phase_incr(dsp_phase, dsp_phase_incr);
dsp_phase_index = fluid_phase_index(dsp_phase);
dsp_amp += dsp_amp_incr;
}
start_index -= 2; /* set back to original start index */
/* interpolate the sequence of sample points */
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_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 3)
+ coeffs[1] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 2)
+ coeffs[2] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 1)
+ coeffs[3] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index)
+ coeffs[4] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 1)
+ coeffs[5] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 2)
+ coeffs[6] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 3));
/* increment phase and amplitude */
fluid_phase_incr(dsp_phase, dsp_phase_incr);
dsp_phase_index = fluid_phase_index(dsp_phase);
dsp_amp += dsp_amp_incr;
}
/* break out if buffer filled */
if(dsp_i >= FLUID_BUFSIZE)
{
break;
}
end_index++; /* we're now interpolating the 3rd to last point */
/* interpolate within 3rd to last point */
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_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 3)
+ coeffs[1] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 2)
+ coeffs[2] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 1)
+ coeffs[3] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index)
+ coeffs[4] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 1)
+ coeffs[5] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 2)
+ coeffs[6] * end_points[0]);
/* increment phase and amplitude */
fluid_phase_incr(dsp_phase, dsp_phase_incr);
dsp_phase_index = fluid_phase_index(dsp_phase);
dsp_amp += dsp_amp_incr;
}
end_index++; /* we're now interpolating the 2nd to last point */
/* interpolate within 2nd to last point */
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_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 3)
+ coeffs[1] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 2)
+ coeffs[2] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 1)
+ coeffs[3] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index)
+ coeffs[4] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 1)
+ coeffs[5] * end_points[0]
+ coeffs[6] * end_points[1]);
/* increment phase and amplitude */
fluid_phase_incr(dsp_phase, dsp_phase_incr);
dsp_phase_index = fluid_phase_index(dsp_phase);
dsp_amp += dsp_amp_incr;
}
end_index++; /* we're now interpolating the last point */
/* interpolate within last point */
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_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 3)
+ coeffs[1] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 2)
+ coeffs[2] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 1)
+ coeffs[3] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index)
+ coeffs[4] * end_points[0]
+ coeffs[5] * end_points[1]
+ coeffs[6] * end_points[2]);
/* increment phase and amplitude */
fluid_phase_incr(dsp_phase, dsp_phase_incr);
dsp_phase_index = fluid_phase_index(dsp_phase);
dsp_amp += dsp_amp_incr;
}
if(!looping)
{
break; /* break out if not looping (end of sample) */
}
/* go back to loop start */
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] = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopend - 1);
start_points[1] = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopend - 2);
start_points[2] = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopend - 3);
}
}
/* break out if filled buffer */
if(dsp_i >= FLUID_BUFSIZE)
{
break;
}
end_index -= 3; /* set end back to 4th to last sample point */
}
/* sub 1/2 sample from dsp_phase since 7th order interpolation is centered on
* the 4th sample point (correct back to real value) */
fluid_phase_decr(dsp_phase, (fluid_phase_t)0x80000000);
voice->phase = dsp_phase;
voice->amp = dsp_amp;
return (dsp_i);
}