func spectral_analyze(af *sndfile.File, Frames, FftBins int) (s *SpectralAnalysis) { SpectrumBands := FftBins/2 - 1 s = new(SpectralAnalysis) s.Frames = make([]SpecFrame, Frames) var maxPower float64 for f := 0; f < Frames; f++ { full := make([]float64, int32(FftBins)*af.Format.Channels) _, err := af.ReadFrames(full) if err != nil { panic(err) } samps := mixdown(full, int(af.Format.Channels)) c := fftw.Alloc1d(len(samps)) o := fftw.Alloc1d(len(samps)) for i := 0; i < FftBins; i++ { hann := (float64(1) - math.Cos(float64(i)/float64(FftBins))*math.Pi*2.0) hamming := hann*0.92 + 0.08 c[i] = complex(samps[i]*hamming, 0) defer func() { if x := recover(); x != nil { fmt.Fprintf(os.Stderr, "panicked at i = %d\n", i) } }() } p := fftw.PlanDft1d(c, o, fftw.Forward, 0) p.Execute() s.Frames[f] = make(SpecFrame, SpectrumBands) for i := 0; i < SpectrumBands; i++ { pow := math.Sqrt(math.Pow(real(c[i+1]), 2) + math.Pow(imag(c[i+1]), 2)) s.Frames[f][i] = pow if pow > maxPower { maxPower = pow } } } for f := 0; f < Frames; f++ { for i := 0; i < SpectrumBands; i++ { s.Frames[f][i] /= maxPower } } s.Freqs = make([]float64, SpectrumBands) for i, _ := range s.Freqs { s.Freqs[i] = float64(((float64(44100) * 0.5) / float64(SpectrumBands+1)) * float64(i+1)) } return }
func (f *Fseq) pdetect(af *sndfile.File, lower, upper float64, length, fftbins int) { windowWidth := SampleRate / lower t := math.Trunc(windowWidth) for index := 0; index < length; index++ { var width uint if int(math.Trunc((windowWidth-t)*10.0)) < 5 { width = uint(t) } else { width = uint(math.Ceil(windowWidth)) } full := make([]float64, int32(width*2)*af.Format.Channels) _, err := af.Seek(af.Format.Frames*int64(index)/int64(length), sndfile.Set) if err != nil { panic(err) } read, err := af.ReadFrames(full) if err != nil { panic(err) } if sumread := read; read != int64(width*2) { _, err = af.Seek(0, sndfile.Set) if err != nil { panic(err) } read, err = af.ReadFrames(full[(int32(sumread) * af.Format.Channels):]) if err != nil { panic(err) } if read+sumread != int64(width*2) { width = uint((read + sumread) / 2) } } samps := mixdown(full, int(af.Format.Channels)) bestComb := uint(0) bestPower := float64(-999999) combLow := width combHigh := uint(math.Ceil(SampleRate / upper)) for comb := combLow; comb >= combHigh; comb -= QuickCombInterval { var power float64 for w := uint(0); w < comb; w++ { power += samps[w] * samps[w+comb] } if power > bestPower { bestPower = power bestComb = comb } } f.Pitches = append(f.Pitches, SampleRate/float64(bestComb)) } }