diff options
author | Robin Gareus <robin@gareus.org> | 2018-10-18 00:41:02 +0200 |
---|---|---|
committer | Robin Gareus <robin@gareus.org> | 2018-10-18 01:43:43 +0200 |
commit | abf7905d5f82ad796544aa664cf3abaf20385cf7 (patch) | |
tree | 982dc729adea5bb604a12cd511f5f20a95a9b74d /libs/fluidsynth/src/fluid_rvoice_dsp.c | |
parent | 5b280463ce220ca27c067ce33cd9af2f457f240b (diff) |
Update Fluidsynth to 2.0.1
Diffstat (limited to 'libs/fluidsynth/src/fluid_rvoice_dsp.c')
-rw-r--r-- | libs/fluidsynth/src/fluid_rvoice_dsp.c | 1112 |
1 files changed, 576 insertions, 536 deletions
diff --git a/libs/fluidsynth/src/fluid_rvoice_dsp.c b/libs/fluidsynth/src/fluid_rvoice_dsp.c index df7da5022d..cc162829f6 100644 --- a/libs/fluidsynth/src/fluid_rvoice_dsp.c +++ b/libs/fluidsynth/src/fluid_rvoice_dsp.c @@ -3,16 +3,16 @@ * 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 Library General Public License - * as published by the Free Software Foundation; either version 2 of + * 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 - * Library General Public License for more details. + * Lesser General Public License for more details. * - * You should have received a copy of the GNU Library General Public + * 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 @@ -28,7 +28,7 @@ * Interpolates audio data (obtains values between the samples of the original * waveform data). * - * Variables loaded from the voice structure (assigned in fluid_voice_write()): + * 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). @@ -61,122 +61,138 @@ static fluid_real_t sinc_table7[FLUID_INTERP_MAX][7]; /* Initializes interpolation tables */ -void fluid_rvoice_dsp_config (void) +void fluid_rvoice_dsp_config(void) { - int i, i2; - double x, v; - double i_shifted; - - /* Initialize the coefficients for the interpolation. The math comes - * from a mail, posted by Olli Niemitalo to the music-dsp mailing - * list (I found it in the music-dsp archives - * http://www.smartelectronix.com/musicdsp/). */ - - 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; - } - - /* i: Offset in terms of whole samples */ - for (i = 0; i < SINC_INTERP_ORDER; i++) - { /* i2: Offset in terms of fractional samples ('subsamples') */ - for (i2 = 0; i2 < FLUID_INTERP_MAX; i2++) + int i, i2; + double x, v; + double i_shifted; + + /* Initialize the coefficients for the interpolation. The math comes + * from a mail, posted by Olli Niemitalo to the music-dsp mailing + * list (I found it in the music-dsp archives + * http://www.smartelectronix.com/musicdsp/). */ + + 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; + } + + /* i: Offset in terms of whole samples */ + for(i = 0; i < SINC_INTERP_ORDER; i++) { - /* center on middle of table */ - i_shifted = (double)i - ((double)SINC_INTERP_ORDER / 2.0) - + (double)i2 / (double)FLUID_INTERP_MAX; - - /* sinc(0) cannot be calculated straightforward (limit needed for 0/0) */ - if (fabs (i_shifted) > 0.000001) - { - v = (fluid_real_t)sin (i_shifted * M_PI) / (M_PI * i_shifted); - /* Hamming window */ - 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; + /* i2: Offset in terms of fractional samples ('subsamples') */ + for(i2 = 0; i2 < FLUID_INTERP_MAX; i2++) + { + /* center on middle of table */ + i_shifted = (double)i - ((double)SINC_INTERP_ORDER / 2.0) + + (double)i2 / (double)FLUID_INTERP_MAX; + + /* sinc(0) cannot be calculated straightforward (limit needed for 0/0) */ + if(fabs(i_shifted) > 0.000001) + { + double arg = M_PI * i_shifted; + v = (fluid_real_t)sin(arg) / (arg); + /* Hanning window */ + v *= (fluid_real_t)0.5 * (1.0 + cos(2.0 * arg / (fluid_real_t)SINC_INTERP_ORDER)); + } + else + { + v = 1.0; + } + + sinc_table7[FLUID_INTERP_MAX - i2 - 1][i] = v; + } } - } #if 0 - for (i = 0; i < FLUID_INTERP_MAX; i++) - { - printf ("%d %0.3f %0.3f %0.3f %0.3f %0.3f %0.3f %0.3f\n", - i, sinc_table7[0][i], sinc_table7[1][i], sinc_table7[2][i], - sinc_table7[3][i], sinc_table7[4][i], sinc_table7[5][i], sinc_table7[6][i]); - } + + for(i = 0; i < FLUID_INTERP_MAX; i++) + { + printf("%d %0.3f %0.3f %0.3f %0.3f %0.3f %0.3f %0.3f\n", + i, sinc_table7[0][i], sinc_table7[1][i], sinc_table7[2][i], + sinc_table7[3][i], sinc_table7[4][i], sinc_table7[5][i], sinc_table7[6][i]); + } + #endif - fluid_check_fpe("interpolation table calculation"); + fluid_check_fpe("interpolation table calculation"); +} + +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_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; - 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; - - /* Convert playback "speed" floating point value to phase index/fract */ - fluid_phase_set_float (dsp_phase_incr, voice->phase_incr); - - /* voice is currently looping? */ - looping = voice->is_looping; - - 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++) + 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_buf[dsp_i] = dsp_amp * dsp_data[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; + 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; + } } - /* 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; - } + voice->phase = dsp_phase; + voice->amp = dsp_amp; - /* break out if filled buffer */ - if (dsp_i >= FLUID_BUFSIZE) break; - } - - voice->phase = dsp_phase; - voice->amp = dsp_amp; - - return (dsp_i); + return (dsp_i); } /* Straight line interpolation. @@ -184,88 +200,99 @@ fluid_rvoice_dsp_interpolate_none (fluid_rvoice_dsp_t *voice) * smaller if end of sample occurs). */ int -fluid_rvoice_dsp_interpolate_linear (fluid_rvoice_dsp_t *voice) +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; - 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; - - /* Convert playback "speed" floating point value to phase index/fract */ - fluid_phase_set_float (dsp_phase_incr, voice->phase_incr); - - /* voice is currently looping? */ - looping = voice->is_looping; - - /* 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 = dsp_data[voice->loopstart]; /* loop start */ - else point = dsp_data[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++) + 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) { - 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]); - - /* 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; + point = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopstart); /* loop start */ } - - /* 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++) + else { - 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); - - /* 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 */ + point = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->end); /* duplicate end for samples no longer looping */ } - if (!looping) break; /* break out if not looping (end of sample) */ - - /* go back to loop start (if past */ - if (dsp_phase_index > end_index) + while(1) { - fluid_phase_sub_int (dsp_phase, voice->loopend - voice->loopstart); - voice->has_looped = 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 */ } - /* 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; - voice->phase = dsp_phase; - voice->amp = dsp_amp; - - return (dsp_i); + return (dsp_i); } /* 4th order (cubic) interpolation. @@ -273,149 +300,158 @@ fluid_rvoice_dsp_interpolate_linear (fluid_rvoice_dsp_t *voice) * smaller if end of sample occurs). */ int -fluid_rvoice_dsp_interpolate_4th_order (fluid_rvoice_dsp_t *voice) +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; - 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; - - /* Convert playback "speed" floating point value to phase index/fract */ - fluid_phase_set_float (dsp_phase_incr, voice->phase_incr); - - /* voice is currently looping? */ - looping = voice->is_looping; - - /* 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 = dsp_data[voice->loopend - 1]; /* last point in loop (wrap around) */ - } - else - { - start_index = voice->start; - start_point = dsp_data[voice->start]; /* just duplicate the point */ - } - - /* get points off the end (loop start if looping, duplicate point if end) */ - 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); - - /* interpolate first sample point (start or loop start) if needed */ - for ( ; dsp_phase_index == start_index && dsp_i < FLUID_BUFSIZE; dsp_i++) + 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 */ { - 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]); - - /* 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 = voice->loopstart; + start_point = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopend - 1); /* last point in loop (wrap around) */ } - - /* interpolate the sequence of sample points */ - for ( ; dsp_i < FLUID_BUFSIZE && dsp_phase_index <= end_index; dsp_i++) + else { - 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]); - - /* 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 = voice->start; + start_point = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->start); /* just duplicate the point */ } - /* 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++) + /* get points off the end (loop start if looping, duplicate point if end) */ + if(looping) { - 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); - - /* 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_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); } - - 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++) + else { - 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); - - /* 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_point1 = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->end); + end_point2 = end_point1; } - if (!looping) break; /* break out if not looping (end of sample) */ - - /* go back to loop start */ - if (dsp_phase_index > end_index) + while(1) { - 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]; - } + 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 */ } - /* break out if filled buffer */ - if (dsp_i >= FLUID_BUFSIZE) break; + voice->phase = dsp_phase; + voice->amp = dsp_amp; - end_index -= 2; /* set end back to third to last sample point */ - } - - voice->phase = dsp_phase; - voice->amp = dsp_amp; - - return (dsp_i); + return (dsp_i); } /* 7th order interpolation. @@ -423,253 +459,257 @@ fluid_rvoice_dsp_interpolate_4th_order (fluid_rvoice_dsp_t *voice) * smaller if end of sample occurs). */ int -fluid_rvoice_dsp_interpolate_7th_order (fluid_rvoice_dsp_t *voice) +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; - 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; - - /* 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); - - /* voice is currently looping? */ - looping = voice->is_looping; - - /* 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] = 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]; /* 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] = 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); - - /* 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] * (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]); - - /* 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] * (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]); - - /* 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++) + 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 */ { - 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]); - - /* 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 = 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); } - - 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_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]); - - /* 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++) + else { - 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]); - - /* 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 = 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]; } - 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++) + /* get the 3 points off the end (loop start if looping, duplicate point if end) */ + if(looping) { - 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]); - - /* 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_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); } - - 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++) + else { - 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]); - - /* 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_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]; } - if (!looping) break; /* break out if not looping (end of sample) */ - - /* go back to loop start */ - if (dsp_phase_index > end_index) + while(1) { - 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]; - } + 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 */ } - /* 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); + /* 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; + voice->phase = dsp_phase; + voice->amp = dsp_amp; - return (dsp_i); + return (dsp_i); } |