# Every thing is a `sin()`

February 11, 2023 -

Draft

What do heat transfer, music, JPEG, and Wi-Fi have in common? In 1807 Jean-Baptiste Fourier presented his paper "*On the propagation of heat in solid bodies*" to the Paris Institute and it made a lot nerds happy.

## Inanimate carbon rod

We'll start by looking at this rod with an infrared camera:

If we graph the temperature we get a beautifiul sine wave:

Let's measure the rod temperature while it cools off:

Fourier found that for a perfect sine wave like ours, we can get the temperature over time using this formula:

$\cos(\omega x)e^{-k\omega^2t}$

In the programming world we can translate this to the following code currently running on your graphic card:

```
float curve(float x, float t) {
float o = 2.0 * pi; // omega: adjust frequency
float k = 1.0; // conductivity: adjust how fast heat propagates
return cos(o * x) * exp(-k * o * o * t);
}
```

`ω`

: angle in radians` * π`

`k`

: how fast heat propagatesNow here is what happens when we make contact between a hot rod and a cold rod:

How can we compute the heat flow in this case? We have a formula for sine waves, but what we have here is a square wave.

## Hip to be square

Let's pull some fairly standard electronic music production gear: an oscillator, an oscilloscope, and a spectrum analyzer with an harmonics indicator.

The numbers on the spectrum analyzer are called harmonics:

- the first harmonic, also called the fundamental, equals
`frequency * 1`

- the second, also called the octave, equals
`frequency * 2`

- the third equals
`frequency * 3`

- and so on..

If you play with the oscillator a bit you will notice two important things:

- a sine wave only has one harmonic: itself
- a square wave only has odd harmonics decreasing exponentially

And that's all a square wave is, a sine wave with odd harmonics decreasing exponentially. So we have everything needed to decompose a square wave into sine waves and compute heat diffusion using them. Let's update our code:

```
float temperature(float x, float t) {
float o = 2 * pi; // omega: adjust frequency
float k = 1; // conductivity: adjust how fast heat propagates
return cos(o * x) * exp(-k * o * o * t);
}
float curve(float x, float t) {
float h = 3.0; // harmonics
float c = 0.0; // sum of curves
// Loop over odd harmonics: 1, 3, 5, 7, ...
for (float i = 1.0; i <= h; i += 2.0) {
// add the temperature for frequency * i and amplitude / i
c += temperature(x * i, t) / i;
}
return c;
}
```

`ω`

: angle in radians` * π`

`k`

: how fast heat propagates`h`

: how many harmonics## Do the astral plane

But how do you do a Fourier transform?

It's time to open our third eye and switch dimensions: instead of representing time as a plane we're going represent it in its true form, which as we all know is a circle repeating itself.

To help us visualize that, let's make the curve draw into a spinning disk:

Rotation speed

Tweaking the rotation speed gives us different shapes. Let's graph the average horizontal position based on the rotation speed:

Let's plug a square wave generate into this graph and see what happens:

Input frequency

What we have here isn't exactly a Fourier transform, but it's close enough. It does what Fourier transforms does: represent signals as a function of frequency instead of a function time.

## Shape of things to come

Every thing can be represented as signal, and every signal can be represented as an infinite sum of sine waves. So

## Final thoughts

That's all for today folks, hope you enjoyed the ride.

All animations in this post are computed in real-time using WebGL and SVG, feel free to look at the souce code and even run it locally using the `readme`

instructions!

Discuss on HN - Discuss on GitHub

## Appendix

The center of mass visualization is based on work by Grant Sanderson from 3Blue1Brown, I recommend checking his videos out if you're interested in this topic.

If you're like me the formula might be hard to grasp:

$\hat{g}(f)=\int_{t1}^{t2}g(t)e^{-2{\pi}ift}dt$

Here is what I ended up with using JavaScript and simple math:

```
function kindaFFT({
// Input signal
g = (x) => Math.sin(x * Math.PI * 2),
// Rotation frequency
f = 1,
// How many samples should we collect
samples = 64,
} = {}) {
// Store the graph data
let x = []
let y = []
// Store weighted averages
let centerX = 0
let centerY = 0
// Store averages weight
let divider = 0
// Loop over all the angles
for (let i = 1; i <= samples; i++) {
// Loop for each winding rotation
for (let t = (i / samples) * f; t <= f; t++) {
// Get the curve value for this angle and winding
let value = g(t / f)
// We now have a vector: an angle and an amplitude,
// convert it vector into cartesian coordinates:
centerX += value * Math.cos(t * Math.PI * 2)
centerY += value * Math.sin(t * Math.PI * 2)
// Add the value to the average weights
divider += value
}
}
// Compute the average position
return {
x: centerX / divider,
y: centerY / divider,
}
}
```