Hi and thanks for a great tool set.

I've implemented a faster FM demodulator for rlt_fm. Its an instantaneous frequency demodulator, like the already implemented atan method, but it uses some math tricks to get rid of the the actual atan calculation. Feel free to use it if you wish

Best regards
Anders
commit 2e3b03a840e750e29fb842cf2dc131928608b596
Author: Anders Lynge Esbensen <[email protected]>
Date:   Thu Jan 30 10:06:59 2014 +0100

    Added new fast FM demodulator

diff --git a/src/rtl_fm.c b/src/rtl_fm.c
index dffa62a..018d36c 100644
--- a/src/rtl_fm.c
+++ b/src/rtl_fm.c
@@ -128,6 +128,7 @@ struct demod_state
 	int      rate_out2;
 	int      now_r, now_j;
 	int      pre_r, pre_j;
+	int      pre2_r, pre2_j;
 	int      prev_index;
 	int      downsample;    /* min 1, max 256 */
 	int      post_downsample;
@@ -544,6 +545,62 @@ void fm_demod(struct demod_state *fm)
 	fm->result_len = fm->lp_len/2;
 }
 
+/**
+FM demodulator, algorithm
+
+The imput signal is on the form s(t) = a*exp(-i*w*t+p)
+where a is the amplitude
+w if the angular frequncy, (in reality w is a function of t but we will ignore that)
+p if the phase difference
+
+We wish to find w...
+
+First we take the time derivative(s') of s
+s' = -i(w)*a*exp(-i*w*t+p)
+
+then we multiply s' by by conj(s) where conj is complex conjugation
+
+s'*conj(s) = -i*w*a*exp(-i*w*t+p)*a*exp(i*w*t + p)
+           = -i*w*a*a
+
+finally we devide the result by the norm of s squared
+
+s'*conj(s) / |s|^2 = -i*w
+*/
+void fm_demod2(struct demod_state *fm)
+{
+	int i;
+	int r1 = fm->pre_r;
+	int j1 = fm->pre_j;
+	int r2 = fm->pre2_r;
+	int j2 = fm->pre2_j;
+	int16_t *lp = fm->lowpassed;
+
+	for (i = 0; i < (fm->lp_len-1); i += 2) {
+		int r = lp[i];
+		int j = lp[i+1];
+		int dr = (r2 - r); /*The derivative times 2 */
+		int dj = (j2 - j);
+
+		int cj = j1*dr + r1*(-dj); /*imaginary part of ds*conj(s) */
+		fm->result[i/2] = ((double)(cj)/ (double)(r1*r1+j1*j1+1) / (2*3.14159) ) * (1 <<14);
+
+		//long int cj = j1*dr + r1*(-dj); /*imaginary part of ds*conj(s) */
+		//fm->result[i/2] = (cj<<11) / (r1*r1+j1*j1+1);
+		r2=r1;
+		j2=j1;
+		r1=r;
+		j1=j;
+	}
+
+	fm->pre_r = r1;
+	fm->pre_j = j1;
+	fm->pre2_r = r2;
+	fm->pre2_j = j2;
+
+	fm->result_len = fm->lp_len/2;
+}
+
 void am_demod(struct demod_state *fm)
 // todo, fix this extreme laziness
 {
@@ -1127,6 +1184,8 @@ int main(int argc, char **argv)
 		case 'M':
 			if (strcmp("fm",  optarg) == 0) {
 				demod.mode_demod = &fm_demod;}
+			if (strcmp("fm2",  optarg) == 0) {
+				demod.mode_demod = &fm_demod2;}
 			if (strcmp("raw",  optarg) == 0) {
 				demod.mode_demod = &raw_demod;}
 			if (strcmp("am",  optarg) == 0) {

Reply via email to