commit 906187fe7adc0c8d8b4da51f2c6e4b360cf04f55
Author: Ondřej Hruška <ondra@ondrovo.com>
Date:   Thu Dec 24 14:43:07 2015 +0100

    initial

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 0000000..a371e96
Binary files /dev/null and b/a.out differ
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