I am trying to detect the envelope of a high-frequency signal (similar to below) using Matlab Hilbert function

enter image description here

This is my output

enter image description here

It generally follows the envelope, but there is a high-frequency ripple in the envelope, see zoomed version below

enter image description here

Here is my code:

t =out.tout';
x =out.Itxmod';
y = hilbert(x);
env = abs(y);
plot_param = {'Color', [0.6 0.1 0.2],'Linewidth',2};
hold on
hold off
xlim([0.001 0.002])
title('Hilbert Envelope')

Question: How can I get a smooth envelope the signal without this high-frequency ripple?


This must be an artifact of the implementation for the hilbert function, in that any implementation of finite length will have a finite ripple. It doesn't appear the underlying filter using in the hilbert function can be modified, so there are three suggestions to obtain a smoothed demodulated result:

Method 1: Implement the Hilbert using the FFT: take the FFT of the original signal, set all the negative frequencies to zero (the upper half of the FFT) and double the positive frequencies leaving bin 0 (DC) as is (and as Overlord pointed out in the comments, leave the Nyquist bin at $N/2$ as is when the FFT length $N$ is even). The IFFT will be the Hilbert Transform and taking the absolute value of this signal will be the desired envelope. (As @aconcernedcitizen pointed out in the comments, this IS the method specifically implemented by Octave using the hilbert function from the signal package.)

Method 2: Implement the Hilbert with quadrature phase tracking filters where the filter length versus ripple can be traded.

Method 3: Use a traditional AM demodulator by multiplying the modulated signal with the coherent carrier and then low pass filtering the result.

A demonstration of Method 1 is shown below, which is a suitable solution for the OP's case:

signal and envelope

Zooming in on the start of the signal shows the distortion limited to the start-up condition and the smooth envelope after that.

zoom in

The Matlab code for this is as follows:

N = length(sig);
sig_spectrum = fft(sig);
hilbert_spectrum = zeros(1, N);
hilbert_spectrum(1) = sig_spectrum(1);
hilbert_spectrum(2: ceil(N/2) - 1) = 2 * sig_spectrum(2:ceil(N/2) - 1);
if mod(N, 2) == 0
  hilbert_spectrum(N/2) = sig_spectrum(N/2);
hilbert_time = ifft(hilbert_spectrum);
envelope = abs(hilbert_time);
  • 1
    $\begingroup$ Caveat, Nyquist bin shouldn't be doubled (even N). $\endgroup$ – OverLordGoldDragon Apr 23 at 20:44
  • 1
    $\begingroup$ Good point! The bin at N/2 should not be doubled when N is even. $\endgroup$ – Dan Boschen Apr 24 at 0:24
  • $\begingroup$ I thought method 1 is the one that it's done by default with hilbert()? I know Octave uses it like that. $\endgroup$ – a concerned citizen Apr 24 at 8:07
  • 1
    $\begingroup$ @aconcernedcitizen you're right, I just looked at the code in Octave and it is exactly method 1 $\endgroup$ – Dan Boschen Apr 24 at 11:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.