This repository has been archived on 2019-12-11. You can view files and clone it, but cannot push or open issues/pull-requests.
jlaudio/lib/extractfreq/harmonicwindow.go

66 lines
1.7 KiB
Go

package extractfreq
import (
"log"
"gonum.org/v1/gonum/floats"
"gonum.org/v1/gonum/stat"
)
type HarmonicWindow struct {
Harmonic float64 // 0.25, 0.5, 1, 2, 3, ...
Amps []float64
Freqs []float64
IdxPeak int
IdxPeakInterp float64
FreqPeakInterp float64
AmpPeak float64
AmpMean float64
AmpStd float64
}
func NewHarmonicWindow(
fFundamental float64,
harmonic float64,
rawAmps []float64,
rawFreqs []float64,
) *HarmonicWindow {
deltaF := rawFreqs[1] - rawFreqs[0]
// TODO: At higher harmonic numbers, the harmonics are going to be spaced
// more cloesly together. That means that the window size must shrink.
//winSizeCents := float64(150)
// To start, we create a window around the approximate harmonic location.
idxPeak := int((fFundamental * harmonic) / deltaF)
winSize := int(0.5 * fFundamental / deltaF)
amps := rawAmps[idxPeak-winSize : idxPeak+winSize]
freqs := rawFreqs[idxPeak-winSize : idxPeak+winSize]
// Next, we refine the window be centering it on the actual peak.
idxPeak += (floats.MaxIdx(amps) - winSize)
amps = rawAmps[idxPeak-winSize : idxPeak+winSize]
freqs = rawFreqs[idxPeak-winSize : idxPeak+winSize]
idxPeak = winSize
// Next we compute statistical properties to determine if this peak is worth
// using.
mean, std := stat.MeanStdDev(amps, nil)
ampPeak := amps[idxPeak]
log.Printf("%0.2f: %0.4f", harmonic, (ampPeak-mean)/std)
// TODO: Actual interpolation.
return &HarmonicWindow{
Harmonic: harmonic,
Amps: amps,
Freqs: freqs,
IdxPeak: idxPeak,
IdxPeakInterp: float64(idxPeak),
FreqPeakInterp: freqs[idxPeak],
AmpPeak: ampPeak,
AmpMean: mean,
AmpStd: std,
}
}