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
Raw Normal View History

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