mirror of
https://github.com/gonum/gonum.git
synced 2025-10-06 07:37:03 +08:00

This reverts efc4dabf2a
The reason for the reversion is confusion caused between different
approaches for window sizing and ease of use.
121 lines
4.7 KiB
Go
121 lines
4.7 KiB
Go
// Copyright ©2020 The Gonum Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package window_test
|
|
|
|
import (
|
|
"fmt"
|
|
"math"
|
|
"math/cmplx"
|
|
|
|
"gonum.org/v1/gonum/dsp/fourier"
|
|
"gonum.org/v1/gonum/dsp/window"
|
|
)
|
|
|
|
func Example() {
|
|
// The input sequence is a 2.5 period of the Sin function.
|
|
src := make([]float64, 20)
|
|
k := 5 * math.Pi / float64(len(src)-1)
|
|
for i := range src {
|
|
src[i] = math.Sin(k * float64(i))
|
|
}
|
|
|
|
// Initialize an FFT and perform the analysis.
|
|
fft := fourier.NewFFT(len(src))
|
|
coeff := fft.Coefficients(nil, src)
|
|
|
|
// The result shows that width of the main lobe with center
|
|
// between frequencies 0.1 and 0.15 is small, but that the
|
|
// height of the side lobes is large.
|
|
fmt.Println("Rectangular window (or no window):")
|
|
for i, c := range coeff {
|
|
fmt.Printf("freq=%.4f\tcycles/period, magnitude=%.4f,\tphase=%.4f\n",
|
|
fft.Freq(i), cmplx.Abs(c), cmplx.Phase(c))
|
|
}
|
|
|
|
// Initialize an FFT and perform the analysis on a sequence
|
|
// transformed by the Hamming window function.
|
|
fft = fourier.NewFFT(len(src))
|
|
coeff = fft.Coefficients(nil, window.Hamming(src))
|
|
|
|
// The result shows that width of the main lobe is wider,
|
|
// but height of the side lobes is lower.
|
|
fmt.Println("Hamming window:")
|
|
// The magnitude of all bins has been decreased by β.
|
|
// Generally in an analysis amplification may be omitted, but to
|
|
// make a comparable data, the result should be amplified by -β
|
|
// of the window function — +5.37 dB for the Hamming window.
|
|
// -β = 20 log_10(amplifier).
|
|
amplifier := math.Pow(10, 5.37/20.0)
|
|
for i, c := range coeff {
|
|
fmt.Printf("freq=%.4f\tcycles/period, magnitude=%.4f,\tphase=%.4f\n",
|
|
fft.Freq(i), amplifier*cmplx.Abs(c), cmplx.Phase(c))
|
|
}
|
|
// Output:
|
|
//
|
|
// Rectangular window (or no window):
|
|
// freq=0.0000 cycles/period, magnitude=2.2798, phase=0.0000
|
|
// freq=0.0500 cycles/period, magnitude=2.6542, phase=0.1571
|
|
// freq=0.1000 cycles/period, magnitude=5.3115, phase=0.3142
|
|
// freq=0.1500 cycles/period, magnitude=7.3247, phase=-2.6704
|
|
// freq=0.2000 cycles/period, magnitude=1.6163, phase=-2.5133
|
|
// freq=0.2500 cycles/period, magnitude=0.7681, phase=-2.3562
|
|
// freq=0.3000 cycles/period, magnitude=0.4385, phase=-2.1991
|
|
// freq=0.3500 cycles/period, magnitude=0.2640, phase=-2.0420
|
|
// freq=0.4000 cycles/period, magnitude=0.1530, phase=-1.8850
|
|
// freq=0.4500 cycles/period, magnitude=0.0707, phase=-1.7279
|
|
// freq=0.5000 cycles/period, magnitude=0.0000, phase=0.0000
|
|
// Hamming window:
|
|
// freq=0.0000 cycles/period, magnitude=0.0218, phase=3.1416
|
|
// freq=0.0500 cycles/period, magnitude=0.8022, phase=-2.9845
|
|
// freq=0.1000 cycles/period, magnitude=7.1723, phase=0.3142
|
|
// freq=0.1500 cycles/period, magnitude=8.6285, phase=-2.6704
|
|
// freq=0.2000 cycles/period, magnitude=2.0420, phase=0.6283
|
|
// freq=0.2500 cycles/period, magnitude=0.0702, phase=0.7854
|
|
// freq=0.3000 cycles/period, magnitude=0.0217, phase=-2.1991
|
|
// freq=0.3500 cycles/period, magnitude=0.0259, phase=-2.0420
|
|
// freq=0.4000 cycles/period, magnitude=0.0184, phase=-1.8850
|
|
// freq=0.4500 cycles/period, magnitude=0.0092, phase=-1.7279
|
|
// freq=0.5000 cycles/period, magnitude=0.0000, phase=0.0000
|
|
}
|
|
|
|
func ExampleHamming() {
|
|
src := []float64{1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
|
|
|
|
// Window functions change data in place. So, if input data
|
|
// needs to stay unchanged, it must be copied.
|
|
srcCpy := append([]float64(nil), src...)
|
|
// Apply window function to srcCpy.
|
|
dst := window.Hamming(srcCpy)
|
|
|
|
// src is unchanged.
|
|
fmt.Printf("src: %f\n", src)
|
|
// srcCpy is altered.
|
|
fmt.Printf("srcCpy: %f\n", srcCpy)
|
|
// dst mirrors the srcCpy slice.
|
|
fmt.Printf("dst: %f\n", dst)
|
|
|
|
// Output:
|
|
//
|
|
// src: [1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000]
|
|
// srcCpy: [0.086957 0.111692 0.183218 0.293785 0.431409 0.581178 0.726861 0.852672 0.944977 0.993774 0.993774 0.944977 0.852672 0.726861 0.581178 0.431409 0.293785 0.183218 0.111692 0.086957]
|
|
// dst: [0.086957 0.111692 0.183218 0.293785 0.431409 0.581178 0.726861 0.852672 0.944977 0.993774 0.993774 0.944977 0.852672 0.726861 0.581178 0.431409 0.293785 0.183218 0.111692 0.086957]
|
|
}
|
|
|
|
func ExampleValues() {
|
|
src := []float64{1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
|
|
|
|
// Create a Sine Window lookup table.
|
|
sine := window.NewValues(window.Sine, len(src))
|
|
|
|
// Apply the transformation to the src.
|
|
fmt.Printf("dst: %f\n", sine.Transform(src))
|
|
|
|
// Output:
|
|
//
|
|
// dst: [0.000000 0.164595 0.324699 0.475947 0.614213 0.735724 0.837166 0.915773 0.969400 0.996584 0.996584 0.969400 0.915773 0.837166 0.735724 0.614213 0.475947 0.324699 0.164595 0.000000]
|
|
}
|