Path: blob/master/libs/fluidsynth/src/rvoice/fluid_rvoice_dsp.c
4396 views
/* FluidSynth - A Software Synthesizer1*2* Copyright (C) 2003 Peter Hanappe and others.3*4* This library is free software; you can redistribute it and/or5* modify it under the terms of the GNU Lesser General Public License6* as published by the Free Software Foundation; either version 2.1 of7* the License, or (at your option) any later version.8*9* This library is distributed in the hope that it will be useful, but10* WITHOUT ANY WARRANTY; without even the implied warranty of11* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU12* Lesser General Public License for more details.13*14* You should have received a copy of the GNU Lesser General Public15* License along with this library; if not, write to the Free16* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA17* 02110-1301, USA18*/1920#include "fluid_sys.h"21#include "fluid_phase.h"22#include "fluid_rvoice.h"23#include "fluid_rvoice_dsp_tables.inc.h"2425/* Purpose:26*27* Interpolates audio data (obtains values between the samples of the original28* waveform data).29*30* Variables loaded from the voice structure (assigned in fluid_rvoice_write()):31* - dsp_data: Pointer to the original waveform data32* - dsp_phase: The position in the original waveform data.33* This has an integer and a fractional part (between samples).34* - dsp_phase_incr: For each output sample, the position in the original35* waveform advances by dsp_phase_incr. This also has an integer36* part and a fractional part.37* If a sample is played at root pitch (no pitch change),38* dsp_phase_incr is integer=1 and fractional=0.39* - dsp_amp: The current amplitude envelope value.40* - dsp_amp_incr: The changing rate of the amplitude envelope.41*42* A couple of variables are used internally, their results are discarded:43* - dsp_i: Index through the output buffer44* - dsp_buf: Output buffer of floating point values (FLUID_BUFSIZE in length)45*/4647/* Interpolation (find a value between two samples of the original waveform) */4849static FLUID_INLINE fluid_real_t50fluid_rvoice_get_float_sample(const short int *dsp_msb, const char *dsp_lsb, unsigned int idx)51{52int32_t sample = fluid_rvoice_get_sample(dsp_msb, dsp_lsb, idx);53return (fluid_real_t)sample;54}5556/* No interpolation. Just take the sample, which is closest to57* the playback pointer. Questionable quality, but very58* efficient. */59int60fluid_rvoice_dsp_interpolate_none(fluid_rvoice_dsp_t *voice, fluid_real_t *FLUID_RESTRICT dsp_buf, int looping)61{62fluid_phase_t dsp_phase = voice->phase;63fluid_phase_t dsp_phase_incr;64short int *dsp_data = voice->sample->data;65char *dsp_data24 = voice->sample->data24;66fluid_real_t dsp_amp = voice->amp;67fluid_real_t dsp_amp_incr = voice->amp_incr;68unsigned int dsp_i = 0;69unsigned int dsp_phase_index;70unsigned int end_index;7172/* Convert playback "speed" floating point value to phase index/fract */73fluid_phase_set_float(dsp_phase_incr, voice->phase_incr);7475end_index = looping ? voice->loopend - 1 : voice->end;7677while(1)78{79dsp_phase_index = fluid_phase_index_round(dsp_phase); /* round to nearest point */8081/* interpolate sequence of sample points */82for(; dsp_i < FLUID_BUFSIZE && dsp_phase_index <= end_index; dsp_i++)83{84dsp_buf[dsp_i] = dsp_amp * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index);8586/* increment phase and amplitude */87fluid_phase_incr(dsp_phase, dsp_phase_incr);88dsp_phase_index = fluid_phase_index_round(dsp_phase); /* round to nearest point */89dsp_amp += dsp_amp_incr;90}9192/* break out if not looping (buffer may not be full) */93if(!looping)94{95break;96}9798/* go back to loop start */99if(dsp_phase_index > end_index)100{101fluid_phase_sub_int(dsp_phase, voice->loopend - voice->loopstart);102voice->has_looped = 1;103}104105/* break out if filled buffer */106if(dsp_i >= FLUID_BUFSIZE)107{108break;109}110}111112voice->phase = dsp_phase;113voice->amp = dsp_amp;114115return (dsp_i);116}117118/* Straight line interpolation.119* Returns number of samples processed (usually FLUID_BUFSIZE but could be120* smaller if end of sample occurs).121*/122int123fluid_rvoice_dsp_interpolate_linear(fluid_rvoice_dsp_t *voice, fluid_real_t *FLUID_RESTRICT dsp_buf, int looping)124{125fluid_phase_t dsp_phase = voice->phase;126fluid_phase_t dsp_phase_incr;127short int *dsp_data = voice->sample->data;128char *dsp_data24 = voice->sample->data24;129fluid_real_t dsp_amp = voice->amp;130fluid_real_t dsp_amp_incr = voice->amp_incr;131unsigned int dsp_i = 0;132unsigned int dsp_phase_index;133unsigned int end_index;134fluid_real_t point;135const fluid_real_t *FLUID_RESTRICT coeffs;136137/* Convert playback "speed" floating point value to phase index/fract */138fluid_phase_set_float(dsp_phase_incr, voice->phase_incr);139140/* last index before 2nd interpolation point must be specially handled */141end_index = (looping ? voice->loopend - 1 : voice->end) - 1;142143/* 2nd interpolation point to use at end of loop or sample */144if(looping)145{146point = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopstart); /* loop start */147}148else149{150point = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->end); /* duplicate end for samples no longer looping */151}152153while(1)154{155dsp_phase_index = fluid_phase_index(dsp_phase);156157/* interpolate the sequence of sample points */158for(; dsp_i < FLUID_BUFSIZE && dsp_phase_index <= end_index; dsp_i++)159{160coeffs = interp_coeff_linear[fluid_phase_fract_to_tablerow(dsp_phase)];161dsp_buf[dsp_i] = dsp_amp * (coeffs[0] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index)162+ coeffs[1] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 1));163164/* increment phase and amplitude */165fluid_phase_incr(dsp_phase, dsp_phase_incr);166dsp_phase_index = fluid_phase_index(dsp_phase);167dsp_amp += dsp_amp_incr;168}169170/* break out if buffer filled */171if(dsp_i >= FLUID_BUFSIZE)172{173break;174}175176end_index++; /* we're now interpolating the last point */177178/* interpolate within last point */179for(; dsp_phase_index <= end_index && dsp_i < FLUID_BUFSIZE; dsp_i++)180{181coeffs = interp_coeff_linear[fluid_phase_fract_to_tablerow(dsp_phase)];182dsp_buf[dsp_i] = dsp_amp * (coeffs[0] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index)183+ coeffs[1] * point);184185/* increment phase and amplitude */186fluid_phase_incr(dsp_phase, dsp_phase_incr);187dsp_phase_index = fluid_phase_index(dsp_phase);188dsp_amp += dsp_amp_incr; /* increment amplitude */189}190191if(!looping)192{193break; /* break out if not looping (end of sample) */194}195196/* go back to loop start (if past */197if(dsp_phase_index > end_index)198{199fluid_phase_sub_int(dsp_phase, voice->loopend - voice->loopstart);200voice->has_looped = 1;201}202203/* break out if filled buffer */204if(dsp_i >= FLUID_BUFSIZE)205{206break;207}208209end_index--; /* set end back to second to last sample point */210}211212voice->phase = dsp_phase;213voice->amp = dsp_amp;214215return (dsp_i);216}217218/* 4th order (cubic) interpolation.219* Returns number of samples processed (usually FLUID_BUFSIZE but could be220* smaller if end of sample occurs).221*/222int223fluid_rvoice_dsp_interpolate_4th_order(fluid_rvoice_dsp_t *voice, fluid_real_t *FLUID_RESTRICT dsp_buf, int looping)224{225fluid_phase_t dsp_phase = voice->phase;226fluid_phase_t dsp_phase_incr;227short int *dsp_data = voice->sample->data;228char *dsp_data24 = voice->sample->data24;229fluid_real_t dsp_amp = voice->amp;230fluid_real_t dsp_amp_incr = voice->amp_incr;231unsigned int dsp_i = 0;232unsigned int dsp_phase_index;233unsigned int start_index, end_index;234fluid_real_t start_point, end_point1, end_point2;235const fluid_real_t *FLUID_RESTRICT coeffs;236237/* Convert playback "speed" floating point value to phase index/fract */238fluid_phase_set_float(dsp_phase_incr, voice->phase_incr);239240/* last index before 4th interpolation point must be specially handled */241end_index = (looping ? voice->loopend - 1 : voice->end) - 2;242243if(voice->has_looped) /* set start_index and start point if looped or not */244{245start_index = voice->loopstart;246start_point = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopend - 1); /* last point in loop (wrap around) */247}248else249{250start_index = voice->start;251start_point = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->start); /* just duplicate the point */252}253254/* get points off the end (loop start if looping, duplicate point if end) */255if(looping)256{257end_point1 = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopstart);258end_point2 = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopstart + 1);259}260else261{262end_point1 = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->end);263end_point2 = end_point1;264}265266while(1)267{268dsp_phase_index = fluid_phase_index(dsp_phase);269270/* interpolate first sample point (start or loop start) if needed */271for(; dsp_phase_index == start_index && dsp_i < FLUID_BUFSIZE; dsp_i++)272{273coeffs = interp_coeff[fluid_phase_fract_to_tablerow(dsp_phase)];274dsp_buf[dsp_i] = dsp_amp *275(coeffs[0] * start_point276+ coeffs[1] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index)277+ coeffs[2] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 1)278+ coeffs[3] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 2));279280/* increment phase and amplitude */281fluid_phase_incr(dsp_phase, dsp_phase_incr);282dsp_phase_index = fluid_phase_index(dsp_phase);283dsp_amp += dsp_amp_incr;284}285286/* interpolate the sequence of sample points */287for(; dsp_i < FLUID_BUFSIZE && dsp_phase_index <= end_index; dsp_i++)288{289coeffs = interp_coeff[fluid_phase_fract_to_tablerow(dsp_phase)];290dsp_buf[dsp_i] = dsp_amp *291(coeffs[0] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 1)292+ coeffs[1] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index)293+ coeffs[2] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 1)294+ coeffs[3] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 2));295296/* increment phase and amplitude */297fluid_phase_incr(dsp_phase, dsp_phase_incr);298dsp_phase_index = fluid_phase_index(dsp_phase);299dsp_amp += dsp_amp_incr;300}301302/* break out if buffer filled */303if(dsp_i >= FLUID_BUFSIZE)304{305break;306}307308end_index++; /* we're now interpolating the 2nd to last point */309310/* interpolate within 2nd to last point */311for(; dsp_phase_index <= end_index && dsp_i < FLUID_BUFSIZE; dsp_i++)312{313coeffs = interp_coeff[fluid_phase_fract_to_tablerow(dsp_phase)];314dsp_buf[dsp_i] = dsp_amp *315(coeffs[0] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 1)316+ coeffs[1] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index)317+ coeffs[2] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 1)318+ coeffs[3] * end_point1);319320/* increment phase and amplitude */321fluid_phase_incr(dsp_phase, dsp_phase_incr);322dsp_phase_index = fluid_phase_index(dsp_phase);323dsp_amp += dsp_amp_incr;324}325326end_index++; /* we're now interpolating the last point */327328/* interpolate within the last point */329for(; dsp_phase_index <= end_index && dsp_i < FLUID_BUFSIZE; dsp_i++)330{331coeffs = interp_coeff[fluid_phase_fract_to_tablerow(dsp_phase)];332dsp_buf[dsp_i] = dsp_amp *333(coeffs[0] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 1)334+ coeffs[1] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index)335+ coeffs[2] * end_point1336+ coeffs[3] * end_point2);337338/* increment phase and amplitude */339fluid_phase_incr(dsp_phase, dsp_phase_incr);340dsp_phase_index = fluid_phase_index(dsp_phase);341dsp_amp += dsp_amp_incr;342}343344if(!looping)345{346break; /* break out if not looping (end of sample) */347}348349/* go back to loop start */350if(dsp_phase_index > end_index)351{352fluid_phase_sub_int(dsp_phase, voice->loopend - voice->loopstart);353354if(!voice->has_looped)355{356voice->has_looped = 1;357start_index = voice->loopstart;358start_point = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopend - 1);359}360}361362/* break out if filled buffer */363if(dsp_i >= FLUID_BUFSIZE)364{365break;366}367368end_index -= 2; /* set end back to third to last sample point */369}370371voice->phase = dsp_phase;372voice->amp = dsp_amp;373374return (dsp_i);375}376377/* 7th order interpolation.378* Returns number of samples processed (usually FLUID_BUFSIZE but could be379* smaller if end of sample occurs).380*/381int382fluid_rvoice_dsp_interpolate_7th_order(fluid_rvoice_dsp_t *voice, fluid_real_t *FLUID_RESTRICT dsp_buf, int looping)383{384fluid_phase_t dsp_phase = voice->phase;385fluid_phase_t dsp_phase_incr;386short int *dsp_data = voice->sample->data;387char *dsp_data24 = voice->sample->data24;388fluid_real_t dsp_amp = voice->amp;389fluid_real_t dsp_amp_incr = voice->amp_incr;390unsigned int dsp_i = 0;391unsigned int dsp_phase_index;392unsigned int start_index, end_index;393fluid_real_t start_points[3], end_points[3];394const fluid_real_t *FLUID_RESTRICT coeffs;395396/* Convert playback "speed" floating point value to phase index/fract */397fluid_phase_set_float(dsp_phase_incr, voice->phase_incr);398399/* add 1/2 sample to dsp_phase since 7th order interpolation is centered on400* the 4th sample point */401fluid_phase_incr(dsp_phase, (fluid_phase_t)0x80000000);402403/* last index before 7th interpolation point must be specially handled */404end_index = (looping ? voice->loopend - 1 : voice->end) - 3;405406if(voice->has_looped) /* set start_index and start point if looped or not */407{408start_index = voice->loopstart;409start_points[0] = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopend - 1);410start_points[1] = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopend - 2);411start_points[2] = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopend - 3);412}413else414{415start_index = voice->start;416start_points[0] = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->start); /* just duplicate the start point */417start_points[1] = start_points[0];418start_points[2] = start_points[0];419}420421/* get the 3 points off the end (loop start if looping, duplicate point if end) */422if(looping)423{424end_points[0] = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopstart);425end_points[1] = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopstart + 1);426end_points[2] = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopstart + 2);427}428else429{430end_points[0] = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->end);431end_points[1] = end_points[0];432end_points[2] = end_points[0];433}434435while(1)436{437dsp_phase_index = fluid_phase_index(dsp_phase);438439/* interpolate first sample point (start or loop start) if needed */440for(; dsp_phase_index == start_index && dsp_i < FLUID_BUFSIZE; dsp_i++)441{442coeffs = sinc_table7[fluid_phase_fract_to_tablerow(dsp_phase)];443444dsp_buf[dsp_i] = dsp_amp445* (coeffs[0] * start_points[2]446+ coeffs[1] * start_points[1]447+ coeffs[2] * start_points[0]448+ coeffs[3] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index)449+ coeffs[4] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 1)450+ coeffs[5] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 2)451+ coeffs[6] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 3));452453/* increment phase and amplitude */454fluid_phase_incr(dsp_phase, dsp_phase_incr);455dsp_phase_index = fluid_phase_index(dsp_phase);456dsp_amp += dsp_amp_incr;457}458459start_index++;460461/* interpolate 2nd to first sample point (start or loop start) if needed */462for(; dsp_phase_index == start_index && dsp_i < FLUID_BUFSIZE; dsp_i++)463{464coeffs = sinc_table7[fluid_phase_fract_to_tablerow(dsp_phase)];465466dsp_buf[dsp_i] = dsp_amp467* (coeffs[0] * start_points[1]468+ coeffs[1] * start_points[0]469+ coeffs[2] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 1)470+ coeffs[3] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index)471+ coeffs[4] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 1)472+ coeffs[5] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 2)473+ coeffs[6] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 3));474475/* increment phase and amplitude */476fluid_phase_incr(dsp_phase, dsp_phase_incr);477dsp_phase_index = fluid_phase_index(dsp_phase);478dsp_amp += dsp_amp_incr;479}480481start_index++;482483/* interpolate 3rd to first sample point (start or loop start) if needed */484for(; dsp_phase_index == start_index && dsp_i < FLUID_BUFSIZE; dsp_i++)485{486coeffs = sinc_table7[fluid_phase_fract_to_tablerow(dsp_phase)];487488dsp_buf[dsp_i] = dsp_amp489* (coeffs[0] * start_points[0]490+ coeffs[1] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 2)491+ coeffs[2] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 1)492+ coeffs[3] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index)493+ coeffs[4] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 1)494+ coeffs[5] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 2)495+ coeffs[6] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 3));496497/* increment phase and amplitude */498fluid_phase_incr(dsp_phase, dsp_phase_incr);499dsp_phase_index = fluid_phase_index(dsp_phase);500dsp_amp += dsp_amp_incr;501}502503start_index -= 2; /* set back to original start index */504505506/* interpolate the sequence of sample points */507for(; dsp_i < FLUID_BUFSIZE && dsp_phase_index <= end_index; dsp_i++)508{509coeffs = sinc_table7[fluid_phase_fract_to_tablerow(dsp_phase)];510511dsp_buf[dsp_i] = dsp_amp512* (coeffs[0] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 3)513+ coeffs[1] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 2)514+ coeffs[2] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 1)515+ coeffs[3] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index)516+ coeffs[4] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 1)517+ coeffs[5] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 2)518+ coeffs[6] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 3));519520/* increment phase and amplitude */521fluid_phase_incr(dsp_phase, dsp_phase_incr);522dsp_phase_index = fluid_phase_index(dsp_phase);523dsp_amp += dsp_amp_incr;524}525526/* break out if buffer filled */527if(dsp_i >= FLUID_BUFSIZE)528{529break;530}531532end_index++; /* we're now interpolating the 3rd to last point */533534/* interpolate within 3rd to last point */535for(; dsp_phase_index <= end_index && dsp_i < FLUID_BUFSIZE; dsp_i++)536{537coeffs = sinc_table7[fluid_phase_fract_to_tablerow(dsp_phase)];538539dsp_buf[dsp_i] = dsp_amp540* (coeffs[0] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 3)541+ coeffs[1] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 2)542+ coeffs[2] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 1)543+ coeffs[3] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index)544+ coeffs[4] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 1)545+ coeffs[5] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 2)546+ coeffs[6] * end_points[0]);547548/* increment phase and amplitude */549fluid_phase_incr(dsp_phase, dsp_phase_incr);550dsp_phase_index = fluid_phase_index(dsp_phase);551dsp_amp += dsp_amp_incr;552}553554end_index++; /* we're now interpolating the 2nd to last point */555556/* interpolate within 2nd to last point */557for(; dsp_phase_index <= end_index && dsp_i < FLUID_BUFSIZE; dsp_i++)558{559coeffs = sinc_table7[fluid_phase_fract_to_tablerow(dsp_phase)];560561dsp_buf[dsp_i] = dsp_amp562* (coeffs[0] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 3)563+ coeffs[1] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 2)564+ coeffs[2] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 1)565+ coeffs[3] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index)566+ coeffs[4] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 1)567+ coeffs[5] * end_points[0]568+ coeffs[6] * end_points[1]);569570/* increment phase and amplitude */571fluid_phase_incr(dsp_phase, dsp_phase_incr);572dsp_phase_index = fluid_phase_index(dsp_phase);573dsp_amp += dsp_amp_incr;574}575576end_index++; /* we're now interpolating the last point */577578/* interpolate within last point */579for(; dsp_phase_index <= end_index && dsp_i < FLUID_BUFSIZE; dsp_i++)580{581coeffs = sinc_table7[fluid_phase_fract_to_tablerow(dsp_phase)];582583dsp_buf[dsp_i] = dsp_amp584* (coeffs[0] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 3)585+ coeffs[1] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 2)586+ coeffs[2] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 1)587+ coeffs[3] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index)588+ coeffs[4] * end_points[0]589+ coeffs[5] * end_points[1]590+ coeffs[6] * end_points[2]);591592/* increment phase and amplitude */593fluid_phase_incr(dsp_phase, dsp_phase_incr);594dsp_phase_index = fluid_phase_index(dsp_phase);595dsp_amp += dsp_amp_incr;596}597598if(!looping)599{600break; /* break out if not looping (end of sample) */601}602603/* go back to loop start */604if(dsp_phase_index > end_index)605{606fluid_phase_sub_int(dsp_phase, voice->loopend - voice->loopstart);607608if(!voice->has_looped)609{610voice->has_looped = 1;611start_index = voice->loopstart;612start_points[0] = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopend - 1);613start_points[1] = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopend - 2);614start_points[2] = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopend - 3);615}616}617618/* break out if filled buffer */619if(dsp_i >= FLUID_BUFSIZE)620{621break;622}623624end_index -= 3; /* set end back to 4th to last sample point */625}626627/* sub 1/2 sample from dsp_phase since 7th order interpolation is centered on628* the 4th sample point (correct back to real value) */629fluid_phase_decr(dsp_phase, (fluid_phase_t)0x80000000);630631voice->phase = dsp_phase;632voice->amp = dsp_amp;633634return (dsp_i);635}636637638