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