From 906187fe7adc0c8d8b4da51f2c6e4b360cf04f55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= <ondra@ondrovo.com> Date: Thu, 24 Dec 2015 14:43:07 +0100 Subject: [PATCH] initial --- .gitignore | 73 +++++++++++++++++++++ a.out | Bin 0 -> 9376 bytes envelope-proj.pro | 9 +++ main.c | 161 ++++++++++++++++++++++++++++++++++++++++++++++ style.astylerc | 13 ++++ 5 files changed, 256 insertions(+) create mode 100644 .gitignore create mode 100755 a.out create mode 100644 envelope-proj.pro create mode 100644 main.c create mode 100644 style.astylerc diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fab7372 --- /dev/null +++ b/.gitignore @@ -0,0 +1,73 @@ +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + diff --git a/a.out b/a.out new file mode 100755 index 0000000000000000000000000000000000000000..a371e96caf01d0a0cb45fa2397b0eed110f64a2e GIT binary patch literal 9376 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 Az5oCK literal 0 HcmV?d00001 diff --git a/envelope-proj.pro b/envelope-proj.pro new file mode 100644 index 0000000..dda002f --- /dev/null +++ b/envelope-proj.pro @@ -0,0 +1,9 @@ +TEMPLATE = app +CONFIG += console +CONFIG -= app_bundle +CONFIG -= qt + +SOURCES += main.c + +DISTFILES += \ + style.astylerc diff --git a/main.c b/main.c new file mode 100644 index 0000000..e32124f --- /dev/null +++ b/main.c @@ -0,0 +1,161 @@ +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <stdbool.h> +#include <string.h> +#include <limits.h> +#include <float.h> + +#define DATA_LEN 11 + +#define SQUARE(a) ((a)*(a)) + + +static float reference[DATA_LEN] = { + 0, 10, 20, 30, 40, 50, 40, 30, 20, 10, 0 +}; + + +static float data[DATA_LEN] = { + 0, 10, 20, 30, 40, 50, 40, 30, 20, 10, 0 +}; + + + +/** + * 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() +{ + printf("REF: "); + for (int i = 0; i < DATA_LEN; i++) { + printf("%.0f, ", reference[i]); + } + printf("\n"); + + printf("MEAS: "); + for (int i = 0; i < DATA_LEN; i++) { + printf("%.0f, ", data[i]); + } + printf("\n"); + + float env_e, abs_e; + + bool ok = match_envelope(data, reference, DATA_LEN, 1, 5, &env_e, &abs_e); + printf("%s", ok ? "MATCH OK" : "MATCH FAILED"); + printf("\n"); + + 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"); + */ +} diff --git a/style.astylerc b/style.astylerc new file mode 100644 index 0000000..0569d9a --- /dev/null +++ b/style.astylerc @@ -0,0 +1,13 @@ +style=kr +indent=tab +max-instatement-indent=60 + +convert-tabs + +indent-switches + +pad-oper +unpad-paren +pad-header + +verbose