new plots for Diss. Mostly AI gen. Few changes in actual codebase
This commit is contained in:
@@ -212,6 +212,81 @@ classdef ChannelFreqResp < handle
|
||||
|
||||
end
|
||||
|
||||
function Target = apply(obj,Target,options)
|
||||
% Apply the measured magnitude-only channel response.
|
||||
arguments
|
||||
obj
|
||||
Target
|
||||
options.fileName = ''
|
||||
options.loadPath = ''
|
||||
options.maxampdb double = 0
|
||||
end
|
||||
|
||||
if isempty(obj.H)
|
||||
obj.load("fileName",options.fileName,"loadPath",options.loadPath);
|
||||
end
|
||||
|
||||
fstarget = Target.fs;
|
||||
N_target = numel(Target.signal);
|
||||
|
||||
% Ignore measured DC attenuation when setting the response
|
||||
% reference level.
|
||||
H_measured = abs(obj.H(:)).';
|
||||
H_measured_valid = isfinite(H_measured);
|
||||
H_measured_dB = 20*log10(H_measured);
|
||||
|
||||
idx_old = (obj.faxis > 0) & ...
|
||||
(obj.faxis < fstarget/2) & H_measured_valid;
|
||||
H_reference_dB = max(H_measured_dB(idx_old));
|
||||
|
||||
H_measured_dB = H_measured_dB - H_reference_dB + options.maxampdb;
|
||||
H_measured = 10.^(H_measured_dB/20);
|
||||
H_measured(~H_measured_valid) = 0;
|
||||
|
||||
% Positive-frequency FFT bins, excluding DC and Nyquist.
|
||||
N_positive = floor((N_target - 1)/2);
|
||||
fnew = (1:N_positive)*fstarget/N_target;
|
||||
|
||||
f_old = obj.faxis(idx_old);
|
||||
H_old = H_measured(idx_old);
|
||||
H_interp = interp1(f_old,H_old,fnew,'linear');
|
||||
|
||||
% Match the edge handling used by the precompensation path.
|
||||
nH = find(isfinite(H_interp),1,'first');
|
||||
if isempty(nH)
|
||||
error('ChannelFreqResp:InterpolationFailed', ...
|
||||
'The measured response does not overlap the target frequency grid.');
|
||||
end
|
||||
H_interp(1:nH-1) = H_interp(nH);
|
||||
|
||||
nH = find(isfinite(H_interp),1,'last');
|
||||
H_interp(nH+1:end) = H_interp(nH);
|
||||
|
||||
% Real, zero-phase, conjugate-symmetric FFT response.
|
||||
if mod(N_target,2) == 0
|
||||
H_apply = [H_interp(1), H_interp, 0, fliplr(H_interp)];
|
||||
else
|
||||
H_apply = [H_interp(1), H_interp, fliplr(H_interp)];
|
||||
end
|
||||
H_apply = H_apply(:);
|
||||
|
||||
% Re-anchor the final interpolated response using only the
|
||||
% positive-frequency bins, so DC attenuation is ignored.
|
||||
H_apply_dB = 20*log10(abs(H_apply));
|
||||
positive_bins = 2:(N_positive + 1);
|
||||
H_apply_dB = H_apply_dB - max(H_apply_dB(positive_bins)) + options.maxampdb;
|
||||
H_apply = 10.^(H_apply_dB/20);
|
||||
|
||||
obj.H_apply = H_apply;
|
||||
|
||||
% Apply the channel in the frequency domain and preserve shape.
|
||||
signal_shape = size(Target.signal);
|
||||
signal_in = real(Target.signal(:));
|
||||
signal_out = real(ifft(fft(signal_in).*H_apply));
|
||||
Target.signal = reshape(signal_out,signal_shape);
|
||||
|
||||
end
|
||||
|
||||
function plot(obj)
|
||||
|
||||
figure();
|
||||
|
||||
Reference in New Issue
Block a user