/// <summary>
        /// 発声を検出された帯域情報を返す
        /// </summary>
        /// <exception cref="SystemException">演算条件がセットされていない場合にスロー</exception>
        /// <returns>帯域情報</returns>
        public Band[] GetDetectedBands()
        {
            if (this.IsSetuped == false)
            {
                throw new SystemException("演算条件がセットされていません。Setup()を行ってください。");
            }
            int i = 0;

            for (int k = 0; k < this.sensor.Length; k++)
            {
                if (this.sensor[k].FrontDetection == true)
                {
                    i++;                                                                                    // 信号が検出された帯域数をカウント
                }
            }
            Signal.FrequencyAnalysis.Band[] bands = new Signal.FrequencyAnalysis.Band[i];                   // 信号が検出された数だけ帯域を示すクラスを生成
            i = 0;
            for (int k = 0; k < this.sensor.Length; k++)
            {
                if (this.sensor[k].FrontDetection == true)
                {
                    bands[i] = this.band[k];
                    i++;
                }
            }
            return(bands);
        }
 /// <summary>
 /// 本クラスが内部に保持している帯域のリストを返す
 /// </summary>
 /// <exception cref="SystemException">演算条件がセットされていない場合にスロー</exception>
 /// <returns>帯域のリスト</returns>
 public Band[] GetBands()
 {
     if (this.IsSetuped == false)
     {
         throw new SystemException("演算条件がセットされていません。Setup()を行ってください。");
     }
     Signal.FrequencyAnalysis.Band[] bands = new Signal.FrequencyAnalysis.Band[this.band.Length];
     for (int i = 0; i < this.band.Length; i++)                              // クローンを作って返す(Bandを構造体で設計しているのでこれでもよい)
     {
         bands[i] = this.band[i];
     }
     return(bands);
 }
 /// <summary>
 /// 強制的に、指定帯域で発声があることを認識させる
 /// 2011/11/18 呼び出し先が未実装・・・
 /// </summary>
 /// <param name="band">指定帯域</param>
 /// <exception cref="SystemException">演算条件がセットされていない場合にスロー</exception>
 public void RecognizeSignal(Signal.FrequencyAnalysis.Band band)
 {
     if (this.IsSetuped == false)
     {
         throw new SystemException("演算条件がセットされていません。Setup()を行ってください。");
     }
     for (int i = 0; i < this.band.Length; i++)                                                      // 本クラス内に用意されている検査器を全てチェック
     {
         if (this.band[i].CenterFrequency > band.Min && this.band[i].CenterFrequency > band.Max)
         {
             this.sensor[i].RecognizeSignal();                                                       // 検査器に発声を認識させる
         }
     }
     return;
 }
        /// <summary>
        /// 任意の帯域において発声が検出されているかどうかを返す
        /// 検査対象外の帯域だったり、検出されていなければfalseが返ります。
        /// </summary>
        /// <param name="band">指定帯域</param>
        /// <exception cref="SystemException">演算条件がセットされていない場合にスロー</exception>
        /// <returns>検出されていればtrue</returns>
        public Boolean CheckDetection(Signal.FrequencyAnalysis.Band band)
        {
            if (this.IsSetuped == false)
            {
                throw new SystemException("演算条件がセットされていません。Setup()を行ってください。");
            }
            Boolean ans = false;

            for (int i = 0; i < this.band.Length; i++)                                                      // 本クラス内に用意されている検査器を全てチェック
            {
                if (this.band[i].CenterFrequency > band.Min && this.band[i].CenterFrequency > band.Max && this.sensor[i].FrontDetection == true)
                {
                    ans = true;
                    break;
                }
            }
            return(ans);
        }
        /// <summary>
        /// 演算条件の設定を行う
        /// <para>引数のbandInfoを用いて、フィルタの帯域情報を読み込みます。</para>
        /// <para>テキストフォーマットは、カンマ区切りで下記のように定めます。</para>
        /// <para>"ID,maxFrequency,minFrequency,minTimeWidth" 例:"キビタキ,4500,2500,0.3"</para>
        /// </summary>
        /// <param name="condition">特徴ベクトル生成コアユニットに渡すパラメータ</param>
        /// <param name="waveSamplingFrequency">WAVEファイルのサンプリング周波数[Hz]</param>
        /// <param name="frequencyOfFft">FFTの実施周波数[Hz]<para>0.1秒毎のWAVEファイルを処理するのであれば、1/0.1=10 Hz</para></param>
        /// <param name="bandInfo">帯域情報</param>
        public virtual void Setup(Object condition, double waveSamplingFrequency, double frequencyOfFft, string bandInfo)
        {
            MinimumCondition mCondition;
            if (condition is MinimumCondition)
                mCondition = (MinimumCondition)condition;
            else
                throw new Exception("型の一致しない演算条件のセットを検出しました。conditionの型を再確認してください。");
            if (bandInfo == "default")
            {
                double minTimeWidth = 1.0 / frequencyOfFft * 3.0;      // 最小の有効検出時間を設定する。最小分解能の3倍とする。
                bandInfo = "NA," + waveSamplingFrequency.ToString("00") + ",0," + minTimeWidth.ToString();
            }
            if (this.CheckSettingStringMatch(bandInfo) == false)
                throw new Exception("帯域情報文字列のフォーマット不一致を検出しました。bandInfoのフォーマットを再確認してください。");
            this._time = 0.0;
            this._frequencyOfFFT = frequencyOfFft;
            this._generatedFeatures = new List<Result>(0);
            // 文字列を解析してパラメータをセットする
            try
            {
                string[] field = bandInfo.Split(',');
                this.FileterName = field[0];                                        // 帯域名例えば、"キビタキ"
                long maxFrequency = long.Parse(field[1]);                           // 文字を数値に直す
                long minFrequency = long.Parse(field[2]);                           //
                this._minTimeWidth = double.Parse(field[3]);                        // 鳥の鳴き声が続く最小の時間幅を取得
                this._band = new Band(maxFrequency + 1000.0, minFrequency - 1000.0);// リストに帯域情報を書き込む

                this._sensor = new SongDetector();
                this._sensor.Setup(1, new Band(maxFrequency, minFrequency), new TimeSpan(0, 0, 0, (int)this._minTimeWidth, (int)((this._minTimeWidth % 1.0) * 1000.0)), this._frequencyOfFFT);

                Condition _condition = new Condition(mCondition, this._frequencyOfFFT, this._minTimeWidth);
                this._genetator = this.GetCoreGenerator();
                this._genetator.Setup(_condition);
                this.IsSetuped = true;
            }
            catch (SystemException e)
            {
                string message = "GeneratorUnit構造体のSetupメソッドにおいて、帯域情報ファイルの文字列解析に失敗しました。";
                Console.WriteLine(message);
                Console.WriteLine(e.Message);
                throw new SystemException(message);
            }
            return;
        }
 /// <summary>
 /// 演算条件をセットします
 /// </summary>
 /// <param name="numberOfPartitions">
 /// 用意する帯域数(分割数)
 /// <para>1以上を指定してください。</para>
 /// <para>分割数が多ければより狭い帯域の変化を監視することができます。(が、処理時間もかかります。)</para>
 /// </param>
 /// <param name="band">検査対象とする周波数帯域</param>
 /// <param name="timespan">
 /// 検査に利用する最小の時間幅
 /// <para>時間幅が大きいと追随性が悪くなりますが、短すぎると連続して長時間囀る鳥のノイズフロアをうまく捉えることが難しいこともあります。</para>
 /// <para>標準偏差を計算する関係上、最小 26 / samplingFreaquency [s]に置換されます。</para>
 /// <para>3秒を推奨します。</para>
 /// </param>
 /// <param name="samplingFreaquency">サンプリング周期<para>FFTを実施している周期を格納してください。</para></param>
 public void Setup(int numberOfPartitions, Band band, TimeSpan timespan, double samplingFreaquency)
 {
     if (numberOfPartitions <= 0) throw new Exception("SongDetectorクラスのSetupメソッドにおいてエラーがスローされました。帯域数は1以上をセットして下さい。");
     this._numOfStock = (int)(timespan.TotalSeconds * samplingFreaquency);               // 用意すべきストック数を計算
     if (this._numOfStock < 26) this._numOfStock = 26;
     if (numberOfPartitions > 0 && band.Max > 0 && band.Min >= 0 && band.Max > band.Min)
     {
         this._numberOfPartitions = numberOfPartitions;
         this.sensor = new SubDetector[numberOfPartitions];                              // 配列の大きさを定義
         this.band = new Signal.FrequencyAnalysis.Band[numberOfPartitions];              // 帯域の数を調整
         double delta_freq = (band.Max - band.Min) / (double)numberOfPartitions;         // 一つの帯域あたりの周波数幅を計算
         double lower_freq = band.Min;                                                   // 帯域の下限周波数
         // 指定された帯域数だけ、検出器を構成する
         for (int i = 0; i < this.sensor.Length; i++)
         {
             this.sensor[i] = new SubDetector(this._numOfStock, samplingFreaquency, new TimeSpan(0, 0, 10)); // インスタンス生成
             double upper_freq = delta_freq * (i + 1) + lower_freq;                      // 帯域の上限を計算
             this.band[i] = new Band(upper_freq, lower_freq);
             lower_freq = upper_freq;                                                    // 下限周波数を更新
         }
     }
     else
     {
         Console.WriteLine("SongDetectorクラスのSetup()にてエラーがスローされました。\n引数に不正が確認されています。");
         throw new System.FormatException("引数に不正が確認されました。");               // 引数に不正があれば例外をスロー
     }
     this.IsSetuped = true;
     return;
 }
 /// <summary>
 /// 発声を検出された帯域情報を返す
 /// </summary>
 /// <exception cref="SystemException">演算条件がセットされていない場合にスロー</exception>
 /// <returns>帯域情報</returns>
 public Band[] GetDetectedBands()
 {
     if (this.IsSetuped == false) throw new SystemException("演算条件がセットされていません。Setup()を行ってください。");
     int i = 0;
     for (int k = 0; k < this.sensor.Length; k++) if (this.sensor[k].FrontDetection == true) i++;    // 信号が検出された帯域数をカウント
     Signal.FrequencyAnalysis.Band[] bands = new Signal.FrequencyAnalysis.Band[i];                   // 信号が検出された数だけ帯域を示すクラスを生成
     i = 0;
     for (int k = 0; k < this.sensor.Length; k++)
     {
         if (this.sensor[k].FrontDetection == true)
         {
             bands[i] = this.band[k];
             i++;
         }
     }
     return bands;
 }
 /// <summary>
 /// 本クラスが内部に保持している帯域のリストを返す
 /// </summary>
 /// <exception cref="SystemException">演算条件がセットされていない場合にスロー</exception>
 /// <returns>帯域のリスト</returns>
 public Band[] GetBands()
 {
     if (this.IsSetuped == false) throw new SystemException("演算条件がセットされていません。Setup()を行ってください。");
     Signal.FrequencyAnalysis.Band[] bands = new Signal.FrequencyAnalysis.Band[this.band.Length];
     for (int i = 0; i < this.band.Length; i++ )                             // クローンを作って返す(Bandを構造体で設計しているのでこれでもよい)
         bands[i] = this.band[i];
     return bands;
 }