web-dev-qa-db-ja.com

Librosaピッチトラッキング-STFT

this アルゴリズムを使用して、- this オーディオファイルのピッチを検出しています。あなたが聞くことができるように、それはバックグラウンドで少しのノイズでギターで演奏されるE2ノートです。

STFTを使用してこのスペクトログラムを生成しました: spectrogram

そして、私は上記のようにリンクされたアルゴリズムを次のように使用しています:

y, sr = librosa.load(filename, sr=40000)
pitches, magnitudes = librosa.core.piptrack(y=y, sr=sr, fmin=75, fmax=1600)

np.set_printoptions(threshold=np.nan)
print pitches[np.nonzero(pitches)]

結果として、私のfminfmaxの間のほぼすべての可能な周波数を取得しています。時間フレームの基本周波数を検出するために、piptrackメソッドの出力をどのように処理する必要がありますか?

[〜#〜]更新[〜#〜]

しかし、それらの2D配列が何を表しているのかはまだわかりません。フレーム5で82Hzがどの程度強いかを調べたいとしましょう。これは、2Dマトリックス(スペクトログラムのプロットに使用された)を返すだけのSTFT関数を使用して実行できます。

しかし、piptrackは何か追加のことをしてくれるので便利かもしれません。 pitches[f, t] contains instantaneous frequency at bin f, time t。つまり、時間フレームtで最大周波数を見つけたい場合、次のことを行う必要があります。

  1. magnitudes[][t]配列、最大の大きさのビンを見つけます。
  2. ビンを変数fに割り当てます。
  3. 検索pitches[b][t]そのビンに属する周波数を見つけるには?
13
pavlos163

特定のフレームでピッチを選ぶ方法がわかりましたtは簡単です:

def detect_pitch(y, sr, t):
  index = magnitudes[:, t].argmax()
  pitch = pitches[index, t]

  return pitch

最初にmagnitudes配列を見て最も強い周波数のビンを取得し、次にpitches[index, t]でピッチを見つけます。

5
pavlos163

ピッチの検出はトリッキーなトピックであり、直感に反することがよくあります。この特定の関数のソースコードを文書化する方法について私はワイルドではありません。開発者が「調和」と「ピッチ」を混同しているようです。

単音(「ピッチ」)がギターまたはピアノで作られるとき、私たちが聞くのは、1つの周波数の振動だけではなく、高調波と呼ばれる、数学的に関連する異なる周波数で発生する複数の音の振動の複合。典型的なピッチ追跡技術には、FFTの結果を検索して、予想される高調波の周波数に対応する特定のビンの大きさを求めます。たとえば、ピアノの中央のCキーを押すと、複合周波数の個々の周波数は基本周波数として261.6 Hzから始まります。523Hzは2次高調波、785 Hzは3次高調波、1046 Hzは後の高調波は基本周波数の整数倍、261.6 Hzです(例:2 x 261.6 = 523、3 x 261.6 = 785、4 x 261.6 = 1046)。ただし、高調波が配置されている周波数は対数的に間隔がありますが、FFTは線形間隔を使用します。多くの場合、FFTの垂直間隔は、低い周波数では十分に解決されません。

そのため、ピッチ検出アプリケーション(PitchScope Player)を作成したとき、FFTではなく対数間隔のDFTを作成することを選択したので、音楽に関心のある正確な周波数に焦点を合わせることができます(カスタムDFTの添付図を参照)ギターソロの3秒から)。ピッチ検出の追求に真剣に取り組んでいる場合は、トピックをさらに読み、他のサンプルコード(私のリンクは下にあります)を確認し、周波数を測定する独自の関数を作成することを検討してください。

https://en.wikipedia.org/wiki/Transcription_(music)#Pitch_detection

https://github.com/CreativeDetectors/PitchScope_Player

enter image description here

6