Main Content

このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。

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

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

任意の係数によるサンプル レート変換は、数多くのアプリケーション (デジタル受信器のシンボルの同期、音声処理符号化および合成、連続時間システムのコンピューター シミュレーションなど) で必要になります。この例では、信号のサンプリング レートを 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)
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 
     '

cost(sampRateConv)
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)
ans = struct with fields:
                  NumCoefficients: 16
                        NumStates: 3
    MultiplicationsPerInputSample: 66.1500
          AdditionsPerInputSample: 60.6375

cost(farrowSampRateConv_4th)
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')

Figure Figure 1: Magnitude Response (dB) contains an axes object. The axes object with title Magnitude Response (dB), xlabel Frequency (kHz), ylabel Magnitude (dB) (normalized to 0 dB) contains 3 objects of type line. These objects represent Polyphase Sample-Rate Converter, 3rd-Order Farrow Interpolator, 4th-Order Farrow Interpolator.

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

farrowSampRateConv_4th = dsp.FarrowRateConverter('InputSampleRate',8e3, ...
    'OutputSampleRate',44.1e3,'PolynomialOrder',4, ...
    'OutputRateTolerance',0.01);
info(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                '

cost(farrowSampRateConv_4th)
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)
ans = struct with fields:
                  NumCoefficients: 34
                        NumStates: 11
    MultiplicationsPerInputSample: 34
          AdditionsPerInputSample: 31

cost(farrowSampRateConv)
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')

Figure contains an axes object. The axes object with xlabel Frequency (Hz), ylabel Magnitude (dB) contains an object of type line. This object represents Combined polyphase and Farrow sample rate converters.

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

scope = spectrumAnalyzer('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