Skip to content

Commit e23b92c

Browse files
committed
rtl_fm: in-place demodulators
1 parent ebb5f2a commit e23b92c

File tree

1 file changed

+47
-55
lines changed

1 file changed

+47
-55
lines changed

src/rtl_fm.c

Lines changed: 47 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ struct dongle_state
104104
uint32_t freq;
105105
uint32_t rate;
106106
int gain;
107-
uint16_t buf16[MAXIMUM_BUF_LENGTH];
107+
int16_t buf16[MAXIMUM_BUF_LENGTH];
108108
uint32_t buf_len;
109109
int ppm_error;
110110
int offset_tuning;
@@ -132,10 +132,8 @@ struct demod_state
132132
int lp_len;
133133
int16_t lp_i_hist[10][6];
134134
int16_t lp_q_hist[10][6];
135-
int16_t result[MAXIMUM_BUF_LENGTH];
136135
int16_t droop_i_hist[9];
137136
int16_t droop_q_hist[9];
138-
int result_len;
139137
int rate_in;
140138
int rate_out;
141139
int rate_out2;
@@ -364,22 +362,23 @@ void low_pass_real(struct demod_state *s)
364362
/* simple square window FIR */
365363
// add support for upsampling?
366364
{
365+
int16_t *lp = s->lowpassed;
367366
int i=0, i2=0;
368367
int fast = (int)s->rate_out;
369368
int slow = s->rate_out2;
370-
while (i < s->result_len) {
371-
s->now_lpr += s->result[i];
369+
while (i < s->lp_len) {
370+
s->now_lpr += lp[i];
372371
i++;
373372
s->prev_lpr_index += slow;
374373
if (s->prev_lpr_index < fast) {
375374
continue;
376375
}
377-
s->result[i2] = (int16_t)(s->now_lpr / (fast/slow));
376+
lp[i2] = (int16_t)(s->now_lpr / (fast/slow));
378377
s->prev_lpr_index -= fast;
379378
s->now_lpr = 0;
380379
i2 += 1;
381380
}
382-
s->result_len = i2;
381+
s->lp_len = i2;
383382
}
384383

385384
void fifth_order(int16_t *data, int length, int16_t *hist)
@@ -557,115 +556,107 @@ int esbensen(int ar, int aj, int br, int bj)
557556

558557
void fm_demod(struct demod_state *fm)
559558
{
560-
int i, pcm;
559+
int i, pcm = 0;
561560
int16_t *lp = fm->lowpassed;
562-
pcm = polar_discriminant(lp[0], lp[1],
563-
fm->pre_r, fm->pre_j);
564-
fm->result[0] = (int16_t)pcm;
565-
for (i = 2; i < (fm->lp_len-1); i += 2) {
561+
int16_t pr = fm->pre_r;
562+
int16_t pj = fm->pre_j;
563+
for (i = 0; i < (fm->lp_len-1); i += 2) {
566564
switch (fm->custom_atan) {
567565
case 0:
568-
pcm = polar_discriminant(lp[i], lp[i+1],
569-
lp[i-2], lp[i-1]);
566+
pcm = polar_discriminant(lp[i], lp[i+1], pr, pj);
570567
break;
571568
case 1:
572-
pcm = polar_disc_fast(lp[i], lp[i+1],
573-
lp[i-2], lp[i-1]);
569+
pcm = polar_disc_fast(lp[i], lp[i+1], pr, pj);
574570
break;
575571
case 2:
576-
pcm = polar_disc_lut(lp[i], lp[i+1],
577-
lp[i-2], lp[i-1]);
572+
pcm = polar_disc_lut(lp[i], lp[i+1], pr, pj);
578573
break;
579574
case 3:
580-
pcm = esbensen(lp[i], lp[i+1],
581-
lp[i-2], lp[i-1]);
575+
pcm = esbensen(lp[i], lp[i+1], pr, pj);
582576
break;
583577
}
584-
fm->result[i/2] = (int16_t)pcm;
578+
pr = lp[i];
579+
pj = lp[i+1];
580+
fm->lowpassed[i/2] = (int16_t)pcm;
585581
}
586-
fm->pre_r = lp[fm->lp_len - 2];
587-
fm->pre_j = lp[fm->lp_len - 1];
588-
fm->result_len = fm->lp_len/2;
582+
fm->pre_r = pr;
583+
fm->pre_j = pj;
584+
fm->lp_len = fm->lp_len / 2;
589585
}
590586

591587
void am_demod(struct demod_state *fm)
592588
// todo, fix this extreme laziness
593589
{
594590
int i, pcm;
595591
int16_t *lp = fm->lowpassed;
596-
int16_t *r = fm->result;
597592
for (i = 0; i < fm->lp_len; i += 2) {
598593
// hypot uses floats but won't overflow
599594
//r[i/2] = (int16_t)hypot(lp[i], lp[i+1]);
600595
pcm = lp[i] * lp[i];
601596
pcm += lp[i+1] * lp[i+1];
602-
r[i/2] = (int16_t)sqrt(pcm) * fm->output_scale;
597+
lp[i/2] = (int16_t)sqrt(pcm) * fm->output_scale;
603598
}
604-
fm->result_len = fm->lp_len/2;
599+
fm->lp_len = fm->lp_len / 2;
605600
// lowpass? (3khz) highpass? (dc)
606601
}
607602

608603
void usb_demod(struct demod_state *fm)
609604
{
610605
int i, pcm;
611606
int16_t *lp = fm->lowpassed;
612-
int16_t *r = fm->result;
613607
for (i = 0; i < fm->lp_len; i += 2) {
614608
pcm = lp[i] + lp[i+1];
615-
r[i/2] = (int16_t)pcm * fm->output_scale;
609+
lp[i/2] = (int16_t)pcm * fm->output_scale;
616610
}
617-
fm->result_len = fm->lp_len/2;
611+
fm->lp_len = fm->lp_len / 2;
618612
}
619613

620614
void lsb_demod(struct demod_state *fm)
621615
{
622616
int i, pcm;
623617
int16_t *lp = fm->lowpassed;
624-
int16_t *r = fm->result;
625618
for (i = 0; i < fm->lp_len; i += 2) {
626619
pcm = lp[i] - lp[i+1];
627-
r[i/2] = (int16_t)pcm * fm->output_scale;
620+
lp[i/2] = (int16_t)pcm * fm->output_scale;
628621
}
629-
fm->result_len = fm->lp_len/2;
622+
fm->lp_len = fm->lp_len / 2;
630623
}
631624

632625
void raw_demod(struct demod_state *fm)
633626
{
634-
int i;
635-
for (i = 0; i < fm->lp_len; i++) {
636-
fm->result[i] = (int16_t)fm->lowpassed[i];
637-
}
638-
fm->result_len = fm->lp_len;
627+
return;
639628
}
640629

641630
void deemph_filter(struct demod_state *fm)
642631
{
643-
static int avg; // cheating...
632+
static int avg; // cheating, not threadsafe
644633
int i, d;
634+
int16_t *lp = fm->lowpassed;
645635
// de-emph IIR
646636
// avg = avg * (1 - alpha) + sample * alpha;
647-
for (i = 0; i < fm->result_len; i++) {
648-
d = fm->result[i] - avg;
637+
for (i = 0; i < fm->lp_len; i++) {
638+
d = lp[i] - avg;
649639
if (d > 0) {
650640
avg += (d + fm->deemph_a/2) / fm->deemph_a;
651641
} else {
652642
avg += (d - fm->deemph_a/2) / fm->deemph_a;
653643
}
654-
fm->result[i] = (int16_t)avg;
644+
lp[i] = (int16_t)avg;
655645
}
656646
}
657647

658648
void dc_block_filter(struct demod_state *fm)
659649
{
660650
int i, avg;
661651
int64_t sum = 0;
662-
for (i=0; i < fm->result_len; i++) {
663-
sum += fm->result[i];
652+
int16_t *lp = fm->lowpassed;
653+
for (i=0; i < fm->lp_len; i++) {
654+
sum += lp[i];
664655
}
665-
avg = sum / fm->result_len;
656+
avg = sum / fm->lp_len;
666657
avg = (avg + fm->dc_avg * 9) / 10;
667-
for (i=0; i < fm->result_len; i++) {
668-
fm->result[i] -= avg;
658+
for (i=0; i < fm->lp_len; i++) {
659+
lp[i] -= avg;
669660
}
670661
fm->dc_avg = avg;
671662
}
@@ -797,9 +788,10 @@ void software_agc(struct demod_state *d)
797788
int i = 0;
798789
int output;
799790
struct agc_state *agc = d->agc;
791+
int16_t *lp = d->lowpassed;
800792

801-
for (i=0; i < d->result_len; i++) {
802-
output = (int)((int64_t)d->result[i] * agc->gain_num / agc->gain_den);
793+
for (i=0; i < d->lp_len; i++) {
794+
output = (int)((int64_t)lp[i] * agc->gain_num / agc->gain_den);
803795

804796
if (abs(output) < agc->peak_target) {
805797
agc->gain_num += agc->decay_step;
@@ -813,7 +805,7 @@ void software_agc(struct demod_state *d)
813805
agc->gain_num = agc->gain_max;}
814806

815807
agc->gain_int = (int)(agc->gain_num / agc->gain_den);
816-
d->result[i] = output;
808+
lp[i] = output;
817809
}
818810
}
819811

@@ -860,21 +852,21 @@ void full_demod(struct demod_state *d)
860852
if (d->squelch_level && d->squelch_hits > d->conseq_squelch) {
861853
d->agc->gain_num = d->agc->gain_den;
862854
}
863-
d->mode_demod(d); /* lowpassed -> result */
855+
d->mode_demod(d); /* lowpassed -> lowpassed */
864856
if (d->mode_demod == &raw_demod) {
865857
return;
866858
}
867859
/* todo, fm noise squelch */
868860
// use nicer filter here too?
869861
if (d->post_downsample > 1) {
870-
d->result_len = low_pass_simple(d->result, d->result_len, d->post_downsample);}
862+
d->lp_len = low_pass_simple(d->lowpassed, d->lp_len, d->post_downsample);}
871863
if (d->deemph) {
872864
deemph_filter(d);}
873865
if (d->dc_block) {
874866
dc_block_filter(d);}
875867
if (d->rate_out2 > 0) {
876868
low_pass_real(d);
877-
//arbitrary_resample(d->result, d->result, d->result_len, d->result_len * d->rate_out2 / d->rate_out);
869+
//arbitrary_resample(d->lowpassed, d->lowpassed, d->lp_len, d->lp_len * d->rate_out2 / d->rate_out);
878870
}
879871
}
880872

@@ -929,8 +921,8 @@ static void *demod_thread_fn(void *arg)
929921
continue;
930922
}
931923
pthread_rwlock_wrlock(&o->rw);
932-
memcpy(o->result, d->result, 2*d->result_len);
933-
o->result_len = d->result_len;
924+
memcpy(o->result, d->lowpassed, 2*d->lp_len);
925+
o->result_len = d->lp_len;
934926
pthread_rwlock_unlock(&o->rw);
935927
safe_cond_signal(&o->ready, &o->ready_m);
936928
}

0 commit comments

Comments
 (0)