Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
9
Help us understand the problem. What is going on with this article?
@Talokay

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

More than 5 years have passed since last update.

[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の値が大きければ、より多様な周波数スペクトラムを含む音信号、逆に小さければ、より純音に近い音信号となります。

まとめ

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

9
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Talokay
株式会社adNote 代表取締役 作曲家、メディアアーティスト、プログラマ(信号処理) Twitter : @keterize

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
9
Help us understand the problem. What is going on with this article?