diff --git a/src/rtl_fm.c b/src/rtl_fm.c index 0d23fdc..1acdfde 100644 --- a/src/rtl_fm.c +++ b/src/rtl_fm.c @@ -32,13 +32,15 @@ * scale squelch to other input parameters * test all the demodulations * pad output on hop - * nearest gain approx * frequency ranges could be stored better * scaled AM demod amplification * auto-hop after time limit * peak detector to tune onto stronger signals * use slower sample rates (250k) for nbfm * offset tuning + * fifo for active hop frequency + * clips + * real squelch math */ #include @@ -150,10 +152,16 @@ void usage(void) "\t[-U enables USB mode (default: off)]\n" //"\t[-D enables DSB mode (default: off)]\n" "\t[-R enables raw mode (default: off, 2x16 bit output)]\n" - "\t[-F enables high quality FIR (default: off/square)]\n" + "\t[-F enables Hamming FIR (default: off/square)]\n" "\t[-D enables de-emphasis (default: off)]\n" "\t[-C enables DC blocking of output (default: off)]\n" - "\t[-A std/fast/lut choose atan math (default: std)]\n\n" + "\t[-A std/fast/lut choose atan math (default: std)]\n" + //"\t[-C clip_path (default: off)\n" + //"\t (create time stamped raw clips, requires squelch)\n" + //"\t (path must have '\%s' and will expand to date_time_freq)\n" + //"\t[-H hop_fifo (default: off)\n" + //"\t (fifo will contain the active frequency)\n" + "\n" "Produces signed 16 bit ints, use Sox or aplay to hear them.\n" "\trtl_fm ... - | play -t raw -r 24k -es -b 16 -c 1 -V1 -\n" "\t | aplay -r 24k -f S16_LE -t raw -c 1\n" @@ -230,17 +238,18 @@ void low_pass(struct fm_state *fm, unsigned char *buf, uint32_t len) } void build_fir(struct fm_state *fm) -/* for now, a simple triangle - * fancy FIRs are equally expensive, so use one */ +/* hamming */ /* point = sum(sample[i] * fir[i] * fir_len / fir_sum) */ { + double a, b, w, N1; int i, len; len = fm->downsample; - for(i = 0; i < (len/2); i++) { - fm->fir[i] = i; - } - for(i = len-1; i >= (len/2); i--) { - fm->fir[i] = len - i; + a = 25.0/46.0; + b = 21.0/46.0; + N1 = (double)(len-1); + for(i = 0; i < len; i++) { + w = a - b*cos(2*i*M_PI/N1); + fm->fir[i] = (int)(w * 255); } fm->fir_sum = 0; for(i = 0; i < len; i++) { @@ -255,13 +264,17 @@ void low_pass_fir(struct fm_state *fm, unsigned char *buf, uint32_t len) int i=0, i2=0, i3=0; while (i < (int)len) { i3 = fm->prev_index; - fm->now_r += ((int)buf[i] - 127) * fm->fir[i3] * fm->downsample / fm->fir_sum; - fm->now_j += ((int)buf[i+1] - 127) * fm->fir[i3] * fm->downsample / fm->fir_sum; + fm->now_r += ((int)buf[i] - 127) * fm->fir[i3]; + fm->now_j += ((int)buf[i+1] - 127) * fm->fir[i3]; i += 2; fm->prev_index++; if (fm->prev_index < fm->downsample) { continue; } + fm->now_r *= fm->downsample; + fm->now_j *= fm->downsample; + fm->now_r /= fm->fir_sum; + fm->now_j /= fm->fir_sum; fm->signal[i2] = fm->now_r; //* fm->output_scale; fm->signal[i2+1] = fm->now_j; //* fm->output_scale; fm->prev_index = 0; @@ -730,6 +743,28 @@ void frequency_range(struct fm_state *fm, char *arg) step[-1] = ':'; } +int nearest_gain(int target_gain) +{ + int i, err1, err2, count, close_gain; + int* gains; + count = rtlsdr_get_tuner_gains(dev, NULL); + if (count <= 0) { + return 0; + } + gains = malloc(sizeof(int) * count); + count = rtlsdr_get_tuner_gains(dev, gains); + close_gain = gains[0]; + for (i=0; ifreqs[0] = 100000000; @@ -952,6 +987,7 @@ int main(int argc, char **argv) r = rtlsdr_set_tuner_gain_mode(dev, 0); } else { r = rtlsdr_set_tuner_gain_mode(dev, 1); + gain = nearest_gain(gain); r = rtlsdr_set_tuner_gain(dev, gain); } if (r != 0) {