10
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

[vDSP][信号処理]オーディオ・音声分析への道8 FFT 音の明度

Posted at

#[vDSP][信号処理]オーディオ・音声分析への道7 FFT 音の明度

##概要

今回は、FFTで得られたスペクトラル情報を分析し、音の明度を計る尺度の一つ、スペクトラル中心(Centroid)について書きます。
FFTのプログラムについては触れません。過去のこの記事や、この記事を参考にしてください。

スペクトラル中心とは、スペクトラムの重心の位置(単位はHz)を計算しる事で得る事ができます。例えば、440hzの純音のCentroidは理論上440HzのCentroidを持つ事になります。また、純音に高周波数を足し合わせていくと、その程度に沿ってCentroidの値は大きくなっていきます。

##数式

Centroidの算出方法は、以下の様に定義されます。

Centroid_t = \frac{\sum_{n=0}^{N-1} (F_n \cdot M_n)}{ \sum_{k=0}^{N-1} M_n}

FFTフレームtに於ける、周波数Fと音の強度Mの積の総和を、音の強度Mの総和で割った値になります。NはFFTサイズになります。

##総和 : vDSP_sve

vDSPには総和を行う関数が用意されています。

void vDSP_sve (
   float *__vDSP_A,
   vDSP_Stride __vDSP_I,
   float *__vDSP_C,
   vDSP_Length __vDSP_N
);

##Centroid
wikipedia

音の強度、Magnitudeの算出は以下の通りです。

 MagnitudeSum = sqrt(real * real + img * img);

vDSPの関数を使うと

vDSP_zvabs(&splitComplex,1,magnitude,1,ffthalfsize);

FFTの各binに対応する周波数の算出方法は、

float freq_bin = SamplingRate/fftsize;

よってCentroid式の分子部分は、

float cen = 0;
for(i=0;i<ffthalfsize;i++){
    cen = freq_bin * i * magnitude[i];
}

となり、centroidは

centroid = cen/MagnitudeSum;

となります。単位はHzです。
音の明るさを示す尺度となるCentroidですが、Centroidの数値単体では信頼性にかける場合があります。

例えば、以下のようなスペクトラルを例に出します。

spread2.jpg
上の図はスペクトラルの中心に強い強度を持つ信号を示しています。
この場合得られるCentroidは、スペクトラルの中心地点、サンプリングレートが44.1Hzならば、10kHzくらいになります。

ところが次のスペクトラルを見てみてください。

spread1.jpg
今度は、最低音と最高音に大きな強度を持つ信号で、スペクトラルの中心を境に線対称になっています。
このCentroidはどのような値になるでしょうか。Centroidはスペクトラルの重心を計算する事になりますので、初めの図と同じく、10kHz付近の値が得られます。これでは、全く異なる性質を持つ音信号でも、同じCentroidの値を持ってしまいます。

以上を解決する為にCentroidは、それ単体で音の性質を評価するよりも、以下のSpectral spreadという尺度と一緒に扱うと、より高い信頼性を得る事ができます。

##Spectral Spread

Spectral Spreadは、スペクトラル上に於いて、各ビンの強度がどの様に分布しているかを表します。分布度は以下の数式で定義されます。

Spread = \frac{\sum_{n=0}^{N-1} (|F_n - C \cdot M_n)}{ \sum_{k=0}^{N-1} M_n}

この時、CはCentroidを表します。

1FFTframeに於けるSpectral Spreadの計算方法は、

spread
for(i=0;i<ffthalfsize;i++){
    accum_spread += magnitude[i] * fabs(i*freq_bin - Centroid);
    accum_mag += magnitude[i];

}

とし、最後に

spread2
    spread = accum_spread / accum_mag;

で得られます。
Spreadの値が大きければ、より多様な周波数スペクトラムを含む音信号、逆に小さければ、より純音に近い音信号となります。

##まとめ
今回は、信号のスペクトラル情報を分析し、その信号の性質を測る事を目的としました。一つの尺度のみを利用するだけでは、正確な音の性質はなかなか得る事はできません。複数の尺度を上手く組み合わせる事で、より正確な尺度が得られると思います。いずれにせよ、使用する音信号の性質をあらかじめ把握し、それに適した分析法を取捨選択するのが最良の道かもしれません。

10
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?