kopia lustrzana https://github.com/kamocat/uSDX
Testing Hilbert transforms in Octave
rodzic
48da6efd08
commit
53194c65e4
|
@ -0,0 +1,82 @@
|
||||||
|
%% Generate Hilbert coeffecients
|
||||||
|
order = 8;
|
||||||
|
if 1
|
||||||
|
order = floor(order/2)*2; %Make sure order is even
|
||||||
|
%See instructions for generating poles/zeros at https://dsp.stackexchange.com/questions/8692/hilbert-transform-filter-for-audio-applications-using-iir-half-band-parallel-al
|
||||||
|
Ik = e.^(pi./(2.^(1:1:order)));
|
||||||
|
Ik = Ik.*((-1).**(1:order));
|
||||||
|
Isos = zp2sos([Ik], 1./[Ik], 1);
|
||||||
|
Qsos = zp2sos([-Ik], 1./[-Ik], 1);
|
||||||
|
[b a] = sos2tf(Isos);
|
||||||
|
h1 = freqz(b,a);
|
||||||
|
Isos = zp2sos([Ik], 1./[Ik], 1/max(abs(h1)));
|
||||||
|
Qsos = zp2sos([-Ik], 1./[-Ik], 1/max(abs(h1)));
|
||||||
|
else
|
||||||
|
order = floor(order/2)*2+1; %Make sure order is odd
|
||||||
|
if 1 % Type III FIR
|
||||||
|
window = hamming(order*2+1);
|
||||||
|
a = (-order:order);
|
||||||
|
b = abs(rem(a,2)); %Remove even values
|
||||||
|
c = 2/pi./a; %Scale and invert
|
||||||
|
c(order+1)=0; % Remove NaN
|
||||||
|
c = c.* window' .* b;
|
||||||
|
else % Type IV FIR
|
||||||
|
window = hamming(order+1);
|
||||||
|
a = (-order:2:order);
|
||||||
|
c = 2/pi./a; %Scale and invert
|
||||||
|
c = c.* window';
|
||||||
|
end
|
||||||
|
Qsos = tf2sos(c,[1]);
|
||||||
|
% delay compensation
|
||||||
|
Isos = zeros(floor(order/2),6);
|
||||||
|
Isos(:,3:4)=1;
|
||||||
|
end
|
||||||
|
|
||||||
|
%% Create test audio
|
||||||
|
fs = 20e3;
|
||||||
|
start_freq = 10; %Hz
|
||||||
|
stop_freq = 10e3; %Hz
|
||||||
|
duration = 3; %Seconds
|
||||||
|
w = logspace(log10(start_freq),log10(stop_freq),fs*duration);
|
||||||
|
%t = linspace(start_freq, stop_freq, fs*duration);
|
||||||
|
t = sosfilt([1 0 0 1 -1 0], w); %Numerical integration
|
||||||
|
audio1 = cos(2*pi/fs*t);
|
||||||
|
scale = 2^11;
|
||||||
|
audio = round(audio1 * scale)/scale;
|
||||||
|
%audio = chirp([0:0.001:5]);
|
||||||
|
%% Hilbert transform
|
||||||
|
if 0
|
||||||
|
h = hilbert(audio);
|
||||||
|
I = real(h);
|
||||||
|
Q = imag(h);
|
||||||
|
else
|
||||||
|
I = sosfilt(Isos, audio);
|
||||||
|
Q = sosfilt(Qsos, audio);
|
||||||
|
end
|
||||||
|
%% Reconstruction
|
||||||
|
if 0
|
||||||
|
A = real(hilbert(I)); %To compensate for group delay
|
||||||
|
B = imag(hilbert(Q));
|
||||||
|
audio2 = (A-B)/2;
|
||||||
|
elseif 1
|
||||||
|
A = sosfilt(Isos, I);
|
||||||
|
B = sosfilt(Qsos, Q);
|
||||||
|
audio2 = (A-B)/2;
|
||||||
|
else
|
||||||
|
A = sosfilt(Qsos, I);
|
||||||
|
B = sosfilt(Isos, Q);
|
||||||
|
audio2 = (A+B)/2;
|
||||||
|
end
|
||||||
|
%%Playback
|
||||||
|
figure(1);
|
||||||
|
specgram(audio);
|
||||||
|
p1=audioplayer(audio1,fs,24);
|
||||||
|
play(p1);
|
||||||
|
pause(duration);
|
||||||
|
figure(2);
|
||||||
|
specgram(audio2);
|
||||||
|
p2=audioplayer(audio2,fs,8);
|
||||||
|
play(p2);
|
||||||
|
pause(duration);
|
||||||
|
figure(3);
|
||||||
|
semilogx(w,audio2);
|
|
@ -0,0 +1,31 @@
|
||||||
|
fs = 5e3; % Sample frequency
|
||||||
|
len = 7; % half-filter length
|
||||||
|
%window = flattopwin(len*2+1)';
|
||||||
|
|
||||||
|
%%%% Hilbert Transform
|
||||||
|
if 1 % Type III FIR
|
||||||
|
window = hamming(len*2+1);
|
||||||
|
a = (-len:len);
|
||||||
|
b = abs(rem(a,2)); %Remove even values
|
||||||
|
c = 2/pi./a; %Scale and invert
|
||||||
|
c(len+1)=0; % Remove NaN
|
||||||
|
c = c.* window' .* b;
|
||||||
|
else % Type IV FIR
|
||||||
|
len = 2*len+1;
|
||||||
|
window = hamming(len+1);
|
||||||
|
a = (-len:2:len);
|
||||||
|
c = 2/pi./a; %Scale and invert
|
||||||
|
c = c.* window';
|
||||||
|
end
|
||||||
|
|
||||||
|
B = c;
|
||||||
|
A = [1];
|
||||||
|
W = logspace(-4, -0.7, 512);
|
||||||
|
h = freqz(B, A, W);
|
||||||
|
figure(1);
|
||||||
|
subplot(2,1,1);
|
||||||
|
loglog(W,abs(h));
|
||||||
|
subplot(2,1,2);
|
||||||
|
g = unwrap(-angle(h));
|
||||||
|
g -= len * W; % Subtract constant group delay
|
||||||
|
semilogx(W,g/pi*180);
|
|
@ -0,0 +1,20 @@
|
||||||
|
order = 12;
|
||||||
|
I = e.^(pi./(2.^(1:2:order)));
|
||||||
|
Q = e.^(pi./(2.^(2:2:order)));
|
||||||
|
I = [I -I];
|
||||||
|
Q = [Q -Q];
|
||||||
|
W = logspace(-4, -.7, 512);
|
||||||
|
[B A] = zp2tf(I, 1./I, 1);
|
||||||
|
h1 = freqz(B,A,W);
|
||||||
|
h1gain = 1/abs(h1(end));
|
||||||
|
[B A] = zp2tf(I, 1./I, h1gain);
|
||||||
|
h1 = freqz(B,A,W);
|
||||||
|
[B A] = zp2tf(Q, 1./Q, 1);
|
||||||
|
h2 = freqz(B,A,W);
|
||||||
|
h2gain = 1/abs(h2(end));
|
||||||
|
[B A] = zp2tf(Q, 1./Q, h2gain);
|
||||||
|
h2 = freqz(B,A,W);
|
||||||
|
figure(1);
|
||||||
|
semilogx(W, 180/pi.*[unwrap(angle(h1))- unwrap(angle(h2))]);
|
||||||
|
figure(2);
|
||||||
|
semilogx(W, abs([h1;h2]));
|
|
@ -0,0 +1,54 @@
|
||||||
|
fs = 5e3; % Sample frequency
|
||||||
|
len = 7; % half-filter length
|
||||||
|
%window = flattopwin(len*2+1)';
|
||||||
|
|
||||||
|
%%%% Hilbert Transform
|
||||||
|
if 0 % Type III FIR
|
||||||
|
window = hamming(len*2+1);
|
||||||
|
a = (-len:len);
|
||||||
|
b = abs(rem(a,2)); %Remove even values
|
||||||
|
c = 2/pi./a; %Scale and invert
|
||||||
|
c(len+1)=0; % Remove NaN
|
||||||
|
c = c.* window' .* b;
|
||||||
|
else % Type IV FIR
|
||||||
|
len = 2*len+1;
|
||||||
|
window = hamming(len+1);
|
||||||
|
a = (-len:2:len);
|
||||||
|
c = 2/pi./a; %Scale and invert
|
||||||
|
c = c.* window';
|
||||||
|
end
|
||||||
|
|
||||||
|
function mag = hilmag(test_f, fs, hilbert)
|
||||||
|
test_f /= fs;
|
||||||
|
test_len = max(100, 2/test_f + 2*length(hilbert));
|
||||||
|
x = sin(2*pi*test_f.*(1:test_len));
|
||||||
|
y = conv(x, hilbert);
|
||||||
|
y = y(length(hilbert)+1:end-length(hilbert)); % Only take the middle section
|
||||||
|
mag1 = rms(y);
|
||||||
|
mag2 = rms(x);
|
||||||
|
mag = [mag1 mag2];
|
||||||
|
end
|
||||||
|
|
||||||
|
function p = phase(test_f, fs, hilbert)
|
||||||
|
test_f /= fs;
|
||||||
|
test_len = max(100, 2/test_f + 2*length(hilbert));
|
||||||
|
x = sin(2*pi*test_f.*(1:test_len));
|
||||||
|
y = x;
|
||||||
|
y = conv(y, hilbert);
|
||||||
|
test_len = floor(test_len/2);
|
||||||
|
b = floor(length(hilbert));
|
||||||
|
amp = rms(x)/rms(y);
|
||||||
|
p = atan2(x(test_len), y(test_len+b));
|
||||||
|
end
|
||||||
|
|
||||||
|
f = logspace(log10(10),log10(2400),200);
|
||||||
|
%f = linspace(10, 5000, 200);
|
||||||
|
m = zeros(length(f),2);
|
||||||
|
p = zeros(length(f),1);
|
||||||
|
for i=1:length(f)
|
||||||
|
m(i,:)=hilmag(f(i), fs, c);
|
||||||
|
% p(i,:)=phase(f(i), fs, c);
|
||||||
|
end
|
||||||
|
loglog(f,m)
|
||||||
|
%p = unwrap(p);
|
||||||
|
%plot(f,p)
|
|
@ -0,0 +1,52 @@
|
||||||
|
fs = 5e3; % Sample frequency
|
||||||
|
len = 7; % half-filter length
|
||||||
|
window = hamming(len*2+1)';
|
||||||
|
|
||||||
|
%%%% Hilbert Transform
|
||||||
|
a = (-len:len);
|
||||||
|
b = abs(rem(a,2)); %Remove even values
|
||||||
|
c = 2/pi./a.*b; %Scale and invert
|
||||||
|
c(len+1)=0; %Fix the divide-by-zero
|
||||||
|
c = c.* window;
|
||||||
|
figure(1);
|
||||||
|
subplot(1,2,1)
|
||||||
|
bar(c) % This is an FIR hilbert transform
|
||||||
|
|
||||||
|
%%%% Differentiation
|
||||||
|
d = (-1).**a;
|
||||||
|
d = d./a;
|
||||||
|
d(len+1) = 0; %Fix the divide by zero
|
||||||
|
d = d.* window;
|
||||||
|
%subplot(1,3,2)
|
||||||
|
%bar(d)
|
||||||
|
|
||||||
|
test_f = 0.01;
|
||||||
|
test_len = 200;
|
||||||
|
x = sin(2*pi*test_f.*(1:test_len));
|
||||||
|
%y = sosfilt([1 0 0 1 0 -1],x);
|
||||||
|
y = conv(x, c); % Hilbert transform
|
||||||
|
y = y(len+1:end-len); % Only take the middle section
|
||||||
|
x = conv(x, [-1 0 2 0 -1]); % Compensation Filter
|
||||||
|
x = x(3:end-2);
|
||||||
|
subplot(1,2,2)
|
||||||
|
plot(y);
|
||||||
|
hold on;
|
||||||
|
plot(x);
|
||||||
|
hold off;
|
||||||
|
|
||||||
|
phase = atan2(x,y);
|
||||||
|
phase = unwrap(phase);
|
||||||
|
%f = conv(phase,d); % differentiate
|
||||||
|
%f = f(len*2+1:end-len*2);
|
||||||
|
f = phase(2:end)-phase(1:end-1);
|
||||||
|
f *= 1/2/pi;
|
||||||
|
figure(2);
|
||||||
|
subplot(1,2,1)
|
||||||
|
plot(phase);
|
||||||
|
subplot(1,2,2)
|
||||||
|
plot(f);
|
||||||
|
|
||||||
|
##h = conv(c,d);
|
||||||
|
##h = round(h)
|
||||||
|
##subplot(1,3,3)
|
||||||
|
##bar(h)
|
Ładowanie…
Reference in New Issue