/// <summary> /// 矩形波をFFTにより周波数分析を行う /// <para>実行後、ファイルが作成されますのでソースコードと合わせて確認してみてください。</para> /// </summary> public static void FftSquare() { double freq = 50.0; double samplingFreq = freq * 100.0; var dft = new DFT(FFTpoint.size4096, Window.WindowKind.NoWindow); var result = dft.FFT(SignalTest.GetSquare(freq, 0.5, samplingFreq, 1.0, dft.FFTsize), samplingFreq); result.Save("FftSquare.csv"); return; }
// ---- メソッド --------------------------------------- /// <summary> /// 特徴ベクトルを返す /// </summary> /// <returns>特徴ベクトル</returns> public override PatternRecognition.Feature GetFeature() { if (this.Ready) { // 最大のパワーとなった帯域を探すとその最大値を求める double maxPSDofBand = this._sumOfPSDbyBand.Max(); // 最大値を取得 int indexOfMax = -1; // -1としておくことで、↓2行のアルゴリズムにより最大となる帯域のインデックス-1を得る for (int i = 0; i < this._sumOfPSDbyBand.Length && this._sumOfPSDbyBand[i] != maxPSDofBand; i++) indexOfMax = i;// 最大となった帯域のインデックス-1を取得する indexOfMax++; // 等しいと代入の前にループを抜けるので、抜けた後で加算してインデックスとする // SN比を求める。求まればよいが。 double noiseLevelPSD = this._timeSeriesPSD[0][indexOfMax]; // フレームの初めはノイズレベルに近いはず double maxPSDofFlame = double.MinValue; for (int i = 0; i < this._timeSeriesPSD.Count; i++) if (maxPSDofFlame < this._timeSeriesPSD[i][indexOfMax]) maxPSDofFlame = this._timeSeriesPSD[i][indexOfMax]; this._SNratio = 10.0 * Math.Log10(maxPSDofFlame / noiseLevelPSD); // 帯域パワーの最大値が1になるように正規化 var fea1 = new PatternRecognition.Feature(this._sumOfPSDbyBand); fea1.Normalizing(); // 変調スペクトルをもとめる double[] modulatedSongAtUniBand = new double[this._timeSeriesPSD.Count]; for (int i = 0; i < modulatedSongAtUniBand.Length; i++) modulatedSongAtUniBand[i] = this._timeSeriesPSD[i][indexOfMax];// 最大であった帯域のパワーを取得する(変調されたパワー) DFT fft = new DFT(modulatedSongAtUniBand.Length, Window.WindowKind.Hanning); // FFTを実施する準備 FFTresult modulationSpectrum = fft.FFT(modulatedSongAtUniBand, this._condition.FrequencyOfFFT); double[] spectrum = new double[this._condition.MaxModulationSpectrumFrequency * 10]; //for (int i = 0; i < spectrum.Length; i++) Parallel.For(0, spectrum.Length, i => { double minFrequency = (double)i * 0.1; double maxFrequency = minFrequency + 0.1; spectrum[i] = modulationSpectrum.GetPSD(minFrequency, maxFrequency); // 帯域毎にコピー }); // コピーした変調スペクトルを正規化 var fea2 = new PatternRecognition.Feature(spectrum); fea2.Normalizing(); // 特徴ベクトルとしてまとめる var ans = new PatternRecognition.Feature(fea1.ToArray()); ans.Add(fea2.ToArray()); ans.Normalizing(); return ans; } else return null; }
/// <summary> /// サイン関数をFFTにより周波数分析を行う /// <para>実行後、2つのファイルが作成されますのでソースコードと合わせて確認してみてください。</para> /// </summary> public static void FftSin() { double freq, samplingFreq; var dft = new DFT(FFTpoint.size4096, Window.WindowKind.NoWindow); // part 1 // デフォルトではFFT窓の幅よりも小さなデータになるようにした場合 freq = 60.5; samplingFreq = freq * 4.0; var result = dft.FFT(SignalTest.GetSin(freq, 0.0, samplingFreq, 1.0, dft.FFTsize / 2), samplingFreq); result.Save("FftSin part 1.csv"); // part 2 // 窓いっぱいに波形を埋めた場合 freq = 60.5; samplingFreq = freq * 4.0; result = dft.FFT(SignalTest.GetSin(freq, 0.0, samplingFreq, 1.0, dft.FFTsize), samplingFreq); result.Save("FftSin part 2.csv"); }
/// <summary> /// 音声ファイルを開き、生成された特徴ベクトルのリストを返す /// </summary> /// <param name="waveFilePath">WAVEファイルのフルパス</param> /// <param name="discriminator">識別器<para>識別させない場合は省略して下さい。</para></param> /// <param name="threshold">棄却レベル<para>識別のさせる場合、この値を下回ると識別結果をUnknownと判定します。</para></param> /// <returns> /// 生成された特徴ベクトルのリスト /// <para>識別器を指定している場合は、識別結果を添付します。</para> /// </returns> public List<Result> GenerateFeatureList(string waveFilePath, Discriminator discriminator = null, double threshold = 0.0) { var ans = new List<Result>(0); // 結果を格納する if (System.IO.File.Exists(waveFilePath)) { WaveReader wave_file = new WaveReader(); wave_file.Open(waveFilePath); // waveファイルを開く if (wave_file.IsOpen) { try { this.Lock = true; this.SetGenerator(wave_file); this._generator.Log = this.Log; DFT fft = new DFT(this.ReadAmount, Window.WindowKind.Hanning); // FFTを実施する準備 while (wave_file.IsOpen && wave_file.ReadLimit == false) // 読めるなら、全て読むまでループ { MusicData data = wave_file.Read(this.ReadAmount); // ファイルからread_size_sec秒間読み込み。 double[] sound; if (data.UsableCH == MusicData.UsableChannel.Left) // データの入っている方を格納する sound = data.GetData(MusicData.Channel.Left); // else sound = data.GetData(MusicData.Channel.Right); FFTresult result = fft.FFT(sound, (double)wave_file.SamplingRate); // FFTを実行. FFTサイズが音声データよりも小さい場合、始めの方しか処理されないので注意. this._generator.Add(result); if (this._generator.Ready) { //Console.WriteLine("検出したようです。"); // デバッグモードで動かしながら確認するためのコンソール出力 Result feature = this._generator.GetFeature(); // 特徴ベクトル生成 if (discriminator == null) ans.Add(feature); // 答えを格納 else { Discriminator.IDandLikelihood id = discriminator.Discriminate(feature.FeatureVector); string name = id.ID; if (id.Likelihood < threshold) name = "Unknown"; feature.DiscriminationResult = name; if (!(this.MatchOnlyAtDiscrimination == true && name != feature.FilterName)) ans.Add(feature); } } } } catch (SystemException e) { throw new Exception(e.Message); } } else throw new Exception("Waveファイルを開くことができませんでした。\nWaveReaderクラスエラーメッセージ:" + wave_file.ErrorMessage); wave_file.Close(); // waveファイルを閉じる } this.Lock = false; return ans; }