If I'm understanding the example, on each period, you want to traverse
half wave table linearly within some fraction dist of the total period,
and then traverse the rest of the table linearly for the remainder of
the period (please correct me if I'm wrong).
This is a special case of FM: you are modulating the frequency up and
down with a rectangular wave. Ignoring rounding error, you could do this
with Nyquist's FMOSC, but then you are left with the problem of creating
the modulator and I suspect that the phase would drift due to rounding
error whereas it seems like this algorithm assumes the modulator is
synchronized to waveform traversal (the up/down frequency modulation
occurs at the same phase every period).
Another possibility is to use SNDCOMPOSE, which computes the functional
composition of two signals: f(g(t)). You'd want to make f() be just the
output of an oscillator with a nice integer number of samples per
period. Then g() is the modulator: a monotonically increasing piecewise
linear function. You'd have to construct this by splicing together
linear segments, probably using something like (PWLV start dur end)
inside a seqrep().
SNDCOMPOSE uses linear interpolation, so the quality won't be really
high, but then the modulator is not bandlimited so there will be
aliasing in any case. At least if you're careful you can get a subsample
accurate g() which will help make slow modulation of the distortion
parameter result in a slowly changing waveform as opposed to one where
changes are quantized to sample boundaries.
This is definitely the highlevel view. Let me know if you need more
detailed help.
Also, in the example code, the use of SEQ is not correct (I can see how
it might work due to some implementation shortcuts in Nyquist). The
main problem is this will build a huge tree of unevaluated/suspended
SOUNDS, probably a couple of kbytes per period.
The "right" way to do this would look something like
(seqrep (i n) (let (...) ... (seq (computea) (computeb))))
or in SAL, it's more like
begin
with ... initialize variables ...
return seqrep(i, n, seq(computea(), computeb()))
end
Roger
