als-fft
v3.4.1
Published
**als-fft** is a small library for performing Fast Fourier Transforms (FFT) and Inverse Fast Fourier Transforms (IFFT) on arrays of real (or complex) data in JavaScript.
Readme
als-fft v3.2.0
See change-log.md for changes.
Features
Short-Time Fourier Transform (STFT) Support
Enabling time-frequency analysis of signals with configurable overlap and windowing.Forward FFT:
Compute the FFT of an input signal (array of real numbers or complex pairs).Inverse FFT (IFFT):
Reconstruct the time-domain signal from its frequency-domain representation.Segmented FFT Processing:
Automatically splits the input signal into fixed-size segments (with zero-padding when necessary) and computes the FFT for each segment.Spectral Restoration:
Restores the full spectrum from a half-spectrum using mirror symmetry.Signal Restoration:
Recombines FFT segments back into a continuous time-domain signal via thesamplesgetter.Cutting (Segment Removal) Functionality:
Remove unwanted FFT segments by:- Directly specifying segment indices.
- Specifying a range of segments.
- Specifying a time interval (in milliseconds).
Flexible API:
Use static methods for direct processing or instantiate the FFT class for segmented operations and dynamic editing.Works in Node.js and Browsers:
Available as a module for Node.js (via npm) and as a bundled script for browser environments.
Installation
Node.js
Install via npm:
npm install als-fftThen require it in your project:
const FFT = require("als-fft");or
import FFT from 'als-fft';Browser
Include the bundled script (e.g., fft.js) in your HTML:
<script src="node_modules/als-fft/fft.js"></script>This exposes the FFT class as a global variable.
API Reference
Class: FFT
The FFT class provides both static and instance methods for FFT-based operations, signal restoration, and segment cutting.
Static Methods & Utilities
FFT.fft(data)
Computes the forward Fast Fourier Transform of the input data.- Parameters:
data: An array of lengthN(a power of 2) containing real numbers or complex pairs[re, im].
- Returns:
An array of complex pairs[re, im]representing the frequency-domain data. - Example:
const signal = [1, 0, 1, 0, 2, 0, 2, 0]; const spectrum = FFT.fft(signal); console.log(spectrum);
- Parameters:
FFT.ifft(data)
Computes the inverse FFT (IFFT) of the input frequency-domain data.- Parameters:
data: An array of complex pairs[re, im].
- Returns:
An array of real numbers representing the reconstructed time-domain signal. - Example:
const recovered = FFT.ifft(spectrum); console.log(recovered);
- Parameters:
FFT.restoreSymmetry(halfSpectrum)
Re-creates the full Hermitian spectrum from a half-spectrum that was produced when the FFT was run withsplited: true.Parameters
halfSpectrum— array of complex pairs[re, im]of lengthN / 2.
Returns
An array of lengthN(complex pairs) where the negative-frequency part is rebuilt by mirror symmetry.Example
const half = fftInstance.timePoints[0]; // stored half-spectrum const full = FFT.restoreSymmetry(half);
Instance Methods
Constructor:
new FFT(samples, options)Parameters:
samples: An array (or Float32Array) of real-valued samples.options: An object with the following properties:segmentSize(number, required): The length of each FFT segment (must be a power of 2).splited(boolean, optional, defaultfalse): Store FFT segments as half-spectra iftrue.sampleRate(number, required for time-based cutting): The sample rate (in Hz) of the input signal.hopSizeFactor(number, optional, default1): Fraction ofsegmentSizedefining the step size between segments (e.g.,0.25for 75% overlap).hannWindow(boolean, optional, defaultfalse): Apply a Hann window to each segment iftrue.zeroPadding(boolean, default false)
If true, each segment is zero-padded up totargetSizebefore the FFT. Increases spectral resolution without changing the analysed window length.targetSize(number, optional)
Absolute FFT size to pad to (must be a power of two and≥ segmentSize). Ignored unlesszeroPaddingis true.normalize(boolean, default false)
When enabled, values returned in.$timePointsare divided by the effective FFT size (segmentSizeortargetSize). Useful for comparing spectra obtained with different padding factors.
getComputedTimePoints()
Calculates and caches magnitude values√(re² + im²)for each frequency bin in every segment.- If the instance was created with
normalize: truethe magnitudes are additionally divided by the effective FFT size (segmentSizeortargetSize), so spectra obtained with different padding factors remain comparable. - Example:
const fftInstance = new FFT(signal, { segmentSize: 1024, sampleRate: 44100 }); fftInstance.getComputedTimePoints();
- If the instance was created with
get samples
A getter that restores and returns the time-domain signal from the current FFT segments (after any cuts).- Example:
const restoredSignal = fftInstance.samples; console.log(restoredSignal);
- Example:
freqStepfreqStep property - frequency step for each time point
Cutting Methods
The FFT class provides cutting (segment removal) functionality via a helper instance exposed by the cut getter.
fftInstance.cut.timepoints(arr)
Removes FFT segments whose indices are included in the provided array.- Example:
fftInstance.cut.timepoints([2, 3, 7]);
- Example:
fftInstance.cut.timepointsRange(from, to)
Removes FFT segments over a continuous index range.
Note: This method uses an internalrange()helper to generate the indices.- Example:
fftInstance.cut.timepointsRange(5, 10);
- Example:
fftInstance.cut.byTime(from, to)
Removes FFT segments corresponding to a time interval specified in milliseconds.
The start and end times are converted to segment indices using the segment duration computed fromsegmentSizeandsampleRate.- Example:
fftInstance.cut.byTime(1000, 2000); // Remove segments from 1s to 2s of the signal
- Example:
For convenience, the FFT class also provides shortcut instance methods:
cutTimepoints(arr)– equivalent tofftInstance.cut.timepoints(arr).cutTimepointsRange(from, to)– equivalent tofftInstance.cut.timepointsRange(from, to).cutByTime(from, to)– equivalent tofftInstance.cut.byTime(from, to).
Short-Time Fourier Transform (STFT) Support
Starting with version 3.2.0, als-fft supports Short-Time Fourier Transform (STFT), enabling time-frequency analysis of signals with configurable overlap and windowing. This is useful for applications like speech analysis, where frequency content changes over time.
New Options
The FFT constructor now accepts additional options to enable STFT:
hopSizeFactor(number, optional, default1):
Defines the step size between segments as a fraction ofsegmentSize. A value less than 1 introduces overlap (e.g.,0.25means 75% overlap, step size =segmentSize * 0.25).hannWindow(boolean, optional, defaultfalse):
Whentrue, applies a Hann window to each segment before computing the FFT, reducing spectral leakage.
STFT Matrix
get computeSTFTMatrix
A getter that returns a 2D array representing the STFT of the signal:- Rows: Frequency bins (half-spectrum if
splited = true, full otherwise). - Columns: Time frames (number depends on
hopSizeFactor). - Values: Amplitude magnitudes computed as
√(re² + im²)for each frequency-time point. - Example:
const samples = new Float32Array(1024).fill(1); const fft = new FFT(samples, { segmentSize: 256, hopSizeFactor: 0.25, hannWindow: true, sampleRate: 44100, splited: true }); const stftMatrix = fft.computeSTFTMatrix; console.log(stftMatrix); // [128 frequencies] × [13 time frames]
- Rows: Frequency bins (half-spectrum if
Enhanced Signal Restoration
When using hopSizeFactor < 1 and hannWindow = true, the samples getter restores the signal using overlap-add normalization to account for overlapping segments, ensuring accurate reconstruction.
Example Usage
Basic STFT Analysis
const FFT = require('als-fft');
// Example signal: 1 second of 100 Hz sine wave at 44100 Hz
const samples = new Float32Array(44100).map((_, i) => Math.sin(2 * Math.PI * 100 * i / 44100));
const fft = new FFT(samples, {
segmentSize: 1024,
hopSizeFactor: 0.25, // 256-point step, 75% overlap
hannWindow: true,
sampleRate: 44100,
splited: true
});
// Get STFT matrix
const stftMatrix = fft.computeSTFTMatrix;
console.log('STFT Matrix:', stftMatrix);
// Restore signal
const restored = fft.samples;
console.log('Restored Signal Length:', restored.length);Cutting with STFT
const fft = new FFT(samples, {
segmentSize: 1024,
hopSizeFactor: 0.25,
hannWindow: true,
sampleRate: 44100
});
// Remove segments from 0.5s to 1s
fft.cut.byTime(500, 1000);
// Get updated STFT matrix
const updatedStftMatrix = fft.computeSTFTMatrix;
console.log('Updated STFT Matrix:', updatedStftMatrix);Zero-Padding & Normalisation (v3.4.0+)
Zero-padding allows you to keep a short analysis window
(e.g. 32 ms) while obtaining a denser frequency grid.
const fft = new FFT(samples, {
segmentSize : 512, // 32 ms at 16 kHz
zeroPadding : true,
targetSize : 2048, // four-fold finer bin spacing
normalize : true // keep amplitudes comparable
});Helper Class: CutTimePoints
This internal helper class is instantiated via the cut getter of an FFT instance. It provides methods to generate index ranges and remove FFT segments:
range(start, end, step = 1)
Returns an array of numbers fromstart(inclusive) toend(exclusive) with the specified step.timepoints(arr)
Removes FFT segments at indices specified in the arrayarrand updates the computed time points.timepointsRange(from, to)
Convenience method that removes FFT segments over a continuous index range.byTime(from, to)
Converts the given time interval (in milliseconds) to segment indices and removes the corresponding FFT segments.
Example Usage
Node.js Example
const FFT = require('als-fft');
// Example signal: 0.5 seconds of 100 Hz sine wave at 44100 Hz
const samples = new Float32Array(22050).map((_, i) => Math.sin(2 * Math.PI * 100 * i / 44100));
const fftInstance = new FFT(samples, {
segmentSize: 1024,
hopSizeFactor: 0.25,
hannWindow: true,
sampleRate: 44100
});
// Get STFT matrix
const stftMatrix = fftInstance.computeSTFTMatrix;
console.log("STFT Matrix:", stftMatrix);Browser Example
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>als-fft v3.2.0 Demo</title>
<script src="fft.js"></script>
</head>
<body>
<input type="file" id="fileInput" accept="audio/wav">
<script>
document.getElementById('fileInput').addEventListener('change', async (e) => {
const file = e.target.files[0];
if (!file) return;
const arrayBuffer = await file.arrayBuffer();
const samples = new Float32Array(arrayBuffer); // Simplified, requires WAV parsing
const fftInstance = new FFT(samples, {
segmentSize: 1024,
hopSizeFactor: 0.25,
hannWindow: true,
sampleRate: 44100
});
// Get STFT matrix
const stftMatrix = fftInstance.computeSTFTMatrix;
console.log("STFT Matrix:", stftMatrix);
});
</script>
</body>
</html>