mirror of
https://github.com/cookiengineer/audacity
synced 2025-04-30 15:49:41 +02:00
64 lines
3.0 KiB
Plaintext
64 lines
3.0 KiB
Plaintext
(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)
|
|
(SAMPLE-RATE (MAX input))
|
|
(LINEAR input)
|
|
(INTERNAL-SCALING delaysnd) ; incorporated into delay_scale_factor
|
|
(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 = (sample_type) feedback;
|
|
delaysamp = (sample_type) (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);")
|
|
)
|
|
|