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.
Thanks to LouisErigHerve for his 'Improved NXDN Detection' update on his version, implemented it and works SO MUCH BETTER!
This commit is contained in:
lwvmobile 2022-01-31 23:26:10 -05:00 committed by GitHub
parent 93ccc668d7
commit fee56ecf9c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 135 additions and 45 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"
@ -257,6 +257,17 @@ typedef struct
#define NXDN_BS_DATA_SYNC "313133113131111313"
#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"
@ -327,6 +338,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 ((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 ((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 ((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,10 @@ 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
printf ("Setting symbol rate to 2400 / second\n");
printf ("Enabling only GFSK modulation optimizations.\n");
//printf ("Enabling only GFSK modulation optimizations.\n");
printf ("Decoding only NXDN 4800 baud frames.\n");
}
else if (optarg[0] == 'n')
@ -799,11 +828,12 @@ main (int argc, char **argv)
opts.frame_nxdn96 = 1;
opts.frame_dmr = 0;
opts.frame_provoice = 0;
opts.mod_c4fm = 0;
opts.mod_qpsk = 0;
opts.mod_gfsk = 1;
state.rf_mod = 2;
printf ("Enabling only GFSK modulation optimizations.\n");
//opts.mod_c4fm = 0;
//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");
opts.symboltiming = 2400; //no idea if this will do anything
printf ("Decoding only NXDN 9600 baud frames.\n");
}
else if (optarg[0] == 'r')