The Fast Fourier Transform for EEG
That Squiggly Line on Your Screen Is Hiding Something
You've seen an EEG trace before. Maybe in a movie, maybe in a research paper, maybe streaming live from your own head through the Neurosity SDK. It looks like a squiggly line. Voltage going up, voltage going down, in what appears to be an organic mess of random fluctuations.
But that line isn't random. And it isn't one signal.
It's dozens of signals, all stacked on top of each other. Slow oscillations rolling at 4 cycles per second. Faster rhythms humming at 10 cycles per second. Even faster activity buzzing at 40 cycles per second. All of them superimposed into a single, messy voltage trace that your electrode dutifully records as one continuous squiggle.
This is the fundamental problem of EEG analysis. The raw signal is a cocktail. And to do anything useful, whether that's detecting focus, tracking meditation depth, or building a brain-computer interface, you need to know the recipe. You need to know how much of each frequency is in the mix.
The tool that cracks this problem has been around since 1965. It's called the Fast Fourier Transform, or FFT. And if you're working with brain data, it's the single most important algorithm you'll ever encounter.
The Idea That Makes FFT Click
Here's the core insight, and once you get it, everything else about FFT falls into place.
Any signal, no matter how complex, messy, or random-looking, can be perfectly reconstructed by adding together a set of pure sine waves at different frequencies, amplitudes, and phases.
Read that again, because it's one of the most profound facts in all of mathematics.
That chaotic EEG trace on your screen? It's literally just the sum of a bunch of smooth sine waves. Each sine wave represents one frequency component of the signal. The slow, rolling 4 Hz sine wave is the delta band. The medium 10 Hz sine wave is alpha. The fast 40 Hz sine wave is gamma. Stack them all on top of each other, and you get the original messy squiggle back, perfectly.
This was Joseph Fourier's insight, published in 1807. He proved that any periodic function can be decomposed into a sum of sines and cosines. His contemporaries thought he was wrong. (Lagrange literally voted against the paper.) But Fourier was right, and his idea became one of the most widely applied mathematical tools in human history, powering everything from MP3 compression to medical imaging to the EEG analysis running right now on any brain-sensing device you might own.
The Fourier Transform is the mathematical operation that does the actual decomposition. You give it a signal, and it gives you back the list of sine waves (their frequencies, amplitudes, and phases) that, when added together, recreate that signal.
The Fast Fourier Transform is just a computationally efficient algorithm for computing this. Developed by Cooley and Tukey in 1965, it reduced the number of calculations from N-squared to N-log-N, which is the difference between "takes a minute" and "takes a millisecond." That speedup is what made real-time EEG frequency analysis possible.
From Time Domain to Frequency Domain: A Translation
Let's make this concrete with an EEG example.
You're recording from one EEG channel at 256 Hz (256 samples per second). You grab one second of data. That gives you 256 numbers, each one representing the voltage at your electrode at that instant in time. Plotted, these 256 numbers form the familiar squiggly line. This is the time domain representation. The x-axis is time, the y-axis is voltage.
Now you run FFT on those 256 numbers.
What comes out is a completely different set of numbers. Instead of 256 voltage-at-time-X values, you get 129 amplitude-at-frequency-Y values. (Why 129? We'll get to that.) Each value tells you how much energy exists at a particular frequency. Plotted, this forms a curve where the x-axis is frequency (in Hertz) and the y-axis is amplitude or power. This is the frequency domain representation.
Same data. Same information. Two radically different ways of looking at it.
The time domain tells you when things happened. The frequency domain tells you what frequencies are present. For EEG, the frequency domain is almost always more useful, because cognitive states correspond to frequency patterns, not raw voltage patterns.
Time domain (raw EEG): 256 voltage measurements per second per channel. Looks like a squiggly line. Useful for detecting sharp transients like spikes and artifacts. Hard to interpret visually for brain state.
Frequency domain (after FFT): Power values for each frequency bin from 0 Hz to 128 Hz. Looks like a spectrum or bar chart. Directly shows how much delta, theta, alpha, beta, and gamma the brain is producing. This is what neurofeedback, focus detection, and band power analysis use.
Both representations contain identical information. FFT converts between them without any loss. You can go from time domain to frequency domain and back again (inverse FFT) and get exactly the original signal.
The Key Parameters That Shape Your FFT Output
If you're writing code that uses FFT on EEG data, or if you're consuming FFT output from a device like the Crown, there are four parameters you need to understand. Get these wrong and your frequency data will be misleading or useless.
Sampling Rate
This one's straightforward. The sampling rate is how many voltage measurements your device takes per second. The Crown samples at 256 Hz. Clinical EEG systems often sample at 500 Hz or 1,000 Hz. Research-grade systems can go to 2,048 Hz or higher.
The sampling rate determines the highest frequency you can analyze. This limit is called the Nyquist frequency, and it's exactly half the sampling rate. At 256 Hz, your Nyquist frequency is 128 Hz. Any frequency above 128 Hz simply cannot be captured. If it exists in the real signal, it gets "folded" back into lower frequencies, creating a distortion called aliasing.
For EEG, this isn't usually a problem. The interesting brain activity for most applications lives between 0.5 Hz and 50 Hz. gamma brainwaves above 50 Hz are scientifically interesting but difficult to measure reliably from the scalp because the signals are tiny and easily contaminated by muscle artifact.
Window Size (Segment Length)
This is where things get interesting and where most beginners make their first mistake.
FFT operates on a fixed chunk of data. You don't feed it a continuous stream; you feed it a discrete segment. The size of that segment, measured in samples, determines a crucial property of your output: frequency resolution.
Frequency resolution equals the sampling rate divided by the window size in samples. Think of it as the "pixel size" of your frequency display.
| Window Size (samples) | Window Size (seconds) at 256 Hz | Frequency Resolution | What It Means |
|---|---|---|---|
| 128 | 0.5 s | 2.0 Hz | Can tell 8 Hz apart from 10 Hz, but not 9 Hz from 10 Hz |
| 256 | 1.0 s | 1.0 Hz | Can distinguish every integer frequency: 8, 9, 10, 11 Hz |
| 512 | 2.0 s | 0.5 Hz | Can distinguish 9.5 Hz from 10.0 Hz |
| 1024 | 4.0 s | 0.25 Hz | Very fine resolution, but needs 4 full seconds of data |
There's a fundamental tradeoff here, and it's inescapable. Want finer frequency resolution? You need a longer time window. But a longer time window means your analysis covers a bigger chunk of time, which means you lose temporal precision. You can't say "the brain had strong alpha at exactly second 3.2" if your FFT window spans from second 2 to second 4.
This is sometimes called the time-frequency uncertainty principle (yes, it's the same fundamental idea as Heisenberg's uncertainty principle in physics). You can know precisely what frequencies are present, or you can know precisely when they're present. You can't have perfect precision in both simultaneously.
For most EEG applications, a 1-second window (256 samples at 256 Hz) giving 1 Hz resolution is a reasonable default. That's fine enough to separate the standard frequency bands and fast enough to track state changes in near real-time.
Window Function (Tapering)
Here's a subtle but important problem. FFT assumes the signal segment you're analyzing repeats infinitely. It treats your 1-second chunk as if it loops forever, like a GIF. But your actual EEG segment almost certainly doesn't start and end at the same voltage. The beginning doesn't match the end. As far as FFT is concerned, there's a sudden jump where the signal "wraps around," and that abrupt discontinuity creates phantom high-frequency energy that doesn't exist in the real signal.
This artifact is called spectral leakage, and it smears energy from the true frequencies into neighboring frequency bins, polluting your spectrum.
The fix is a window function. Before running FFT, you multiply your signal segment by a bell-shaped curve that tapers smoothly to zero at both edges. This eliminates the discontinuity at the boundaries. The signal now starts and ends at zero, so the "looping" is smooth, and the phantom frequencies disappear.
| Window Function | Frequency Resolution | Leakage Suppression | Best For |
|---|---|---|---|
| Rectangular (none) | Best | Worst | Only use when signal is perfectly periodic (rare) |
| Hanning | Good | Good | General-purpose EEG analysis (most common choice) |
| Hamming | Good | Good | Similar to Hanning, slightly different sidelobe profile |
| Blackman | Lower | Excellent | When you need very clean separation between nearby frequencies |
| Kaiser | Tunable | Tunable | Advanced use; adjustable tradeoff via beta parameter |
The Hanning (sometimes called Hann) window is the default choice for EEG work. It's the workhorse. Unless you have a specific reason to choose something else, Hanning will serve you well.
Window functions reduce spectral leakage, but they come at a cost. Because they taper the signal to zero at the edges, they effectively throw away data at the beginning and end of each segment. This reduces the signal-to-noise ratio. The solution is overlapping windows: you slide the FFT window forward by 50% (or even 75%) of its length instead of a full window length. This way, the tapered edges of one window overlap with the well-preserved center of the next. A 1-second window with 50% overlap gives you a new FFT result every 0.5 seconds, and no data point ever falls entirely in the tapered zone. This is called Welch's method, and it's the standard approach for computing power spectral density from EEG.
Zero Padding
One more trick that sometimes confuses newcomers. You can append zeros to your data segment before computing FFT. If you have 256 real samples and you pad it to 512, the FFT output will have 257 frequency bins instead of 129. More bins means a smoother-looking spectrum.
But here's the catch: zero padding does not improve your actual frequency resolution. It only interpolates between the real frequency bins, like adding more pixels to an image by averaging adjacent colors. The underlying sharpness doesn't change. It can make your plots look nicer, and it can be useful for certain peak-detection algorithms, but it doesn't give you information that wasn't already there.
What the FFT Output Actually Looks Like
Let's walk through what you get when you run FFT on real EEG data.
You start with 256 samples of raw EEG (one second at 256 Hz). You apply a Hanning window. You run FFT. The output is a set of complex numbers, one for each frequency bin. Each complex number has two parts:
- Magnitude (or amplitude): how strong that frequency is in the signal
- Phase: where in its cycle that frequency was at the start of the window
For most EEG applications, you only care about the magnitude. Phase information matters for some advanced analyses (like coherence between channels or connectivity studies), but for power spectral analysis, focus detection, and neurofeedback, magnitude is what you need.
To get power, you square the magnitude. Power spectral density (PSD) plots show power (magnitude squared) on the y-axis and frequency on the x-axis. This is the bread-and-butter output of EEG frequency analysis.
A typical EEG PSD from a person with their eyes closed will show a prominent peak around 10 Hz. That's the alpha rhythm, and the fact that it pops up so clearly in the frequency domain is why FFT is so useful. In the raw time-domain signal, alpha might be subtle and hard to see among all the other overlapping oscillations. In the frequency domain, it jumps out as an obvious peak.

From FFT to Brain State: How Frequency Data Becomes Useful
Raw FFT output gives you power at every individual frequency bin. But cognitive states don't correspond to single frequencies. They correspond to bands, ranges of frequencies that tend to behave together.
This is where the standard EEG frequency bands come in:
| Band | Frequency Range | Associated State | Typical Application |
|---|---|---|---|
| Delta | 0.5 to 4 Hz | Deep sleep, unconsciousness | Sleep staging, injury detection |
| Theta | 4 to 8 Hz | Drowsiness, meditation, memory encoding | Meditation depth, creative state tracking |
| Alpha | 8 to 13 Hz | Relaxed wakefulness, eyes closed | Relaxation feedback, calm scoring |
| Beta | 13 to 30 Hz | Active thinking, concentration, alertness | Focus detection, attention monitoring |
| Gamma | 30 to 100 Hz | High-level cognition, binding, peak focus | Peak performance, cross-modal processing |
To get band power, you sum (or average) the FFT power values across all frequency bins within each band's range. A 1 Hz resolution FFT covering 0 to 128 Hz gives you individual bins at 0 Hz, 1 Hz, 2 Hz, and so on. To get alpha power, you sum the bins from 8 Hz through 13 Hz. To get beta power, you sum 13 Hz through 30 Hz.
The result is a set of five numbers, one per band, that together describe the brain's frequency "fingerprint" at that moment. Track these over time and you can watch the brain shift states: alpha power climbing when the person closes their eyes, beta power rising when they focus on a task, theta creeping in when they start to zone out.
This is exactly what the Crown's powerByBand observable provides. The device runs FFT on-chip, computes the band powers, and streams them to your application. No signal processing library required on your end.
The "I Had No Idea" Part: Why 1 Hz Matters More Than You Think
Here's something that surprises most people learning about FFT for EEG.
The difference between 1 Hz frequency resolution and 2 Hz frequency resolution isn't just a minor technical detail. It can determine whether your analysis is scientifically meaningful or garbage.
Consider the alpha band (8 to 13 Hz). There's strong evidence that lower alpha (8 to 10 Hz) and upper alpha (10 to 13 Hz) serve different cognitive functions. Lower alpha is associated with general alertness and attention. Upper alpha is associated with semantic memory processing and task-specific engagement. In neurofeedback, training lower alpha vs. upper alpha can produce different clinical outcomes.
With 2 Hz frequency resolution (from a 0.5-second window), your frequency bins land at 8 Hz, 10 Hz, and 12 Hz. You have exactly one bin for lower alpha and one for upper alpha, which might be enough for a rough estimate. But you can't see the fine structure within each sub-band.
With 1 Hz resolution (from a 1-second window), your bins land at 8, 9, 10, 11, 12, 13 Hz. Now you have three bins for lower alpha and three for upper alpha. You can see whether the alpha peak is at 9 Hz or 11 Hz, which tells you something physiologically meaningful. The peak alpha frequency varies between individuals (ranging from about 8 Hz to 12 Hz) and shifts within individuals depending on cognitive demand, age, and neurological health.
With 0.5 Hz resolution (from a 2-second window), you get six bins for lower alpha and six for upper alpha. Now you can precisely locate the individual alpha peak frequency and track shifts of half a hertz, which some researchers use as a biomarker for cognitive load and even neurological conditions.
The point is this: your choice of FFT window length isn't just a performance tuning decision. It's a scientific decision that determines what you can and can't detect in the data.
Putting It All Together: An FFT Pipeline for EEG
If you're building your own EEG analysis from raw data (rather than using the Crown's on-device processing), here's the standard pipeline:
Step 1: Acquire raw data. Collect a segment of EEG samples. For real-time applications, use a sliding window (e.g., 1 second of data, updated every 0.5 seconds).
Step 2: Remove the DC offset. Subtract the mean of the segment from every sample. This eliminates the 0 Hz component, which is just the average voltage and carries no useful brain information.
Step 3: Apply a window function. Multiply the segment by a Hanning window (element-wise). This tapers the edges and prevents spectral leakage.
Step 4: Compute the FFT. Use any standard FFT library (NumPy's numpy.fft.rfft in Python, or the Web Audio API's AnalyserNode in JavaScript). The output is an array of complex numbers.
Step 5: Compute power. Take the absolute value of each complex number and square it. This gives you the power at each frequency bin.
Step 6: Normalize. Divide by the window length (and by the window function's power correction factor) to get power spectral density in proper units (microvolts-squared per Hertz).
Step 7: Extract band powers. Sum or average the PSD values within each frequency band of interest (delta, theta, alpha, beta, gamma).
Step 8: Log-transform (optional but recommended). EEG power values span several orders of magnitude. Taking the log (usually log base 10) compresses the range and makes the data more normally distributed, which is better for statistical analysis and machine learning.
If you're using the Neurosity SDK, the Crown handles steps 1 through 7 on-device. You subscribe to brainwaves("powerByBand") or brainwaves("psd") and receive the processed frequency data directly. The on-device processing isn't just convenient. It also means your raw EEG data never leaves the device, which matters for privacy.
Common FFT Pitfalls (And How to Avoid Them)
After watching developers work with EEG frequency data for years, the same mistakes come up again and again. Here are the big ones.
Pitfall 1: Using too short a window for the analysis you're doing. If you're trying to separate alpha sub-bands, a 0.5-second window (2 Hz resolution) won't cut it. Match your window length to the frequency precision your application actually needs.
Pitfall 2: Forgetting to window the data. Running FFT on a raw, unwindowed segment produces spectral leakage that can significantly distort your band power estimates. Always apply a window function. Always.
Pitfall 3: Confusing amplitude and power. Amplitude is the FFT magnitude. Power is amplitude squared. Band power analyses use power (or power spectral density), not amplitude. Mixing them up will give you numbers that are off by a large factor and that don't match published reference values.
Pitfall 4: Ignoring artifacts before FFT. A single eye blink during your 1-second FFT window will inject a massive low-frequency artifact into delta and theta bands. Clean your data (or reject contaminated segments) before computing FFT. Garbage in, garbage out.
Pitfall 5: Treating FFT frequency bins as exact frequencies. A bin labeled "10 Hz" in a 1 Hz resolution FFT actually represents all energy between 9.5 Hz and 10.5 Hz. The bin is a bucket, not a pinpoint. This matters when you're defining band boundaries or looking for narrow-band peaks.
Beyond Basic FFT: Where to Go Next
FFT is the foundation, but it's not the only tool in the signal processing toolkit. Once you're comfortable with basic spectral analysis, these extensions open up deeper analysis:
Short-Time Fourier Transform (STFT): Run FFT on overlapping windows across your entire recording. The result is a spectrogram, a 2D image with time on one axis, frequency on the other, and color representing power. Spectrograms let you see how frequency content changes over time, which is invaluable for tracking state transitions.
Welch's Method: Average the power spectra from multiple overlapping windows to get a smoother, more reliable PSD estimate. This reduces the variance of your spectral estimates at the cost of temporal resolution. It's the standard approach for computing "the" PSD of an EEG segment.
Multitaper Method: Instead of one window function, use multiple orthogonal tapers (called Slepian sequences) and average the resulting spectra. This gives you better spectral estimates with less leakage than single-taper methods, especially for short data segments. It's popular in research-grade EEG analysis.
Wavelet Transform: Uses wavelets instead of sine waves as basis functions. Wavelets are naturally localized in both time and frequency, which gives you better time-frequency resolution than STFT for signals with transient features. Particularly useful for analyzing EEG events that are brief and non-stationary.
Each of these builds on the same core idea: decomposing a time-domain signal into frequency components. FFT is the first step. Master it, and the rest follows naturally.
Why This Matters for What You're Building
If you're reading this, you're probably a developer who wants to build something with brain data. Maybe a focus tracker. Maybe a neurofeedback app. Maybe something nobody's thought of yet.
Whatever it is, your application is almost certainly going to consume frequency-domain EEG data. Not raw voltages. Frequencies. Band powers. Spectral features. And every one of those comes from FFT.
The Neurosity Crown and its SDK are designed for exactly this use case. The Crown's N3 chipset runs FFT on-device across all 8 channels at 256 Hz, computing power spectral density and band powers in real-time. Through the JavaScript SDK, you can subscribe to brainwaves("powerByBand") and get delta, theta, alpha, beta, and gamma power values streaming into your application, updated several times per second.
You don't have to implement FFT yourself (though you certainly can, if you want to customize the parameters). The important thing is understanding what the numbers mean. Knowing that your alpha power just jumped 40% because the user closed their eyes, or that their beta-to-theta ratio just crossed a threshold that correlates with focused attention. That understanding is what lets you build applications that genuinely respond to how someone's brain is working.
The Remarkable Thing About a 200-Year-Old Idea
Joseph Fourier was trying to solve heat equations. He was a mathematician in Napoleonic France who wanted to understand how temperature distributes through solid objects. He had no idea his decomposition theorem would end up inside a chip on someone's head in 2026, running hundreds of times per second, converting the electrical murmur of 86 billion neurons into frequency data that a JavaScript application can subscribe to in three lines of code.
That's the thing about foundational mathematics. The best ideas outlive every specific application. Fourier's insight, that any complex signal is just a sum of simple oscillations, has been applied to radio, radar, audio compression, image processing, quantum mechanics, and now, reading your brain.
Every time the Crown computes a power spectrum, it's running an algorithm that connects directly back to an idea first published 219 years ago. And every time you build an application that uses that spectrum to do something no one has done before, you're extending a chain of invention that started with a French mathematician, a stack of equations, and a question about heat.
That's a pretty good reason to understand what FFT actually does.

