Fourier Analysis
Decomposing periodic functions into their constituent frequencies, and analyzing the amplitude and phase of each frequency.
- November 18, 2025
Decomposing periodic functions into their constituent frequencies, and analyzing the amplitude and phase of each frequency.
Ever wondered how computers process and analyze images and shapes? You might have seen images stored as .png, .jpg, .bmp, or .svg while working with graphics or image processing. Broadly, image files can be represented using two fundamental formats: raster graphics and vector graphics.
In mathematical terms, an image in a two-dimensional space can be represented in two ways: spatial domain and frequency domain. In the spatial domain, the image is represented as a grid of pixels, where each pixel has a specific intensity value. In the frequency domain, the image is represented as a combination of different frequencies, which can be analyzed using Fourier analysis.
Fourier analysis is a mathematical technique used to decompose periodic functions into their constituent frequencies and analyze the amplitude and phase of each frequency component. Some of the key applications of Fourier analysis include audio processing, audio filtering, noise reduction, signal reconstruction, image compression, feature extraction, and recognition, object detection, and speech recognition among others. This means AirPods in your ears use some form of Fourier analysis to filter out the background noise when you activate noise cancellation in a subway or on a plane.
At its core, Fourier analysis is about decomposing a time-domain signal into its constituent frequencies, and inferring the amplitude and phase of each frequency component.
Draw a shape on the left canvas and watch Fourier epicycles trace it on the right! [1]
Left: Draw your shape | Right: Fourier epicycles tracing it
Instead of jumping straight into the math, I’ll try to build an intuitive understanding of how waves and signals work which would make it easier to grasp the need for Fourier analysis.
Here’s a quick overview recap on how waves and signals work, followed by an introduction to Fourier series, Fourier transform, and discrete Fourier transform.
A wave is a disturbance that travels through a medium, and a signal is a wave that carries information.
The most fundamental wave pattern in nature is the sinusoidal wave (or sine wave). A sine wave is a smooth, continuous oscillation that repeats periodically. It’s described mathematically by the sine function, which produces a characteristic S-shaped curve when plotted.
The basic sine wave equation is:
where oscillates smoothly between -1 and +1 as increases.
This simple mathematical function appears everywhere in nature—from the oscillation of a pendulum to the vibration of guitar strings, from alternating current in electrical circuits to the propagation of light and sound waves.
Sinusoidal waves are special because they are the building blocks of all other periodic waves. No matter how complex a wave pattern looks, it can be broken down into a sum of simple sine (and cosine) waves—this is the fundamental insight of Fourier analysis.
The equation represents a simple harmonic wave or oscillation with the following parameters:
Suppose we have a wave with frequency Hz; the wave oscillates 2 times per second,
The example equation describes a wave with an amplitude of 40 units and a frequency of 2 Hz. This means the wave oscillates between -40 and +40 units, completing 2 full cycles every second.
This equation describes many periodic phenomena, such as a vibrating string, sound waves, light waves (for small angles in the wave equation), etc.
In mathematics, when we add two functions (say, and ) together), we simply add their output values at each input point. This is expressed as:
This simple property of functions has profound implications in physics. When two waves occupy the same space simultaneously, they don’t collide or bounce off each other like physical objects. Instead, they superpose—their effects combine according to the principle of superposition.
The total displacement at any point is simply the sum of the individual wave displacements:
And this leads us to the fascinating phenomenon of wave interference.
Constructive Interference occurs when two waves are in phase (peaks align with peaks). Their amplitudes add together, creating a stronger wave:
For example, when two sound waves constructively interfere, they produce louder noise. In light waves, constructive interference creates bright spots on reflective surfaces.
Destructive Interference occurs when waves are out of phase (peaks align with troughs). They cancel each other out:
This is the principle behind noise-cancelling headphones—they detect incoming sound waves and generate an exact opposite wave to cancel them out. When light waves destructively interfere, they appear as dim patches.
These wave behaviors demonstrate that mathematical function addition directly corresponds to physical wave superposition, bridging abstract mathematics with observable phenomena in our universe.
Now that we have a basic understanding of waves and signals, imagine being given a complex wave pattern, like a sound wave or an image signal, and being asked to figure out what simple sine and cosine waves make up that complex pattern. This is exactly where Fourier analysis comes in. Fourier analysis provides the mathematical tools to decompose complex signals into their constituent sine and cosine waves, allowing us to analyze the frequency content of the signal.
Complex Wave
Component 1
Component 2
This means when you record a sound using your phone, Fourier analysis can identify which low amplitude high-frequency signals are present in the complex sound wave, apply a 180-degree phase shift to them, and add them back to the original sound wave to cancel out the noise.
The Fourier series is a powerful tool that represents any reasonable[2] periodic function as a sum of sine and cosine waves with different frequencies, amplitudes, and phases.
For periodic signals (functions that repeat over time, with period T), a signal 𝑓(𝑡) can be written as a sum of sine and cosine terms:
where is the fundamental frequency (the lowest frequency component), and , , and are the Fourier coefficients that determine the amplitude of each frequency component:
Alternatively, this can be written in amplitude-phase form:
where is the amplitude and is the phase of the -th harmonic component.
Sound waves are periodic signals, and the Fourier series can be used to decompose them into their constituent frequencies.
Fourier series can approximate any periodic function by summing up sine and cosine waves. The more terms we include in the series, the better our approximation becomes. With an infinite number of terms, we can perfectly reconstruct the original function. (In practice, we use a finite number of terms to get a good approximation.)
Let’s see this in action with a square wave - a function that abruptly alternates between +1 and -1:
━━ Target Wave (Square Wave)
━━ Fourier Approximation
As you increase the number of terms, notice how the red Fourier approximation gets closer to the gray target square wave. With just a few terms, we can already capture the general shape. With more terms, the approximation becomes remarkably accurate, though you’ll always see some overshoot at the discontinuities (known as the Gibbs phenomenon)—this happens because finite sums of smooth waves can’t perfectly match a jump discontinuity. Even functions with sharp corners and discontinuities can be represented as sums of smooth, continuous sine waves!
Coming back to recreating images using mechanical arms above, we can use Fourier series to break down complex 2D paths and use the same principles of wave decomposition to reconstruct them.
When you draw a picture, your pen traces a path through 2D space. You go in two directions simultaneously: horizontally (x-axis) and vertically (y-axis). At any moment in time , your pen has:
This means any drawing can be represented as two separate functions of time - one tracking horizontal movement, the other tracking vertical movement.
Batman silhouette drawn as a continuous path
Just like we decomposed sound waves, we can analyze the path by separating it into two time-domain signals.
The path decomposed into x(t) and y(t) signals
We have two functions now: and . Using Fourier series, we can approximate both functions as sums of sine and cosine waves. Which means, two sets of Fourier coefficients - one for and one for can be used to retrace the path of the drawing.
With just a few terms, we get a rough outline. As we increase the number of terms, the Fourier reconstruction gets closer and closer to the original bat silhouette.
There are primarily two ways to represent coordinates in 2D space: Cartesian coordinates and Polar coordinates . In Cartesian coordinates, a point is defined by its horizontal (x) and vertical (y) distances from the origin; P(x, y). In Polar coordinates, a point is defined by its distance from the origin (radius ) and the angle () it makes with the positive x-axis; P(r, θ).
Polar coordinates use trigonometric functions to relate to Cartesian coordinates: , . In the polar coordinates system, a point can be represented as a vector originating from the origin, with length and angle .
Look at this example of represented as a rotating vector in the complex plane:
Sine wave represented as a rotating vector
Notice how the tip of the rotating vector traces out the sine wave over time. Similarly, a periodic function can be represented as a sum of rotating vectors (epicycles) in the complex plane. Attach an epicycle on the tip of another epicycle, and so on.
y(t) = 50·sin(ωt) + 30·sin(3ωt)
Earlier, we wrote the Fourier Transform and DFT using separate sine and cosine terms. There’s a more elegant way to write this using Euler’s formula, which establishes a beautiful connection between exponentials and trigonometry:
This remarkable equation means a complex exponential represents a rotating vector in the complex plane. From this, we can derive:
Why this matters: Instead of writing separate terms, we can combine them into a single complex exponential:
This is the compact form of the Fourier Transform you’ll see in textbooks. It’s the same math as before, just written more concisely.
Similarly, the DFT can be written as:
Now, coming back to the Fourier series representation of our drawing, we combine x and y into one complex signal:
Fourier coefficients can be expressed as:
Each term represents a rotating vector (an epicycle) at frequency . The magnitude gives the radius, and gives the starting phase.
Each term in the Fourier series can be visualized as a circle rotating at a specific frequency. When you connect these circles end-to-end (placing the center of each circle at the tip of the previous one), their combined motion traces out your original drawing.
Rotating circles (epicycles) tracing a path
Your drawing is sampled at discrete pixel points—not a continuous mathematical curve. For such sampled periodic signals, we use the Discrete Fourier Transform (DFT) to extract the frequency components.
The DFT takes sampled points and computes frequency components, each with amplitude and phase:
Each complex number tells us:
Since our drawing is 2D, we combine and coordinates into one complex signal: . The DFT treats this closed path as one period of a repeating pattern—that’s why the epicycles loop perfectly!
Summing up, we have:
Since your drawing is sampled at discrete points (not a continuous function), we use the Discrete Fourier Transform (DFT)—the sampled version of the Fourier transform.
Step 1: Analyzing the Drawing (DFT)
We compute complex coefficients by projecting the sampled path onto each rotating basis :
for (let n = -numFrequencies; n <= numFrequencies; n++) {
let realSum = 0, imagSum = 0;
for (let k = 0; k < N; k++) {
const angle = (-2 * Math.PI * n * k) / N;
realSum += x[k] * Math.cos(angle) - y[k] * Math.sin(angle);
imagSum += x[k] * Math.sin(angle) + y[k] * Math.cos(angle);
}
// Convert to polar form: amplitude and phase
amplitude = sqrt(realSum² + imagSum²) / N;
phase = atan2(imagSum, realSum);
}
This gives us:
Step 2: Reconstructing the Path (Inverse DFT)
To redraw at time (from 0 to 1):
x(t) = Σ amplitude[n] * cos(2π * freq[n] * t + phase[n])
y(t) = Σ amplitude[n] * sin(2π * freq[n] * t + phase[n])
Each term is one rotating epicycle. Sum them all up to get the final pen position.
Step 3: Animation
for (t = 0; t < 1; t += 0.01) {
position = evaluateEpicycles(coefficients, t);
drawPoint(position.x, position.y);
}
As goes from 0 → 1, we complete one full cycle and trace the entire drawing!
Now, for each Fourier coefficient, we create an epicycle (rotating circle) in the complex plane. By connecting these epicycles tip-to-tail, the final tip traces out the original drawing.
More epicycles = better approximation
If you’ve followed this far, you’d have a fair understanding of how we used Fourier series to decompose a 2D drawing into two time-domain signals, approximated those signals using sine and cosine waves, and represented those waves as rotating vectors (epicycles) in the complex plane.
For a closed curve sampled at points , we calculate the Fourier coefficients:
Each coefficient can be converted to polar form:
At any time , the position is:
where is the number of terms used in the approximation, and represents the pen’s position in the complex plane.
This technique works because:
So far, we’ve treated your drawing as a periodic signal—one complete cycle that the DFT assumes repeats infinitely. This is why closed curves work perfectly with epicycles.
But what about signals that truly don’t repeat? A recording of your voice, a single burst of noise, or any one-time event?
The Fourier Transform generalizes the Fourier series to non-periodic signals. Instead of discrete harmonics (1×, 2×, 3× the fundamental frequency), we now have a continuous spectrum of all possible frequencies.
Using complex exponential notation, the Fourier Transform is:
Forward Transform (Signal → Frequency):
Inverse Transform (Frequency → Signal):
where:
The Fourier Transform is essential for analyzing non-repeating signals in audio processing, image filtering, and countless other applications.
The Discrete Fourier Transform (DFT) we used for drawings combines two properties:
For a sequence of samples :
Inverse DFT (reconstructing the signal):
Each decomposes into:
where and are the cosine and sine components.
The DFT is the foundation of all digital signal processing—analyzing digital audio, compressing images (JPEG), processing video, and more.
While our visualizations use the standard DFT algorithm shown above, real-world applications use a much faster algorithm called the Fast Fourier Transform (FFT).
The DFT we implemented has a critical limitation: computational complexity.
For a signal with points:
Example: For a 1-second audio clip at 44,100 Hz (CD quality):
This is too slow for real-time applications like audio processing, video streaming, or live music visualizers.
In 1965, Cooley and Tukey rediscovered an algorithm (originally found by Gauss in 1805) that computes the exact same result as DFT, but much faster:
FFT complexity: operations
Same example (44,100 samples):
The FFT uses a divide-and-conquer strategy:
The key insight: many of the calculations in DFT are redundant. The FFT eliminates this redundancy by reusing intermediate results.
// DFT: Computes everything from scratch
for (n in frequencies) {
for (k in points) {
// N² operations total
}
}
// FFT: Divides work recursively
function FFT(points) {
if (points.length === 1) return points;
even = FFT(points[0, 2, 4, ...]); // Recursion
odd = FFT(points[1, 3, 5, ...]); // Recursion
return combine(even, odd); // N log N operations total
}
Performance deep dive:
For production systems, three details matter:
Power-of-two sizes: FFT is fastest when (e.g., 512, 1024, 2048). This is because the divide-and-conquer splits evenly at each level. Non-power-of-two sizes work but require different algorithms (Bluestein’s, mixed-radix) that are slower.
Iterative vs recursive: The code above shows recursive FFT for clarity, but production libraries use iterative FFT (bit-reversal + in-place butterfly operations). Why? Recursive FFT has function call overhead and poor cache locality. Iterative FFT processes data in cache-friendly sequential passes.
Cache friendliness: Modern FFT implementations (like FFTW) use clever memory layouts and loop tiling to keep data in L1/L2 cache. A well-tuned FFT is often an order of magnitude faster in practice than a naive implementation, even with the same complexity.
This is why audio buffer sizes are always powers of two (256, 512, 1024)—it’s not arbitrary, it’s for FFT performance!
DFT is great for:
FFT is essential for:
Most programming languages provide optimized FFT libraries:
// JavaScript (using Web Audio API)
const fft = new FFT(bufferSize);
fft.forward(audioData); // O(N log N) instead of O(N²)
// Python (NumPy)
import numpy as np
frequencies = np.fft.fft(signal) // Uses FFTW library
// MATLAB
X = fft(x); // Built-in FFT
These libraries use highly optimized implementations like FFTW (Fastest Fourier Transform in the West), which can be 100× faster than a naive FFT implementation.
Equipped with this you can now go on to explore the vast west of signal processing. This new weaponry can help you build something cool, like:
This article including the image retracing is inspired from injuly’s fourier series blog. ↩︎
“Reasonable” functions are those that are piecewise continuous and have a finite number of discontinuities within a period. Not every periodic function is representable in a strong sense. There are periodic functions that are so pathological that: 1.the Fourier series fails to converge at some points, or even 2. diverges almost everywhere. These exist (classic results by du Bois-Reymond, later strengthened by others). You won’t meet them in engineering, but mathematically they kill the fully-general “any periodic function” claim. ↩︎