@DAVEYC Whoops! Missed the patch you posted at the bottom. This is one of those things where I'm a little lost trying to patch in Gen and a C version makes way more sense to me but it shouldn't be hard to adapt the C version to a Gen codebox.
@RAJA_THE_RESIDENT_ASSWIPE If I remember right it's a trick to weed out NaN errors. The way I'd been calculating the phase increment could result in a divide-by-zero when the frequency was set to zero. NaN's fail the equality test so nothing happens in the perform routine.
Hi Davey, I wanted to offer some encouragement, first, using plot~ I got much better results for your sawtooth than for my LTR version. The difference didn't show up with the simpler spectral analysis object, but with a peopler Fourier with 1024 unwindwed samples, yours is definitely better, and better than the MSP object too below 50Hz (strangely, the cycle~ object also shows this distortion below 50Hz for some reason, but the noise below 50Hz doesn't appear if you use cycle with phase lookup in gen~. I tried to think of a rational explanation for the MSP noise at low frequencies, but so far Im at a blank).
Second, at least by Peter's definition, I think this is an EPTR, because it does only perform polynomial calculations during the transition region. Maybe I did something wrong when I tried to simplify the equations. Perhaps you could check it?
It might well be EPTR. I'm not too sure. It sounds and looks pretty good. It would be nice to compare it with the PTR in terms of CPU usage. I could use Max 6 but it struck me I don't know how to see how much CPU a patch is using in Max 7. Any ideas?
I havent seen any difference between max 6 and max7. I think max7 patches open in max6 at the moment, unless you are using any of the new objects, which this doesnt. For cpu there is an example in the max help file for the gen~ object, on the profiling tab, which provides average usage over consecutive time periods. On Macs it takes into account parallel processing and on PCs it doesn't.
For eptr there isnt really a single simple measurement, because it has a much larger peak usage than average. Average usage will increase at higher frequencies when the transition window becomes a larger proportion of the audio cycles. Even so typically engineers provide average usage at 1khz for technical comparisons in most cases.
But with regarded to performance, I did take a deeper look at the pulse width polynomial, and in fact, it also is an EPTR by Peter's definition, and I dont know exactly where you got it, but at least half of it isn't a polynomial, it's simply a linear curve. P0 is samplerate/FC, and p is Fc/samplerate. So when you square or cube the two together, the result is always 1. Hence after including the scaling factors to get the output into the -1 to +1 range, I get this:
I think it would be possible to simplify it, but it's been 35 years since I ever simplified a factorial, so I leave that thought to you. but it does explain why the noise reduction on Peter's tanh method is better, because it provides a curved response over the transition period, instead of linear as in the above.
I'm very busy with my day job right now but I appreciate your input and I'll definitely look into optimising the pulse polynomial as soon as I get the chance, probably next week sometime and post any results. Have a good weekend.
Wups, I think I made a mistake that inc is a fraction which should be included. But I am sure it can be simplified like I am trying to, and I think there is another problem that w should not be included in the first half:
I think that's because all values are represented as doubles, so even if you get the int value of a number, it's still a double internally.
The other problem with allowing users to do bitwise manipulation is that it ties it to the implementation so if the implementation changes, your code no longer works. You can, of course, still do these types of things in your own C/C++ code... This is all just supposition on my part, though.