4
$\begingroup$

Re-create Fourier Transforms IFFT / FFT using geometry nodes.

I have some imported frequency and amplitude data.

Example imported data:

Frequency Amplitude 7 0.4 5 0.2 2 0.7 

My thought process:

  1. Import data. (I can do this) My blend file.

img2

  1. Re-create ifft transform using For each loop node (if needed). (issues here)
  2. Set sample size. (issues here)
  3. Re-create fft transform using For each loop node (if needed) . (issues here)

Note: this is just an example image of what I'm trying to create

IMG1

What I've researched: https://www.reddit.com/r/blender/comments/z5enmo/i_made_the_fourier_transform_in_geometry_nodes/

Location of someone else's Blend file with no For each node https://drive.google.com/file/d/1w095tzoWLfwdNUfnS5giwquhy6gHuR-J/view?usp=sharing

The For each loop node wasn't implemented yet when this users blend file was created and I would like to import / use my own data sets which will vary in the amount of frequencies used (also not sure if the Fourier formulas used here are fully correct, seems to be missing phase).

Yes, I know this can be easily done in Python, but the goal is to:

  1. Allow different data sets to be selected (using the Object Info node)
  2. Dynamically alter the frequencies and amplitudes to show how it affects the signal (see animation below). Note: I was thinking of using the index to access and change the imported data values that way but if there's another way I'm open to it.

ani1

$\endgroup$
4
  • $\begingroup$ What is the rough number of points you will have? It's fairly easy to make a DFT without needing loops and with reasonable performance if you're not going for thousands. $\endgroup$ Commented Feb 14 at 2:31
  • $\begingroup$ @DanielMöller The thing is, it could range from hundreds to thousands. The datasets will vary in the number of frequencies, with the for-each node / loop, I thought, being the most variable. But I'm always willing to try something out. $\endgroup$ Commented Feb 14 at 4:17
  • $\begingroup$ How many frequencies are we talking about? I'm evaluating if you really need an FFT or if you could simply stack cosines together. Do you also mean hundreds of frequencies? $\endgroup$ Commented Feb 14 at 4:19
  • $\begingroup$ @DanielMöller Yes, it could be hundreds or thousands of frequencies they will vary. Hence I thought the for loop node would be the best option. But I'm wiling to try all options. $\endgroup$ Commented Feb 14 at 4:50

1 Answer 1

1
$\begingroup$

So, by your data (sparse frequencies and amplitudes), you don't need a "Fourier Transform", just a sum of a fourier series.

As for the frequency curve, it comes straight from the data without transformations.

So, here is my suggestion, where a signal and a frequency curve can be produced:

Results

Nodes

There is a group that creates the signal and another that creates the frequency curve.

I added a "phase" attribute for the sake of completeness, but it will not affect the result if you don't have the attribute.

Nodes

Frequency Curve group

This groups simply plots a line with N points, N being the maximum frequency you expect to see + 1.

Important: I don't have blender 4.3, so I used a "Repeat Zone", but you will definitely get a better performance using "For Each Element" to avoid the "Separate Geometry" node with a selection.

Fun Fact: If you're able to provide full data for all the frequencies (including frequencies with amplitude 0), and sorted by frequency, you can avoid the loop too by setting position sampling the point with the same index - this probably increases performance significantly.

The idea is:

  • Loop the data points
  • Set the position on the curve selecting the point whose index is equal to the frequency
  • The height of this point is the amplitude

Freq Curve

Fourier Series

Here, since we have discrete frequencies, a "transformation" does not really apply, we just sum the cosine components using the data

Here I used some geometry tricks to avoid a loop (loops in blender are very costly)

The main idea is:

  • For each X, sum the data point components which are amp * cos(x * 2pi * freq + phase)

I added a "phase" even though it's not in your data, if you leave it empty, phase is considered zero.

Explanation:

To avoid looping, I created a grid:

  • The grid has the same number of points in the X direction as the curve we will generate, their positions equal to the X positions on the curve
  • And in the Y direction there are a number equal to the data points, their positions being the index of the data point

For each point on the curve, we sample an accumulation of the Y (data points) dimension of the grid:

  • Grid X groups the accumulation and serves as the X input for the cosine
  • Grid Y samples the respective data point

For some reason, choosing lengths lower than 1 cause bugs, I believe it's a rounding issue in the group ID, but I'm not sure. I didn't see the bug with lengths >= 1, though.

Fourier Series

About dynamic edits

Unfortunately I have no good idea about how to make it dynamic when importing a CSV. The only way I can see it working dynamically is by creating a node group with a few frequencies and sliding these frequencies by hand.

Maybe you could use the position of the points as values (instead of attributes) and grab their positions to change values dynamically.

For instance, create a node group that sets the position of the points:

  • X = frequency
  • Y = amplitude

And in the Fourier nodes, sample X and Y of the points instead of the attributes. Then you can probably grab the points to vary the values.

Fourier transforms

I believe the above solves your question, although I haven't provided a fourier transform.

It's possible to create transforms that work like numpy.fft.rfft though, but they would add extra computation / complication for less precise results and a lack of freedom in curve resolutions.

File

$\endgroup$

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.