go-audio-fft
A lightweight Go library for basic audio frequency analysis using the Fast Fourier Transform (FFT).
Features
- Split audio samples into overlapping frames
- Apply a Hamming window
- Perform recursive FFT
- Calculate frequency values in Hz
- Calculate magnitude for each frequency bin
- Process multiple frames concurrently
Installation
go get github.com/rsudikshan/go-audio-fft
Usage Example
This example generates a 440 Hz sine wave, processes it through the library, and finds the dominant frequency.
package main
import (
"fmt"
"math"
audiofft "github.com/rsudikshan/go-audio-fft"
)
func main() {
const (
sampleRate = 44100.0
targetFreq = 440.0
duration = 1.0
frameSize = 4096
hopSize = 2048
)
// Generate a 440 Hz sine wave.
numSamples := int(sampleRate * duration)
samples := make([]float64, numSamples)
for i := range samples {
t := float64(i) / sampleRate
samples[i] = math.Sin(2 * math.Pi * targetFreq * t)
}
// Split samples into overlapping frames.
frames := audiofft.FrameSignal(
samples,
frameSize,
hopSize,
true,
)
// Perform FFT.
spectra := audiofft.FFT(frames, sampleRate)
// Find the strongest frequency in the first frame.
var dominant audiofft.FrequencyBin
for _, bin := range spectra[0] {
if bin.Magnitude > dominant.Magnitude {
dominant = bin
}
}
fmt.Printf(
"Dominant Frequency: %.2f Hz\nMagnitude: %.2f\n",
dominant.Frequency,
dominant.Magnitude,
)
}
Expected Output
The result should be close to:
Dominant Frequency: ~440 Hz
Magnitude: ...
The exact frequency may not be exactly 440 Hz because an FFT divides frequencies into discrete bins.
How It Works
Audio Samples
↓
Framing
↓
Hamming Window
↓
FFT
↓
Complex Frequency Bins
↓
Frequency + Magnitude
1. Framing
Audio samples are divided into smaller frames before performing the FFT.
Example:
frameSize = 4
hopSize = 2
Samples:
[s1, s2, s3, s4, s5, s6, s7, s8]
Frames:
[s1, s2, s3, s4]
[s3, s4, s5, s6]
[s5, s6, s7, s8]
- Frame size determines how many samples are processed by one FFT.
- Hop size determines how far forward the next frame starts.
- When
hopSize < frameSize, frames overlap.
2. Hamming Window
A Hamming window can be applied to each frame before performing the FFT.
Original Frame
↓
Multiply samples by Hamming coefficients
↓
Windowed Frame
↓
FFT
Windowing helps reduce spectral leakage.
3. FFT
The FFT converts time-domain audio samples into frequency-domain complex values.
Example:
Bin 0 → 10 + 0i
Bin 1 → 3 + 4i
Bin 2 → 1 - 2i
Each position is a frequency bin.
4. Frequency
The frequency represented by a bin is calculated using:
frequency = bin × sampleRate / FFTSize
For example:
sampleRate = 44100 Hz
FFTSize = 4096
Frequency resolution:
44100 / 4096
≈ 10.7666 Hz
Therefore:
Bin 0 → 0 Hz
Bin 1 → 10.7666 Hz
Bin 2 → 21.5332 Hz
Bin 3 → 32.2998 Hz
5. Magnitude
The FFT returns complex values.
For example:
3 + 4i
The magnitude is:
√(3² + 4²) = 5
Magnitude represents the strength of a frequency component.
The library returns:
type FrequencyBin struct {
Frequency float64
Magnitude float64
}
For example:
Frequency: 440 Hz
Magnitude: 250.45
This means the 440 Hz frequency component has a strength of 250.45.
Audio PCM samples are real-valued.
Because of this, the FFT output contains mirrored information in the second half of the spectrum. The library keeps the first half of the FFT output for frequency analysis.
Concurrency
Each frame can be processed independently.
The library divides frames into chunks and processes them concurrently using goroutines.
Frames
↓
Worker 1 → FFT
Worker 2 → FFT
Worker 3 → FFT
Worker 4 → FFT
↓
Combined Spectra
Return Structure
FFT returns:
[][]FrequencyBin
Conceptually:
spectra
│
├── Frame 0
│ ├── {Frequency, Magnitude}
│ ├── {Frequency, Magnitude}
│ └── ...
│
├── Frame 1
│ ├── {Frequency, Magnitude}
│ └── ...
│
└── Frame 2
├── {Frequency, Magnitude}
└── ...
Each frame contains frequency and magnitude information for a different portion of the audio.
License
This project is licensed under the MIT License. See the LICENSE file for details.