(ALPASSVC-ALG ;; ;; delay is variable -- but we don't want to reallocate the delay buffer, so ;; use an additional parameter for the maximum allowable delay. The sound will ;; be written into the buffer every sample, but read using linear ;; interpolation. As in tapv, duplicate the sample at the first and last ;; locations in the buffer. ;; (NAME "alpassvv") (ARGUMENTS ("sound_type" "input") ("sound_type" "delaysnd") ("sound_type" "feedback") ("double" "maxdelay")) (START (MAX input delaysnd)) (STATE ("float" "delay_scale_factor" "(float) (input->sr * delaysnd->scale)") ("long" "buflen" "max(2, (long) (input->sr * maxdelay + 2.5))") ("sample_type *" "delaybuf" "(sample_type *) calloc (susp->buflen + 1, sizeof(sample_type))") ("sample_type *" "delayptr" "susp->delaybuf") ;; since we allocate one extra sample, endptr points to the last sample ("sample_type *" "endptr" "susp->delaybuf + susp->buflen")) (CONSTANT "delaylen" "endptr" "delay_scale_factor") (NOT-REGISTER delaybuf) (LINEAR input) (TERMINATE (MIN input)) (INNER-LOOP-LOCALS " register sample_type y, z, delaysamp; register int delayi; register sample_type *yptr;\n") (INNER-LOOP " /* compute where to read y, we want y to be delay_snd samples * after delay_ptr, where we write the new sample. First, * conver from seconds to samples. Note: don't use actual sound_type * names in comments! The translator isn't smart enough. */ register sample_type fb = feedback; delaysamp = delaysnd * delay_scale_factor; delayi = (int) delaysamp; /* get integer part */ delaysamp = delaysamp - delayi; /* get phase */ yptr = delayptr + buflen - (delayi + 1); if (yptr >= endptr) yptr -= buflen; /* now get y, the out-put of the delay, using interpolation */ /* note that as phase increases, we use more of yptr[0] because positive phase means longer buffer means read earlier sample */ y = (float) ((yptr[0] * delaysamp) + (yptr[1] * (1.0 - delaysamp))); /* WARNING: no check to keep delaysamp in range, so do this in LISP */ *delayptr++ = z = (sample_type) (fb * y + input); /* Time out to update the buffer: * this is a tricky buffer: buffer[0] == buffer[bufflen] * the logical length is bufflen, but the actual length * is bufflen + 1 to allow for a repeated sample at the * end. This allows for efficient interpolation. */ if (delayptr > endptr) { delayptr = susp->delaybuf; *delayptr++ = *endptr; } output = (sample_type) (y - fb * z);") (FINALIZATION "free(susp->delaybuf);") )