FIRディジタルフィルタの作成」でPython言語によるFIRディジタルフィルタの作成を作成しました。今回は、C#言語を使って、FIRディジタルフィルタを作成します。入力・出力ともwavファイルとします。

開発/実行環境

  • Visual Studio2013 Express (C#)
  • Windows 7 Professional

FIRディジタルフィルタソフトの作成

C#言語を使ってFIRディジタルフィルタスクリプトを作成します。「wavファイルの作成とwavファイル情報の表示」で作成したwavファイルを入力します。ただし、記録時間は30秒から3秒にしました。

  • 32行目のSystem.IO.StreamReaderメソッドでフィルタ係数ファイル「constant」を読み込み、38行目でフィルタ係数を保存します。
  • 48行目でFile.ReadAllBytesメソッドを使ってwavファイルをバイナリで読み込みます。
  • 49行目のfor文で、「0x2c」バイト分オフセットをかけて、wavファイルのヘッダ部分をスキップします。wavファイルのヘッダ部分の構成については「C#によるWaveファイルの解析」を参照してください。
  • FIRディジタルフィルタの処理にはQueue クラスを使用します。タップ数分キューに挿入しておき、64行目でそれぞれの入力データに対してフィルタ係数を乗算していきます。
  • 67行目は、キューに挿入されているデータがタップ数に満たない場合の判断を行っています。
  • 58行目の「32768.0」や73行目の「10000.0」は正規化もどきの為に使用しています。処理結果を見ながら増減させてください。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.IO;


namespace FirFilter
{
    class Program
    {
        static void Main(string[] args)
        {
            string line;
            string coeffFile = "constant";
            string wavFile = "100-500-1000-8000hz.wav";
            string wavFileOut = "100-500-1000-8000hzOut.wav";

            const int taps = 10;
            double[] coefficients = new double[taps];
            Queue<double> buffer = new Queue<double>();

            int i = 0;
            double output = 0;
            double input = 0;
            byte[] data;
            byte[] sounddata = new byte[4];
            int posoffset = 0x2c;

            StreamReader file = new System.IO.StreamReader(coeffFile);

            for (i = 0; i < taps; i++)
            {
                if ((line = file.ReadLine()) != null)
                {
                    coefficients[i] = double.Parse(line);
                }
                else
                {
                    Console.WriteLine("Could not read the coefficients from {0}", coeffFile);
                }
            }

            file.Close();

            data = File.ReadAllBytes(wavFile);
            for (i = posoffset; i < data.Length; i += 2)
            {

                if (buffer.Count == taps)
                {
                    buffer.Dequeue();
                }
                input = (short)((data[i + 1] << 8) + data[i + 0]);

                buffer.Enqueue(input/32768.0);
                int k = buffer.Count - 1;
                //            i = 0;
                output = 0;
                foreach (double value in buffer)
                {
                    output += coefficients[k] * value;
//                    Console.WriteLine("coefficients:{0} value:{1} ", coefficients[k], value);
                    k--;
                    if (k < 0)
                    {
                        break;
                    }
                }
//                Console.WriteLine("****pixcel: {0} {1} /{2} ",i, input, output);
                output *= 10000.0;
                sounddata = BitConverter.GetBytes((int)output);

                data[i + 0] = sounddata[0];
                data[i + 1] = sounddata[1];

            }

            File.WriteAllBytes(wavFileOut, data);

        }
    }
}

System.IO.StreamReaderメソッドで読み込まれるファイル「constant」の内容を次に示します。この係数により高周波成分が減衰し、波形も滑らかになります。

 0.1
 0.1
 0.1
 0.1
 0.1
 0.1
 0.1
 0.1
 0.1
 0.1

FIRディジタルフィルタソフトの実行

入力したwavファイル「100-500-1000-8000hz.wav」を次に示します。


FIRディジタルフィルタ後のwavファイル「100-500-1000-8000hzOut.wav」を次に示します。高周波成分が減衰したため高い音が小さくなり、低音が拡大されています。


audacityアプリを用いて、今回のC#言語によるFIRディジタルフィルタ後の波形「100-500-1000-8000hzOut.wav」(上側)と前回のPython言語によるFIRディジタルフィルタ後の波形「fir.wav」(下側)を比較します。

audacityアプリでFIRディジタルフィルタ後の波形をFFT処理すると、100、500、1000、8000hzのそれぞれが変わっていないことが確認できました。