+samplecnt_t
+CubicInterpolation::interpolate (int channel, samplecnt_t input_samples, Sample *input, samplecnt_t & output_samples, Sample *output)
+{
+ assert (input_samples > 0);
+ assert (output_samples > 0);
+ assert (input);
+ assert (output);
+ assert (phase.size () > channel);
+
+ _speed = fabs (_speed);
+
+ if (invalid (0)) {
+
+ /* z[0] not set. Two possibilities
+ *
+ * 1) we have just been constructed or ::reset()
+ *
+ * 2) we were only given 1 sample after construction or
+ * ::reset, and stored it in z[1]
+ */
+
+ if (invalid (1)) {
+
+ /* first call after construction or after ::reset */
+
+ switch (input_samples) {
+ case 1:
+ /* store one sample for use next time. We don't
+ * have enough points to interpolate or even
+ * compute the first z[0] value, but keep z[1]
+ * around.
+ */
+ z[1] = input[0]; validate (1);
+ output_samples = 0;
+ return 0;
+ case 2:
+ /* store two samples for use next time, and
+ * compute a value for z[0] that will maintain
+ * the slope of the first actual segment. We
+ * still don't have enough samples to interpolate.
+ */
+ z[0] = input[0] - (input[1] - input[0]); validate (0);
+ z[1] = input[0]; validate (1);
+ z[2] = input[1]; validate (2);
+ output_samples = 0;
+ return 0;
+ default:
+ /* We have enough samples to interpolate this time,
+ * but don't have a valid z[0] value because this is the
+ * first call after construction or ::reset.
+ *
+ * First point is based on a requirement to maintain
+ * the slope of the first actual segment
+ */
+ z[0] = input[0] - (input[1] - input[0]); validate (0);
+ break;
+ }
+ } else {
+
+ /* at least one call since construction or
+ * after::reset, since we have z[1] set
+ *
+ * we can now compute z[0] as required
+ */
+
+ z[0] = z[1] - (input[0] - z[1]); validate (0);
+
+ /* we'll check the number of samples we've been given
+ in the next switch() statement below, and either
+ just save some more samples or actual interpolate
+ */
+ }