簡単なデジタルフィルタのサンプルコード
簡単なデジタルフィルタの実装で説明したフィルタのサンプルコードです。
ご利用の際はコピペしてお使いください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 |
#pragma once; #include <math.h> // -------------------------------------------------------------------------------- // CMyFilter // -------------------------------------------------------------------------------- class CMyFilter { private: // フィルタの係数 float a0, a1, a2, b0, b1, b2; // バッファ float out1, out2; float in1, in2; public: inline CMyFilter(); // 入力信号にフィルタを適用する関数 inline float Process(float in); // フィルタ係数を計算するメンバー関数 inline void LowPass (float freq, float q , float samplerate = 44100.0f); inline void HighPass (float freq, float q , float samplerate = 44100.0f); inline void BandPass (float freq, float bw, float samplerate = 44100.0f); inline void Notch (float freq, float bw, float samplerate = 44100.0f); inline void LowShelf (float freq, float q , float gain, float samplerate = 44100.0f); inline void HighShelf(float freq, float q , float gain, float samplerate = 44100.0f); inline void Peaking (float freq, float bw, float gain, float samplerate = 44100.0f); inline void AllPass (float freq, float q , float samplerate = 44100.0f); }; // -------------------------------------------------------------------------------- // コンストラクタ // -------------------------------------------------------------------------------- CMyFilter::CMyFilter() { // メンバー変数を初期化 a0 = 1.0f; // 0以外にしておかないと除算でエラーになる a1 = 0.0f; a2 = 0.0f; b0 = 1.0f; b1 = 0.0f; b2 = 0.0f; in1 = 0.0f; in2 = 0.0f; out1 = 0.0f; out2 = 0.0f; } // -------------------------------------------------------------------------------- // 入力信号にフィルタを適用する関数 // -------------------------------------------------------------------------------- float CMyFilter::Process(float in) { // 入力信号にフィルタを適用し、出力信号変数に保存。 float out = b0 / a0 * in + b1 / a0 * in1 + b2 / a0 * in2 - a1 / a0 * out1 - a2 / a0 * out2; in2 = in1; // 2つ前の入力信号を更新 in1 = in; // 1つ前の入力信号を更新 out2 = out1; // 2つ前の出力信号を更新 out1 = out; // 1つ前の出力信号を更新 // 出力信号を返す return out; } // -------------------------------------------------------------------------------- // フィルタ係数を計算するメンバー関数 // -------------------------------------------------------------------------------- void CMyFilter::LowPass(float freq, float q, float samplerate) { // フィルタ係数計算で使用する中間値を求める。 float omega = 2.0f * 3.14159265f * freq / samplerate; float alpha = sin(omega) / (2.0f * q); // フィルタ係数を求める。 a0 = 1.0f + alpha; a1 = -2.0f * cos(omega); a2 = 1.0f - alpha; b0 = (1.0f - cos(omega)) / 2.0f; b1 = 1.0f - cos(omega); b2 = (1.0f - cos(omega)) / 2.0f; } void CMyFilter::HighPass(float freq, float q, float samplerate) { // フィルタ係数計算で使用する中間値を求める。 float omega = 2.0f * 3.14159265f * freq / samplerate; float alpha = sin(omega) / (2.0f * q); // フィルタ係数を求める。 a0 = 1.0f + alpha; a1 = -2.0f * cos(omega); a2 = 1.0f - alpha; b0 = (1.0f + cos(omega)) / 2.0f; b1 = -(1.0f + cos(omega)); b2 = (1.0f + cos(omega)) / 2.0f; } void CMyFilter::BandPass(float freq, float bw, float samplerate) { // フィルタ係数計算で使用する中間値を求める。 float omega = 2.0f * 3.14159265f * freq / samplerate; float alpha = sin(omega) * sinh(log(2.0f) / 2.0 * bw * omega / sin(omega)); // フィルタ係数を求める。 a0 = 1.0f + alpha; a1 = -2.0f * cos(omega); a2 = 1.0f - alpha; b0 = alpha; b1 = 0.0f; b2 = -alpha; } void CMyFilter::Notch(float freq, float bw, float samplerate) { // フィルタ係数計算で使用する中間値を求める。 float omega = 2.0f * 3.14159265f * freq / samplerate; float alpha = sin(omega) * sinh(log(2.0f) / 2.0 * bw * omega / sin(omega)); // フィルタ係数を求める。 a0 = 1.0f + alpha; a1 = -2.0f * cos(omega); a2 = 1.0f - alpha; b0 = 1.0f; b1 = -2.0f * cos(omega); b2 = 1.0f; } void CMyFilter::LowShelf(float freq, float q, float gain, float samplerate) { // フィルタ係数計算で使用する中間値を求める。 float omega = 2.0f * 3.14159265f * freq / samplerate; float alpha = sin(omega) / (2.0f * q); float A = pow(10.0f, (gain / 40.0f)); float beta = sqrt(A) / q; // フィルタ係数を求める。 a0 = (A + 1.0f) + (A - 1.0f) * cos(omega) + beta * sin(omega); a1 = -2.0f * ((A - 1.0f) + (A + 1.0f) * cos(omega)); a2 = (A + 1.0f) + (A - 1.0f) * cos(omega) - beta * sin(omega); b0 = A * ((A + 1.0f) - (A - 1.0f) * cos(omega) + beta * sin(omega)); b1 = 2.0f * A * ((A - 1.0f) - (A + 1.0f) * cos(omega)); b2 = A * ((A + 1.0f) - (A - 1.0f) * cos(omega) - beta * sin(omega)); } void CMyFilter::HighShelf(float freq, float q, float gain, float samplerate) { // フィルタ係数計算で使用する中間値を求める。 float omega = 2.0f * 3.14159265f * freq / samplerate; float alpha = sin(omega) / (2.0f * q); float A = pow(10.0f, (gain / 40.0f)); float beta = sqrt(A) / q; // フィルタ係数を求める。 a0 = (A + 1.0f) - (A - 1.0f) * cos(omega) + beta * sin(omega); a1 = 2.0f * ((A - 1.0f) - (A + 1.0f) * cos(omega)); a2 = (A + 1.0f) - (A - 1.0f) * cos(omega) - beta * sin(omega); b0 = A * ((A + 1.0f) + (A - 1.0f) * cos(omega) + beta * sin(omega)); b1 = -2.0f * A * ((A - 1.0f) + (A + 1.0f) * cos(omega)); b2 = A * ((A + 1.0f) + (A - 1.0f) * cos(omega) - beta * sin(omega)); } void CMyFilter::Peaking(float freq, float bw, float gain, float samplerate) { // フィルタ係数計算で使用する中間値を求める。 float omega = 2.0f * 3.14159265f * freq / samplerate; float alpha = sin(omega) * sinh(log(2.0f) / 2.0 * bw * omega / sin(omega)); float A = pow(10.0f, (gain / 40.0f)); // フィルタ係数を求める。 a0 = 1.0f + alpha / A; a1 = -2.0f * cos(omega); a2 = 1.0f - alpha / A; b0 = 1.0f + alpha * A; b1 = -2.0f * cos(omega); b2 = 1.0f - alpha * A; } void CMyFilter::AllPass(float freq, float q, float samplerate) { // フィルタ係数計算で使用する中間値を求める。 float omega = 2.0f * 3.14159265f * freq / samplerate; float alpha = sin(omega) / (2.0f * q); // フィルタ係数を求める。 a0 = 1.0f + alpha; a1 = -2.0f * cos(omega); a2 = 1.0f - alpha; b0 = 1.0f - alpha; b1 = -2.0f * cos(omega); b2 = 1.0f + alpha; } |
使用例
Wavファイル等へ適用する場合は下記のような感じで使用いただけます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
// それぞれの変数は下記のとおりとする // short input[] …44100Hzでサンプリングされた入力信号の格納されたバッファ。 // short output[] …フィルタ処理した値を書き出す出力信号のバッファ。 // int size …入力信号・出力信号のバッファのサイズ。 CMyFilter filter; // カットオフ周波数 1000Hz、Q値 1/√2のローパスフィルタに設定 filter.LowPass(1000.0f, 1.0f/sqrt(2.0f)); // 入力信号にフィルタを適用していく。 for(int i = 0; i < size; i++) { // 入力信号にフィルタを適用し、出力信号として書き出す。 output[i] = (short)filter.Process((float)input[i]); } |
VSTのように入力・出力のバッファがfloat型の場合、使い方は下記のような感じです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
// それぞれの変数は下記のとおりとする // float input[] …44100Hzでサンプリングされた入力信号の格納されたバッファ。 // float output[] …フィルタ処理した値を書き出す出力信号のバッファ。 // int size …入力信号・出力信号のバッファのサイズ。 CMyFilter filter; // カットオフ周波数 1000Hz、Q値 1/√2のローパスフィルタに設定 filter.LowPass(1000.0f, 1.0f/sqrt(2.0f)); // 入力信号にフィルタを適用していく。 for(int i = 0; i < size; i++) { // 入力信号にフィルタを適用し、出力信号として書き出す。 output[i] = filter.Process(input[i]); } |