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