最新のリリースでは、このページがまだ翻訳されていません。 このページの最新版は英語でご覧になれます。

任意の係数による効率的なサンプルレート変換

この例では、任意の係数間で効率的にサンプルレートを変換する方法を示します。

任意の係数によるサンプルレート変換は、数多くのアプリケーション (デジタル受信器のシンボルの同期、音声処理符号化および合成、連続時間システムのコンピューター シミュレーションなど) で必要になります。この例では、信号のサンプリング レートを 8 kHz から 44.1 kHz に変換する場合に、多項式ベースのフィルターおよびポリフェーズ フィルターのカスケードによって効率的なソリューションを形成できる例を見ていきます。

単一ステージのポリフェーズ アプローチ

ポリフェーズ構造は、一般的にマルチレート フィルターの効率的な実装であると見なされます。ただし、分数のサンプルレート変換の場合には、位相数、したがってフィルターの次数が急激に過剰に高くなることがあります。信号を 8 kHz から 44.1 kHz にリサンプリングするために、441 で内挿し、80 で間引きます (8*441/80=44.1)。

sampRateConv = dsp.SampleRateConverter('Bandwidth',6e3, ...
    'InputSampleRate',8e3,'OutputSampleRate',44.1e3, ...
    'StopbandAttenuation',50);

これは、2 つのステージにより、比較的高い効率で実行できます。

info(sampRateConv)
cost(sampRateConv)
ans =

    'Overall Interpolation Factor    : 441
     Overall Decimation Factor       : 80
     Number of Filters               : 2
     Multiplications per Input Sample: 95.175000
     Number of Coefficients          : 1774
     Filters:                         
        Filter 1:
        dsp.FIRRateConverter - Interpolation Factor: 147
                             - Decimation Factor   : 80 
        Filter 2:
        dsp.FIRInterpolator  - Interpolation Factor: 3 
     '


ans = 

  struct with fields:

                  NumCoefficients: 1774
                        NumStates: 30
    MultiplicationsPerInputSample: 95.1750
          AdditionsPerInputSample: 89.6750

入力サンプルあたりの演算数 (第 1 ステージ終了後に周波数が 14.7 kHz に増加することを考慮して、約 95 の乗算と加算) は妥当な数ですが、この場合には 1774 の係数をメモリに格納しなければなりません。

出力レートの許容誤差の設定

多数の係数を軽減する方法の 1 つは、出力サンプルの正確なレートが重要でない場合にはレートの許容誤差を設けることです。たとえば、許容誤差 1% を設定すると、出力レートは 44.1 kHz ではなく 44 kHz になります。これは、11 で内挿して 2 で間引きする必要があります。これは単一ステージで効率的に実行できます。

sampRateConvWithTol = dsp.SampleRateConverter('Bandwidth',6e3, ...
    'InputSampleRate',8e3,'OutputSampleRate',44.1e3, ...
    'StopbandAttenuation',50,'OutputRateTolerance',0.01);
cost(sampRateConvWithTol)
ans = 

  struct with fields:

                  NumCoefficients: 120
                        NumStates: 12
    MultiplicationsPerInputSample: 60
          AdditionsPerInputSample: 55

この場合、120 係数が必要で、入力サンプルあたりの乗算の数は 60 です。

単一ステージの Farrow アプローチ

多数の係数を保存しなければならないという問題を克服するもう 1 つの方法は、多項式ベースのフィルターです。Farrow 構造は、このようなフィルターの効率的な実装です。

farrowSampRateConv_3rd = dsp.FarrowRateConverter('InputSampleRate',8e3, ...
    'OutputSampleRate',44.1e3,'PolynomialOrder',3);

farrowSampRateConv_4th = dsp.FarrowRateConverter('InputSampleRate',8e3, ...
    'OutputSampleRate',44.1e3,'PolynomialOrder',4);

cost(farrowSampRateConv_3rd)
cost(farrowSampRateConv_4th)
ans = 

  struct with fields:

                  NumCoefficients: 16
                        NumStates: 3
    MultiplicationsPerInputSample: 66.1500
          AdditionsPerInputSample: 60.6375


ans = 

  struct with fields:

                  NumCoefficients: 25
                        NumStates: 4
    MultiplicationsPerInputSample: 121.2750
          AdditionsPerInputSample: 99.2250

3 次多項式では、16 の係数と入力サンプルあたり約 66 の乗算が必要です。4 次多項式では、ローパス応答が若干優れていますが、より高コストで、係数は 25、入力サンプルあたりの乗算は 121 です。

filts = getFilters(sampRateConv);
W = linspace(0,44.1e3,2048);  % Define the frequency range analysis
Fs1 = 8e3*147;  % The equivalent single stage filter is clocked at 3.53 MHz
hfvt = fvtool(filts.Stage1,farrowSampRateConv_3rd, ...
    farrowSampRateConv_4th,'FrequencyRange','Specify freq. vector', ...
    'FrequencyVector',W,'Fs',[Fs1 3*Fs1 3*Fs1], ...
    'NormalizeMagnitudeto1','on','Color','white');
legend(hfvt,'Polyphase Sample-Rate Converter', ...
    '3rd-Order Farrow Interpolator','4th-Order Farrow Interpolator', ...
    'Location','NorthEast')

出力レートの許容誤差を設定しても、Farrow フィルターの実装コストには大きな影響はありません。しかし、dsp.SampleRateConverter と同様に、内挿係数と間引き係数は変わります。

farrowSampRateConv_4th = dsp.FarrowRateConverter('InputSampleRate',8e3, ...
    'OutputSampleRate',44.1e3,'PolynomialOrder',4, ...
    'OutputRateTolerance',0.01);
info(farrowSampRateConv_4th)
cost(farrowSampRateConv_4th)
ans =

  12x52 char array

    'Discrete-Time FIR Multirate Filter (real)           '
    '-----------------------------------------           '
    'Filter Structure      : Farrow Sample-Rate Converter'
    'Interpolation Factor  : 11                          '
    'Decimation Factor     : 2                           '
    'Filter Length         : 5                           '
    'Stable                : Yes                         '
    'Linear Phase          : No                          '
    '                                                    '
    'Arithmetic            : double                      '
    'Output Rate Tolerance : 1.000000 %                  '
    'Adjusted Output Rate  : 44000.000000                '


ans = 

  struct with fields:

                  NumCoefficients: 25
                        NumStates: 4
    MultiplicationsPerInputSample: 121
          AdditionsPerInputSample: 99

Farrow および FIR ポリフェーズ構造のカスケード

次に、これまでに見てきた 2 種類のフィルターを利用した複合ソリューションを設計してみましょう。ポリフェーズ フィルターは、整数ファクターによる内挿または間引きと、内挿係数および間引き係数が低い非整数レート変換に特に適しています。Farrow フィルターは任意の (無理数を含む) レート変換ファクターを効果的に実装できます。まず、FIR ハーフバンド フィルターのカスケードを使用して、元の 8 kHz 信号を 4 で内挿します。

intSampRateConv = dsp.SampleRateConverter('Bandwidth',6e3, ...
    'InputSampleRate',8e3,'OutputSampleRate',32e3, ...
    'StopbandAttenuation',50);
info(intSampRateConv)
ans =

    'Overall Interpolation Factor    : 4
     Overall Decimation Factor       : 1
     Number of Filters               : 1
     Multiplications per Input Sample: 34.000000
     Number of Coefficients          : 34
     Filters:                         
        Filter 1:
        dsp.FIRInterpolator  - Interpolation Factor: 4 
     '

次に、44.1/32 = 1.378125 によって中間の 32 kHz 信号を内挿し、目的の最終的な 44.1 kHz のサンプリング周波数を取得します。この目的には 3 次ラグランジュ多項式ベース フィルターを使用します。

farrowSampRateConv = dsp.FarrowRateConverter('InputSampleRate',32e3, ...
    'OutputSampleRate',44.1e3,'PolynomialOrder',3);

全体的なフィルターは、単に 2 つのフィルターをカスケードすることで求めます。

cost(intSampRateConv)
cost(farrowSampRateConv)
ans = 

  struct with fields:

                  NumCoefficients: 34
                        NumStates: 11
    MultiplicationsPerInputSample: 34
          AdditionsPerInputSample: 31


ans = 

  struct with fields:

                  NumCoefficients: 16
                        NumStates: 3
    MultiplicationsPerInputSample: 16.5375
          AdditionsPerInputSample: 15.1594

このハイブリッド設計の係数の数は比較的低く (36)、入力サンプルあたりの乗算の数も比較的低くなります (28 + 16*4 = 92)。これら 2 つの設計の周波数応答の結合は、farrowSampRateConv_3rd または farrowSampRateConv_4th より優れています。

[Hsrc,f]     = freqz(intSampRateConv);
Fsfar        = 32e3*441;
Hfsrc        = freqz(farrowSampRateConv,f,Fsfar);
Hhybrid      = Hsrc.*Hfsrc;
Hhybrid_norm = Hhybrid/norm(Hhybrid,inf); % Normalize magnitude to 0 dB
plot(f,20*log10(abs(Hhybrid_norm)));
xlabel('Frequency (Hz)')
ylabel('Magnitude (dB)')
legend('Combined polyphase and Farrow sample rate converters', ...
       'Location','NorthEast')

次に、単一ステージ設計と多段設計の周波数応答を重ねます。応答は、明らかに非常に近いものとなっています。

scope = dsp.SpectrumAnalyzer('SpectralAverages',50, ...
    'SampleRate',44.1e3,'PlotAsTwoSidedSpectrum',false, ...
    'YLimits',[-80 20],'ShowLegend',true, ...
    'ChannelNames',{'Single-stage design','Multi-stage design'});
tic,
while toc < 20
    % Run for 20 seconds
    x = randn(8000,1);

    % Convert rate using multistage FIR filters
    y1 = sampRateConv(x);

    % Convert rate using cascade of multistage FIR and Farrow filter
    ytemp  = intSampRateConv(x);
    y2     = farrowSampRateConv(ytemp);

    % Compare the output from both approaches
    scope([y1,y2])
end