ともさんのHP >プロブラミング >自作JavaLibrary >JAVAでフーリエ変換する方法
JAVAでフーリエ変換する方法
フーリエ変換をするCLASSを作ろうとインターネットを探したのですが、参考になるHPが意外に少なかったので、私の作ったCLASSをここに置いておきます。
これから作ろうとされる方は参考にされてください。
下のDftというclassは離散フーリエ変換を行うクラスです。
クラス、TextFileとBynaryFileはファイルを読み書きする自作クラスです。(掲載していません)
離散フーリエ変換を行うJavaClassソース
package tomolib.wave;
import tomolib.wave.*;
import tomolib.util.*;
/**
離散フーリエ変換(DFT) 実行Class<BR>
2004/1/4作成
*/
public class Dft {
/**
* メソッド:public void dft( int[] data ,int samp ) <BR>
* 引数:data:音声DATA<BR>
* 引数:samp:サンプリング周波数(回/秒)<BR>
* 引数:interbal:解析する間隔(1/samp*iterbal秒)<BR>
* 引数:stop :解析終了周波数<BR>
* 機能:音声DATAをdftする<BR>
* 返り値:周波数ごとの強度<BR>
*/
public double[][] dft( int[] datatmp ,int samp ,int interbal , int stop )
{
int[] data = null;
//data数が2のべき乗であるように多ければカットする。
int datanos=1;
while( datanos = datatmp.length ){ datanos = datanos * 2;}
if( datanos == datatmp.length )
{ data = datatmp; }
else
{
datanos = (int)( datanos / 2. );
data = new int[ datanos ];
for(int I=0;I datanos;I++) {data[I] = datatmp[I]; }
}
//解析結果data数の設定
int sampn = (int)((double)( stop )/((double)interbal));
double[][] kekka = new double[sampn][2];
double tmpx,tmpy;
for ( int I=0; I sampn ; I++) {
tmpx = 0;
tmpy = 0;
for ( int j=0 ; j data.length ; j++) {
tmpx = tmpx + data[j] * Math.cos( 2. * Math.PI * ( interbal * I) * j / (double)samp );
tmpy = tmpy - data[j] * Math.sin( 2. * Math.PI * ( interbal * I) * j / (double)samp );
}
kekka[I][1] = Math.sqrt( tmpx * tmpx + tmpy * tmpy ) * 2. / (double)samp ;
kekka[I][0] = (double)( interbal * I);
}
return kekka;
}
/**
* アプリケーション:main()<BR>
* 機能:このclassの動作確認用<BR>
*/
public static void main(String args[])
{
Wav wav = new Wav();
wav.readWav( test.wav );
Dft dft = new Dft();
double kekka[][] = dft.dft( wav.DATA , wav.SAMP , 10 , 2500 );
TextFile t = new TextFile();
t.OutOpen( test.csv );
for(int I=0;I kekka.length ;I++)
{
System.out.println( kekka[I][0]+ +kekka[I][1] );
t.Write( kekka[I][0] + , + kekka[I][1] );
}
t.OutClose();
}
}
wav形式のファイルの中身を読み込むJavaClassソース
↓はwav形式のファイルの中身を読み込むWav.java
package tomolib.wave;
import tomolib.util.*;
import tomolib.wave.*;
import java.util.*;
/**
.wav形式の音声ファイルの処理を行う<BR>
条件で名称変更する<BR>
2004/1/4作成
*/
public class Wav {
/**1秒間あたりのサンプリング数*/
public int SAMP;
/**1サンプルのバイト数*/
public int BYTE;
/**サンプルDATA数*/
public int DATA[]=null;
/**
* メソッド:public void readWav( String wavfile ) <BR>
* 引数:<BR>
* 機能:Wav形式のデータファイルを開いてこのClassに格納する<BR>
読み込むのはDATAと、サンプリング周期、DATAバイト数。
* 返り値:なし<BR>
*/
public void readWav( String wavfile )
{
BynaryFile b = new BynaryFile();
b.InOpen( wavfile );
b.readStringN( 24 );
SAMP = b.ReadInt( 1 );
SAMP = SAMP + 256 * b.ReadInt( 1 );
SAMP = SAMP + 256 * 256 * b.ReadInt( 1 );
SAMP = SAMP + 256 * 256 * 256 * b.ReadInt( 1 );
b.readStringN( 4 );
BYTE = b.ReadInt( 1 );
BYTE = BYTE + 256 * b.ReadInt( 1 );
b.readStringN( 16 );
b.readStringN( 4 ) ; //ここには data が入る
Vector vect = new Vector();
int tmpi=b.ReadInt( 1 );
int tmpii =0;
while( tmpii==0 )
{
vect.addElement( new Integer(tmpi) );
tmpi=b.ReadInt( 1 );
if( tmpi == -1 ){tmpii=1;}
}
b.InClose();
DATA = new int[vect.size()];
for( int I =0;I vect.size(); I++)
{
DATA[I] = ((Integer)vect.get( I )).intValue();
}
return;
}
/**
* メソッド:public void writeData() <BR>
* 引数:<BR>
* 機能:格納されたDATAをテキストファイルに出力(試験用)<BR>
* 返り値:なし<BR>
*/
public void writeData()
{
TextFile t = new TextFile();
t.OutOpen( wav-txt.txt );
t.Write( + SAMP );
for( int I =0;I DATA.length ; I++)
{
t.Write( + DATA[I] );
}
t.OutClose();
}
/**
* アプリケーション:main()<BR>
* 機能:このclassの動作確認用<BR>
*/
public static void main(String args[])
{
Wav wav = new Wav();
wav.readWav( test__.wav );
wav.writeData();
}
Javaフーリエ変換の実行結果
私の声をwavファイルに記録し、Wavクラスを用いてグラフにしたものが下のグラフ。60Hzと600Hzくらいの波が重なっているのがわかります。
このwavファイルをDft.classに通してフーリエ変換したのがしたのグラフ。正常に変換されているようです。
最終更新日: 2018-03-30 08:27:24
ともさんのHP >プロブラミング >自作JavaLibrary >JAVAでフーリエ変換する方法
ツイート