[FFmpeg-devel] [PATCH 6/6] avradio/sdrdemux: slightly different normalization of FM scores

Michael Niedermayer michael at niedermayer.cc
Wed Jul 5 01:23:02 EEST 2023


This way teh scores now resemble station vs noise floor while before
they where "whatever"
This results in somewhat cleaner results from probing as well

Signed-off-by: Michael Niedermayer <michael at niedermayer.cc>
---
 libavradio/sdrdemux.c | 78 ++++++++++++++++++++++++-------------------
 1 file changed, 43 insertions(+), 35 deletions(-)

diff --git a/libavradio/sdrdemux.c b/libavradio/sdrdemux.c
index 598dab8f18..d3f0368d7d 100644
--- a/libavradio/sdrdemux.c
+++ b/libavradio/sdrdemux.c
@@ -72,7 +72,7 @@
 #define AM_MAX23 0.06     //smaller causes failure on synthetic signals
 #define AM_MAX4  0.02
 
-#define FM_THRESHOLD .8 //TODO adjust
+#define FM_THRESHOLD  50 //TODO adjust
 
 //Least squares fit at 1khz points of frequency response shown by Frank McClatchie, FM SYSTEMS, INC. 800-235-6960
 static double emphasis75us(int f)
@@ -707,53 +707,61 @@ static int probe_fm(SDRContext *sdr)
     int bandwidth_f  = 180*1000;
     int bandwidth_p2 =  38*1000; //phase 2 bandwidth
     int half_bw_i = bandwidth_f * (int64_t)sdr->block_size / sdr->sdr_sample_rate;
-    double avg[2] = {0}, tri = 0;
     float last_score[3] = {FLT_MAX, FLT_MAX, FLT_MAX};
     int border_i = (sdr->sdr_sample_rate - sdr->bandwidth) * sdr->block_size / sdr->sdr_sample_rate;
+    double noise_floor = FLT_MAX;
 
     if (2*half_bw_i > 2*sdr->block_size)
         return 0;
 
-    for (i = 0; i<half_bw_i; i++) {
-        avg[0] += sdr->len2block[i];
-        tri    += i*sdr->len2block[i];
-    }
-    for (; i<2*half_bw_i; i++) {
-        avg[1] += sdr->len2block[i];
-        tri    += (2*half_bw_i-i)*sdr->len2block[i];
-    }
+    for (int pass = 0; pass < 2; pass ++) {
+        double avg[2] = {0}, tri = 0;
+        for (i = 0; i<half_bw_i; i++) {
+            avg[0] += sdr->len2block[i];
+            tri    += i*sdr->len2block[i];
+        }
+        for (; i<2*half_bw_i; i++) {
+            avg[1] += sdr->len2block[i];
+            tri    += (2*half_bw_i-i)*sdr->len2block[i];
+        }
 
-    for(i = half_bw_i; i<2*sdr->block_size - half_bw_i; i++) {
-        double b = avg[0] + sdr->len2block[i];
-        avg[0] += sdr->len2block[i] - sdr->len2block[i - half_bw_i];
-        avg[1] -= sdr->len2block[i] - sdr->len2block[i + half_bw_i];
-        b += avg[1];
-        tri += avg[1] - avg[0];
+        for(i = half_bw_i; i<2*sdr->block_size - half_bw_i; i++) {
+            double b = avg[0] + sdr->len2block[i];
+            avg[0] += sdr->len2block[i] - sdr->len2block[i - half_bw_i];
+            avg[1] -= sdr->len2block[i] - sdr->len2block[i + half_bw_i];
+            b += avg[1];
+            tri += avg[1] - avg[0];
 
-        last_score[2] = last_score[1];
-        last_score[1] = last_score[0];
-        last_score[0] = tri / (b * half_bw_i);
-        if (i < border_i || i > 2*sdr->block_size - border_i)
-            continue;
+            if (i < border_i || i > 2*sdr->block_size - border_i)
+                continue;
 
-        if (last_score[1] >= last_score[0] &&
-            last_score[1] > last_score[2] &&
-            last_score[1] > FM_THRESHOLD) {
+            if (pass == 0) {
+                noise_floor = FFMIN(noise_floor, tri);
+            } else {
+                last_score[2] = last_score[1];
+                last_score[1] = last_score[0];
+                last_score[0] = tri / (noise_floor);
 
-            float rmax   = max_in_range(sdr, i-half_bw_i/4, i+half_bw_i/4);
-            int lowcount = countbelow(sdr, i-half_bw_i/4, i+half_bw_i/4, rmax / 100);
-            double peak_i;
+                if (last_score[1] >= last_score[0] &&
+                    last_score[1] > last_score[2] &&
+                    last_score[1] > FM_THRESHOLD) {
 
-            if (lowcount / (half_bw_i*0.5) > 0.99)
-                continue;
+                    float rmax   = max_in_range(sdr, i-half_bw_i/4, i+half_bw_i/4);
+                    int lowcount = countbelow(sdr, i-half_bw_i/4, i+half_bw_i/4, rmax / 100);
+                    double peak_i;
 
-            // as secondary check, we could check that without the center 3 samples we are still having a strong signal FIXME
+                    if (lowcount / (half_bw_i*0.5) > 0.99)
+                        continue;
 
-            peak_i = find_peak(sdr, last_score, 1, 3) + i - 1;
-            if (peak_i < 0)
-                continue;
-            av_assert0(fabs(peak_i-i) < 2);
-            create_candidate_station(sdr, FM, peak_i * 0.5 * sdr->sdr_sample_rate / sdr->block_size + sdr->block_center_freq - sdr->sdr_sample_rate/2, bandwidth_f, bandwidth_p2, last_score[1]);
+                    // as secondary check, we could check that without the center 3 samples we are still having a strong signal FIXME
+
+                    peak_i = find_peak(sdr, last_score, 1, 3) + i - 1;
+                    if (peak_i < 0)
+                        continue;
+                    av_assert0(fabs(peak_i-i) < 2);
+                    create_candidate_station(sdr, FM, peak_i * 0.5 * sdr->sdr_sample_rate / sdr->block_size + sdr->block_center_freq - sdr->sdr_sample_rate/2, bandwidth_f, bandwidth_p2, last_score[1]);
+                }
+            }
         }
     }
 
-- 
2.31.1



More information about the ffmpeg-devel mailing list