diff options
author | Kyle Keen <keenerd@gmail.com> | 2012-05-29 13:02:36 -0400 |
---|---|---|
committer | Steve Markgraf <steve@steve-m.de> | 2012-07-17 20:42:03 +0200 |
commit | 37f5559d1c21421241a9b1d791e297edfd462d36 (patch) | |
tree | 7ad6e5fb76a62df8c33db469e528105cc08ca175 /src | |
parent | fc390b32247e954cedcb6ff1fac580e768016014 (diff) |
rtl_fm: satisfactory squelch
Signed-off-by: Steve Markgraf <steve@steve-m.de>
Diffstat (limited to 'src')
-rw-r--r-- | src/rtl_fm.c | 54 |
1 files changed, 44 insertions, 10 deletions
diff --git a/src/rtl_fm.c b/src/rtl_fm.c index 5b6e9e4..1110cb1 100644 --- a/src/rtl_fm.c +++ b/src/rtl_fm.c @@ -26,8 +26,7 @@ * replace atan2 with a fast approximation * in-place array operations * wide band support - * squelch - * better threading + * refactor to look like rtl_tcp */ #include <errno.h> @@ -63,6 +62,7 @@ struct fm_state int prev_index; int downsample; /* min 4, max 256 */ int output_scale; + int squelch_level; int signal[2048]; /* 16 bit signed i/q pairs */ int16_t signal2[2048]; /* signal has lowpass, signal2 has demod */ int signal_len; @@ -82,6 +82,7 @@ void usage(void) "\t[-s samplerate (default: 24000 Hz)]\n" "\t[-d device_index (default: 0)]\n" "\t[-g tuner_gain (default: -1dB)]\n" + "\t[-l squelch_level (default: 150)]\n" "\tfilename (a '-' dumps samples to stdout)\n\n" "Produces signed 16 bit ints, use sox to hear them.\n" "\trtl_fm ... | play -t raw -r 24k -e signed-integer -b 16 -c 1 -\n\n"); @@ -116,9 +117,8 @@ void rotate_90(unsigned char *buf, uint32_t len) { uint32_t i; unsigned char tmp; - for (i=0; i<len; i+=8) - { - /* uint_8 negation = 255 - x */ + for (i=0; i<len; i+=8) { + /* uint8_t negation = 255 - x */ tmp = 255 - buf[i+3]; buf[i+3] = buf[i+2]; buf[i+2] = tmp; @@ -168,9 +168,6 @@ int polar_discriminant(int ar, int aj, int br, int bj) int cr, cj; double angle; multiply(ar, aj, br, -bj, &cr, &cj); - /* fake squelch */ - //if (abs(cr) + abs(cj) < 50000) - // {return 0;} angle = atan2((double)cj, (double)cr); return (int)(angle / 3.14159 * (1<<14)); } @@ -190,16 +187,49 @@ void fm_demod(struct fm_state *fm) fm->pre_j = fm->signal[fm->signal_len - 1]; } +int mad(int *samples, int len, int step) +/* mean average deviation */ +{ + int i=0, sum=0, ave=0; + for (i=0; i<len; i+=step) { + sum += samples[i]; + } + ave = sum / (len * step); + sum = 0; + for (i=0; i<len; i+=step) { + sum += abs(samples[i] - ave); + } + return sum / (len * step); +} + +void post_squelch(struct fm_state *fm) +{ + int i, i2, dev_r, dev_j, len, sq_l; + /* only for small samples, big samples need chunk processing */ + len = fm->signal_len; + sq_l = fm->squelch_level; + dev_r = mad(&(fm->signal[0]), len, 2); + dev_j = mad(&(fm->signal[1]), len, 2); + if ((dev_r > sq_l) || (dev_j > sq_l)) { + return; + } + /* weak signal, kill it entirely */ + for (i=0; i<len; i++) { + fm->signal2[i/2] = 0; + } +} + static void rtlsdr_callback(unsigned char *buf, uint32_t len, void *ctx) { struct fm_state *fm2; if (!ctx) { return; } - fm2 = (struct fm_struct*)(ctx); // bad conversion? + fm2 = (struct fm_struct*)(ctx); // warning? rotate_90(buf, len); low_pass(fm2, buf, len); fm_demod(fm2); + post_squelch(fm2); /* ignore under runs for now */ fwrite(fm2->signal2, 2, fm2->signal_len/2, fm2->file); } @@ -246,8 +276,9 @@ int main(int argc, char **argv) uint32_t out_block_size = DEFAULT_BUF_LENGTH; int device_count; char vendor[256], product[256], serial[256]; + fm.squelch_level = 150; #ifndef _WIN32 - while ((opt = getopt(argc, argv, "d:f:g:s:b:S::")) != -1) { + while ((opt = getopt(argc, argv, "d:f:g:s:b:l:S::")) != -1) { switch (opt) { case 'd': dev_index = atoi(optarg); @@ -258,6 +289,9 @@ int main(int argc, char **argv) case 'g': gain = (int)(atof(optarg) * 10); break; + case 'l': + fm.squelch_level = (int)atof(optarg); + break; case 's': samp_rate = (uint32_t)atof(optarg); break; |