NXDN48 Voice Decoding is Good Now

NXDN48 Voice Decoding is Good Now

Just use squelch if using SDR++ or GQRX to feed it. RTL-SDR input mode and NXDN still makes tons of false positives, and doesn't work well at all. May just be a bad signal issue but still think the RTLSDR input uses wrong center freq/tuned freq/"optimizations", need to get back to that some time, maybe also implement squelch settings on rtl_fm mode.

Thanks to LouisErigHerve for his 'Improved NXDN Detection' update on his version, implemented it and works SO MUCH BETTER!

May still disable the if ((state->lastsynctype == 9) || (state->lastsynctype == 17)) condition in dsd_frame_sync.c if I think it leads to more consistent decoding vs false positives. USE SQUELCH!
This commit is contained in:
lwvmobile
2022-01-31 23:54:14 -05:00
committed by GitHub
parent 93ccc668d7
commit 1e95db0977
4 changed files with 134 additions and 36 deletions

View File

@@ -248,7 +248,7 @@ typedef struct
#define INV_DSTAR_HD "313131313111311331313333"
#define DSTAR_SYNC "313131313133131113313111"
#define INV_DSTAR_SYNC "131313131311313331131333"
// original sync numbers which is FSW plus LICH
#define NXDN_MS_DATA_SYNC "313133113131111333"
#define INV_NXDN_MS_DATA_SYNC "131311331313333111"
#define NXDN_MS_VOICE_SYNC "313133113131113133"
@@ -258,6 +258,19 @@ typedef struct
#define INV_NXDN_BS_VOICE_SYNC "131311331313331331"
#define NXDN_BS_VOICE_SYNC "313133113131113113"
//Try using only FSW and no LICH
/*
#define NXDN_MS_DATA_SYNC "3131331131"
#define INV_NXDN_MS_DATA_SYNC "1313113313"
#define NXDN_MS_VOICE_SYNC "313133113131113133"
#define INV_NXDN_MS_VOICE_SYNC "131311331313331311"
#define INV_NXDN_BS_DATA_SYNC "1313113313"
#define NXDN_BS_DATA_SYNC "3131331131"
#define INV_NXDN_BS_VOICE_SYNC "131311331313331331"
#define NXDN_BS_VOICE_SYNC "313133113131113113"
//how do two values equate to 4 symbol types? shouldn't it be -3, -1, 1, 3?
*/
#define DMR_BS_DATA_SYNC "313333111331131131331131"
#define DMR_BS_VOICE_SYNC "131111333113313313113313"
#define DMR_MS_DATA_SYNC "311131133313133331131113"
@@ -327,6 +340,10 @@ void processDSTAR_HD (dsd_opts * opts, dsd_state * state);
short dmr_filter(short sample);
short nxdn_filter(short sample);
//borrow from LEH for testing 'improved NXDN detection'
int strncmperr(const char *s1, const char *s2, size_t size, int MaxErr);
//
#ifdef __cplusplus
extern "C" {
#endif

View File

@@ -31,7 +31,7 @@ printFrameInfo (dsd_opts * opts, dsd_state * state)
level = (int) state->max / 164;
if (opts->verbose > 0)
{
//printf ("inlvl: %2i%% ", level);
printf ("inlvl: %2i%% ", level);
}
if (state->nac != 0)
{
@@ -78,10 +78,10 @@ processFrame (dsd_opts * opts, dsd_state * state)
state->minref = state->min;
}
if ((state->synctype == 8) || (state->synctype == 9))
if ((state->synctype == 8) || (state->synctype == 9)) //lets make this NOT do this...maybe...
{
state->rf_mod = 2;
state->nac = 0;
//state->rf_mod = 2; //wrong type of modulation HERE HERE
//state->nac = 0;
state->lastsrc = 0;
state->lasttg = 0;
if (opts->errorbars == 1)
@@ -89,7 +89,7 @@ processFrame (dsd_opts * opts, dsd_state * state)
if (opts->verbose > 0)
{
level = (int) state->max / 164;
//printf ("inlvl: %2i%% ", level);
printf ("inlvl: %2i%% ", level);
}
}
state->nac = 0;
@@ -103,8 +103,8 @@ processFrame (dsd_opts * opts, dsd_state * state)
}
else if ((state->synctype == 16) || (state->synctype == 17))
{
state->rf_mod = 2;
state->nac = 0;
//state->rf_mod = 2;
//state->nac = 0;
state->lastsrc = 0;
state->lasttg = 0;
if (opts->errorbars == 1)
@@ -112,7 +112,7 @@ processFrame (dsd_opts * opts, dsd_state * state)
if (opts->verbose > 0)
{
level = (int) state->max / 164;
//printf ("inlvl: %2i%% ", level);
printf ("inlvl: %2i%% ", level);
}
}
state->nac = 0;
@@ -134,7 +134,7 @@ processFrame (dsd_opts * opts, dsd_state * state)
if (opts->verbose > 0)
{
level = (int) state->max / 164;
//printf ("inlvl: %2i%% ", level);
printf ("inlvl: %2i%% ", level);
}
}
state->nac = 0;
@@ -156,7 +156,7 @@ processFrame (dsd_opts * opts, dsd_state * state)
if (opts->verbose > 0)
{
level = (int) state->max / 164;
//printf ("inlvl: %2i%% ", level);
printf ("inlvl: %2i%% ", level);
}
}
state->nac = 0;
@@ -179,7 +179,7 @@ processFrame (dsd_opts * opts, dsd_state * state)
if (opts->verbose > 0)
{
level = (int) state->max / 164;
//printf ("inlvl: %2i%% ", level);
printf ("inlvl: %2i%% ", level);
}
}
if ((state->synctype == 11) || (state->synctype == 12))
@@ -233,7 +233,7 @@ processFrame (dsd_opts * opts, dsd_state * state)
if (opts->verbose > 0)
{
level = (int) state->max / 164;
//printf ("inlvl: %2i%% ", level);
printf ("inlvl: %2i%% ", level);
}
}
if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL))

View File

@@ -19,6 +19,39 @@
#include <locale.h>
#include <ncurses.h>
//borrowed from LEH for 'improved NXDN sync detection'
int strncmperr(const char *s1, const char *s2, size_t size, int MaxErr)
{
int Compare = -1;
size_t i = 0;
int err = 0;
int BreakBeforeEnd = 0;
if(s1 && s2)
{
for(i = 0; i < size; i++)
{
if(((s1[i] & 0xFF) != '\0') && ((s2[i] & 0xFF) != '\0'))
{
if((s1[i] & 0xFF) != (s2[i] & 0xFF)) err++;
}
else
{
BreakBeforeEnd = 1;
break;
}
}
if((err <= MaxErr) && (BreakBeforeEnd == 0))
{
Compare = 0;
}
} /* End if(s1 && s2) */
return Compare;
} /* End strncmperr() */
//end LEH
time_t now;
char * getTime(void) //get pretty hh:mm:ss timestamp
{
@@ -64,8 +97,10 @@ printFrameSync (dsd_opts * opts, dsd_state * state, char *frametype, int offset,
//strftime (datestr, 31, "%Y-%m-%d-%H%M%S", &timep);
//printf ("Sync: %s ", frametype);
//printf ("%s %s Sync: %s ", getDate(), getTime(), frametype);
printf ("%s Sync: %s ", getTime(), frametype);
printw("%s Sync: %s ", getTime(), frametype);
printf ("%s ", getTime());
printf ("Sync: %s ", frametype);
//printf("%s Sync: %s ", getTime(), frametype);
//printw("%s Sync: %s ", getTime(), frametype);
}
if (opts->verbose > 2)
{
@@ -562,12 +597,16 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
}
}
if ((opts->frame_nxdn96 == 1) || (opts->frame_nxdn48 == 1))
{
strncpy (synctest18, (synctest_p - 17), 18);
if ((strcmp (synctest18, NXDN_BS_VOICE_SYNC) == 0) || (strcmp (synctest18, NXDN_MS_VOICE_SYNC) == 0))
strncpy (synctest18, (synctest_p - 17), 18); //seems like other sync tests do this as well
//if ((strcmp (synctest18, NXDN_BS_VOICE_SYNC) == 0) || (strcmp (synctest18, NXDN_MS_VOICE_SYNC) == 0)) //or is this the double up test?
//borrowing from LEH here WOW! This works so much better, its not even a joke
if ((strncmperr (synctest18, NXDN_BS_VOICE_SYNC, 18, 1) == 0) || (strncmperr (synctest18, NXDN_MS_VOICE_SYNC, 18, 1) == 0))
{
if ((state->lastsynctype == 8) || (state->lastsynctype == 16))
if ((state->lastsynctype == 8) || (state->lastsynctype == 16)) //is this checking for multiple matches first, could be causing 'skips' in audio decode HERE HERE
//if ( (opts->frame_nxdn96 == 1) ||(opts->frame_nxdn48 == 1)) //kind of hacky, but too lazy to remove brackets and re-indent
{
state->carrier = 1;
state->offset = synctest_pos;
@@ -597,9 +636,11 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
state->lastsynctype = 8;
}
}
else if ((strcmp (synctest18, INV_NXDN_BS_VOICE_SYNC) == 0) || (strcmp (synctest18, INV_NXDN_MS_VOICE_SYNC) == 0))
//else if ((strcmp (synctest18, INV_NXDN_BS_VOICE_SYNC) == 0) || (strcmp (synctest18, INV_NXDN_MS_VOICE_SYNC) == 0))
else if ((strncmperr (synctest18, NXDN_BS_DATA_SYNC, 18, 1) == 0) || (strncmperr (synctest18, NXDN_MS_DATA_SYNC, 18, 1) == 0))
{
if ((state->lastsynctype == 9) || (state->lastsynctype == 17))
//if ( (opts->frame_nxdn96 == 1) ||(opts->frame_nxdn48 == 1)) //again, skip the double up
{
state->carrier = 1;
state->offset = synctest_pos;
@@ -629,9 +670,11 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
state->lastsynctype = 9;
}
}
else if ((strcmp (synctest18, NXDN_BS_DATA_SYNC) == 0) || (strcmp (synctest18, NXDN_MS_DATA_SYNC) == 0))
//else if ((strcmp (synctest18, NXDN_BS_DATA_SYNC) == 0) || (strcmp (synctest18, NXDN_MS_DATA_SYNC) == 0))
else if ((strncmperr (synctest18, NXDN_BS_DATA_SYNC, 18, 1) == 0) || (strncmperr (synctest18, NXDN_MS_DATA_SYNC, 18, 1) == 0))
{
if ((state->lastsynctype == 8) || (state->lastsynctype == 16))
//if ( (opts->frame_nxdn96 == 1) ||(opts->frame_nxdn48 == 1))
{
state->carrier = 1;
state->offset = synctest_pos;
@@ -661,9 +704,11 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
state->lastsynctype = 16;
}
}
else if ((strcmp (synctest18, INV_NXDN_BS_DATA_SYNC) == 0) || (strcmp (synctest18, INV_NXDN_MS_DATA_SYNC) == 0))
//else if ((strcmp (synctest18, INV_NXDN_BS_DATA_SYNC) == 0) || (strcmp (synctest18, INV_NXDN_MS_DATA_SYNC) == 0))
else if ((strncmperr (synctest18, INV_NXDN_BS_DATA_SYNC, 18, 1) == 0) || (strncmperr (synctest18, INV_NXDN_MS_DATA_SYNC, 18, 1) == 0))
{
if ((state->lastsynctype == 9) || (state->lastsynctype == 17))
//if ( (opts->frame_nxdn96 == 1) ||(opts->frame_nxdn48 == 1))
{
state->carrier = 1;
state->offset = synctest_pos;

View File

@@ -25,19 +25,46 @@
#include "dmr_const.h"
#include "provoice_const.h"
#include "git_ver.h"
#include "p25p1_heuristics.h"
#include "pa_devs.h"
//pretty pretty colors
#define KNRM "\x1B[0m"
#define KRED "\x1B[31m"
#define KGRN "\x1B[32m"
#define KYEL "\x1B[33m"
#define KBLU "\x1B[34m"
#define KMAG "\x1B[35m"
#define KCYN "\x1B[36m"
#define KWHT "\x1B[37m"
int pretty_colors()
{
printf("%sred\n", KRED);
printf("%sgreen\n", KGRN);
printf("%syellow\n", KYEL);
printf("%sblue\n", KBLU);
printf("%smagenta\n", KMAG);
printf("%scyan\n", KCYN);
printf("%swhite\n", KWHT);
printf("%snormal\n", KNRM);
return 0;
}
//#include "p25p1_heuristics.h" //accidentally had this disabled when getting good NXDN, so if it breaks again, try disabling this
//#include "pa_devs.h" //accidentally had this disabled when getting good NXDN, so if it breaks again, try disabling this
short int butt = 1;
#include <locale.h>
#include <ncurses.h>
char * FM_banner[9] = {
" CTRL + C twice to exit",
"██████╗ ██████╗██████╗    ███████╗███╗ ███╗███████╗",
"██╔══██╗██╔════╝██╔══██╗   ██╔════╝████╗ ████║██╔════╝",
"██║ ██║╚█████╗ ██║ ██║   █████╗ ██╔████╔██║█████╗ ",
"██║ ██║ ╚═══██╗██║ ██║   ██╔══╝ ██║╚██╔╝██║██╔══╝ ",
"██████╔╝██████╔╝██████╔╝   ██║ ██║ ╚═╝ ██║███████╗",
"╚═════╝ ╚═════╝ ╚═════╝    ╚═╝ ╚═╝ ╚═╝╚══════╝",
" ██████╗ ██████╗██████╗    ███████╗███╗ ███╗███████╗",
" ██╔══██╗██╔════╝██╔══██╗   ██╔════╝████╗ ████║██╔════╝",
" ██║ ██║╚█████╗ ██║ ██║   █████╗ ██╔████╔██║█████╗ ",
" ██║ ██║ ╚═══██╗██║ ██║   ██╔══╝ ██║╚██╔╝██║██╔══╝ ",
" ██████╔╝██████╔╝██████╔╝   ██║ ██║ ╚═╝ ██║███████╗",
" ╚═════╝ ╚═════╝ ╚═════╝    ╚═╝ ╚═╝ ╚═╝╚══════╝",
};
@@ -159,7 +186,7 @@ initOpts (dsd_opts * opts)
opts->use_cosine_filter = 1;
opts->unmute_encrypted_p25 = 0;
opts->rtl_dev_index = 0; //choose which device we want by index number
opts->rtl_gain_value = 0; //set actual gain and not automatic gain
opts->rtl_gain_value = 0; //set actual gain and not automatic gain
}
void
@@ -333,7 +360,7 @@ usage ()
printf (" -M <num> Min/Max buffer size for QPSK decision point tracking\n");
printf (" (default=15)\n");
printf ("\n");
printf ("Report bugs to: https://github.com/szechyjs/dsd/issues\n");
printf ("Report bugs to: Nobody Mwuhaha \n");
exit (0);
}
@@ -556,8 +583,10 @@ main (int argc, char **argv)
for (short int i = 0; i < 7; i++) {
printf("%s \n", FM_banner[i]);
printf("%s%s \n", FM_banner[i], KCYN);
}
printf("%s", KNRM); //change back to normal
//pretty_colors();
//printf ("Digital Speech Decoder 1.7.0-dev (build:%s)\n", GIT_TAG);
printf ("Digital Speech Decoder: Florida Man Edition\n");
printf ("mbelib version %s\n", versionstr);
@@ -632,12 +661,12 @@ main (int argc, char **argv)
case 'G': //Set rtl device gain
sscanf (optarg, "%d", &opts.rtl_gain_value); //multiple value by ten to make it consitent with the way rtl_fm really works
//opts->audio_in_type = 3; //set to use RTL this way and maybe ditch the other shitty way
//opts->audio_in_type = 3;
break;
case 'D': //Set rtl device index number
sscanf (optarg, "%d", &opts.rtl_dev_index);
//opts->audio_in_type = 3; //set to use RTL this way and maybe ditch the other shitty way
//opts->audio_in_type = 3;
break;
@@ -784,10 +813,13 @@ main (int argc, char **argv)
state.symbolCenter = 10;
opts.mod_c4fm = 0;
opts.mod_qpsk = 0;
opts.mod_gfsk = 1;
state.rf_mod = 2;
opts.mod_gfsk = 1; //was 1 with others on zero
state.rf_mod = 2; //was 2
//opts.symboltiming = 2400; //NXDN48 uses 2400 symbol rate
printf ("Setting symbol rate to 2400 / second\n");
printf ("Enabling only GFSK modulation optimizations.\n");
printf ("Why are we using GFSK modulations? Isn't NXDN FSK4/C4FM??.\n");
printf ("Well, it works now, so probably just the way DSD interprets symbols.\n");
printf ("Decoding only NXDN 4800 baud frames.\n");
}
else if (optarg[0] == 'n')
@@ -803,7 +835,11 @@ main (int argc, char **argv)
opts.mod_qpsk = 0;
opts.mod_gfsk = 1;
state.rf_mod = 2;
//printf ("Enabling only C4FM/FSK4 modulation optimizations. I really need a new FSK4 modulator\n");
printf ("Enabling only GFSK modulation optimizations.\n");
printf ("Why are we using GFSK modulations? Isn't NXDN FSK4/C4FM??.\n");
printf ("Well, it works now, so probably just the way DSD interprets symbols.\n");
//opts.symboltiming = 4800; //NXDN96 uses 4800 symbol rate
printf ("Decoding only NXDN 9600 baud frames.\n");
}
else if (optarg[0] == 'r')