希尔伯特变换原理公式
MATLAB官方帮助文档中希尔伯特变换算法
hilbert uses a four-step algorithm:
Calculate the FFT of the input sequence, storing the result in a vector x.
Create a vector h whose elements h(i) have the values:
1 for i = 1, (n/2)+1
2 for i = 2, 3, ... , (n/2)
0 for i = (n/2)+2, ... , n
Calculate the element-wise product of x and h.
Calculate the inverse FFT of the sequence obtained in step 3 and returns the first n elements of the result.
常量和结构体定义
// ConstParam.h
#ifndef CONSTPARAM
#define CONSTPARAM
#include "fftw3.h"
const float PI = 3.1415926535897932;
const float TWO_PI = 6.2831853071795864;
const int REAL = 0;
const int IMAG = 1;
const __int64 BufSize = 1048576;
float CosVal[5] = {
1,0.309016994374947,-0.809016994374947 ,-0.809016994374948,0.309016994374947 };
float SinVal[5] = {
0,0.951056516295154, 0.587785252292473, -0.587785252292473, -0.951056516295154 };
const float ACC = 40.0;
const float BIGNO = 1.0e10;
const float BIGNI = 1.0e-10;
#define max(a,b) (a>b?a:b)
typedef struct _Resampler_
{
int _upRate;
int _downRate;
float *_transposedCoefs;
float *_state;
float *_stateEnd;
int _paddedCoefCount; // ceil(len(coefs)/upRate)*upRate
int _coefsPerPhase; // _paddedCoefCount / upRate
__int64 _t; // "time" (modulo upRate)
__int64 _xOffset;
}sResampler;
#endif
C语言实现(FFTW库的float版,double版类似)
// hilbert.h
#include <memory.h>
#include "ConstParam.h"
/*
in - 输入数据指针
out - 希尔伯特变换结果数组指针
N - 数据长度
*/
void hilbert(float* in, fftwf_complex* out,int N)
{
// copy the data into the complex array
for (int i = 0; i < N; ++i)
{
out[i][REAL] = in[i];
out[i][IMAG] = 0;
}
//create a DFT plan and execute it
fftwf_plan plan = fftwf_plan_dft_r2c_1d(N, in, out, FFTW_ESTIMATE);
fftwf_execute(plan);
//destroy the plan to prevent a memory leak
fftwf_destroy_plan(plan);
int hN = N >> 1; // half of the length (N /2)
int numRem = hN; // the number of remaining elements
// multiply the appropriate values by 2
// (those that should be multiplied by 1 are left intact because they wouldn't change)
for (int i = 1; i < hN; ++i) // 1,2,...,N/2 - 1 的项乘以2
{
out[i][REAL] *= 2;
out[i][IMAG] *= 2;
}
// if the length is even, the number of remaining elements decreases by 1
if (N % 2 == 0)
numRem--;
// if it's odd and greater than 1, the middle value must be multiplied by 2
else if (N > 1) // 奇数非空
{
out[hN][REAL] *= 2;
out[hN][IMAG] *= 2;
}
// set the remaining values to 0
// (multiplying by 0 gives 0, so we don't care about the multiplicands)
memset(&out[hN + 1][REAL], 0, numRem * sizeof(fftwf_complex));
// create an IDFT plan and execute it
plan = fftwf_plan_dft_1d(N, out, out, FFTW_BACKWARD, FFTW_ESTIMATE);
fftwf_execute(plan);
// do some cleaning
fftwf_destroy_plan(plan);
fftwf_cleanup();
// scale the IDFT output
for (int i = 0; i < N; ++i)
{
out[i][REAL] /= N;
out[i][IMAG] /= N;
}
}