2017-11-03 46 views
1

私はremez交換アルゴリズム(https://github.com/janovetz/remez-exchange/blob/master/remez.c)のC実装を見つけました。これを汎用プロトタイプローパスフィルタを実装するために使用したいと思います。コメントの使用方法を説明するためのコメントが提供されていますが、実装に問題があります。私は正しい入力を提供していないと思われるので、私は誰が私には、ローパスフィルタの係数を取得するためにremez()関数に与えると考えている正しい入力を教えてください。フィルタ設計のためのremez交換アルゴリズムの実装

私がしようとしていることに関する情報:私はコードを読んで実験していますが、ローパスフィルタではタイプを1(つまり、バンドパス)にする必要があります。とにかく、コードを試してみると、私はMATLABのバンドパスフィルタのパラメータとremez()と同じパラメータを与えましたが、結果は非常に異なります。誰かが私の係数を見て、私がそれを得られないので私が間違っていることを教えてもらえますか?

MATLAB:

% All frequency values are in Hz. 
Fs = 2000; % Sampling Frequency 
Fstop1 = 200;    % First Stopband Frequency 
Fpass1 = 300;    % First Passband Frequency 
Fpass2 = 700;    % Second Passband Frequency 
Fstop2 = 800;    % Second Stopband Frequency 
Dstop1 = 0.000177827941; % First Stopband Attenuation 
Dpass = 0.0057563991496; % Passband Ripple 
Dstop2 = 0.000177827941; % Second Stopband Attenuation 
dens = 20;    % Density Factor 
% Calculate the order from the parameters using FIRPMORD. 
[N, Fo, Ao, W] = firpmord([Fstop1 Fpass1 Fpass2 Fstop2]/(Fs/2), [0 1 ... 
          0], [Dstop1 Dpass Dstop2]); 

MATLABから得られたこれらの値(N、Foは、青、W)は、私は(レメズへの供給)機能。(私はのRemez関数を呼び出していますちょうど一部)

int numtaps = 64; 
int numbands = 3; 
std::vector<double> h(numtaps); 
double bands[] = [0, 0.2000, 0.3000, 0.7000, 0.8000, 1.000]; 
double des[] = [0, 0, 1, 1, 0, 0]; 
double weight[] = [0.000177827941, 0.0057563991496, 0.000177827941]; 
int type = 1; 
int griddensity = 20; 
remez(&(h[0]), int *numtaps, int *numband, const double bands[], const double des[], const double weight[], int *type, int *griddensity); 

誰がどのようにこのコードを正しく使用する方法を教えてもらえ:

ので、C++の関数は次のようになります。私はそれについてオンラインで何かを見つけることができませんでした。

答えて

2

Matlabのfirpmおよびfirpmordは、指定された周波数が[0,1]の範囲に入るように、ナイキストレートで正規化された帯域エッジ周波数を使用します。 remez関数の実装では、バンドエッジ周波数がサンプリングレートで正規化されていると仮定しています。これらの周波数は[0,0.5]の範囲にあります。その結果、あなたは2によってそれぞれ指定された周波数を分割する必要があります。

double bands[] = [0, 0.2000/2, 0.3000/2, 0.7000/2, 0.8000/2, 1.000/2]; 

また、あなたはあなたが提供しなければならない正しい相対リップル振幅を得るために、そのバンドに関連付けられた重みを増やす必要があり、所与のバンドに小さなリップルを有すること波紋に反比例する重み:

double weight[] = {1.0/0.000177827941, 1.0/0.0057563991496, 1.0/0.000177827941}; 

あなたはその後、次のようにremezを呼び出すことができる必要があります:

remez(&(h[0]), &numtaps, &numbands, bands, des, weight, &type, &griddensity); 

これにより、指定されたバンドパスフィルタの妥当な近似値が得られます。所望のフィルタ特性が周波数領域で提供されるので、(時間領域にある)フィルタ係数hではなく、設計されたフィルタの周波数応答を比較しなければならないことに留意されたい。この目的のためにfreqzとすることができます。フィルタの仕様を実際に満たすには、firpmordで与えられるN=64の推定値から約68に、Nを増やす必要があります。

最終的には、ローパスフィルタを取得することが目的だと述べたので、2つのバンドを持つバンドパスフィルタを指定して、最初のバンドが1の望ましい値を持ち、2番目のバンドが望ましい0の値次のような方法で入力します。

int numbands = 2; 
double bands[] = [0, 0.2000/2, 0.3000/2, 0.5]; 
double des[] = [1, 1, 0, 0]; 
... 
+0

これは非常に役に立ちました。説明してくれてありがとう。私はフィルタ係数をMATLABにインポートしていましたが、fftを実行してフィルタの応答を確認するためにプロットしましたが、私はどこにもいませんでした。そしてあなたはフィルターの順序についても正しいです。 68は、通過帯域内に多くの「より滑らかな」リップルを与えます。 – Preeti

+0

私はMATLABと同じバンドエッジ周波数を与えていました(つまり、ナイキスト周波数で正規化しました)。ここにあるコードの764行目(https://github.com/janovetz/remez-exchange/blob/master/remez.c)。バンドエッジ周波数をサンプリング周波数で正規化する必要があることをどのように知っていますか? – Preeti

+1

[Line 764](https://github.com/janovetz/remez-exchange/blob/master/remez.c#L764)はOctaveインターフェイスの一部です。オクターブインターフェイスはMatlabとできるだけ互換性があるように作られているので、オクターブ入力はナイキストレートで正規化され、後で[798行目](https://github.com/janovetz/remez-exchange/blob/master/remez .c#L798)、周波数は実際のC 'remez関数に渡される前に2で割ることによって再計算されます。 – SleuthEye

関連する問題