-
Notifications
You must be signed in to change notification settings - Fork 0
/
resample_PMARXL.m
136 lines (124 loc) · 4.83 KB
/
resample_PMARXL.m
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
function [y, h] = resample_PMARXL( x, p, q, N, bta )
%RESAMPLE Change the sampling rate of a signal.
% Y = RESAMPLE(X,P,Q) resamples the sequence in vector X at P/Q times
% the original sample rate using a polyphase implementation. Y is P/Q
% times the length of X (or the ceiling of this if P/Q is not an integer).
% P and Q must be positive integers.
%
% RESAMPLE applies an anti-aliasing (lowpass) FIR filter to X during the
% resampling process, and compensates for the filter's delay. The filter
% is designed using FIRLS. RESAMPLE provides an easy-to-use alternative
% to UPFIRDN, relieving the user of the need to supply a filter or
% compensate for the signal delay introduced by filtering.
%
% In its filtering process, RESAMPLE assumes the samples at times before
% and after the given samples in X are equal to zero. Thus large
% deviations from zero at the end points of the sequence X can cause
% inaccuracies in Y at its end points.
%
% Y = RESAMPLE(X,P,Q,N) uses a weighted sum of 2*N*max(1,Q/P) samples of X
% to compute each sample of Y. The length of the FIR filter RESAMPLE applies
% is proportional to N; by increasing N you will get better accuracy at the
% expense of a longer computation time. If you don't specify N, RESAMPLE uses
% N = 10 by default. If you let N = 0, RESAMPLE performs a nearest
% neighbor interpolation; that is, the output Y(n) is X(round((n-1)*Q/P)+1)
% ( Y(n) = 0 if round((n-1)*Q/P)+1 > length(X) ).
%
% Y = RESAMPLE(X,P,Q,N,BTA) uses BTA as the BETA design parameter for the
% Kaiser window used to design the filter. RESAMPLE uses BTA = 5 if
% you don't specify a value.
%
% Y = RESAMPLE(X,P,Q,B) uses B to filter X (after upsampling) if B is a
% vector of filter coefficients. RESAMPLE assumes B has odd length and
% linear phase when compensating for the filter's delay; for even length
% filters, the delay is overcompensated by 1/2 sample. For non-linear
% phase filters consider using UPFIRDN.
%
% [Y,B] = RESAMPLE(X,P,Q,...) returns in B the coefficients of the filter
% applied to X during the resampling process (after upsampling).
%
% If X is a matrix, RESAMPLE resamples the columns of X.
%
% % Example:
% % Resample a sinusoid at 3/2 the original rate.
%
% tx = 3:3:300; % Time vector for original signal
% x = sin(2*pi*tx/300); % Define a sinusoid
% ty = 2:2:300; % Time vector for resampled signal
% y = resample(x,3,2); % Change sampling rate
% plot(tx,x,'+-',ty,y,'o:')
% legend('original','resampled'); xlabel('Time')
%
% See also UPFIRDN, INTERP, DECIMATE, FIRLS, KAISER, INTFILT.
% NOTE-1: digital anti-alias filter is desiged via windowing
% Author(s): James McClellan, 6-11-93
% Modified to use upfirdn, T. Krauss, 2-27-96
% Copyright 1988-2011 The MathWorks, Inc.
%
if nargin < 5, bta = 5; end %--- design parameter for Kaiser window LPF
if nargin < 4, N = 10; end
if abs(round(p))~=p || p==0
error(message('signal:resample:MustBePosInteger', 'P'));
end
if abs(round(q))~=q || q==0
error(message('signal:resample:MustBePosInteger', 'Q'));
end
[p,q] = rat( p/q, 1e-8 ); %--- reduce to lowest terms
% (usually exact, sometimes not; loses at most 1 second every 10^12 seconds)
if (p==1) && (q==1)
y = x;
h = 1;
return
end
pqmax = max(p,q);
if length(N)>1 % use input filter
L = length(N);
h = N;
else % design filter
if( N>0 )
fc = 1/2/pqmax;
L = 2*N*pqmax + 1;
h = p*firls( L-1, [0 2*fc 2*fc 1], [1 1 0 0]).*kaiser(L,bta)' ;
% h = p*fir1( L-1, 2*fc, kaiser(L,bta)) ;
else
L = p;
h = ones(1,p);
end
end
Lhalf = (L-1)/2;
isvect = any(size(x)==1);
if isvect
Lx = length(x);
else
Lx = size(x, 1);
end
% Need to delay output so that downsampling by q hits center tap of filter.
nz = floor(q-mod(Lhalf,q));
z = zeros(1,nz);
h = [z h(:).']; % ensure that h is a row vector.
Lhalf = Lhalf + nz;
% Number of samples removed from beginning of output sequence
% to compensate for delay of linear phase filter:
delay = floor(ceil(Lhalf)/q);
% Need to zero-pad so output length is exactly ceil(Lx*p/q).
nz1 = 0;
while ceil( ((Lx-1)*p+length(h)+nz1 )/q ) - delay < ceil(Lx*p/q)
nz1 = nz1+1;
end
h = [h zeros(1,nz1)];
% ---- HERE'S THE CALL TO UPFIRDN ----------------------------
y = upfirdn(x,h,p,q);
% Get rid of trailing and leading data so input and output signals line up
% temporally:
Ly = ceil(Lx*p/q); % output length
% Ly = floor((Lx-1)*p/q+1); <-- alternately, to prevent "running-off" the
% data (extrapolation)
if isvect
y(1:delay) = [];
y(Ly+1:end) = [];
else
y(1:delay,:) = [];
y(Ly+1:end,:) = [];
end
h([1:nz (end-nz1+1):end]) = []; % get rid of leading and trailing zeros
% in case filter is output