Lich - Gen~ phasor vs cycle and audio levels discussion + cv out

I get gnarly noise when i am hitting low frequencies in a cobbled together oscillator - some literature or input would be welcome if you know the limit to keep frequencies above. It gets super noisy and then goes into digital mayhem - kinda cool but also not :slight_smile:

It might also be related to another chaos oscillator I build that seems to cut out audio all together once in a while, but I haven’t explored the issue with that yet - probably horrible gen patching.

I am happy to upload the patch publicly - been avoiding it since Lich CV and gate out aren’t ready yet.

Looks like the issue is conversion of the oscillator. Cycle from gen seems fine at super low rates - phasor playing a triangle iny my setup seems ultra noisy at around 0, unlike the web and maxmsp playback.

Apart from the introduced noise, there is also a difference in pitch - wonder if this is a hardware or software issue. The lowest knob setting produces a lower pitch than the lowest setting on the website preview and in maxmsp. Website and Max are the same.

Lich has DC coupled outputs, so lowest frequency it can output is 0 Hz (that is, constant CV value).

Some amount of noise will always be present with analog values. You can filter away some of it, but it’s unavoidable. If you want to control patch frequency precisely with no noise, you’d have to control it digitally - use MIDI or write a sequencer as part of your patch.

Roger that. The noise floor is actually very nice on it - the problem seems to be an issue with the compiled patch - the noise sounds like memory garbage at around 20-0 hz. I can upload it in case someone with a Lich wants to see what happens. I guess you can get away with a lot when using max but when compiling gen its a toss up on what will happen on the Lich. Would be great to have a best practices manual

1 Like

It’s possible something with the oscillator blows up at low frequencies due to rounding errors. Biquads, very frequently used in digital filters, are notoriously unstable below something like 1/160 of the sampling frequency (ref). Double precision floats, as used in standalone Max, might hide this sort of problem.

If you post a link to your patch then I could have a look at the generated code to see how they implement it. Also curious about the frequency difference, I wonder if there’s a default sample rate set somewhere (ie 44.1 instead of 48kHz).

btw is there not a low frequency oscillator object in gen~?

Does the website also hide it with double precision maths? Although I understand that stuff can be notoriously blowing up or well known to not work, I hope you can take a look at the implementation i used so we can map out how to prepare patches in gen for the Lich - since I am basing how a patch will sound based on what maxmsp and the website playback. But yeah, hopefully making stuff for lich will improve my patches anyway and make them more universal instead of just working on a pc.

heres a cycle and a phasor/triangle (from cycling forum) that come out at Left and Right channels and share a tuning knob. You can also compare the pitch at the minimum knob position with the website version - its a bit lower on the Lich for some reason.
I’ve made the tuning range purposely cross 0 and go into negative in this example to show what happens to the phasor vs the cycle on the lich.

Pretty sure that it would use 32 bit floats on site (and there’s a mistake in this comment)

There could be other potential sources of rounding errors. We have some optimized maths functions and they could have increased errors, especially in extreme values. At least one of them is used by safepow() function . It’s just a theory, but I remember that Martin ended up disabling some similar functions for this very reason.

cool thanks @undefined, I’ll check that out.
Could you upload your .gendsp file as well? Then we can see how the patch is put together!

Oh right!
Updated the patch and included the maxpat too.

must be just the weird operations that are done in that oscillator example (it is supposed to work inside a polysynth that oversamples by 8x - differentiated polynomial waveform oscillators - Gen Forum | Cycling '74) and they get rounded off and mess with the Lich patch (very low signal is getting extremely boosted at the end) - pretty interesting what happens vs max and website.

  • also noticed that the “cycle” object doesn’t go into 50hz after getting a -50 value while the “phasor” does in that patch on the lich. Pretty sure gen doesn’t care if it gets negative or positve values for the frequency - this might explain why another patch wasn’t working though!
    Putting an “abs” before the “cycle” frequency fixes it obviously. https://www.rebeltech.org/patch-library/patch/Phasor_to_Triangle_Test_Abs
  • also wondering if knobs B, C, D affect the oscillator frequency on your hardware - maybe mine is leaky and needs a clean, since they seem to affect it even though they are not assigned to anything and only Param A is controlling the frequency

Yep the low frequency freak-out is because of how safepow() is implemented, on the hardware we use a high-performance approximative function with lookup tables.

If I change it to use standard powf() implementation it stops making weird noise at near-zero frequencies. But the CPU usage goes up, from 11% to 26%.

I think the optimised approximative maths functions are very useful, and work perfectly in most cases. Maybe what we should do however is to also use them in the web version of the patch, so that any side effects can be spotted there.

It is also clear without the extra noise that on the hardware, with the abs patch, the range goes past zero when you turn fully anti-clockwise. Is that intentional? Does it make time run backwards - should I be worried? :smile:

must be just the weird operations that are done in that oscillator example

Maybe good to find a better low-frequency oscillator example!

wondering if knobs B, C, D affect the oscillator frequency on your hardware

Nope, I’m not getting any pitch changes when turning the other knobs.

maybe mine is leaky and needs a clean

Already??

I am always too lazy to clean solder residue and then 3 days later funky things happen. But no worries.

With the abs example I just put in an “abs” object so any negative value becomes positive - i guess cycle in gen~ doesn’t care or can run inverted or something with negative values for frequency.

I made an example without the funky division and multiplication of the levels and its seems ok - other than my knob issue changing the pitch with unassigned knobs
https://www.rebeltech.org/patch-library/patch/Phasor_to_Triangle_2 - no issues with low frequencies there

It’s dangerous only if left on for a long time and you wake up in diapers.

Regarding powf optimization, we could allow disabling optimized function by adding defines (one for each function). Or maybe we could have a different implementation that would only use LUT in the range where its reasonably precise.

yessss this “cycle” discovery and switching to manually creating a sine with phasor and fastsin fixed my original patch. It doesn’t lose power now and I am really glad there wasn’t something funky with the history or sample rate that was causing it to not always work. I am still not sure how stuff is processed, but seems like doing gen~ feedback loops works well!
Now eagerly awaiting gate and cv out :slight_smile:

Martin is looking into that, but the problem is that gen~ doesn’t really have a concept for parameters output. So it would probably have to be done by adding “fake” output audio channels that would be converted to CV when running the patch. This still is not great as we will have to use extra memory for that and maybe patch would be generating CV on audio rate. The latter would be a big deal because some devices (i.e. Magus) can output more CV channels - up to 20 parameters can be used for output there.

I assume this was already explored with the cycling peeps too. I assumed that with gen you could assign a parameter to a cv out - param F, G and Push for example - and OWL would watch those parameters when running the patch and if they are changed by the gen patch - the value would be output to the cv’s. So you would use an encapsulated parameter in a nested gen object and then use “setparam” to change it.

This approach with nested object is something that I’ve thought about recently too. I suspect that there would be some kind of issue, but you could try setting up a patch with a nested object that would be editable via setparam and we’ll see what happens.

I suspect that if you just have a param that is not used for anything, gen~ may end up removing it from compiled code. If that would be the case we would need some way to force it to keep it. Maybe that would require doing something like creating a virtual output channel that would act as sink to force parameter update computation to run.

It didn’t work when I tried it, but I can upload a patch for science