質問

Pythonでグラフィカルなスペクトルアナライザーを作成しようとしています。

現在、1024ビットの16ビットデュアルチャネル44,100 Hzのサンプルレートオーディオストリームの1024バイトを読み取り、2つのチャネルの振幅を平均しています。だから今、私は256の署名付きショートパンツの配列を持っています。 numpyなどのモジュールを使用して、その配列でfftを実行し、その結果を使用してグラフィカルなスペクトルアナライザーを作成します。

高速フーリエ変換と離散フーリエ変換に関するウィキペディアの記事を読みましたが、結果の配列が何を表しているのかまだわかりません。これは、numpyを使用して配列にfftを実行した後の配列です。

   [ -3.37260500e+05 +0.00000000e+00j   7.11787022e+05 +1.70667403e+04j
   4.10040193e+05 +3.28653370e+05j   9.90933073e+04 +1.60555003e+05j
   2.28787050e+05 +3.24141951e+05j   2.09781047e+04 +2.31063376e+05j
  -2.15941453e+05 +1.63773851e+05j  -7.07833051e+04 +1.52467334e+05j
  -1.37440802e+05 +6.28107674e+04j  -7.07536614e+03 +5.55634993e+03j
  -4.31009964e+04 -1.74891657e+05j   1.39384348e+05 +1.95956947e+04j
   1.73613033e+05 +1.16883207e+05j   1.15610357e+05 -2.62619884e+04j
  -2.05469722e+05 +1.71343186e+05j  -1.56779748e+04 +1.51258101e+05j
  -2.08639913e+05 +6.07372799e+04j  -2.90623668e+05 -2.79550838e+05j
  -1.68112214e+05 +4.47877871e+04j  -1.21289916e+03 +1.18397979e+05j
  -1.55779104e+05 +5.06852464e+04j   1.95309737e+05 +1.93876325e+04j
  -2.80400414e+05 +6.90079265e+04j   1.25892113e+04 -1.39293422e+05j
   3.10709174e+04 -1.35248953e+05j   1.31003438e+05 +1.90799303e+05j...

これらの数値が正確に何を表しているのか、これらの数値を32のバーそれぞれの高さのパーセンテージに変換する方法を知りたいのですが。また、2つのチャネルを一緒に平均化する必要がありますか?

役に立ちましたか?

解決

表示している配列は、オーディオ信号のフーリエ変換係数です。これらの係数は、オーディオの周波数コンテンツを取得するために使用できます。 FFTは複素数値の入力関数に対して定義されているため、入力がすべて実数値であっても、得られる係数は虚数になります。各周波数の電力量を取得するには、各周波数のFFT係数の大きさを計算する必要があります。これは、係数の実成分だけではなく[ ]、実成分と虚成分の二乗和の平方根を計算する必要があります。つまり、係数がa + b * jの場合、その大きさはsqrt(a ^ 2 + b ^ 2)です。

各FFT係数の大きさを計算したら、各FFT係数が属するオーディオ周波数を把握する必要があります。 NポイントFFTは、0から始まる等間隔のN個の周波数での信号の周波数成分を提供します。サンプリング周波数は44100サンプル/秒であるためです。 FFTのポイント数が256の場合、周波数間隔は44100/256 = 172 Hz(概算)です

配列の最初の係数は0周波数係数になります。これは基本的にすべての周波数の平均電力レベルです。残りの係数は、128に達するまで0から172 Hzの倍数でカウントアップされます。FFTでは、サンプルポイントの半分までの周波数しか測定できません。 ナイキスト周波数およびナイキスト-シャノンサンプリング定理罰のための大食いとその理由を知る必要がありますが、基本的な結果は、あなたのより低い周波数が複製されるか、高頻度バケットでのエイリアス。したがって、周波数は0から始まり、N / 2係数まで各係数で172 Hz増加し、次にN-1係数まで172 Hz減少します。

これは、開始するのに十分な情報である必要があります。ウィキペディアで提供されているよりもはるかに親しみやすいFFTの紹介が必要な場合は、デジタル信号処理について:第2版。とても助かりました。

それが、これらの数字が表すものです。高さのパーセンテージへの変換は、各周波数成分の大きさをすべての成分の大きさの合計でスケーリングすることにより実行できます。ただし、それは相対的な頻度分布の表現を提供するだけで、各周波数の実際のパワーは提供しません。周波数成分に対して可能な最大の大きさでスケーリングを試みることができますが、それが非常にうまく表示されるかどうかはわかりません。実用的なスケーリング係数を見つける最も簡単な方法は、大きな音と柔らかい音の信号を実験して適切な設定を見つけることです。

最後に、オーディオ信号全体の周波数成分を全体として表示する場合は、2つのチャネルを平均化する必要があります。ステレオオーディオをモノラルオーディオにミキシングし、結合された周波数を表示しています。左右の周波数を別々に表示したい場合は、各チャンネルでフーリエ変換を個別に実行する必要があります。

他のヒント

このスレッドは数年前のものですが、非常に役立ちました。これを見つけて、似たようなものを作成しようとしている人に入力したかっただけです。

バーへの分割に関しては、バーの数に基づいてデータを均等に分割することにより、これをanttiが示唆するように行うべきではありません。最も有用なのは、データをオクターブ部分に分割することです。各オクターブは前の周波数の2倍です。 (つまり、100hzは50hzより1オクターブ上、25hzより1オクターブ上です)。

必要なバーの数に応じて、範囲全体を1 / Xオクターブ範囲に分割します。 バーの指定された中心周波数Aに基づいて、バーの上限と下限を次から取得します。

upper limit = A * 2 ^ ( 1 / 2X )
lower limit = A / 2 ^ ( 1 / 2X )

次の隣接する中心周波数を計算するには、同様の計算を使用します:

next lower =  A / 2 ^ ( 1 / X )
next higher = A * 2 ^ ( 1 / X )

次に、これらの範囲に収まるデータを平均して、各バーの振幅を取得します。

例: 1/3オクターブの範囲に分割し、中心周波数1khzから始めます。

Upper limit = 1000 * 2 ^ ( 1 / ( 2 * 3 ) ) = 1122.5
Lower limit = 1000 / 2 ^ ( 1 / ( 2 * 3 ) ) =  890.9

44100hzおよび1024サンプル(各データポイント間で43hz)を指定すると、21から26までの値を平均化する必要があります(890.9 / 43 = 20.72〜21および1122.5 / 43 = 26.10〜26)

(1/3オクターブ小節では、〜40hz〜〜20khzの間に約30小節が得られます)。 ここまででわかるように、上に行くほど、より広い範囲の数値が平均化されます。通常、低いバーには1つまたは少数のデータポイントのみが含まれます。一方、高いバーは数百ポイントの平均になります。理由は、86hzは43hzより1オクターブ高いためです... 10086hzは10043hzとほぼ同じように聞こえます。

あなたが持っているのは、時間の長さが256/44100 = 0.00580499秒のサンプルです。これは、周波数分解能が1 / 0.00580499 = 172 Hzであることを意味します。 Pythonから取得する256個の値は、基本的に86 Hz〜255 * 172 + 86 Hz = 43946 Hzの周波数に対応しています。取得する数値は複素数です(したがって、1秒おきの数字の最後に「j」が付きます)。

編集:間違った情報の修正

sqrt(i 2 + j 2 )を計算して複素数を振幅に変換する必要があります。ここで、iとjは実数部と虚数部です。

32小節にしたい場合、理解している限り、連続する4つの振幅の平均を取ると、256/4 = 32小節になります。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top