Hilbert transform + atan2() is phase unwrapping needed ?

Dimitri Bosiers's icon

I'm using the following to find the phase in radians of a sinewave ( but it realy can be anything ) to implement a phase shifting on a signal.

[ hilbert~ ] (r, i)-> [ expr~ atan2(r, i) + pi ]

At lower frequencies this gives visible phase wrapping in a scope.
However these become very minor the higher the frequency gets.
Visually and by ear ( on a tone ) it seems like it's not worth to spend CPU on unwrapping the phase as RNBO's as the hilbert and atan2 functions seem to be tweaked to work well in the audible spectrum, but is this the case, or is unwrapping advisable ?

Graham Wakefield's icon

I'm not sure I understand exactly what you are asking, but I can point out a couple of things in the hope that it helps?

A general hilbert transform of real input is going to have less than ideal performance at very low frequencies. This is an artefact of the filters used in the hilbert transform, and is generally a tradeoff between accuracy and latency/complexity. The slower a signal moves, the less certainty we can have about the complex waveform given a window of input.

Atan2(y,x) is always going to give a value in the range of -pi..+pi (https://en.wikipedia.org/wiki/Atan2). But this is just instantaneous phase. As far as I know, the usual goal of phase unwrapping is to preserve continuity in the phase signal, which means avoiding large jumps of phase (e.g. between 0 and 2pi or -pi and +pi) as it wraps around the circle. The code sample you had just repositions the phase into the range 0..2pi, but doesn't prevent wrapping.

A simple way to unwrap phase is to take the sample delta of the instantaneous phase, wrap this in a range of -pi..+pi, and integrate that. E.g. in gen~ this would be atan2(i, r) => delta => wrap -pi pi => accum.

(Note also the order of arguments to atan2 is atan2(y,x) or atan2(i, r)).

Dimitri Bosiers's icon

Hmn...thank you for that reply.

I'm a good listener but sometimes I get confused when math get's involved. I'm catching up on that but I seem to have confused two things, somehow googling got me confusing problems.

The thing I face besides wrapping is that when I put a sine trough this hilbert+atan2 solution and reconstruct the sine from the phase the new sine signal has an anomaly, a bend in the reconstructed waveform that get's worse at lower frequencies but seems to vanish at higher frequencies.

But that doesn't seem to fall under phase unwrapping, and it seems to vanish when I increase the frequency it starts to disappear around 5 Hz becoming barely visible around 10 Hz. So my main concerns are, what is it, what causes it, should I care and if so...how do I fix it.

Roman Thilenius's icon

no matter which method hilbert~ in RNBO uses, but at 2Hz even the best possible hilbert transform gives up and produces only noise as output.

so to check if your patching is right the first thing to do is to use some 30Hz or higher (depending on the quality of the RNBO object) for the test signal.

(MSP)

Dimitri Bosiers's icon

Thanks for clarification, I did the same thing on the standard hilbert and I get a kind of spirograph diagram, only at standard pitch A440 the function approaches a circle. So you did something there with your hilbert-pro. ( how is a mystery to me )
Is it available somewhere ?

I was working on an oscillator that uses chebyshev polynominals to generate harmonics via a lookup buffer, but want to be able to phaseshift the harmonics, independently. I could use fft + ifft specral filtering but it seems a bit overkill if there are only a few harmonics so I was thinking about implementing it at oscillator level. ( not sure yet )

I'm basically looking for a way to make this as cpu efficient as possible, as the final solution has to run on a bulma.

Roman Thilenius's icon

actually the MSP hilbert~ object from cycling (today - not 20 years back) uses the same filters as this patch (they even look like beeing around 0.5 Hz better, because my filter coefficients are provided to the biquad kernel only in 32 bit/7 digits), and that should be the same for RNBO (but i havent tried that.)

love letters for finding the coefficients go to the brilliant -> ollie niemetalo, one of the first implementations in an industry product can be found in 2006´s -> dolby prologic II (or IIx?) decoders, and if you want to read a bit about the theory i´d recommend -> this superb website.

which also shows you how the analogy in fft would look like, so that you can compare them... only to find out that the polyphase butterworths are still 10 times better then an 16k fft.. and that at only 1-3 samples latency.

(note that you have to change the order of the coefficients when you copy a pd biquad to MSP)

if you build that in gen~ with custom filters you can save some CPU compared to that blue lego brick. (since it is butterworths)

why it looks a bit strange in modern versions of scope? no idea, i am used to the nice stone age one, where it "works". (you might want to set its frequency to "auto" or use tones which fit exactly to its window size?)

Roman Thilenius's icon

..... ..... .....

Dimitri Bosiers's icon

Again weird scope behaviour !? It made me doubt to use PD before, I noticed some differences before, the Max scopes do all kinds of interpretations, while at the same time they probably are optimised not to slow sound processing, multithreading with focus on audio processing may also cause this. worse part is at this moment you have no configuration options for them in RNBO.

About a year ago it wasn't really worth it to use RNBO because it basically was PD and with most of MSP not implemented yet. But it's coming along and PD misses the ability to label the in and out of sub-patches. Another reason for me to doubt was my target platform Bulma that did only implement PD until recently but Bulma now also runs C++ code generated from RNBO. Where PD runs native on some platforms like PiSound there isn't really an optimised export option which is a huge another plus for RNBO.

Anyway Still a bit in doubt, I really loved Linux but I had a rough patch with a lot of brain fog and wanted to minimise system maintenance. That's some nice generic art added there,I did some primitive stuff in processing back in 2009 but nobody got the concept, so I gave up on that. Anyway looks like I have some studying to do I might css edit that page in dev mode to ditch the Matrix feeling.

I'm rather new to this started about 2 year ago with a neutron and a keystep ago... to experiment with scales, harmonics, filters...all because at some point in time I decided to embark on a mission to make a niche synth. ( do I really want that, will it make somebody happy ? I hope so ) So here I am...experimenting to create some rather unique voices and envelopes tailored for that. I fear i'll have to buy Max to make room for another subscription to learn the math I need, the biggest problem is there's a lot of math, so your reply helps a lot to find a direction to explore ( since the wikipedia of the Hilbert transform makes me utterly depressed )

EDIT : truely intresting site this might actually help to get my reverse learning almost diagnosed adhd brain around the math. Big thx !

Roman Thilenius's icon

wikipedia always causes headache. even -> julius o. smith´s website is partially difficult to grasp (when you have no formal education like me)

katja´s is perfect. :)