背景
一个完整的正弦波存在如下性质,
波峰间隔,波谷间隔,向上过零间隔,向下过零间隔这四者的值理论上应该一致的。
那么该函数,顾名思义,就是取这四段值的
代码
数据结构
用来保存这四段值得结构 ZeroCrossings
typedef struct {
double *negative_interval_locations; //向下过零x值
double *negative_intervals; //向下过零y值
int number_of_negatives; //向下过零个数
double *positive_interval_locations; //向上过零x值
double *positive_intervals; //向上过零y值
int number_of_positives; //向上过零个数
double *peak_interval_locations; //峰值x值
double *peak_intervals; //峰值y值
int number_of_peaks; //峰值个数
double *dip_interval_locations; //谷值x值
double *dip_intervals; //谷值y值
int number_of_dips; //谷值个数
} ZeroCrossings;
初始化
int maximum_number = y_length;
zero_crossings->negative_interval_locations = new double[maximum_number];
zero_crossings->positive_interval_locations = new double[maximum_number];
zero_crossings->peak_interval_locations = new double[maximum_number];
zero_crossings->dip_interval_locations = new double[maximum_number];
zero_crossings->negative_intervals = new double[maximum_number];
zero_crossings->positive_intervals = new double[maximum_number];
zero_crossings->peak_intervals = new double[maximum_number];
zero_crossings->dip_intervals = new double[maximum_number];
函数ZeroCrossingEngine
计算这四个值都是一个函数,ZeroCrossingEngine.
举个例子(向下过零)
信号如下:
信号时域图如下:
红线部分为两次向下过零点
向下过零统计
for (int i = 0; i < y_length - 1; ++i)
negative_going_points[i] =
0.0 < filtered_signal[i] && filtered_signal[i + 1] <= 0.0 ? i + 1 : 0;
negative_going_points[y_length - 1] = 0;
// 实际值为 negative_going_points =
// [0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0]
//
int *edges = new int[y_length]; // 这里长度实际用不了那么长
int count = 0;
for (int i = 0; i < y_length; ++i)
if (negative_going_points[i] > 0)
edges[count++] = negative_going_points[i];
// edges 值为
// edges = [5,15,0 .... 0 ]
if (count < 2) {
delete[] edges;
delete[] negative_going_points;
return 0;
}
fine edges?
这个含义不是很理解,总体上是将整形的edge数组转成了double型的
double *fine_edges = new double[count];
for (int i = 0; i < count; ++i)
fine_edges[i] = edges[i] - filtered_signal[edges[i] - 1] /
(filtered_signal[edges[i]] - filtered_signal[edges[i] - 1]);
// fine_edges = [5.0, 15.0]
输出intervals和locations
for (int i = 0; i < count - 1; ++i) {
intervals[i] = fs / (fine_edges[i + 1] - fine_edges[i]);
interval_locations[i] = (fine_edges[i] + fine_edges[i + 1]) / 2.0 / fs;
}
其他三种类型计算
向上过零计算就是把原信号反转,然后调用ZeroCrossingEngine计算
for (int i = 0; i < y_length; ++i) filtered_signal[i] = -filtered_signal[i];
zero_crossings->number_of_positives = ZeroCrossingEngine(filtered_signal,
y_length, actual_fs, zero_crossings->positive_interval_locations,
zero_crossings->positive_intervals);
峰值/谷值是通过计算连续两个点是差值,如果差值最小,则为峰值/谷值
for (int i = 0; i < y_length - 1; ++i) filtered_signal[i] =
filtered_signal[i] - filtered_signal[i + 1];
zero_crossings->number_of_peaks = ZeroCrossingEngine(filtered_signal,
y_length - 1, actual_fs, zero_crossings->peak_interval_locations,
zero_crossings->peak_intervals);
for (int i = 0; i < y_length - 1; ++i)
filtered_signal[i] = -filtered_signal[i];
zero_crossings->number_of_dips = ZeroCrossingEngine(filtered_signal,
y_length - 1, actual_fs, zero_crossings->dip_interval_locations,
zero_crossings->dip_intervals);