From 9232d66fcbdf1809b969fa18ea9bcab6c6b71c99 Mon Sep 17 00:00:00 2001 From: xdab <47300315+xdab@users.noreply.github.com> Date: Mon, 21 Sep 2026 20:48:33 +0200 Subject: [PATCH] Frame Sync: Replace per-symbol full sort with single-pass top-5 selection The frame sync hunt loop sorted the entire symbol amplitude window (lbuf2, t_max entries) with qsort on every iteration only to read three ranked values off each end. Replace the copy + qsort with a single O(n) pass maintaining the five smallest and five largest values in two fixed 5-slot arrays, reading the exact same ranks. Rank equivalence: lmn[] ascending = sorted[0..], lmx[] descending = sorted[..t_max-1], so both the short (t_max < 13) and long rank formulas map 1:1. The now-unused lbuf2 scratch buffer is removed. Decode output verified byte-identical (timestamps stripped) against DMR, dPMR, D-Star and YSF sample captures, including runs with a 10 second no-carrier lead-in. --- src/dsd_frame_sync.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/src/dsd_frame_sync.c b/src/dsd_frame_sync.c index 1fec52a..cec602b 100644 --- a/src/dsd_frame_sync.c +++ b/src/dsd_frame_sync.c @@ -16,6 +16,7 @@ */ #include "dsd.h" +#include #include void @@ -197,11 +198,10 @@ getFrameSync (dsd_opts * opts, dsd_state * state) } else t_max = 24; //24 for everything else - int lbuf[48], lbuf2[48]; //if we use t_max in these arrays, and t >= t_max in condition below, then it can overflow those checks in there if t exceeds t_max + int lbuf[48]; //if we use t_max in these arrays, and t >= t_max in condition below, then it can overflow those checks in there if t exceeds t_max int lsum; //init the lbuf memset (lbuf, 0, sizeof(lbuf)); - memset (lbuf2, 0, sizeof(lbuf2)); // detect frame sync t = 0; @@ -374,23 +374,37 @@ getFrameSync (dsd_opts * opts, dsd_state * state) *synctest_p = dibit; if (t >= t_max) //works excelent now with short sync patterns, and no issues with large ones! { + int lmn[5] = {INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX}; + int lmx[5] = {INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN}; + int j, x; for (i = 0; i < t_max; i++) //24 { - lbuf2[i] = lbuf[i]; + x = lbuf[i]; + if (x < lmn[4]) + { + for (j = 4; j > 0 && x < lmn[j - 1]; j--) + lmn[j] = lmn[j - 1]; + lmn[j] = x; + } + if (x > lmx[4]) + { + for (j = 4; j > 0 && x > lmx[j - 1]; j--) + lmx[j] = lmx[j - 1]; + lmx[j] = x; + } } - qsort (lbuf2, t_max, sizeof (int), comp); //on shorter sync patterns, we need to look at the edges since we don't have many to pull from if (t_max < 13) { - lmin = (lbuf2[0] + lbuf2[1] + lbuf2[2]) / 3; - lmax = (lbuf2[t_max - 3] + lbuf2[t_max - 2] + lbuf2[t_max - 1]) / 3; + lmin = (lmn[0] + lmn[1] + lmn[2]) / 3; + lmax = (lmx[2] + lmx[1] + lmx[0]) / 3; } //on longer sync patterns, we can get more towards the middle and eliminate outlier values else { - lmin = (lbuf2[2] + lbuf2[3] + lbuf2[4]) / 3; - lmax = (lbuf2[t_max - 5] + lbuf2[t_max - 4] + lbuf2[t_max - 3]) / 3; + lmin = (lmn[2] + lmn[3] + lmn[4]) / 3; + lmax = (lmx[4] + lmx[3] + lmx[2]) / 3; } if (state->rf_mod == 1)