moved to c and h files

master
Ondřej Hruška 9 years ago
parent 70face0a0a
commit 33a394e3da
  1. 4
      Makefile
  2. 6
      envelope-proj.pro
  3. 135
      main.c
  4. 64
      vec_match.c
  5. 25
      vec_match.h

@ -0,0 +1,4 @@
all: main.out
main.out: main.c vec_match.c vec_match.h
gcc -o main.out main.c vec_match.c -I.

@ -3,7 +3,11 @@ CONFIG += console
CONFIG -= app_bundle CONFIG -= app_bundle
CONFIG -= qt CONFIG -= qt
SOURCES += main.c SOURCES += main.c \
vec_match.c
DISTFILES += \ DISTFILES += \
style.astylerc style.astylerc
HEADERS += \
vec_match.h

135
main.c

@ -1,161 +1,44 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include <string.h>
#include <limits.h>
#include <float.h>
#define DATA_LEN 11 #include "vec_match.h"
#define SQUARE(a) ((a)*(a))
#define DATA_LEN 11
static float reference[DATA_LEN] = { static float reference[DATA_LEN] = {
0, 10, 20, 30, 40, 50, 40, 30, 20, 10, 0 0, 10, 20, 30, 40, 50, 40, 30, 20, 10, 0
}; };
static float data[DATA_LEN] = { static float data[DATA_LEN] = {
0, 10, 20, 30, 40, 50, 40, 30, 20, 10, 0 0, 10, 20, 30, 40, 50, 50, 40, 30, 30, 10
}; };
/**
* Calculate fuzzy envelope
*
* @param data source data
* @param envelope envelope (same length as source data)
* @param length data length
* @param drift_x horizontal offset (left/right growth)
* @param drift_y vertical offset (vertical growth)
*/
void calc_envelope(const float *data, float *envelope, uint32_t length, uint8_t drift_x, float drift_y)
{
int a, b, i, j;
for (i = 0; i < (int)length; i++) {
float peak = FLT_MIN;
// find highest value in the surrounding drift_x points
a = i - drift_x;
b = i + drift_x;
if (a < 0) a = 0;
if (b >= (int)length) b = length - 1;
for (j = a; j <= b; j++) {
if (peak < data[j]) peak = data[j];
}
// apply drift_y
peak += drift_y;
envelope[i] = peak;
}
}
/**
* Match signal to reference, allowing for some offser and noise
*
* @param data matched data
* @param ref reference data
* @param length data length (data & ref length must be equal)
* @param drift_x allowed horizontal drift (Hz drift if values are 1 Hz FFT bins)
* @param offset_y allowed vertical offset (bin amplitude, positive or negative)
* @param envl_match_error error metric calculated with allowed drift and offset
* @param abs_match_error error metric calculated from raw data (can be used if envelope match passes)
* @return envelope match status (match using drift and offset)
*/
bool match_envelope(const float *data,
const float *ref,
uint32_t length,
uint8_t drift_x,
float offset_y,
float *envl_match_error,
float *abs_match_error)
{
int a, b;
int err_cnt = 0;
float env_err = 0;
float abs_err = 0;
for (int i = 0; i < (int)length; i++) {
float peak = FLT_MIN;
float base = FLT_MAX;
// find highest value in the surrounding drift_x points
a = i - drift_x;
b = i + drift_x;
if (a < 0) a = 0;
if (b >= (int)length) b = length - 1;
for (int j = a; j <= b; j++) {
if (peak < ref[j]) peak = ref[j];
if (base > ref[j]) base = ref[j];
}
// apply drift_y
peak += offset_y;
base -= offset_y;
abs_err += SQUARE(ref[i] - data[i]);
if (data[i] >= base && data[i] <= peak) {
// within limits
continue;
} else {
printf("data[%d] out of range: %f, [%f ; %f]\n", i, data[i], base, peak);
if (data[i] < base) env_err += SQUARE(base - data[i]);
if (data[i] > peak) env_err += SQUARE(data[i] - peak);
err_cnt++;
}
}
// write error values to provided fields
if (envl_match_error != NULL) *envl_match_error = env_err;
if (abs_match_error != NULL) *abs_match_error = abs_err;
return err_cnt == 0;
}
int main() int main()
{ {
// example
printf("REF: "); printf("REF: ");
for (int i = 0; i < DATA_LEN; i++) { for (int i = 0; i < DATA_LEN; i++) {
printf("%.0f, ", reference[i]); printf("%.0f, ", reference[i]);
} }
printf("\n"); printf("\n");
printf("MEAS: "); printf("MEAS: ");
for (int i = 0; i < DATA_LEN; i++) { for (int i = 0; i < DATA_LEN; i++) {
printf("%.0f, ", data[i]); printf("%.0f, ", data[i]);
} }
printf("\n"); printf("\n");
// error metric fields
float env_e, abs_e; float env_e, abs_e;
bool ok = match_envelope(data, reference, DATA_LEN, 1, 5, &env_e, &abs_e); bool ok = vec_match(data, reference, DATA_LEN, 1, 5, &env_e, &abs_e);
printf("%s", ok ? "MATCH OK" : "MATCH FAILED"); printf("%s", ok ? "MATCH OK" : "MATCH FAILED");
printf("\n"); printf("\n");
printf("Error rate: ENV %.2f, ABS %.2f\n", env_e, abs_e); printf("Error rate: ENV %.2f, ABS %.2f\n", env_e, abs_e);
/*
calc_envelope(data, envelope, 20, 1, 5);
for (int i = 0; i < 20; i++) {
printf("%.0f, ", envelope[i]);
}
printf("\n");
*/
} }

@ -0,0 +1,64 @@
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include <float.h>
#include "vec_match.h"
#define SQUARE(a) ((a)*(a))
bool vec_match(const float *data,
const float *ref,
uint32_t length,
uint8_t drift_x,
float offset_y,
float *envl_match_error,
float *abs_match_error)
{
int a, b;
int err_cnt = 0;
float env_err = 0;
float abs_err = 0;
for (int i = 0; i < (int)length; i++) {
float peak = FLT_MIN;
float base = FLT_MAX;
// find highest value in the surrounding drift_x points
a = i - drift_x;
b = i + drift_x;
if (a < 0) a = 0;
if (b >= (int)length) b = length - 1;
for (int j = a; j <= b; j++) {
if (peak < ref[j]) peak = ref[j];
if (base > ref[j]) base = ref[j];
}
// apply drift_y
peak += offset_y;
base -= offset_y;
abs_err += SQUARE(ref[i] - data[i]);
if (data[i] >= base && data[i] <= peak) {
// within limits
continue;
} else {
//printf("data[%d] out of range: %f, [%f ; %f]\n", i, data[i], base, peak);
if (data[i] < base) env_err += SQUARE(base - data[i]);
if (data[i] > peak) env_err += SQUARE(data[i] - peak);
err_cnt++;
}
}
// write error values to provided fields
if (envl_match_error != NULL) *envl_match_error = env_err;
if (abs_match_error != NULL) *abs_match_error = abs_err;
return err_cnt == 0;
}

@ -0,0 +1,25 @@
#pragma once
#include <stdint.h>
#include <stdbool.h>
/**
* Match signal to reference, allowing for some offser and noise
*
* @param data matched data
* @param ref reference data
* @param length data length (data & ref length must be equal)
* @param drift_x allowed horizontal drift (Hz drift if values are 1 Hz FFT bins)
* @param offset_y allowed vertical offset (bin amplitude, positive or negative)
* @param envl_match_error error metric calculated with allowed drift and offset
* @param abs_match_error error metric calculated from raw data (can be used if envelope match passes)
* @return envelope match status (match using drift and offset)
*/
bool vec_match(const float *data,
const float *ref,
uint32_t length,
uint8_t drift_x,
float offset_y,
float *envl_match_error,
float *abs_match_error);
Loading…
Cancel
Save