summaryrefslogtreecommitdiffstats
path: root/fourier.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--fourier.c99
1 files changed, 99 insertions, 0 deletions
diff --git a/fourier.c b/fourier.c
new file mode 100644
index 0000000..def5c13
--- /dev/null
+++ b/fourier.c
@@ -0,0 +1,99 @@
+#include <complex.h>
+#include <math.h>
+#include <sys/param.h> // MIN/MAX
+#include <stdio.h> // debug only
+#include "frekvence.h"
+#define SAMPLES 256
+#define FREKVENC (sizeof frekvence/sizeof frekvence[0])
+struct fourier {
+ void (* callback)(struct fourier *);
+ enum ton trenutni;
+ enum ton zadnji_klican;
+ unsigned count;
+ double samples[SAMPLES];
+ unsigned sample;
+ complex sums[FREKVENC];
+ double rate;
+ unsigned minimal_duration;
+#ifdef USERDATA
+ USERDATA
+#else
+ void * userdata;
+#endif
+};
+void add_sample (struct fourier * f, double received) {
+ for (unsigned frekvenca = 0; frekvenca < FREKVENC; frekvenca++) {
+ f->sums[frekvenca] += received*cpow(M_E, -2*M_PI*I*frekvence[frekvenca]*f->sample/f->rate);
+ f->sums[frekvenca] -= f->samples[f->sample % SAMPLES]*cpow(M_E, -2*M_PI*I*frekvence[frekvenca]*(f->sample-SAMPLES)/f->rate);
+ }
+ int najv[3] = { 0 };
+ double val[3] = { 0 };
+ for (unsigned i = 0; i < FREKVENC; i++)
+ for (int j = 0; j < 3; j++) {
+ double iabs = cabs(f->sums[i]);
+ if (iabs > val[j]) {
+ for (int k = 2; k > j; k--) {
+ najv[k] = najv[k-1];
+ val[k] = val[k-1];
+ }
+ najv[j] = i;
+ val[j] = iabs;
+ break;
+ }
+ }
+ enum ton trenutni = ni;
+ if (val[1] > val[0]/3 && val[2] < val[1]/3) {
+ int večja = MAX(frekvence[najv[0]], frekvence[najv[1]]);
+ int manjša = MIN(frekvence[najv[0]], frekvence[najv[1]]);
+ enum ton znaki[4][4] =
+ {{dtmf_1, dtmf_2, dtmf_3, dtmf_a},
+ {dtmf_4, dtmf_5, dtmf_6, dtmf_b},
+ {dtmf_7, dtmf_8, dtmf_9, dtmf_c},
+ {dtmf_zvezdica, dtmf_0, dtmf_lojtra, dtmf_d}};
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wpedantic"
+ int getidx (int freq) {
+ for (int i = 0; i < 8; i++)
+ if (freq == frekvence[i])
+ return i%4;
+ return -1;
+ }
+#pragma GCC diagnostic pop
+ if (getidx(manjša) == -1 || getidx(večja) == -1)
+ trenutni = ni;
+ else
+ trenutni = znaki[getidx(manjša)][getidx(večja)];
+ }
+ if (val[1] < val[0]/3 && najv[0] > 7)
+ trenutni = band+najv[0]-band_tipka;
+ if (trenutni == f->trenutni) {
+ if (f->count++ == f->minimal_duration && f->zadnji_klican != f->trenutni) {
+ f->zadnji_klican = f->trenutni;
+ f->callback(f);
+ }
+ } else {
+ f->count = 0;
+ f->trenutni = trenutni;
+ }
+ f->samples[f->sample++ % SAMPLES] = received;
+}
+#if __INCLUDE_LEVEL__ == 0
+#include <stdio.h>
+#include <string.h>
+void callback (struct fourier * f) {
+ printf("%s\n", toni[f->trenutni]);
+}
+int main (void) {
+ struct fourier f;
+ memset(&f, 0, sizeof f);
+ f.callback = callback;
+ f.minimal_duration = SAMPLES;
+ f.rate = 8000;
+ int received = 0;
+ while ((received = getchar()) != EOF) {
+ unsigned char intermed = received;
+ char recvd = *(char *) &intermed;
+ add_sample(&f, recvd);
+ }
+}
+#endif