package extractfreq import ( "fmt" "log" "math/cmplx" "git.crumpington.com/public/jlaudio/lib/flac" "gonum.org/v1/gonum/fourier" "gonum.org/v1/plot" "gonum.org/v1/plot/plotter" "gonum.org/v1/plot/plotutil" "gonum.org/v1/plot/vg" ) func PlotFFT(path string, nSamples int, targetFreq float64) { L, R, err := flac.Load(path) if err != nil { panic(err) } if nSamples < len(L) { nSamples = len(L) } data := make([]float64, nSamples) for i := range data { data[i] = float64(L[i]) + float64(R[i]) } fft := fourier.NewFFT(nSamples) cCoeffs := fft.Coefficients(nil, data) amps := make([]float64, len(cCoeffs)) freqs := make([]float64, len(cCoeffs)) ampMax := float64(0) for i := range freqs { amps[i] = cmplx.Abs(cCoeffs[i]) if amps[i] > ampMax { ampMax = amps[i] } freqs[i] = fft.Freq(i) * 48000 } // Normalize coefficients. for i := range amps { amps[i] /= ampMax } /* // Use a moving window to search for local peaks. hws := []*HarmonicWindow{} // Bypass low-frequency samples. i := 0 for i < len(freqs) && freqs[i] < 24 { i++ } iCenter := i for iC{ } */ // Find frequency window around midi note. harmonics := []float64{0.25, 0.5, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} for _, harmonic := range harmonics { hw := NewHarmonicWindow( targetFreq, harmonic, amps, freqs) p, err := plot.New() if err != nil { panic(err) } log.Printf("Making points...") pts := make(plotter.XYs, 0, len(hw.Amps)) for i := range hw.Amps { pts = append(pts, plotter.XY{ X: hw.Freqs[i], Y: hw.Amps[i], }) } log.Printf("Plotting...") if err = plotutil.AddLines(p, "fft", pts); err != nil { panic(err) } //p.Y.Scale = plot.LogScale{} //p.X.Scale = plot.LogScale{} log.Printf("Saving...") filename := fmt.Sprintf("plot-%03.2f.png", harmonic) if err := p.Save(8*vg.Inch, 8*vg.Inch, filename); err != nil { panic(err) } } }