codec2/octave/hf_sim.m

79 lines
2.4 KiB
Matlab

% hf_sim.m
% David Rowe March 2014
%
% Two path CCIR poor HF channel simulation, with apaologies to PathSim
% Init HF channel model from stored sample files of spreading signal ----------------------------------
global spread;
global spread_2ms;
global hf_gain;
% convert "spreading" samples from 1kHz carrier at Fs to complex
% baseband, generated by passing a 1kHz sine wave through PathSim with
% the ccir-poor model, enabling one path at a time. Because I'm too
% lazy to generate my own spreading signals
Fc = 1000; Fs=8000;
fspread = fopen("../raw/sine1k_2Hz_spread.raw","rb");
spread1k = fread(fspread, "int16")/10000;
fclose(fspread);
fspread = fopen("../raw/sine1k_2ms_delay_2Hz_spread.raw","rb");
spread1k_2ms = fread(fspread, "int16")/10000;
fclose(fspread);
% down convert to complex baseband
spreadbb = spread1k.*exp(-j*(2*pi*Fc/Fs)*(1:length(spread1k))');
spreadbb_2ms = spread1k_2ms.*exp(-j*(2*pi*Fc/Fs)*(1:length(spread1k_2ms))');
% remove -2000 Hz image
b = fir1(50, 5/Fs);
spread = filter(b,1,spreadbb);
spread_2ms = filter(b,1,spreadbb_2ms);
% discard first 1000 samples as these were near 0, probably as
% PathSim states were ramping up
spread = spread(1000:length(spread));
spread_2ms = spread_2ms(1000:length(spread_2ms));
hf_gain = 1.0/sqrt(var(spread)+var(spread_2ms));
% This function simulates the HF channel at 8kHz for real signals. A
% good use case is passing a vector of speech samples through it to
% simulate SSB over HF. There's a really good reason for the 300 -
% 3000 Hz filter that escapes me right now :-)
function [sim_out snr3kHz_measured ] = hf_sim_real(sim_in, snr3kHz)
% 300 - 3000 Hz filter
b = fir1(100,[300/4000, 3000/4000], 'pass');
% det power of unit variance noise passed through this filter
filter_var = var(filter(b,1,randn(1000,1)));
% Start simulation
s = hilbert(filter(b,1,sim_in));
n1 = length(s); n2 = length(spread);
n = min(n1,n2);
path1 = s(1:n) .* spread(1:n);
path2 = s(1:n) .* spread_2ms(1:n);
delay = floor(0.002*Fs);
combined = path1(delay+1:n) + path2(1:n-delay);
snr = 10 .^ (snr3kHz/10);
variance = (combined'*combined)/(snr*n);
noise = sqrt(variance*0.5/filter_var)*(randn(n-delay,1) + j*randn(n-delay,1));
filtered_noise = filter(b,1,noise);
sim_out = real(combined+filtered_noise);
snr3kHz_measured = 10*log10(var(real(combined))/var(real(filtered_noise)));
endfunction