clearer catastrophic error message, rather than assert()
[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 Library General Public License
7  * as published by the Free Software Foundation; either version 2 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  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library 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
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_voice_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 /* Linear interpolation table (2 coefficients centered on 1st) */
51 static fluid_real_t interp_coeff_linear[FLUID_INTERP_MAX][2];
52
53 /* 4th order (cubic) interpolation table (4 coefficients centered on 2nd) */
54 static fluid_real_t interp_coeff[FLUID_INTERP_MAX][4];
55
56 /* 7th order interpolation (7 coefficients centered on 3rd) */
57 static fluid_real_t sinc_table7[FLUID_INTERP_MAX][7];
58
59
60 #define SINC_INTERP_ORDER 7     /* 7th order constant */
61
62
63 /* Initializes interpolation tables */
64 void fluid_rvoice_dsp_config (void)
65 {
66   int i, i2;
67   double x, v;
68   double i_shifted;
69
70   /* Initialize the coefficients for the interpolation. The math comes
71    * from a mail, posted by Olli Niemitalo to the music-dsp mailing
72    * list (I found it in the music-dsp archives
73    * http://www.smartelectronix.com/musicdsp/).  */
74
75   for (i = 0; i < FLUID_INTERP_MAX; i++)
76   {
77     x = (double) i / (double) FLUID_INTERP_MAX;
78
79     interp_coeff[i][0] = (fluid_real_t)(x * (-0.5 + x * (1 - 0.5 * x)));
80     interp_coeff[i][1] = (fluid_real_t)(1.0 + x * x * (1.5 * x - 2.5));
81     interp_coeff[i][2] = (fluid_real_t)(x * (0.5 + x * (2.0 - 1.5 * x)));
82     interp_coeff[i][3] = (fluid_real_t)(0.5 * x * x * (x - 1.0));
83
84     interp_coeff_linear[i][0] = (fluid_real_t)(1.0 - x);
85     interp_coeff_linear[i][1] = (fluid_real_t)x;
86   }
87
88   /* i: Offset in terms of whole samples */
89   for (i = 0; i < SINC_INTERP_ORDER; i++)
90   { /* i2: Offset in terms of fractional samples ('subsamples') */
91     for (i2 = 0; i2 < FLUID_INTERP_MAX; i2++)
92     {
93       /* center on middle of table */
94       i_shifted = (double)i - ((double)SINC_INTERP_ORDER / 2.0)
95         + (double)i2 / (double)FLUID_INTERP_MAX;
96
97       /* sinc(0) cannot be calculated straightforward (limit needed for 0/0) */
98       if (fabs (i_shifted) > 0.000001)
99       {
100         v = (fluid_real_t)sin (i_shifted * M_PI) / (M_PI * i_shifted);
101         /* Hamming window */
102         v *= (fluid_real_t)0.5 * (1.0 + cos (2.0 * M_PI * i_shifted / (fluid_real_t)SINC_INTERP_ORDER));
103       }
104       else v = 1.0;
105
106       sinc_table7[FLUID_INTERP_MAX - i2 - 1][i] = v;
107     }
108   }
109
110 #if 0
111   for (i = 0; i < FLUID_INTERP_MAX; i++)
112   {
113     printf ("%d %0.3f %0.3f %0.3f %0.3f %0.3f %0.3f %0.3f\n",
114             i, sinc_table7[0][i], sinc_table7[1][i], sinc_table7[2][i],
115             sinc_table7[3][i], sinc_table7[4][i], sinc_table7[5][i], sinc_table7[6][i]);
116   }
117 #endif
118
119   fluid_check_fpe("interpolation table calculation");
120 }
121
122 /* No interpolation. Just take the sample, which is closest to
123   * the playback pointer.  Questionable quality, but very
124   * efficient. */
125 int
126 fluid_rvoice_dsp_interpolate_none (fluid_rvoice_dsp_t *voice)
127 {
128   fluid_phase_t dsp_phase = voice->phase;
129   fluid_phase_t dsp_phase_incr;
130   short int *dsp_data = voice->sample->data;
131   fluid_real_t *dsp_buf = voice->dsp_buf;
132   fluid_real_t dsp_amp = voice->amp;
133   fluid_real_t dsp_amp_incr = voice->amp_incr;
134   unsigned int dsp_i = 0;
135   unsigned int dsp_phase_index;
136   unsigned int end_index;
137   int looping;
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   /* voice is currently looping? */
143   looping = voice->is_looping;
144  
145   end_index = looping ? voice->loopend - 1 : voice->end;
146
147   while (1)
148   {
149     dsp_phase_index = fluid_phase_index_round (dsp_phase);      /* round to nearest point */
150
151     /* interpolate sequence of sample points */
152     for ( ; dsp_i < FLUID_BUFSIZE && dsp_phase_index <= end_index; dsp_i++)
153     {
154       dsp_buf[dsp_i] = dsp_amp * dsp_data[dsp_phase_index];
155
156       /* increment phase and amplitude */
157       fluid_phase_incr (dsp_phase, dsp_phase_incr);
158       dsp_phase_index = fluid_phase_index_round (dsp_phase);    /* round to nearest point */
159       dsp_amp += dsp_amp_incr;
160     }
161
162     /* break out if not looping (buffer may not be full) */
163     if (!looping) break;
164
165     /* go back to loop start */
166     if (dsp_phase_index > end_index)
167     {
168       fluid_phase_sub_int (dsp_phase, voice->loopend - voice->loopstart);
169       voice->has_looped = 1;
170     }
171
172     /* break out if filled buffer */
173     if (dsp_i >= FLUID_BUFSIZE) break;
174   }
175
176   voice->phase = dsp_phase;
177   voice->amp = dsp_amp;
178
179   return (dsp_i);
180 }
181
182 /* Straight line interpolation.
183  * Returns number of samples processed (usually FLUID_BUFSIZE but could be
184  * smaller if end of sample occurs).
185  */
186 int
187 fluid_rvoice_dsp_interpolate_linear (fluid_rvoice_dsp_t *voice)
188 {
189   fluid_phase_t dsp_phase = voice->phase;
190   fluid_phase_t dsp_phase_incr;
191   short int *dsp_data = voice->sample->data;
192   fluid_real_t *dsp_buf = voice->dsp_buf;
193   fluid_real_t dsp_amp = voice->amp;
194   fluid_real_t dsp_amp_incr = voice->amp_incr;
195   unsigned int dsp_i = 0;
196   unsigned int dsp_phase_index;
197   unsigned int end_index;
198   short int point;
199   fluid_real_t *coeffs;
200   int looping;
201
202   /* Convert playback "speed" floating point value to phase index/fract */
203   fluid_phase_set_float (dsp_phase_incr, voice->phase_incr);
204
205   /* voice is currently looping? */
206   looping = voice->is_looping;
207
208   /* last index before 2nd interpolation point must be specially handled */
209   end_index = (looping ? voice->loopend - 1 : voice->end) - 1;
210
211   /* 2nd interpolation point to use at end of loop or sample */
212   if (looping) point = dsp_data[voice->loopstart];      /* loop start */
213   else point = dsp_data[voice->end];                    /* duplicate end for samples no longer looping */
214
215   while (1)
216   {
217     dsp_phase_index = fluid_phase_index (dsp_phase);
218
219     /* interpolate the sequence of sample points */
220     for ( ; dsp_i < FLUID_BUFSIZE && dsp_phase_index <= end_index; dsp_i++)
221     {
222       coeffs = interp_coeff_linear[fluid_phase_fract_to_tablerow (dsp_phase)];
223       dsp_buf[dsp_i] = dsp_amp * (coeffs[0] * dsp_data[dsp_phase_index]
224                                   + coeffs[1] * dsp_data[dsp_phase_index+1]);
225
226       /* increment phase and amplitude */
227       fluid_phase_incr (dsp_phase, dsp_phase_incr);
228       dsp_phase_index = fluid_phase_index (dsp_phase);
229       dsp_amp += dsp_amp_incr;
230     }
231
232     /* break out if buffer filled */
233     if (dsp_i >= FLUID_BUFSIZE) break;
234
235     end_index++;        /* we're now interpolating the last point */
236
237     /* interpolate within last point */
238     for (; dsp_phase_index <= end_index && dsp_i < FLUID_BUFSIZE; dsp_i++)
239     {
240       coeffs = interp_coeff_linear[fluid_phase_fract_to_tablerow (dsp_phase)];
241       dsp_buf[dsp_i] = dsp_amp * (coeffs[0] * dsp_data[dsp_phase_index]
242                                   + coeffs[1] * point);
243
244       /* increment phase and amplitude */
245       fluid_phase_incr (dsp_phase, dsp_phase_incr);
246       dsp_phase_index = fluid_phase_index (dsp_phase);
247       dsp_amp += dsp_amp_incr;  /* increment amplitude */
248     }
249
250     if (!looping) break;        /* break out if not looping (end of sample) */
251
252     /* go back to loop start (if past */
253     if (dsp_phase_index > end_index)
254     {
255       fluid_phase_sub_int (dsp_phase, voice->loopend - voice->loopstart);
256       voice->has_looped = 1;
257     }
258
259     /* break out if filled buffer */
260     if (dsp_i >= FLUID_BUFSIZE) break;
261
262     end_index--;        /* set end back to second to last sample point */
263   }
264
265   voice->phase = dsp_phase;
266   voice->amp = dsp_amp;
267
268   return (dsp_i);
269 }
270
271 /* 4th order (cubic) interpolation.
272  * Returns number of samples processed (usually FLUID_BUFSIZE but could be
273  * smaller if end of sample occurs).
274  */
275 int
276 fluid_rvoice_dsp_interpolate_4th_order (fluid_rvoice_dsp_t *voice)
277 {
278   fluid_phase_t dsp_phase = voice->phase;
279   fluid_phase_t dsp_phase_incr;
280   short int *dsp_data = voice->sample->data;
281   fluid_real_t *dsp_buf = voice->dsp_buf;
282   fluid_real_t dsp_amp = voice->amp;
283   fluid_real_t dsp_amp_incr = voice->amp_incr;
284   unsigned int dsp_i = 0;
285   unsigned int dsp_phase_index;
286   unsigned int start_index, end_index;
287   short int start_point, end_point1, end_point2;
288   fluid_real_t *coeffs;
289   int looping;
290
291   /* Convert playback "speed" floating point value to phase index/fract */
292   fluid_phase_set_float (dsp_phase_incr, voice->phase_incr);
293
294   /* voice is currently looping? */
295   looping = voice->is_looping;
296
297   /* last index before 4th interpolation point must be specially handled */
298   end_index = (looping ? voice->loopend - 1 : voice->end) - 2;
299
300   if (voice->has_looped)        /* set start_index and start point if looped or not */
301   {
302     start_index = voice->loopstart;
303     start_point = dsp_data[voice->loopend - 1]; /* last point in loop (wrap around) */
304   }
305   else
306   {
307     start_index = voice->start;
308     start_point = dsp_data[voice->start];       /* just duplicate the point */
309   }
310
311   /* get points off the end (loop start if looping, duplicate point if end) */
312   if (looping)
313   {
314     end_point1 = dsp_data[voice->loopstart];
315     end_point2 = dsp_data[voice->loopstart + 1];
316   }
317   else
318   {
319     end_point1 = dsp_data[voice->end];
320     end_point2 = end_point1;
321   }
322
323   while (1)
324   {
325     dsp_phase_index = fluid_phase_index (dsp_phase);
326
327     /* interpolate first sample point (start or loop start) if needed */
328     for ( ; dsp_phase_index == start_index && dsp_i < FLUID_BUFSIZE; dsp_i++)
329     {
330       coeffs = interp_coeff[fluid_phase_fract_to_tablerow (dsp_phase)];
331       dsp_buf[dsp_i] = dsp_amp * (coeffs[0] * start_point
332                                   + coeffs[1] * dsp_data[dsp_phase_index]
333                                   + coeffs[2] * dsp_data[dsp_phase_index+1]
334                                   + coeffs[3] * dsp_data[dsp_phase_index+2]);
335
336       /* increment phase and amplitude */
337       fluid_phase_incr (dsp_phase, dsp_phase_incr);
338       dsp_phase_index = fluid_phase_index (dsp_phase);
339       dsp_amp += dsp_amp_incr;
340     }
341
342     /* interpolate the sequence of sample points */
343     for ( ; dsp_i < FLUID_BUFSIZE && dsp_phase_index <= end_index; dsp_i++)
344     {
345       coeffs = interp_coeff[fluid_phase_fract_to_tablerow (dsp_phase)];
346       dsp_buf[dsp_i] = dsp_amp * (coeffs[0] * dsp_data[dsp_phase_index-1]
347                                   + coeffs[1] * dsp_data[dsp_phase_index]
348                                   + coeffs[2] * dsp_data[dsp_phase_index+1]
349                                   + coeffs[3] * dsp_data[dsp_phase_index+2]);
350
351       /* increment phase and amplitude */
352       fluid_phase_incr (dsp_phase, dsp_phase_incr);
353       dsp_phase_index = fluid_phase_index (dsp_phase);
354       dsp_amp += dsp_amp_incr;
355     }
356
357     /* break out if buffer filled */
358     if (dsp_i >= FLUID_BUFSIZE) break;
359
360     end_index++;        /* we're now interpolating the 2nd to last point */
361
362     /* interpolate within 2nd to last point */
363     for (; dsp_phase_index <= end_index && dsp_i < FLUID_BUFSIZE; dsp_i++)
364     {
365       coeffs = interp_coeff[fluid_phase_fract_to_tablerow (dsp_phase)];
366       dsp_buf[dsp_i] = dsp_amp * (coeffs[0] * dsp_data[dsp_phase_index-1]
367                                   + coeffs[1] * dsp_data[dsp_phase_index]
368                                   + coeffs[2] * dsp_data[dsp_phase_index+1]
369                                   + coeffs[3] * end_point1);
370
371       /* increment phase and amplitude */
372       fluid_phase_incr (dsp_phase, dsp_phase_incr);
373       dsp_phase_index = fluid_phase_index (dsp_phase);
374       dsp_amp += dsp_amp_incr;
375     }
376
377     end_index++;        /* we're now interpolating the last point */
378
379     /* interpolate within the last point */
380     for (; dsp_phase_index <= end_index && dsp_i < FLUID_BUFSIZE; dsp_i++)
381     {
382       coeffs = interp_coeff[fluid_phase_fract_to_tablerow (dsp_phase)];
383       dsp_buf[dsp_i] = dsp_amp * (coeffs[0] * dsp_data[dsp_phase_index-1]
384                                   + coeffs[1] * dsp_data[dsp_phase_index]
385                                   + coeffs[2] * end_point1
386                                   + coeffs[3] * end_point2);
387
388       /* increment phase and amplitude */
389       fluid_phase_incr (dsp_phase, dsp_phase_incr);
390       dsp_phase_index = fluid_phase_index (dsp_phase);
391       dsp_amp += dsp_amp_incr;
392     }
393
394     if (!looping) break;        /* break out if not looping (end of sample) */
395
396     /* go back to loop start */
397     if (dsp_phase_index > end_index)
398     {
399       fluid_phase_sub_int (dsp_phase, voice->loopend - voice->loopstart);
400
401       if (!voice->has_looped)
402       {
403         voice->has_looped = 1;
404         start_index = voice->loopstart;
405         start_point = dsp_data[voice->loopend - 1];
406       }
407     }
408
409     /* break out if filled buffer */
410     if (dsp_i >= FLUID_BUFSIZE) break;
411
412     end_index -= 2;     /* set end back to third to last sample point */
413   }
414
415   voice->phase = dsp_phase;
416   voice->amp = dsp_amp;
417
418   return (dsp_i);
419 }
420
421 /* 7th order interpolation.
422  * Returns number of samples processed (usually FLUID_BUFSIZE but could be
423  * smaller if end of sample occurs).
424  */
425 int
426 fluid_rvoice_dsp_interpolate_7th_order (fluid_rvoice_dsp_t *voice)
427 {
428   fluid_phase_t dsp_phase = voice->phase;
429   fluid_phase_t dsp_phase_incr;
430   short int *dsp_data = voice->sample->data;
431   fluid_real_t *dsp_buf = voice->dsp_buf;
432   fluid_real_t dsp_amp = voice->amp;
433   fluid_real_t dsp_amp_incr = voice->amp_incr;
434   unsigned int dsp_i = 0;
435   unsigned int dsp_phase_index;
436   unsigned int start_index, end_index;
437   short int start_points[3];
438   short int end_points[3];
439   fluid_real_t *coeffs;
440   int looping;
441
442   /* Convert playback "speed" floating point value to phase index/fract */
443   fluid_phase_set_float (dsp_phase_incr, voice->phase_incr);
444
445   /* add 1/2 sample to dsp_phase since 7th order interpolation is centered on
446    * the 4th sample point */
447   fluid_phase_incr (dsp_phase, (fluid_phase_t)0x80000000);
448
449   /* voice is currently looping? */
450   looping = voice->is_looping;
451
452   /* last index before 7th interpolation point must be specially handled */
453   end_index = (looping ? voice->loopend - 1 : voice->end) - 3;
454
455   if (voice->has_looped)        /* set start_index and start point if looped or not */
456   {
457     start_index = voice->loopstart;
458     start_points[0] = dsp_data[voice->loopend - 1];
459     start_points[1] = dsp_data[voice->loopend - 2];
460     start_points[2] = dsp_data[voice->loopend - 3];
461   }
462   else
463   {
464     start_index = voice->start;
465     start_points[0] = dsp_data[voice->start];   /* just duplicate the start point */
466     start_points[1] = start_points[0];
467     start_points[2] = start_points[0];
468   }
469
470   /* get the 3 points off the end (loop start if looping, duplicate point if end) */
471   if (looping)
472   {
473     end_points[0] = dsp_data[voice->loopstart];
474     end_points[1] = dsp_data[voice->loopstart + 1];
475     end_points[2] = dsp_data[voice->loopstart + 2];
476   }
477   else
478   {
479     end_points[0] = dsp_data[voice->end];
480     end_points[1] = end_points[0];
481     end_points[2] = end_points[0];
482   }
483
484   while (1)
485   {
486     dsp_phase_index = fluid_phase_index (dsp_phase);
487
488     /* interpolate first sample point (start or loop start) if needed */
489     for ( ; dsp_phase_index == start_index && dsp_i < FLUID_BUFSIZE; dsp_i++)
490     {
491       coeffs = sinc_table7[fluid_phase_fract_to_tablerow (dsp_phase)];
492
493       dsp_buf[dsp_i] = dsp_amp
494         * (coeffs[0] * (fluid_real_t)start_points[2]
495            + coeffs[1] * (fluid_real_t)start_points[1]
496            + coeffs[2] * (fluid_real_t)start_points[0]
497            + coeffs[3] * (fluid_real_t)dsp_data[dsp_phase_index]
498            + coeffs[4] * (fluid_real_t)dsp_data[dsp_phase_index+1]
499            + coeffs[5] * (fluid_real_t)dsp_data[dsp_phase_index+2]
500            + coeffs[6] * (fluid_real_t)dsp_data[dsp_phase_index+3]);
501
502       /* increment phase and amplitude */
503       fluid_phase_incr (dsp_phase, dsp_phase_incr);
504       dsp_phase_index = fluid_phase_index (dsp_phase);
505       dsp_amp += dsp_amp_incr;
506     }
507
508     start_index++;
509
510     /* interpolate 2nd to first sample point (start or loop start) if needed */
511     for ( ; dsp_phase_index == start_index && dsp_i < FLUID_BUFSIZE; dsp_i++)
512     {
513       coeffs = sinc_table7[fluid_phase_fract_to_tablerow (dsp_phase)];
514
515       dsp_buf[dsp_i] = dsp_amp
516         * (coeffs[0] * (fluid_real_t)start_points[1]
517            + coeffs[1] * (fluid_real_t)start_points[0]
518            + coeffs[2] * (fluid_real_t)dsp_data[dsp_phase_index-1]
519            + coeffs[3] * (fluid_real_t)dsp_data[dsp_phase_index]
520            + coeffs[4] * (fluid_real_t)dsp_data[dsp_phase_index+1]
521            + coeffs[5] * (fluid_real_t)dsp_data[dsp_phase_index+2]
522            + coeffs[6] * (fluid_real_t)dsp_data[dsp_phase_index+3]);
523
524       /* increment phase and amplitude */
525       fluid_phase_incr (dsp_phase, dsp_phase_incr);
526       dsp_phase_index = fluid_phase_index (dsp_phase);
527       dsp_amp += dsp_amp_incr;
528     }
529
530     start_index++;
531
532     /* interpolate 3rd to first sample point (start or loop start) if needed */
533     for ( ; dsp_phase_index == start_index && dsp_i < FLUID_BUFSIZE; dsp_i++)
534     {
535       coeffs = sinc_table7[fluid_phase_fract_to_tablerow (dsp_phase)];
536
537       dsp_buf[dsp_i] = dsp_amp
538         * (coeffs[0] * (fluid_real_t)start_points[0]
539            + coeffs[1] * (fluid_real_t)dsp_data[dsp_phase_index-2]
540            + coeffs[2] * (fluid_real_t)dsp_data[dsp_phase_index-1]
541            + coeffs[3] * (fluid_real_t)dsp_data[dsp_phase_index]
542            + coeffs[4] * (fluid_real_t)dsp_data[dsp_phase_index+1]
543            + coeffs[5] * (fluid_real_t)dsp_data[dsp_phase_index+2]
544            + coeffs[6] * (fluid_real_t)dsp_data[dsp_phase_index+3]);
545
546       /* increment phase and amplitude */
547       fluid_phase_incr (dsp_phase, dsp_phase_incr);
548       dsp_phase_index = fluid_phase_index (dsp_phase);
549       dsp_amp += dsp_amp_incr;
550     }
551
552     start_index -= 2;   /* set back to original start index */
553
554
555     /* interpolate the sequence of sample points */
556     for ( ; dsp_i < FLUID_BUFSIZE && dsp_phase_index <= end_index; dsp_i++)
557     {
558       coeffs = sinc_table7[fluid_phase_fract_to_tablerow (dsp_phase)];
559
560       dsp_buf[dsp_i] = dsp_amp
561         * (coeffs[0] * (fluid_real_t)dsp_data[dsp_phase_index-3]
562            + coeffs[1] * (fluid_real_t)dsp_data[dsp_phase_index-2]
563            + coeffs[2] * (fluid_real_t)dsp_data[dsp_phase_index-1]
564            + coeffs[3] * (fluid_real_t)dsp_data[dsp_phase_index]
565            + coeffs[4] * (fluid_real_t)dsp_data[dsp_phase_index+1]
566            + coeffs[5] * (fluid_real_t)dsp_data[dsp_phase_index+2]
567            + coeffs[6] * (fluid_real_t)dsp_data[dsp_phase_index+3]);
568
569       /* increment phase and amplitude */
570       fluid_phase_incr (dsp_phase, dsp_phase_incr);
571       dsp_phase_index = fluid_phase_index (dsp_phase);
572       dsp_amp += dsp_amp_incr;
573     }
574
575     /* break out if buffer filled */
576     if (dsp_i >= FLUID_BUFSIZE) break;
577
578     end_index++;        /* we're now interpolating the 3rd to last point */
579
580     /* interpolate within 3rd to 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_real_t)dsp_data[dsp_phase_index-3]
587            + coeffs[1] * (fluid_real_t)dsp_data[dsp_phase_index-2]
588            + coeffs[2] * (fluid_real_t)dsp_data[dsp_phase_index-1]
589            + coeffs[3] * (fluid_real_t)dsp_data[dsp_phase_index]
590            + coeffs[4] * (fluid_real_t)dsp_data[dsp_phase_index+1]
591            + coeffs[5] * (fluid_real_t)dsp_data[dsp_phase_index+2]
592            + coeffs[6] * (fluid_real_t)end_points[0]);
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     end_index++;        /* we're now interpolating the 2nd to last point */
601
602     /* interpolate within 2nd to last point */
603     for (; dsp_phase_index <= end_index && dsp_i < FLUID_BUFSIZE; dsp_i++)
604     {
605       coeffs = sinc_table7[fluid_phase_fract_to_tablerow (dsp_phase)];
606
607       dsp_buf[dsp_i] = dsp_amp
608         * (coeffs[0] * (fluid_real_t)dsp_data[dsp_phase_index-3]
609            + coeffs[1] * (fluid_real_t)dsp_data[dsp_phase_index-2]
610            + coeffs[2] * (fluid_real_t)dsp_data[dsp_phase_index-1]
611            + coeffs[3] * (fluid_real_t)dsp_data[dsp_phase_index]
612            + coeffs[4] * (fluid_real_t)dsp_data[dsp_phase_index+1]
613            + coeffs[5] * (fluid_real_t)end_points[0]
614            + coeffs[6] * (fluid_real_t)end_points[1]);
615
616       /* increment phase and amplitude */
617       fluid_phase_incr (dsp_phase, dsp_phase_incr);
618       dsp_phase_index = fluid_phase_index (dsp_phase);
619       dsp_amp += dsp_amp_incr;
620     }
621
622     end_index++;        /* we're now interpolating the last point */
623
624     /* interpolate within last point */
625     for (; dsp_phase_index <= end_index && dsp_i < FLUID_BUFSIZE; dsp_i++)
626     {
627       coeffs = sinc_table7[fluid_phase_fract_to_tablerow (dsp_phase)];
628
629       dsp_buf[dsp_i] = dsp_amp
630         * (coeffs[0] * (fluid_real_t)dsp_data[dsp_phase_index-3]
631            + coeffs[1] * (fluid_real_t)dsp_data[dsp_phase_index-2]
632            + coeffs[2] * (fluid_real_t)dsp_data[dsp_phase_index-1]
633            + coeffs[3] * (fluid_real_t)dsp_data[dsp_phase_index]
634            + coeffs[4] * (fluid_real_t)end_points[0]
635            + coeffs[5] * (fluid_real_t)end_points[1]
636            + coeffs[6] * (fluid_real_t)end_points[2]);
637
638       /* increment phase and amplitude */
639       fluid_phase_incr (dsp_phase, dsp_phase_incr);
640       dsp_phase_index = fluid_phase_index (dsp_phase);
641       dsp_amp += dsp_amp_incr;
642     }
643
644     if (!looping) break;        /* break out if not looping (end of sample) */
645
646     /* go back to loop start */
647     if (dsp_phase_index > end_index)
648     {
649       fluid_phase_sub_int (dsp_phase, voice->loopend - voice->loopstart);
650
651       if (!voice->has_looped)
652       {
653         voice->has_looped = 1;
654         start_index = voice->loopstart;
655         start_points[0] = dsp_data[voice->loopend - 1];
656         start_points[1] = dsp_data[voice->loopend - 2];
657         start_points[2] = dsp_data[voice->loopend - 3];
658       }
659     }
660
661     /* break out if filled buffer */
662     if (dsp_i >= FLUID_BUFSIZE) break;
663
664     end_index -= 3;     /* set end back to 4th to last sample point */
665   }
666
667   /* sub 1/2 sample from dsp_phase since 7th order interpolation is centered on
668    * the 4th sample point (correct back to real value) */
669   fluid_phase_decr (dsp_phase, (fluid_phase_t)0x80000000);
670
671   voice->phase = dsp_phase;
672   voice->amp = dsp_amp;
673
674   return (dsp_i);
675 }