예제 #1
0
파일: spectral.go 프로젝트: mkb218/mkfseq
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
}
예제 #2
0
파일: formant.go 프로젝트: mkb218/mkfseq
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))
	}
}