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) {