Hi Jeanette, not sure any of this helps but here are some things I’ve toyed with that use inharmonic waveforms etc. (for these examples I applied PM) that often don’t have zero-crossing start/end values so generally have to be windowed due to artefacts/aliasing :
giTab ftgen 0, 0, 4096, 9, 1,.4,0, 2.2,.5,0, 3.8,1,0
giSinc ftgen 0, 0, 4096, 20, 9, 1, 1
instr 1
; amplitude of phase mod.
kPMA = linseg:a(0, p3/2, 1, p3/2, 0)
kPhs = lfo(kPMA, 220)
aSig = osciliktp(220, giTab, kPhs)
aWin = osciliktp(220, giSinc, kPhs)
out(aSig * aWin)
endin
As you can see it “seems” (?) quite efficient in that it eliminates the need for extra table & phasor opcodes etc. The one thing here is that this requires a ksmps of 1. But if run as an UDO instead it’s inconsequential as there is very little running at k-rate.
It also eliminates the need for window & waveforms to require the same table size.
However, another possible option is to simply convert the inharm. waveforms using GEN30:
giInhPrt ftgen 1, 0, 4096, 9, 1,.4,0, 2.2,.5,0, 3.8,1,0
giHarPrt ftgen 2, 0, 4096, 30, giInhPrt, 1, 12
instr 1
kPMA = linseg:a(0, p3/2, 1, p3/2, 0)
kPhs = lfo(kPMA, 220)
aSig = osciliktp(220, giHarPrt, kPhs)
out(aSig)
endin
This then doesn’t require the use of a window & can provide essentially brick-wall bandlimiting (it appears slightly more efficiently that the sinc win. - freq. above 20kHz remain below -120dB) without losing almost any audible high freq. overtones. It of course comes with it’s own limitations such as setting how many partials to use for GEN30. It also requires converting all waveforms necessary before using something like ftmorf but that’s easy to accomplish with an UDO like the one I sent you.
It also eliminates the need for the second osc. used in the previous ex.
The linked inharm. vs harm. file runs at 192000, for demo purposes (for anyone who might choose to view with some type of FFT/spectrogram).
There are 4 parts to the score : PM of sine, inharm. waveform, GEN30 converted waveform and lastly an example that isolates and plays only the frequencies lost from the GEN30 conversion. Hopefully this demonstrates how little is lost by converting the unwindowed inharm. waves, some audible freq. might even be a result of aliasing, even at 192000, but I’m no expert.
The window approach might be more reliable though in regards to some situations, something I still have to test. The GEN30 has it’s own benefits (such as when used with waveforms created using something like GEN21 that can’t be cleaned up/bandlimited easily using a window) but that’s a different issue.
And of course I haven’t seen your whole “blueprint” so don’t know if these ideas are applicable to your needs or not.
Here are links to 2 example csd files & a demo video for anyone interested:
https://www.dropbox.com/scl/fi/1o2u9mywldj1e67gf3lwg/phase_mod_windowed.csd?rlkey=u75p3ah9ehjo3wfei2xqfanzs&dl=0
https://www.dropbox.com/scl/fi/1bb2j4622arxxjjagim9p/phase_mod_gen30.csd?rlkey=57fiv7uuzrc8h6heu63923x7d&dl=0
https://www.dropbox.com/scl/fi/n325knfjks9o5k5l2ua78/phase_mod_gen30.mp4?rlkey=qlh4u44qe6pttnskku0y1muzp&dl=0
Best,
Scott