Этот пример показывает, как эффективно преобразовать частоты дискретизации между случайными факторами.
Потребность в преобразовании частоты дискретизации случайным фактором возникает во многих приложениях (например, синхронизация символа в цифровых получателях, речевое кодирование и синтез, компьютерное моделирование непрерывно-разовых систем, и т.д.). В этом примере мы исследуем пример, где каскады основанных на полиноме и многофазных фильтров формируют эффективное решение, когда он желаем, чтобы преобразовать уровень выборки сигнала от 8 кГц до 44,1 кГц.
Многофазные структуры обычно рассматриваются эффективными внедрениями многоскоростных фильтров. Однако в случае дробного преобразования частоты дискретизации, количество фаз, и поэтому порядок фильтра, могут быстро стать чрезмерно высокими. Чтобы передискретизировать сигнал от 8 кГц до 44,1 кГц, мы интерполируем 441 и десятикратно уменьшаем 80 (8*441/80=44.1).
sampRateConv = dsp.SampleRateConverter('Bandwidth',6e3, ... 'InputSampleRate',8e3,'OutputSampleRate',44.1e3, ... 'StopbandAttenuation',50);
Это может быть сделано относительно эффективным способом на двух этапах:
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
Несмотря на то, что количество операций на входную выборку разумно (примерно 95 умножения - учет того факта, что повышения ставки после первой стадии к 14,7 кГц), 1 774 коэффициента должны были бы храниться в памяти в этом случае.
Один способ смягчить большое количество коэффициентов мог состоять в том, чтобы допускать допуск в выходной частоте дискретизации, если точный уровень не очень важен. Например, задавая допуск 1%-х результатов в норме выработки 44 кГц скорее затем 44,1 кГц. Это теперь требует, чтобы интерполировать 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.
Основанные на полиноме фильтры являются другим способом преодолеть проблему необходимости в большом количестве коэффициентов, чтобы храниться. Неоплодотворенные структуры являются эффективными внедрениями для таких фильтров.
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 умножения на входную выборку. Полиномы четвертого порядка обеспечивают немного лучше lowpass ответ в более высокой стоимости: 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')
Обеспечение допуска нормы выработки не значительно влияет на стоимость внедрения фильтра Фэрроу. Однако это действительно изменяет факторы интерполяции и десятикратного уменьшения таким же образом, это делает для 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
Мы теперь пытаемся разработать гибридное решение, которое использовало бы в своих интересах два типа фильтров, которые мы ранее видели. Многофазные фильтры особенно хорошо адаптируются к интерполяции или десятикратному уменьшению целочисленным фактором и для дробных преобразований уровня, когда интерполяция и факторы десятикратного уменьшения являются низкими. Неоплодотворенные фильтры могут эффективно реализовать произвольный (включая иррациональный) факторы изменения уровня. Во-первых, мы интерполируем оригинал 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 '
Затем мы интерполируем промежуточный сигнал на 32 кГц 44.1/32 = 1.378125, чтобы получить желаемую итоговую частоту дискретизации на 44,1 кГц. Мы используем кубический Лагранжев основанный на полиноме фильтр с этой целью.
farrowSampRateConv = dsp.FarrowRateConverter('InputSampleRate',32e3, ... 'OutputSampleRate',44.1e3,'PolynomialOrder',3);
Полный фильтр просто получен путем расположения каскадом двух фильтров.
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. Объединенная частотная характеристика этих двух проектов превосходит частотную характеристику 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