Re: [Audacity-nyquist] Here's a phase distortion example
A free multi-track audio editor and recorder
Brought to you by:
aosiniao
From: Roger D. <rb...@cs...> - 2008-03-18 15:18:55
|
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 SND-COMPOSE, 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 piece-wise linear function. You'd have to construct this by splicing together linear segments, probably using something like (PWLV start dur end) inside a seqrep(). SND-COMPOSE uses linear interpolation, so the quality won't be really high, but then the modulator is not band-limited 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 high-level 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 short-cuts 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 (compute-a) (compute-b)))) or in SAL, it's more like begin with ... initialize variables ... return seqrep(i, n, seq(compute-a(), compute-b())) end -Roger |