Path: blob/master/libs/fluidsynth/src/rvoice/fluid_rvoice_dsp.cpp
12346 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) */4849template<bool IS_24BIT>50static FLUID_INLINE fluid_real_t51fluid_rvoice_get_float_sample(const short int *FLUID_RESTRICT dsp_msb, const char *FLUID_RESTRICT dsp_lsb, unsigned int idx)52{53int32_t sample;54if (IS_24BIT)55{56sample = fluid_rvoice_get_sample24(dsp_msb, dsp_lsb, idx);57}58else59{60sample = fluid_rvoice_get_sample16(dsp_msb, idx);61}6263return (fluid_real_t)sample;64}6566/* Special case of interpolate_none for rendering silent voices, i.e. in delay phase or zero volume */67template<bool LOOPING>68static int fluid_rvoice_dsp_silence_local(fluid_rvoice_t *rvoice, fluid_real_t *FLUID_RESTRICT dsp_buf)69{70fluid_rvoice_dsp_t *voice = &rvoice->dsp;71fluid_phase_t dsp_phase = voice->phase;72fluid_phase_t dsp_phase_incr;73unsigned short dsp_i = 0;74unsigned int dsp_phase_index;75unsigned int end_index;7677/* Convert playback "speed" floating point value to phase index/fract */78fluid_phase_set_float(dsp_phase_incr, voice->phase_incr);7980end_index = LOOPING ? voice->loopend - 1 : voice->end;8182while (1)83{84dsp_phase_index = fluid_phase_index_round(dsp_phase); /* round to nearest point */8586/* interpolate sequence of sample points */87for (; dsp_i < FLUID_BUFSIZE && dsp_phase_index <= end_index; dsp_i++)88{89fluid_real_t sample = 0;90dsp_buf[dsp_i] = sample;9192/* increment phase and amplitude */93fluid_phase_incr(dsp_phase, dsp_phase_incr);94}9596/* break out if not looping (buffer may not be full) */97if (!LOOPING)98{99break;100}101102dsp_phase_index = fluid_phase_index_round(dsp_phase); /* round to nearest point */103/* go back to loop start */104if (dsp_phase_index > end_index)105{106fluid_phase_sub_int(dsp_phase, voice->loopend - voice->loopstart);107voice->has_looped = 1;108}109110/* break out if filled buffer */111if (dsp_i >= FLUID_BUFSIZE)112{113break;114}115}116117voice->phase = dsp_phase;118// Note, there is no need to update the amplitude here. When the voice becomes audible again, the amp will be updated anyway in fluid_rvoice_calc_amp().119// voice->amp = dsp_amp;120121return (dsp_i);122}123124/* No interpolation. Just take the sample, which is closest to125* the playback pointer. Questionable quality, but very126* efficient. */127template<bool ENABLE_CUSTOM_FILTER, bool IS_24BIT, bool LOOPING>128static int129fluid_rvoice_dsp_interpolate_none_local(fluid_rvoice_t *rvoice, fluid_real_t *FLUID_RESTRICT dsp_buf)130{131fluid_rvoice_dsp_t *voice = &rvoice->dsp;132fluid_phase_t dsp_phase = voice->phase;133fluid_phase_t dsp_phase_incr;134const short int *FLUID_RESTRICT dsp_data = voice->sample->data;135const char *FLUID_RESTRICT dsp_data24 = voice->sample->data24;136fluid_real_t dsp_amp = voice->amp;137fluid_real_t dsp_amp_incr = voice->amp_incr;138unsigned short dsp_i = 0;139unsigned int dsp_phase_index;140unsigned int end_index;141142/* Convert playback "speed" floating point value to phase index/fract */143fluid_phase_set_float(dsp_phase_incr, voice->phase_incr);144145end_index = LOOPING ? voice->loopend - 1 : voice->end;146147while(1)148{149dsp_phase_index = fluid_phase_index_round(dsp_phase); /* round to nearest point */150151/* interpolate sequence of sample points */152for(; dsp_i < FLUID_BUFSIZE && dsp_phase_index <= end_index; dsp_i++)153{154fluid_real_t sample = fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index);155156fluid_iir_filter_apply(&rvoice->resonant_filter, &sample, 1, voice->output_rate);157if (ENABLE_CUSTOM_FILTER)158{159fluid_iir_filter_apply(&rvoice->resonant_custom_filter, &sample, 1, voice->output_rate);160}161162dsp_buf[dsp_i] = dsp_amp * sample;163164/* increment phase and amplitude */165fluid_phase_incr(dsp_phase, dsp_phase_incr);166dsp_phase_index = fluid_phase_index_round(dsp_phase); /* round to nearest point */167dsp_amp += dsp_amp_incr;168}169170/* break out if not looping (buffer may not be full) */171if(!LOOPING)172{173break;174}175176/* go back to loop start */177if(dsp_phase_index > end_index)178{179fluid_phase_sub_int(dsp_phase, voice->loopend - voice->loopstart);180voice->has_looped = 1;181}182183/* break out if filled buffer */184if(dsp_i >= FLUID_BUFSIZE)185{186break;187}188}189190voice->phase = dsp_phase;191voice->amp = dsp_amp;192193return (dsp_i);194}195196/* Straight line interpolation.197* Returns number of samples processed (usually FLUID_BUFSIZE but could be198* smaller if end of sample occurs).199*/200template<bool ENABLE_CUSTOM_FILTER, bool IS_24BIT, bool LOOPING>201static int202fluid_rvoice_dsp_interpolate_linear_local(fluid_rvoice_t *rvoice, fluid_real_t *FLUID_RESTRICT dsp_buf)203{204fluid_rvoice_dsp_t *voice = &rvoice->dsp;205fluid_phase_t dsp_phase = voice->phase;206fluid_phase_t dsp_phase_incr;207const short int *FLUID_RESTRICT dsp_data = voice->sample->data;208const char *FLUID_RESTRICT dsp_data24 = voice->sample->data24;209fluid_real_t dsp_amp = voice->amp;210fluid_real_t dsp_amp_incr = voice->amp_incr;211unsigned short dsp_i = 0;212unsigned int dsp_phase_index;213unsigned int end_index;214fluid_real_t point;215const fluid_real_t *FLUID_RESTRICT coeffs;216217/* Convert playback "speed" floating point value to phase index/fract */218fluid_phase_set_float(dsp_phase_incr, voice->phase_incr);219220/* last index before 2nd interpolation point must be specially handled */221end_index = (LOOPING ? voice->loopend - 1 : voice->end) - 1;222223/* 2nd interpolation point to use at end of loop or sample */224if(LOOPING)225{226point = fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, voice->loopstart); /* loop start */227}228else229{230point = fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, voice->end); /* duplicate end for samples no longer looping */231}232233while(1)234{235dsp_phase_index = fluid_phase_index(dsp_phase);236237/* interpolate the sequence of sample points */238for(; dsp_i < FLUID_BUFSIZE && dsp_phase_index <= end_index; dsp_i++)239{240fluid_real_t sample;241coeffs = interp_coeff_linear[fluid_phase_fract_to_tablerow(dsp_phase)];242243sample = (coeffs[0] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index)244+ coeffs[1] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index + 1));245246fluid_iir_filter_apply(&rvoice->resonant_filter, &sample, 1, voice->output_rate);247if (ENABLE_CUSTOM_FILTER)248{249fluid_iir_filter_apply(&rvoice->resonant_custom_filter, &sample, 1, voice->output_rate);250}251252dsp_buf[dsp_i] = dsp_amp * sample;253254/* increment phase and amplitude */255fluid_phase_incr(dsp_phase, dsp_phase_incr);256dsp_phase_index = fluid_phase_index(dsp_phase);257dsp_amp += dsp_amp_incr;258}259260/* break out if buffer filled */261if(dsp_i >= FLUID_BUFSIZE)262{263break;264}265266end_index++; /* we're now interpolating the last point */267268/* interpolate within last point */269for(; dsp_phase_index <= end_index && dsp_i < FLUID_BUFSIZE; dsp_i++)270{271fluid_real_t sample;272coeffs = interp_coeff_linear[fluid_phase_fract_to_tablerow(dsp_phase)];273274sample = (coeffs[0] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index)275+ coeffs[1] * point);276277fluid_iir_filter_apply(&rvoice->resonant_filter, &sample, 1, voice->output_rate);278if (ENABLE_CUSTOM_FILTER)279{280fluid_iir_filter_apply(&rvoice->resonant_custom_filter, &sample, 1, voice->output_rate);281}282283dsp_buf[dsp_i] = dsp_amp * sample;284285/* increment phase and amplitude */286fluid_phase_incr(dsp_phase, dsp_phase_incr);287dsp_phase_index = fluid_phase_index(dsp_phase);288dsp_amp += dsp_amp_incr; /* increment amplitude */289}290291if(!LOOPING)292{293break; /* break out if not looping (end of sample) */294}295296/* go back to loop start (if past */297if(dsp_phase_index > end_index)298{299fluid_phase_sub_int(dsp_phase, voice->loopend - voice->loopstart);300voice->has_looped = 1;301}302303/* break out if filled buffer */304if(dsp_i >= FLUID_BUFSIZE)305{306break;307}308309end_index--; /* set end back to second to last sample point */310}311312voice->phase = dsp_phase;313voice->amp = dsp_amp;314315return (dsp_i);316}317318/* 4th order (cubic) interpolation.319* Returns number of samples processed (usually FLUID_BUFSIZE but could be320* smaller if end of sample occurs).321*/322template<bool ENABLE_CUSTOM_FILTER, bool IS_24BIT, bool LOOPING>323static int324fluid_rvoice_dsp_interpolate_4th_order_local(fluid_rvoice_t *rvoice, fluid_real_t *FLUID_RESTRICT dsp_buf)325{326fluid_rvoice_dsp_t *voice = &rvoice->dsp;327fluid_phase_t dsp_phase = voice->phase;328fluid_phase_t dsp_phase_incr;329const short int *FLUID_RESTRICT dsp_data = voice->sample->data;330const char *FLUID_RESTRICT dsp_data24 = voice->sample->data24;331fluid_real_t dsp_amp = voice->amp;332fluid_real_t dsp_amp_incr = voice->amp_incr;333unsigned short dsp_i = 0;334unsigned int dsp_phase_index;335unsigned int start_index, end_index;336fluid_real_t start_point, end_point1, end_point2;337const fluid_real_t *FLUID_RESTRICT coeffs;338339/* Convert playback "speed" floating point value to phase index/fract */340fluid_phase_set_float(dsp_phase_incr, voice->phase_incr);341342/* last index before 4th interpolation point must be specially handled */343end_index = (LOOPING ? voice->loopend - 1 : voice->end) - 2;344345if(voice->has_looped) /* set start_index and start point if looped or not */346{347start_index = voice->loopstart;348start_point = fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, voice->loopend - 1); /* last point in loop (wrap around) */349}350else351{352start_index = voice->start;353start_point = fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, voice->start); /* just duplicate the point */354}355356/* get points off the end (loop start if looping, duplicate point if end) */357if(LOOPING)358{359end_point1 = fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, voice->loopstart);360end_point2 = fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, voice->loopstart + 1);361}362else363{364end_point1 = fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, voice->end);365end_point2 = end_point1;366}367368while(1)369{370dsp_phase_index = fluid_phase_index(dsp_phase);371372/* interpolate first sample point (start or loop start) if needed */373for(; dsp_phase_index == start_index && dsp_i < FLUID_BUFSIZE; dsp_i++)374{375fluid_real_t sample;376coeffs = interp_coeff[fluid_phase_fract_to_tablerow(dsp_phase)];377378sample = (coeffs[0] * start_point379+ coeffs[1] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index)380+ coeffs[2] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index + 1)381+ coeffs[3] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index + 2));382383fluid_iir_filter_apply(&rvoice->resonant_filter, &sample, 1, voice->output_rate);384if (ENABLE_CUSTOM_FILTER)385{386fluid_iir_filter_apply(&rvoice->resonant_custom_filter, &sample, 1, voice->output_rate);387}388389dsp_buf[dsp_i] = dsp_amp * sample;390391/* increment phase and amplitude */392fluid_phase_incr(dsp_phase, dsp_phase_incr);393dsp_phase_index = fluid_phase_index(dsp_phase);394dsp_amp += dsp_amp_incr;395}396397/* interpolate the sequence of sample points */398for(; dsp_i < FLUID_BUFSIZE && dsp_phase_index <= end_index; dsp_i++)399{400fluid_real_t sample;401coeffs = interp_coeff[fluid_phase_fract_to_tablerow(dsp_phase)];402403sample = (coeffs[0] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index - 1)404+ coeffs[1] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index)405+ coeffs[2] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index + 1)406+ coeffs[3] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index + 2));407408fluid_iir_filter_apply(&rvoice->resonant_filter, &sample, 1, voice->output_rate);409if (ENABLE_CUSTOM_FILTER)410{411fluid_iir_filter_apply(&rvoice->resonant_custom_filter, &sample, 1, voice->output_rate);412}413414dsp_buf[dsp_i] = dsp_amp * sample;415416/* increment phase and amplitude */417fluid_phase_incr(dsp_phase, dsp_phase_incr);418dsp_phase_index = fluid_phase_index(dsp_phase);419dsp_amp += dsp_amp_incr;420}421422/* break out if buffer filled */423if(dsp_i >= FLUID_BUFSIZE)424{425break;426}427428end_index++; /* we're now interpolating the 2nd to last point */429430/* interpolate within 2nd to last point */431for(; dsp_phase_index <= end_index && dsp_i < FLUID_BUFSIZE; dsp_i++)432{433fluid_real_t sample;434coeffs = interp_coeff[fluid_phase_fract_to_tablerow(dsp_phase)];435436sample = (coeffs[0] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index - 1)437+ coeffs[1] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index)438+ coeffs[2] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index + 1)439+ coeffs[3] * end_point1);440441fluid_iir_filter_apply(&rvoice->resonant_filter, &sample, 1, voice->output_rate);442if (ENABLE_CUSTOM_FILTER)443{444fluid_iir_filter_apply(&rvoice->resonant_custom_filter, &sample, 1, voice->output_rate);445}446447dsp_buf[dsp_i] = dsp_amp * sample;448449/* increment phase and amplitude */450fluid_phase_incr(dsp_phase, dsp_phase_incr);451dsp_phase_index = fluid_phase_index(dsp_phase);452dsp_amp += dsp_amp_incr;453}454455end_index++; /* we're now interpolating the last point */456457/* interpolate within the last point */458for(; dsp_phase_index <= end_index && dsp_i < FLUID_BUFSIZE; dsp_i++)459{460fluid_real_t sample;461coeffs = interp_coeff[fluid_phase_fract_to_tablerow(dsp_phase)];462463464sample = (coeffs[0] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index - 1)465+ coeffs[1] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index)466+ coeffs[2] * end_point1467+ coeffs[3] * end_point2);468469fluid_iir_filter_apply(&rvoice->resonant_filter, &sample, 1, voice->output_rate);470if (ENABLE_CUSTOM_FILTER)471{472fluid_iir_filter_apply(&rvoice->resonant_custom_filter, &sample, 1, voice->output_rate);473}474475dsp_buf[dsp_i] = dsp_amp * sample;476477/* increment phase and amplitude */478fluid_phase_incr(dsp_phase, dsp_phase_incr);479dsp_phase_index = fluid_phase_index(dsp_phase);480dsp_amp += dsp_amp_incr;481}482483if(!LOOPING)484{485break; /* break out if not looping (end of sample) */486}487488/* go back to loop start */489if(dsp_phase_index > end_index)490{491fluid_phase_sub_int(dsp_phase, voice->loopend - voice->loopstart);492493if(!voice->has_looped)494{495voice->has_looped = 1;496start_index = voice->loopstart;497start_point = fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, voice->loopend - 1);498}499}500501/* break out if filled buffer */502if(dsp_i >= FLUID_BUFSIZE)503{504break;505}506507end_index -= 2; /* set end back to third to last sample point */508}509510voice->phase = dsp_phase;511voice->amp = dsp_amp;512513return (dsp_i);514}515516/* 7th order interpolation.517* Returns number of samples processed (usually FLUID_BUFSIZE but could be518* smaller if end of sample occurs).519*/520template<bool ENABLE_CUSTOM_FILTER, bool IS_24BIT, bool LOOPING>521static int522fluid_rvoice_dsp_interpolate_7th_order_local(fluid_rvoice_t *rvoice, fluid_real_t *FLUID_RESTRICT dsp_buf)523{524fluid_rvoice_dsp_t *voice = &rvoice->dsp;525fluid_phase_t dsp_phase = voice->phase;526fluid_phase_t dsp_phase_incr;527const short int *FLUID_RESTRICT dsp_data = voice->sample->data;528const char *FLUID_RESTRICT dsp_data24 = voice->sample->data24;529fluid_real_t dsp_amp = voice->amp;530fluid_real_t dsp_amp_incr = voice->amp_incr;531unsigned short dsp_i = 0;532unsigned int dsp_phase_index;533unsigned int start_index, end_index;534fluid_real_t start_points[3], end_points[3];535const fluid_real_t *FLUID_RESTRICT coeffs;536537/* Convert playback "speed" floating point value to phase index/fract */538fluid_phase_set_float(dsp_phase_incr, voice->phase_incr);539540/* add 1/2 sample to dsp_phase since 7th order interpolation is centered on541* the 4th sample point */542fluid_phase_incr(dsp_phase, (fluid_phase_t)0x80000000);543544/* last index before 7th interpolation point must be specially handled */545end_index = (LOOPING ? voice->loopend - 1 : voice->end) - 3;546547if(voice->has_looped) /* set start_index and start point if looped or not */548{549start_index = voice->loopstart;550start_points[0] = fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, voice->loopend - 1);551start_points[1] = fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, voice->loopend - 2);552start_points[2] = fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, voice->loopend - 3);553}554else555{556start_index = voice->start;557start_points[0] = fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, voice->start); /* just duplicate the start point */558start_points[1] = start_points[0];559start_points[2] = start_points[0];560}561562/* get the 3 points off the end (loop start if looping, duplicate point if end) */563if(LOOPING)564{565end_points[0] = fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, voice->loopstart);566end_points[1] = fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, voice->loopstart + 1);567end_points[2] = fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, voice->loopstart + 2);568}569else570{571end_points[0] = fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, voice->end);572end_points[1] = end_points[0];573end_points[2] = end_points[0];574}575576while(1)577{578dsp_phase_index = fluid_phase_index(dsp_phase);579580/* interpolate first sample point (start or loop start) if needed */581for(; dsp_phase_index == start_index && dsp_i < FLUID_BUFSIZE; dsp_i++)582{583fluid_real_t sample;584coeffs = sinc_table7[fluid_phase_fract_to_tablerow(dsp_phase)];585586sample = (coeffs[0] * start_points[2]587+ coeffs[1] * start_points[1]588+ coeffs[2] * start_points[0]589+ coeffs[3] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index)590+ coeffs[4] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index + 1)591+ coeffs[5] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index + 2)592+ coeffs[6] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index + 3));593594fluid_iir_filter_apply(&rvoice->resonant_filter, &sample, 1, voice->output_rate);595if (ENABLE_CUSTOM_FILTER)596{597fluid_iir_filter_apply(&rvoice->resonant_custom_filter, &sample, 1, voice->output_rate);598}599dsp_buf[dsp_i] = dsp_amp * sample;600601/* increment phase and amplitude */602fluid_phase_incr(dsp_phase, dsp_phase_incr);603dsp_phase_index = fluid_phase_index(dsp_phase);604dsp_amp += dsp_amp_incr;605}606607start_index++;608609/* interpolate 2nd to first sample point (start or loop start) if needed */610for(; dsp_phase_index == start_index && dsp_i < FLUID_BUFSIZE; dsp_i++)611{612fluid_real_t sample;613coeffs = sinc_table7[fluid_phase_fract_to_tablerow(dsp_phase)];614615sample = (coeffs[0] * start_points[1]616+ coeffs[1] * start_points[0]617+ coeffs[2] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index - 1)618+ coeffs[3] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index)619+ coeffs[4] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index + 1)620+ coeffs[5] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index + 2)621+ coeffs[6] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index + 3));622623fluid_iir_filter_apply(&rvoice->resonant_filter, &sample, 1, voice->output_rate);624if (ENABLE_CUSTOM_FILTER)625{626fluid_iir_filter_apply(&rvoice->resonant_custom_filter, &sample, 1, voice->output_rate);627}628dsp_buf[dsp_i] = dsp_amp * sample;629630/* increment phase and amplitude */631fluid_phase_incr(dsp_phase, dsp_phase_incr);632dsp_phase_index = fluid_phase_index(dsp_phase);633dsp_amp += dsp_amp_incr;634}635636start_index++;637638/* interpolate 3rd to first sample point (start or loop start) if needed */639for(; dsp_phase_index == start_index && dsp_i < FLUID_BUFSIZE; dsp_i++)640{641fluid_real_t sample;642coeffs = sinc_table7[fluid_phase_fract_to_tablerow(dsp_phase)];643644sample = (coeffs[0] * start_points[0]645+ coeffs[1] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index - 2)646+ coeffs[2] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index - 1)647+ coeffs[3] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index)648+ coeffs[4] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index + 1)649+ coeffs[5] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index + 2)650+ coeffs[6] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index + 3));651652fluid_iir_filter_apply(&rvoice->resonant_filter, &sample, 1, voice->output_rate);653if (ENABLE_CUSTOM_FILTER)654{655fluid_iir_filter_apply(&rvoice->resonant_custom_filter, &sample, 1, voice->output_rate);656}657dsp_buf[dsp_i] = dsp_amp * sample;658659/* increment phase and amplitude */660fluid_phase_incr(dsp_phase, dsp_phase_incr);661dsp_phase_index = fluid_phase_index(dsp_phase);662dsp_amp += dsp_amp_incr;663}664665start_index -= 2; /* set back to original start index */666667668/* interpolate the sequence of sample points */669for(; dsp_i < FLUID_BUFSIZE && dsp_phase_index <= end_index; dsp_i++)670{671fluid_real_t sample;672coeffs = sinc_table7[fluid_phase_fract_to_tablerow(dsp_phase)];673674sample = (coeffs[0] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index - 3)675+ coeffs[1] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index - 2)676+ coeffs[2] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index - 1)677+ coeffs[3] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index)678+ coeffs[4] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index + 1)679+ coeffs[5] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index + 2)680+ coeffs[6] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index + 3));681682fluid_iir_filter_apply(&rvoice->resonant_filter, &sample, 1, voice->output_rate);683if (ENABLE_CUSTOM_FILTER)684{685fluid_iir_filter_apply(&rvoice->resonant_custom_filter, &sample, 1, voice->output_rate);686}687dsp_buf[dsp_i] = dsp_amp * sample;688689/* increment phase and amplitude */690fluid_phase_incr(dsp_phase, dsp_phase_incr);691dsp_phase_index = fluid_phase_index(dsp_phase);692dsp_amp += dsp_amp_incr;693}694695/* break out if buffer filled */696if(dsp_i >= FLUID_BUFSIZE)697{698break;699}700701end_index++; /* we're now interpolating the 3rd to last point */702703/* interpolate within 3rd to last point */704for(; dsp_phase_index <= end_index && dsp_i < FLUID_BUFSIZE; dsp_i++)705{706fluid_real_t sample;707coeffs = sinc_table7[fluid_phase_fract_to_tablerow(dsp_phase)];708709sample = (coeffs[0] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index - 3)710+ coeffs[1] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index - 2)711+ coeffs[2] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index - 1)712+ coeffs[3] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index)713+ coeffs[4] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index + 1)714+ coeffs[5] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index + 2)715+ coeffs[6] * end_points[0]);716717fluid_iir_filter_apply(&rvoice->resonant_filter, &sample, 1, voice->output_rate);718if (ENABLE_CUSTOM_FILTER)719{720fluid_iir_filter_apply(&rvoice->resonant_custom_filter, &sample, 1, voice->output_rate);721}722dsp_buf[dsp_i] = dsp_amp * sample;723724/* increment phase and amplitude */725fluid_phase_incr(dsp_phase, dsp_phase_incr);726dsp_phase_index = fluid_phase_index(dsp_phase);727dsp_amp += dsp_amp_incr;728}729730end_index++; /* we're now interpolating the 2nd to last point */731732/* interpolate within 2nd to last point */733for(; dsp_phase_index <= end_index && dsp_i < FLUID_BUFSIZE; dsp_i++)734{735fluid_real_t sample;736coeffs = sinc_table7[fluid_phase_fract_to_tablerow(dsp_phase)];737738sample = (coeffs[0] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index - 3)739+ coeffs[1] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index - 2)740+ coeffs[2] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index - 1)741+ coeffs[3] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index)742+ coeffs[4] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index + 1)743+ coeffs[5] * end_points[0]744+ coeffs[6] * end_points[1]);745746fluid_iir_filter_apply(&rvoice->resonant_filter, &sample, 1, voice->output_rate);747if (ENABLE_CUSTOM_FILTER)748{749fluid_iir_filter_apply(&rvoice->resonant_custom_filter, &sample, 1, voice->output_rate);750}751dsp_buf[dsp_i] = dsp_amp * sample;752753/* increment phase and amplitude */754fluid_phase_incr(dsp_phase, dsp_phase_incr);755dsp_phase_index = fluid_phase_index(dsp_phase);756dsp_amp += dsp_amp_incr;757}758759end_index++; /* we're now interpolating the last point */760761/* interpolate within last point */762for(; dsp_phase_index <= end_index && dsp_i < FLUID_BUFSIZE; dsp_i++)763{764fluid_real_t sample;765coeffs = sinc_table7[fluid_phase_fract_to_tablerow(dsp_phase)];766767sample = (coeffs[0] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index - 3)768+ coeffs[1] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index - 2)769+ coeffs[2] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index - 1)770+ coeffs[3] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index)771+ coeffs[4] * end_points[0]772+ coeffs[5] * end_points[1]773+ coeffs[6] * end_points[2]);774775fluid_iir_filter_apply(&rvoice->resonant_filter, &sample, 1, voice->output_rate);776if (ENABLE_CUSTOM_FILTER)777{778fluid_iir_filter_apply(&rvoice->resonant_custom_filter, &sample, 1, voice->output_rate);779}780dsp_buf[dsp_i] = dsp_amp * sample;781782/* increment phase and amplitude */783fluid_phase_incr(dsp_phase, dsp_phase_incr);784dsp_phase_index = fluid_phase_index(dsp_phase);785dsp_amp += dsp_amp_incr;786}787788if(!LOOPING)789{790break; /* break out if not looping (end of sample) */791}792793/* go back to loop start */794if(dsp_phase_index > end_index)795{796fluid_phase_sub_int(dsp_phase, voice->loopend - voice->loopstart);797798if(!voice->has_looped)799{800voice->has_looped = 1;801start_index = voice->loopstart;802start_points[0] = fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, voice->loopend - 1);803start_points[1] = fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, voice->loopend - 2);804start_points[2] = fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, voice->loopend - 3);805}806}807808/* break out if filled buffer */809if(dsp_i >= FLUID_BUFSIZE)810{811break;812}813814end_index -= 3; /* set end back to 4th to last sample point */815}816817/* sub 1/2 sample from dsp_phase since 7th order interpolation is centered on818* the 4th sample point (correct back to real value) */819fluid_phase_decr(dsp_phase, (fluid_phase_t)0x80000000);820821voice->phase = dsp_phase;822voice->amp = dsp_amp;823824return (dsp_i);825}826827struct ProcessSilence828{829template<bool ENABLE_CUSTOM_FILTER, bool IS_24BIT, bool LOOPING>830int operator()(fluid_rvoice_t *rvoice, fluid_real_t *FLUID_RESTRICT dsp_buf) const831{832return fluid_rvoice_dsp_silence_local<LOOPING>(rvoice, dsp_buf);833}834};835836struct InterpolateNone837{838template<bool ENABLE_CUSTOM_FILTER, bool IS_24BIT, bool LOOPING>839int operator()(fluid_rvoice_t *rvoice, fluid_real_t *FLUID_RESTRICT dsp_buf) const840{841return fluid_rvoice_dsp_interpolate_none_local<ENABLE_CUSTOM_FILTER, IS_24BIT, LOOPING>(rvoice, dsp_buf);842}843};844845struct InterpolateLinear846{847template<bool ENABLE_CUSTOM_FILTER, bool IS_24BIT, bool LOOPING>848int operator()(fluid_rvoice_t *rvoice, fluid_real_t *FLUID_RESTRICT dsp_buf) const849{850return fluid_rvoice_dsp_interpolate_linear_local<ENABLE_CUSTOM_FILTER, IS_24BIT, LOOPING>(rvoice, dsp_buf);851}852};853854struct Interpolate4thOrder855{856template<bool ENABLE_CUSTOM_FILTER, bool IS_24BIT, bool LOOPING>857int operator()(fluid_rvoice_t *rvoice, fluid_real_t *FLUID_RESTRICT dsp_buf) const858{859return fluid_rvoice_dsp_interpolate_4th_order_local<ENABLE_CUSTOM_FILTER, IS_24BIT, LOOPING>(rvoice, dsp_buf);860}861};862863struct Interpolate7thOrder864{865template<bool ENABLE_CUSTOM_FILTER, bool IS_24BIT, bool LOOPING>866int operator()(fluid_rvoice_t *rvoice, fluid_real_t *FLUID_RESTRICT dsp_buf) const867{868return fluid_rvoice_dsp_interpolate_7th_order_local<ENABLE_CUSTOM_FILTER, IS_24BIT, LOOPING>(rvoice, dsp_buf);869}870};871872template<typename T>873int dsp_invoker(fluid_rvoice_t *rvoice, fluid_real_t *FLUID_RESTRICT dsp_buf, int looping)874{875T func;876bool is_24bit = rvoice->dsp.sample->data24 != NULL;877878if (rvoice->resonant_custom_filter.flags & FLUID_IIR_DISABLED)879{880if (is_24bit)881{882if(looping)883{884return func.template operator()<false, true, true>(rvoice, dsp_buf);885}886else887{888return func.template operator()<false, true, false>(rvoice, dsp_buf);889}890}891else892{893// This case is most common, thanks to templating it will also become the fastest one894if (looping)895{896return func.template operator()<false, false, true>(rvoice, dsp_buf);897}898else899{900return func.template operator()<false, false, false>(rvoice, dsp_buf);901}902}903}904else905{906if (is_24bit)907{908if (looping)909{910return func.template operator()<true, true, true>(rvoice, dsp_buf);911}912else913{914return func.template operator()<true, true, false>(rvoice, dsp_buf);915}916}917else918{919if (looping)920{921return func.template operator()<true, false, true>(rvoice, dsp_buf);922}923else924{925return func.template operator()<true, false, false>(rvoice, dsp_buf);926}927}928}929}930931extern "C" int932fluid_rvoice_dsp_silence(fluid_rvoice_t *rvoice, fluid_real_t *FLUID_RESTRICT dsp_buf, int looping)933{934return dsp_invoker<ProcessSilence>(rvoice, dsp_buf, looping);935}936937extern "C" int938fluid_rvoice_dsp_interpolate_none(fluid_rvoice_t *rvoice, fluid_real_t *FLUID_RESTRICT dsp_buf, int looping)939{940return dsp_invoker<InterpolateNone>(rvoice, dsp_buf, looping);941}942943extern "C" int944fluid_rvoice_dsp_interpolate_linear(fluid_rvoice_t *rvoice, fluid_real_t *FLUID_RESTRICT dsp_buf, int looping)945{946return dsp_invoker<InterpolateLinear>(rvoice, dsp_buf, looping);947}948949extern "C" int950fluid_rvoice_dsp_interpolate_4th_order(fluid_rvoice_t *rvoice, fluid_real_t *FLUID_RESTRICT dsp_buf, int looping)951{952return dsp_invoker<Interpolate4thOrder>(rvoice, dsp_buf, looping);953}954955extern "C" int fluid_rvoice_dsp_interpolate_7th_order(fluid_rvoice_t *rvoice, fluid_real_t *FLUID_RESTRICT dsp_buf, int looping)956{957return dsp_invoker<Interpolate7thOrder>(rvoice, dsp_buf, looping);958}959960961