new plots for Diss. Mostly AI gen. Few changes in actual codebase

This commit is contained in:
Silas Oettinghaus
2026-07-30 08:35:45 +02:00
parent 125d8508ca
commit 7a9deaeb0c
62 changed files with 6171 additions and 630 deletions

View File

@@ -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();