summaryrefslogtreecommitdiffstats
path: root/fourier.c
blob: 6df913d17140a1df73007d1a657a2fdddda002b4 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#include <complex.h>
#include <math.h>
#include <sys/param.h> // MIN/MAX
#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 }; // XXX refactor this to support roger_drugi decoding
	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