1 /* FluidSynth - A Software Synthesizer
2  *
3  * Copyright (C) 2003  Peter Hanappe and others.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public License
7  * as published by the Free Software Foundation; either version 2.1 of
8  * the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free
17  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18  * 02110-1301, USA
19  */
20 
21 #include "fluid_sys.h"
22 #include "fluid_phase.h"
23 #include "fluid_rvoice.h"
24 #include "fluid_rvoice_dsp_tables.c"
25 
26 /* Purpose:
27  *
28  * Interpolates audio data (obtains values between the samples of the original
29  * waveform data).
30  *
31  * Variables loaded from the voice structure (assigned in fluid_rvoice_write()):
32  * - dsp_data: Pointer to the original waveform data
33  * - dsp_phase: The position in the original waveform data.
34  *              This has an integer and a fractional part (between samples).
35  * - dsp_phase_incr: For each output sample, the position in the original
36  *              waveform advances by dsp_phase_incr. This also has an integer
37  *              part and a fractional part.
38  *              If a sample is played at root pitch (no pitch change),
39  *              dsp_phase_incr is integer=1 and fractional=0.
40  * - dsp_amp: The current amplitude envelope value.
41  * - dsp_amp_incr: The changing rate of the amplitude envelope.
42  *
43  * A couple of variables are used internally, their results are discarded:
44  * - dsp_i: Index through the output buffer
45  * - dsp_buf: Output buffer of floating point values (FLUID_BUFSIZE in length)
46  */
47 
48 /* Interpolation (find a value between two samples of the original waveform) */
49 
50 static FLUID_INLINE fluid_real_t
fluid_rvoice_get_float_sample(const short int * dsp_msb,const char * dsp_lsb,unsigned int idx)51 fluid_rvoice_get_float_sample(const short int *dsp_msb, const char *dsp_lsb, unsigned int idx)
52 {
53     int32_t sample = fluid_rvoice_get_sample(dsp_msb, dsp_lsb, idx);
54     return (fluid_real_t)sample;
55 }
56 
57 /* No interpolation. Just take the sample, which is closest to
58   * the playback pointer.  Questionable quality, but very
59   * efficient. */
60 int
fluid_rvoice_dsp_interpolate_none(fluid_rvoice_dsp_t * voice,fluid_real_t * FLUID_RESTRICT dsp_buf,int looping)61 fluid_rvoice_dsp_interpolate_none(fluid_rvoice_dsp_t *voice, fluid_real_t *FLUID_RESTRICT dsp_buf, int looping)
62 {
63     fluid_phase_t dsp_phase = voice->phase;
64     fluid_phase_t dsp_phase_incr;
65     short int *dsp_data = voice->sample->data;
66     char *dsp_data24 = voice->sample->data24;
67     fluid_real_t dsp_amp = voice->amp;
68     fluid_real_t dsp_amp_incr = voice->amp_incr;
69     unsigned int dsp_i = 0;
70     unsigned int dsp_phase_index;
71     unsigned int end_index;
72 
73     /* Convert playback "speed" floating point value to phase index/fract */
74     fluid_phase_set_float(dsp_phase_incr, voice->phase_incr);
75 
76     end_index = looping ? voice->loopend - 1 : voice->end;
77 
78     while(1)
79     {
80         dsp_phase_index = fluid_phase_index_round(dsp_phase);	/* round to nearest point */
81 
82         /* interpolate sequence of sample points */
83         for(; dsp_i < FLUID_BUFSIZE && dsp_phase_index <= end_index; dsp_i++)
84         {
85             dsp_buf[dsp_i] = dsp_amp * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index);
86 
87             /* increment phase and amplitude */
88             fluid_phase_incr(dsp_phase, dsp_phase_incr);
89             dsp_phase_index = fluid_phase_index_round(dsp_phase);	/* round to nearest point */
90             dsp_amp += dsp_amp_incr;
91         }
92 
93         /* break out if not looping (buffer may not be full) */
94         if(!looping)
95         {
96             break;
97         }
98 
99         /* go back to loop start */
100         if(dsp_phase_index > end_index)
101         {
102             fluid_phase_sub_int(dsp_phase, voice->loopend - voice->loopstart);
103             voice->has_looped = 1;
104         }
105 
106         /* break out if filled buffer */
107         if(dsp_i >= FLUID_BUFSIZE)
108         {
109             break;
110         }
111     }
112 
113     voice->phase = dsp_phase;
114     voice->amp = dsp_amp;
115 
116     return (dsp_i);
117 }
118 
119 /* Straight line interpolation.
120  * Returns number of samples processed (usually FLUID_BUFSIZE but could be
121  * smaller if end of sample occurs).
122  */
123 int
fluid_rvoice_dsp_interpolate_linear(fluid_rvoice_dsp_t * voice,fluid_real_t * FLUID_RESTRICT dsp_buf,int looping)124 fluid_rvoice_dsp_interpolate_linear(fluid_rvoice_dsp_t *voice, fluid_real_t *FLUID_RESTRICT dsp_buf, int looping)
125 {
126     fluid_phase_t dsp_phase = voice->phase;
127     fluid_phase_t dsp_phase_incr;
128     short int *dsp_data = voice->sample->data;
129     char *dsp_data24 = voice->sample->data24;
130     fluid_real_t dsp_amp = voice->amp;
131     fluid_real_t dsp_amp_incr = voice->amp_incr;
132     unsigned int dsp_i = 0;
133     unsigned int dsp_phase_index;
134     unsigned int end_index;
135     fluid_real_t point;
136     const fluid_real_t *FLUID_RESTRICT coeffs;
137 
138     /* Convert playback "speed" floating point value to phase index/fract */
139     fluid_phase_set_float(dsp_phase_incr, voice->phase_incr);
140 
141     /* last index before 2nd interpolation point must be specially handled */
142     end_index = (looping ? voice->loopend - 1 : voice->end) - 1;
143 
144     /* 2nd interpolation point to use at end of loop or sample */
145     if(looping)
146     {
147         point = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopstart);    /* loop start */
148     }
149     else
150     {
151         point = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->end);    /* duplicate end for samples no longer looping */
152     }
153 
154     while(1)
155     {
156         dsp_phase_index = fluid_phase_index(dsp_phase);
157 
158         /* interpolate the sequence of sample points */
159         for(; dsp_i < FLUID_BUFSIZE && dsp_phase_index <= end_index; dsp_i++)
160         {
161             coeffs = interp_coeff_linear[fluid_phase_fract_to_tablerow(dsp_phase)];
162             dsp_buf[dsp_i] = dsp_amp * (coeffs[0] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index)
163                                         + coeffs[1] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 1));
164 
165             /* increment phase and amplitude */
166             fluid_phase_incr(dsp_phase, dsp_phase_incr);
167             dsp_phase_index = fluid_phase_index(dsp_phase);
168             dsp_amp += dsp_amp_incr;
169         }
170 
171         /* break out if buffer filled */
172         if(dsp_i >= FLUID_BUFSIZE)
173         {
174             break;
175         }
176 
177         end_index++;	/* we're now interpolating the last point */
178 
179         /* interpolate within last point */
180         for(; dsp_phase_index <= end_index && dsp_i < FLUID_BUFSIZE; dsp_i++)
181         {
182             coeffs = interp_coeff_linear[fluid_phase_fract_to_tablerow(dsp_phase)];
183             dsp_buf[dsp_i] = dsp_amp * (coeffs[0] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index)
184                                         + coeffs[1] * point);
185 
186             /* increment phase and amplitude */
187             fluid_phase_incr(dsp_phase, dsp_phase_incr);
188             dsp_phase_index = fluid_phase_index(dsp_phase);
189             dsp_amp += dsp_amp_incr;	/* increment amplitude */
190         }
191 
192         if(!looping)
193         {
194             break;    /* break out if not looping (end of sample) */
195         }
196 
197         /* go back to loop start (if past */
198         if(dsp_phase_index > end_index)
199         {
200             fluid_phase_sub_int(dsp_phase, voice->loopend - voice->loopstart);
201             voice->has_looped = 1;
202         }
203 
204         /* break out if filled buffer */
205         if(dsp_i >= FLUID_BUFSIZE)
206         {
207             break;
208         }
209 
210         end_index--;	/* set end back to second to last sample point */
211     }
212 
213     voice->phase = dsp_phase;
214     voice->amp = dsp_amp;
215 
216     return (dsp_i);
217 }
218 
219 /* 4th order (cubic) interpolation.
220  * Returns number of samples processed (usually FLUID_BUFSIZE but could be
221  * smaller if end of sample occurs).
222  */
223 int
fluid_rvoice_dsp_interpolate_4th_order(fluid_rvoice_dsp_t * voice,fluid_real_t * FLUID_RESTRICT dsp_buf,int looping)224 fluid_rvoice_dsp_interpolate_4th_order(fluid_rvoice_dsp_t *voice, fluid_real_t *FLUID_RESTRICT dsp_buf, int looping)
225 {
226     fluid_phase_t dsp_phase = voice->phase;
227     fluid_phase_t dsp_phase_incr;
228     short int *dsp_data = voice->sample->data;
229     char *dsp_data24 = voice->sample->data24;
230     fluid_real_t dsp_amp = voice->amp;
231     fluid_real_t dsp_amp_incr = voice->amp_incr;
232     unsigned int dsp_i = 0;
233     unsigned int dsp_phase_index;
234     unsigned int start_index, end_index;
235     fluid_real_t start_point, end_point1, end_point2;
236     const fluid_real_t *FLUID_RESTRICT coeffs;
237 
238     /* Convert playback "speed" floating point value to phase index/fract */
239     fluid_phase_set_float(dsp_phase_incr, voice->phase_incr);
240 
241     /* last index before 4th interpolation point must be specially handled */
242     end_index = (looping ? voice->loopend - 1 : voice->end) - 2;
243 
244     if(voice->has_looped)	/* set start_index and start point if looped or not */
245     {
246         start_index = voice->loopstart;
247         start_point = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopend - 1);	/* last point in loop (wrap around) */
248     }
249     else
250     {
251         start_index = voice->start;
252         start_point = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->start);	/* just duplicate the point */
253     }
254 
255     /* get points off the end (loop start if looping, duplicate point if end) */
256     if(looping)
257     {
258         end_point1 = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopstart);
259         end_point2 = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopstart + 1);
260     }
261     else
262     {
263         end_point1 = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->end);
264         end_point2 = end_point1;
265     }
266 
267     while(1)
268     {
269         dsp_phase_index = fluid_phase_index(dsp_phase);
270 
271         /* interpolate first sample point (start or loop start) if needed */
272         for(; dsp_phase_index == start_index && dsp_i < FLUID_BUFSIZE; dsp_i++)
273         {
274             coeffs = interp_coeff[fluid_phase_fract_to_tablerow(dsp_phase)];
275             dsp_buf[dsp_i] = dsp_amp *
276                              (coeffs[0] * start_point
277                               + coeffs[1] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index)
278                               + coeffs[2] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 1)
279                               + coeffs[3] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 2));
280 
281             /* increment phase and amplitude */
282             fluid_phase_incr(dsp_phase, dsp_phase_incr);
283             dsp_phase_index = fluid_phase_index(dsp_phase);
284             dsp_amp += dsp_amp_incr;
285         }
286 
287         /* interpolate the sequence of sample points */
288         for(; dsp_i < FLUID_BUFSIZE && dsp_phase_index <= end_index; dsp_i++)
289         {
290             coeffs = interp_coeff[fluid_phase_fract_to_tablerow(dsp_phase)];
291             dsp_buf[dsp_i] = dsp_amp *
292                              (coeffs[0] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 1)
293                               + coeffs[1] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index)
294                               + coeffs[2] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 1)
295                               + coeffs[3] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 2));
296 
297             /* increment phase and amplitude */
298             fluid_phase_incr(dsp_phase, dsp_phase_incr);
299             dsp_phase_index = fluid_phase_index(dsp_phase);
300             dsp_amp += dsp_amp_incr;
301         }
302 
303         /* break out if buffer filled */
304         if(dsp_i >= FLUID_BUFSIZE)
305         {
306             break;
307         }
308 
309         end_index++;	/* we're now interpolating the 2nd to last point */
310 
311         /* interpolate within 2nd to last point */
312         for(; dsp_phase_index <= end_index && dsp_i < FLUID_BUFSIZE; dsp_i++)
313         {
314             coeffs = interp_coeff[fluid_phase_fract_to_tablerow(dsp_phase)];
315             dsp_buf[dsp_i] = dsp_amp *
316                              (coeffs[0] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 1)
317                               + coeffs[1] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index)
318                               + coeffs[2] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 1)
319                               + coeffs[3] * end_point1);
320 
321             /* increment phase and amplitude */
322             fluid_phase_incr(dsp_phase, dsp_phase_incr);
323             dsp_phase_index = fluid_phase_index(dsp_phase);
324             dsp_amp += dsp_amp_incr;
325         }
326 
327         end_index++;	/* we're now interpolating the last point */
328 
329         /* interpolate within the last point */
330         for(; dsp_phase_index <= end_index && dsp_i < FLUID_BUFSIZE; dsp_i++)
331         {
332             coeffs = interp_coeff[fluid_phase_fract_to_tablerow(dsp_phase)];
333             dsp_buf[dsp_i] = dsp_amp *
334                              (coeffs[0] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 1)
335                               + coeffs[1] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index)
336                               + coeffs[2] * end_point1
337                               + coeffs[3] * end_point2);
338 
339             /* increment phase and amplitude */
340             fluid_phase_incr(dsp_phase, dsp_phase_incr);
341             dsp_phase_index = fluid_phase_index(dsp_phase);
342             dsp_amp += dsp_amp_incr;
343         }
344 
345         if(!looping)
346         {
347             break;    /* break out if not looping (end of sample) */
348         }
349 
350         /* go back to loop start */
351         if(dsp_phase_index > end_index)
352         {
353             fluid_phase_sub_int(dsp_phase, voice->loopend - voice->loopstart);
354 
355             if(!voice->has_looped)
356             {
357                 voice->has_looped = 1;
358                 start_index = voice->loopstart;
359                 start_point = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopend - 1);
360             }
361         }
362 
363         /* break out if filled buffer */
364         if(dsp_i >= FLUID_BUFSIZE)
365         {
366             break;
367         }
368 
369         end_index -= 2;	/* set end back to third to last sample point */
370     }
371 
372     voice->phase = dsp_phase;
373     voice->amp = dsp_amp;
374 
375     return (dsp_i);
376 }
377 
378 /* 7th order interpolation.
379  * Returns number of samples processed (usually FLUID_BUFSIZE but could be
380  * smaller if end of sample occurs).
381  */
382 int
fluid_rvoice_dsp_interpolate_7th_order(fluid_rvoice_dsp_t * voice,fluid_real_t * FLUID_RESTRICT dsp_buf,int looping)383 fluid_rvoice_dsp_interpolate_7th_order(fluid_rvoice_dsp_t *voice, fluid_real_t *FLUID_RESTRICT dsp_buf, int looping)
384 {
385     fluid_phase_t dsp_phase = voice->phase;
386     fluid_phase_t dsp_phase_incr;
387     short int *dsp_data = voice->sample->data;
388     char *dsp_data24 = voice->sample->data24;
389     fluid_real_t dsp_amp = voice->amp;
390     fluid_real_t dsp_amp_incr = voice->amp_incr;
391     unsigned int dsp_i = 0;
392     unsigned int dsp_phase_index;
393     unsigned int start_index, end_index;
394     fluid_real_t start_points[3], end_points[3];
395     const fluid_real_t *FLUID_RESTRICT coeffs;
396 
397     /* Convert playback "speed" floating point value to phase index/fract */
398     fluid_phase_set_float(dsp_phase_incr, voice->phase_incr);
399 
400     /* add 1/2 sample to dsp_phase since 7th order interpolation is centered on
401      * the 4th sample point */
402     fluid_phase_incr(dsp_phase, (fluid_phase_t)0x80000000);
403 
404     /* last index before 7th interpolation point must be specially handled */
405     end_index = (looping ? voice->loopend - 1 : voice->end) - 3;
406 
407     if(voice->has_looped)	/* set start_index and start point if looped or not */
408     {
409         start_index = voice->loopstart;
410         start_points[0] = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopend - 1);
411         start_points[1] = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopend - 2);
412         start_points[2] = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopend - 3);
413     }
414     else
415     {
416         start_index = voice->start;
417         start_points[0] = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->start);	/* just duplicate the start point */
418         start_points[1] = start_points[0];
419         start_points[2] = start_points[0];
420     }
421 
422     /* get the 3 points off the end (loop start if looping, duplicate point if end) */
423     if(looping)
424     {
425         end_points[0] = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopstart);
426         end_points[1] = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopstart + 1);
427         end_points[2] = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopstart + 2);
428     }
429     else
430     {
431         end_points[0] = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->end);
432         end_points[1] = end_points[0];
433         end_points[2] = end_points[0];
434     }
435 
436     while(1)
437     {
438         dsp_phase_index = fluid_phase_index(dsp_phase);
439 
440         /* interpolate first sample point (start or loop start) if needed */
441         for(; dsp_phase_index == start_index && dsp_i < FLUID_BUFSIZE; dsp_i++)
442         {
443             coeffs = sinc_table7[fluid_phase_fract_to_tablerow(dsp_phase)];
444 
445             dsp_buf[dsp_i] = dsp_amp
446                              * (coeffs[0] * start_points[2]
447                                 + coeffs[1] * start_points[1]
448                                 + coeffs[2] * start_points[0]
449                                 + coeffs[3] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index)
450                                 + coeffs[4] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 1)
451                                 + coeffs[5] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 2)
452                                 + coeffs[6] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 3));
453 
454             /* increment phase and amplitude */
455             fluid_phase_incr(dsp_phase, dsp_phase_incr);
456             dsp_phase_index = fluid_phase_index(dsp_phase);
457             dsp_amp += dsp_amp_incr;
458         }
459 
460         start_index++;
461 
462         /* interpolate 2nd to first sample point (start or loop start) if needed */
463         for(; dsp_phase_index == start_index && dsp_i < FLUID_BUFSIZE; dsp_i++)
464         {
465             coeffs = sinc_table7[fluid_phase_fract_to_tablerow(dsp_phase)];
466 
467             dsp_buf[dsp_i] = dsp_amp
468                              * (coeffs[0] * start_points[1]
469                                 + coeffs[1] * start_points[0]
470                                 + coeffs[2] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 1)
471                                 + coeffs[3] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index)
472                                 + coeffs[4] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 1)
473                                 + coeffs[5] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 2)
474                                 + coeffs[6] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 3));
475 
476             /* increment phase and amplitude */
477             fluid_phase_incr(dsp_phase, dsp_phase_incr);
478             dsp_phase_index = fluid_phase_index(dsp_phase);
479             dsp_amp += dsp_amp_incr;
480         }
481 
482         start_index++;
483 
484         /* interpolate 3rd to first sample point (start or loop start) if needed */
485         for(; dsp_phase_index == start_index && dsp_i < FLUID_BUFSIZE; dsp_i++)
486         {
487             coeffs = sinc_table7[fluid_phase_fract_to_tablerow(dsp_phase)];
488 
489             dsp_buf[dsp_i] = dsp_amp
490                              * (coeffs[0] * start_points[0]
491                                 + coeffs[1] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 2)
492                                 + coeffs[2] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 1)
493                                 + coeffs[3] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index)
494                                 + coeffs[4] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 1)
495                                 + coeffs[5] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 2)
496                                 + coeffs[6] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 3));
497 
498             /* increment phase and amplitude */
499             fluid_phase_incr(dsp_phase, dsp_phase_incr);
500             dsp_phase_index = fluid_phase_index(dsp_phase);
501             dsp_amp += dsp_amp_incr;
502         }
503 
504         start_index -= 2;	/* set back to original start index */
505 
506 
507         /* interpolate the sequence of sample points */
508         for(; dsp_i < FLUID_BUFSIZE && dsp_phase_index <= end_index; dsp_i++)
509         {
510             coeffs = sinc_table7[fluid_phase_fract_to_tablerow(dsp_phase)];
511 
512             dsp_buf[dsp_i] = dsp_amp
513                              * (coeffs[0] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 3)
514                                 + coeffs[1] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 2)
515                                 + coeffs[2] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 1)
516                                 + coeffs[3] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index)
517                                 + coeffs[4] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 1)
518                                 + coeffs[5] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 2)
519                                 + coeffs[6] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 3));
520 
521             /* increment phase and amplitude */
522             fluid_phase_incr(dsp_phase, dsp_phase_incr);
523             dsp_phase_index = fluid_phase_index(dsp_phase);
524             dsp_amp += dsp_amp_incr;
525         }
526 
527         /* break out if buffer filled */
528         if(dsp_i >= FLUID_BUFSIZE)
529         {
530             break;
531         }
532 
533         end_index++;	/* we're now interpolating the 3rd to last point */
534 
535         /* interpolate within 3rd to last point */
536         for(; dsp_phase_index <= end_index && dsp_i < FLUID_BUFSIZE; dsp_i++)
537         {
538             coeffs = sinc_table7[fluid_phase_fract_to_tablerow(dsp_phase)];
539 
540             dsp_buf[dsp_i] = dsp_amp
541                              * (coeffs[0] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 3)
542                                 + coeffs[1] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 2)
543                                 + coeffs[2] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 1)
544                                 + coeffs[3] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index)
545                                 + coeffs[4] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 1)
546                                 + coeffs[5] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 2)
547                                 + coeffs[6] * end_points[0]);
548 
549             /* increment phase and amplitude */
550             fluid_phase_incr(dsp_phase, dsp_phase_incr);
551             dsp_phase_index = fluid_phase_index(dsp_phase);
552             dsp_amp += dsp_amp_incr;
553         }
554 
555         end_index++;	/* we're now interpolating the 2nd to last point */
556 
557         /* interpolate within 2nd to last point */
558         for(; dsp_phase_index <= end_index && dsp_i < FLUID_BUFSIZE; dsp_i++)
559         {
560             coeffs = sinc_table7[fluid_phase_fract_to_tablerow(dsp_phase)];
561 
562             dsp_buf[dsp_i] = dsp_amp
563                              * (coeffs[0] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 3)
564                                 + coeffs[1] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 2)
565                                 + coeffs[2] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 1)
566                                 + coeffs[3] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index)
567                                 + coeffs[4] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 1)
568                                 + coeffs[5] * end_points[0]
569                                 + coeffs[6] * end_points[1]);
570 
571             /* increment phase and amplitude */
572             fluid_phase_incr(dsp_phase, dsp_phase_incr);
573             dsp_phase_index = fluid_phase_index(dsp_phase);
574             dsp_amp += dsp_amp_incr;
575         }
576 
577         end_index++;	/* we're now interpolating the last point */
578 
579         /* interpolate within last point */
580         for(; dsp_phase_index <= end_index && dsp_i < FLUID_BUFSIZE; dsp_i++)
581         {
582             coeffs = sinc_table7[fluid_phase_fract_to_tablerow(dsp_phase)];
583 
584             dsp_buf[dsp_i] = dsp_amp
585                              * (coeffs[0] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 3)
586                                 + coeffs[1] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 2)
587                                 + coeffs[2] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 1)
588                                 + coeffs[3] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index)
589                                 + coeffs[4] * end_points[0]
590                                 + coeffs[5] * end_points[1]
591                                 + coeffs[6] * end_points[2]);
592 
593             /* increment phase and amplitude */
594             fluid_phase_incr(dsp_phase, dsp_phase_incr);
595             dsp_phase_index = fluid_phase_index(dsp_phase);
596             dsp_amp += dsp_amp_incr;
597         }
598 
599         if(!looping)
600         {
601             break;    /* break out if not looping (end of sample) */
602         }
603 
604         /* go back to loop start */
605         if(dsp_phase_index > end_index)
606         {
607             fluid_phase_sub_int(dsp_phase, voice->loopend - voice->loopstart);
608 
609             if(!voice->has_looped)
610             {
611                 voice->has_looped = 1;
612                 start_index = voice->loopstart;
613                 start_points[0] = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopend - 1);
614                 start_points[1] = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopend - 2);
615                 start_points[2] = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopend - 3);
616             }
617         }
618 
619         /* break out if filled buffer */
620         if(dsp_i >= FLUID_BUFSIZE)
621         {
622             break;
623         }
624 
625         end_index -= 3;	/* set end back to 4th to last sample point */
626     }
627 
628     /* sub 1/2 sample from dsp_phase since 7th order interpolation is centered on
629      * the 4th sample point (correct back to real value) */
630     fluid_phase_decr(dsp_phase, (fluid_phase_t)0x80000000);
631 
632     voice->phase = dsp_phase;
633     voice->amp = dsp_amp;
634 
635     return (dsp_i);
636 }
637