audiofft

package module
v0.0.0-...-03cd527 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 26, 2026 License: MIT Imports: 7 Imported by: 0

README

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.

Real-Valued Input

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.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ApplyHammingWindow

func ApplyHammingWindow(frame []float64, coeff []float64)

func FFT

func FFT(frames [][]float64, sampleRate float64, unumWorkers uint) [][]FrequencyBin

returns mag and freq

func FrameSignal

func FrameSignal(sample []float64, frameSize int, hopSize int, useHamming bool) [][]float64

func PreComputeHamming

func PreComputeHamming(N int) []float64

func SampleExtract

func SampleExtract(monoBuffer *audio.IntBuffer) []float64

func StereoToMono

func StereoToMono(path string) (*audio.IntBuffer, error)

Types

type FrequencyBin

type FrequencyBin struct {
	Frequency float64
	Magnitude float64
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL