MATLAB库函数hilbert(希尔伯特变换)的C语言实现(FFT采用FFTW库)

希尔伯特变换原理公式

在这里插入图片描述
在这里插入图片描述

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;
	}
}

猜你喜欢

转载自blog.csdn.net/wlwdecs_dn/article/details/108683309