Goでクロマベクトルを求める

Chromagram。ドレミの歌の冒頭を分析した結果です

package main

import (
	"fmt"
	"github.com/mjibson/go-dsp/wav"
	"github.com/r9y9/go-msptools/pcp"
	"log"
	"os"
)

func main() {
	// reading data
	file, err := os.Open("/path/to/file.wav")
	if err != nil {
		log.Fatal(err)
	}
	defer file.Close()

	wav, werr := wav.ReadWav(file)
	if werr != nil {
		log.Fatal(werr)
	}

	// convert to []float64 from []int
	data := make([]float64, len(wav.Data[0]))
	for i := range data {
		data[i] = float64(wav.Data[0][i])
	}

	// settings for analysis
	frameShift := int(float64(wav.SampleRate) / 100.0) // 0.01 sec
	sampleRate := int(wav.SampleRate)

	// create PCP extrator
	p := pcp.NewPCP(sampleRate, frameShift)

	// analysis roop
	result := make([][]float64, p.NumFrames(data))
	for i := 0; i < p.NumFrames(data); i++ {
		pcp := p.PCP(data, i*frameShift)
		//pcp := p.PCPNormalized(data, i*frameShift)
		result[i] = pcp
	}

	// print as a gnuplot 3D plotting format
	fmt.Println("#", len(result[0]), len(result))
	for i, spec := range result {
		for j, val := range spec {
			fmt.Println(i, j, val)
		}
		fmt.Println("")
	}
}

こんな感じでOK。Chromagramをgnuplot形式で標準出力に出力します

Pitch Class Profile (PCP) in Go [Code]

どうやってクロマベクトルを計算しているかざっくり説明すると、

  • 入力信号をガボールウェーブレット変換
  • オクターブ無視して12次元に圧縮(例えば55Hz, 110Hz, 220Hz, 440Hz はすべてAとする)

という手順で求めてます

Goかどうかなんてどうでもいいんだけど、まぁC++に比べて書きやすすぎて泣けるよね