63 lines
1.3 KiB
Go
63 lines
1.3 KiB
Go
// Copyright (c) 2026 Petr Balvín <opensource@petrbalvin.org> (https://petrbalvin.org)
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
// Command fft demonstrates the Fourier transform: it synthesises a
|
|
// signal from two sinusoids, transforms it, and prints the dominant
|
|
// frequency components.
|
|
//
|
|
// Usage: go run ./examples/fft
|
|
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"math"
|
|
|
|
"sourcedock.dev/petrbalvin/tensor"
|
|
sig "sourcedock.dev/petrbalvin/tensor/signal"
|
|
)
|
|
|
|
func main() {
|
|
// Two sinusoids: 5 Hz and 13 Hz, sampled at 100 Hz for 2 seconds.
|
|
const (
|
|
fs = 100.0
|
|
seconds = 2.0
|
|
)
|
|
n := int(fs * seconds)
|
|
vals := make([]float64, n)
|
|
for i := range n {
|
|
t := float64(i) / fs
|
|
vals[i] = math.Sin(2*math.Pi*5*t) + 0.5*math.Sin(2*math.Pi*13*t)
|
|
}
|
|
signal, err := tensor.FromFloats(vals, n)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
spec, err := sig.FFT(signal)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
freqs := sig.FFTFreq(n, 1/fs)
|
|
|
|
// Find the two strongest bins (excluding DC).
|
|
var peaks [2]struct {
|
|
freq float64
|
|
mag float64
|
|
}
|
|
for i := 1; i < n/2; i++ {
|
|
m, _ := tensor.ComplexAt(spec, i)
|
|
mag := math.Hypot(real(m), imag(m))
|
|
for p := range peaks {
|
|
if mag > peaks[p].mag {
|
|
peaks[p].freq, _ = tensor.FloatAt(freqs, i)
|
|
peaks[p].mag = mag
|
|
break
|
|
}
|
|
}
|
|
}
|
|
for _, p := range peaks {
|
|
fmt.Printf("peak at %.1f Hz (magnitude %.1f)\n", p.freq, p.mag)
|
|
}
|
|
}
|