Page 1 of 1

HELP!! GraphFF prim Phase output issue: SOLVED!

Posted: Mon Jul 27, 2020 3:05 pm
by Spogg
Will someone please help a poor Vulcan?

I’ve been struggling for ages with this and I need someone to tell me just how stupid I’ve been. :cry:

My goal was to take a float array, derived from a single cycle wav, and use the Graph FFT to convert it to Magnitude and Phase. Then I intended to edit the magnitudes and convert it back to a waveform using iFFT.

It seems the GraphFF prim doesn’t want to play that game, not with me anyway. Even with a basic sinewave loaded, the Phase array output looks quite bizarre. I know this prim is used in spectrum displays, but I haven’t found a module that uses the Phase output, which is critical for my intended use. I don’t want to edit the phases, just the magnitudes. No way can I reconstruct the original waveform, even with no editing. Some waveforms look close but others are just plain weird.

I’ve prepared a test schematic with lots of comments. The zip also contains a folder of wavs suitable for testing, so you can easily try different waveforms.

One thing I’ve learned is that Magnitude and Phase is not the same as Real and Imaginary. Or maybe I imagined that reality. :lol:

Any advice would be most welcome guys.

Cheers!

Re: HELP!! GraphFF prim Phase output issue...

Posted: Mon Jul 27, 2020 5:51 pm
by tektoog
Hey,
I've just overlooked your schematic but It seems using a resample prim helps a bit...

GraphFF prim issue dev 1 - TekTooG.fsm
(13.2 KiB) Downloaded 1134 times

Take care ;)

Re: HELP!! GraphFF prim Phase output issue...

Posted: Tue Jul 28, 2020 6:35 am
by MichaelBenjamin
.

Re: HELP!! GraphFF prim Phase output issue...

Posted: Tue Jul 28, 2020 7:22 am
by martinvicanek
Hey Spogg, some observations in your schematic:

1. In the lower part after the GraphFFT prim you discard half of the spectrum - that's bad because we need the complete spectrum for reconstruction, even though it seems redundant. Math can be stubborn at times.

2. Apart from magnitude normalisation, there is a pitfall in the prims: GraphFFT will output a phase array in degrees, whereas the RealImg prim expects a phase array in radians! <rage emoticon> To convert, multiply by pi/180.

3. The phase output of a sine wave spectrum seems random, but that's perfectly OK. Most of the spectrum components (= partials) have zero magnitude, hence their phase can be anything. (If you take a step of zero length, it does not matter which way you go. ;) )

Re: HELP!! GraphFF prim Phase output issue...

Posted: Tue Jul 28, 2020 9:10 am
by Spogg
Thanks for your input guys.

@Martin
Thank you so much Mr Saviour! I would never have thought of that. I stupidly assumed that Phase, like all other units, would be consistent across FlowStone. :shock:

I’ve corrected the schematic with the degrees to radians conversion and the harmonics and phase are now correct. However, you’ll see in the schematic that the result from using the GraphFF produces a mirrored float array. I found an old module by Exo that mirrors a float array and now every waveform is identical to the original.

So I’m extremely happy that I have it working now, but puzzled by why I have to “un-mirror” the resulting array.
I expect there’s some very involved mathematical explanation which I wouldn’t understand, but others might if you could explain.

Re: HELP!! GraphFF prim Phase output issue...

Posted: Tue Jul 28, 2020 10:43 am
by martinvicanek
There is another pitfall which I discovered only now: Apparently the GraphFFT prim actually performs an inverse FFT, which has the inverse phase sign compared to the FFT. Therefore, to transform back you can choose one of the following alternatives:

(a) use the FFT prim (instead of the IFFT prim)

(b) convert the phase by -pi/180 (instead of pi/180)

(c) mirror the resulting array and apply a cyclical shift by 1, i.e. reorder according to
[ a[0], a[1], a[2], ..., a[N-1] ] -> [ a[0], a[N-1], a[N-2], ..., a[1] ]

Re: HELP!! GraphFF prim Phase output issue...

Posted: Tue Jul 28, 2020 3:05 pm
by Spogg
I chose option (a) because I thought it had the lowest overhead. And it works! Yay!! :D :D

I’ve attached the corrected version for completeness and I’m quite certain that I would never have got to this solution having messed around for nearly 3 days.

Martin, I’m SO grateful for your help (as always).

Cheers!