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