【发布时间】:2020-12-08 10:42:43
【问题描述】:
我需要计算希尔伯特变换并从我的信号中得到它的绝对数。 我安装了 FFTW 并关注了these YouTube tutorials,都运行良好。
但是,我按照视频的方式实现了希尔伯特变换,我没有得到与 Matlab 计算的值相同的值。
我读过一些人通过使用 FFT 和进行其他计算来解决这个问题,但他们给出的答案不够清楚。 谁能提供几行基于 FFTW 的代码,让结果与 Matlab 计算结果一致?
这是我跟随视频的希尔伯特变换代码:
void hilbert(const double* in, fftw_complex* out)
{
// copy the data to the complex array
for (int i = 0; i < N; ++i) {
out[i][REAL] = in[i];
out[i][IMAG] = 0;
}
// creat a DFT plan and execute it
fftw_plan plan = fftw_plan_dft_1d(N, out, out, FFTW_FORWARD, FFTW_ESTIMATE);
fftw_execute(plan);
// destroy a plan to prevent memory leak
fftw_destroy_plan(plan);
int hN = N >> 1; // half of the length (N/2)
int numRem = hN; // the number of remaining elements
// multiply the appropriate value by 2
//(those should multiplied by 1 are left intact because they wouldn't change)
for (int i = 1; i < hN; ++i) {
out[i][REAL] *= 2;
out[i][IMAG] *= 2;
}
// if the length is even, the number of the remaining elements decrease by 1
if (N % 2 == 0)
numRem--;
else if (N > 1) {
out[hN][REAL] *= 2;
out[hN][IMAG] *= 2;
}
// set the remaining value to 0
// (multiplying by 0 gives 0, so we don't care about the multiplicands)
memset(&out[hN + 1][REAL], 0, numRem * sizeof(fftw_complex));
// creat a IDFT plan and execute it
plan = fftw_plan_dft_1d(N, out, out, FFTW_BACKWARD, FFTW_ESTIMATE);
fftw_execute(plan);
// do some cleaning
fftw_destroy_plan(plan);
fftw_cleanup();
// scale the IDFT output
for (int i = 0; i < N; ++i) {
out[i][REAL] /= N;
out[i][IMAG] /= N;
}
}
我要计算的主程序:
pi16Buffer = (int16 *)pBuffer;
//int16* ch1Buffer;
//int16* ch2Buffer;
double* ch1Buffer = NULL;
double* ch2Buffer = NULL;
fftw_complex result[N] ; // output array
// Allocate size to ch1 and ch2
ch1Buffer = (double*)calloc(u32Size, sizeof(double));
ch2Buffer = (double*)calloc(u32Size, sizeof(double));
//ch1ch2ch1ch2... fulfill the buffer
for (i = 0; i < u32Size/2; i++)
{
ch1Buffer[i] += (double)pi16Buffer[i*2];
ch2Buffer[i] += (double)pi16Buffer[i * 2 + 1];
}
// here hilbert on the whole ch2
hilbert(ch2Buffer, result); //hilbert(inputarray, outputarray)
for (i = 0; i < u32Size; i++)
{
if (ch1Buffer[i] > max1) //Find max value in each segs of ch1 and ch2
max1 = ch1Buffer[i];
if (abs(result[i]) > max2)
max2 = abs(result[i]); // Calculate the absolute value of hilbert result;
}
Corrected = max2 / max1; //do the signal correction
free(ch1Buffer); //free buffer
free(ch2Buffer);
}
return Corrected;
【问题讨论】:
-
如果我们没有看到它,就很难更正您的代码。此外,您应该使用比 youtube 视频更可靠的来源,例如 wikipedia-Hilbert transform
-
嗨@Damien,我现在附上了我的代码,感谢您的通知。
-
注意matlab函数把原始值放在实部,把希尔伯特变换值放在虚部。您可以提供一个非常简单的输入(4 或 8 个元素),以及您的输出和 matlab 输出
-
嗨@Damien,感谢您的回复,但我真的不明白您的想法。您能否写下代码等示例以获得更清晰的解释?谢谢!
-
我用的不是fftw,而是我自己的FFT函数。我可以尝试提供一个简单的 DFT 函数示例。但是,我没有 matlab,它会帮助我有一个好的输入/输出的例子
标签: c signal-processing fft absolute fftw