minimodem: --limit (2.3) sets fsk_confidence_search_limit

Significant performance enhancements from fsk_confidence_search_limit:
runs far fewer FFT's when --limit (default 2.3) is less than INFINITY.
This commit is contained in:
Kamal Mostafa 2012-08-18 21:24:01 -07:00
parent e1b055cf4f
commit f81f069d95
4 changed files with 77 additions and 16 deletions

View File

@ -409,8 +409,10 @@ fsk_frame_analyze( fsk_plan *fskp, float *samples, float samples_per_bit,
/* returns confidence value [0.0 to 1.0] */
float
fsk_find_frame( fsk_plan *fskp, float *samples, unsigned int frame_nsamples,
unsigned int try_first_sample,
unsigned int try_max_nsamples,
unsigned int try_step_nsamples,
float try_confidence_search_limit,
unsigned int *bits_outp,
unsigned int *frame_start_outp
)
@ -419,25 +421,34 @@ fsk_find_frame( fsk_plan *fskp, float *samples, unsigned int frame_nsamples,
// try_step_nsamples = 1; // pedantic TEST
unsigned int t;
unsigned int best_t = 0;
float best_c = 0.0;
unsigned int best_bits = 0;
for ( t=0; t+try_step_nsamples<=try_max_nsamples; t+=try_step_nsamples )
// Scan the frame positions starting with the one try_first_sample,
// alternating between a step above that, a step below that, above, below,
// and so on, until we've scanned the whole try_max_nsamples range.
int j;
for ( j=0; ; j++ )
{
int up = j%2 ? 1 : -1;
int t = try_first_sample + up*((j+1)/2)*try_step_nsamples;
if ( t >= (int)try_max_nsamples )
break;
if ( t < 0 )
continue;
float c;
unsigned int bits_out = 0;
debug_log("try fsk_frame_analyze(skip=%+d)\n", t);
debug_log("try fsk_frame_analyze at t=%d\n", t);
c = fsk_frame_analyze(fskp, samples+t, samples_per_bit, &bits_out);
if ( best_c < c ) {
best_t = t;
best_c = c;
best_bits = bits_out;
// TEST
// if ( best_c > 100.0f )
// break;
// if we find a perfect frame, stop scanning for a better one
if ( best_c == INFINITY )
// If we find a frame with confidence > try_confidence_search_limit
// quit searching.
if ( best_c >= try_confidence_search_limit )
break;
}
}

View File

@ -63,8 +63,10 @@ fsk_plan_destroy( fsk_plan *fskp );
/* returns confidence value [0.0 to 1.0] */
float
fsk_find_frame( fsk_plan *fskp, float *samples, unsigned int frame_nsamples,
unsigned int try_first_sample,
unsigned int try_max_nsamples,
unsigned int try_step_nsamples,
float try_confidence_search_limit,
unsigned int *bits_outp,
unsigned int *frame_start_outp
);
@ -78,7 +80,7 @@ fsk_set_tones_by_bandshift( fsk_plan *fskp, unsigned int b_mark, int b_shift );
// FIXME move this?:
//#define FSK_DEBUG
// #define FSK_DEBUG
#ifdef FSK_DEBUG
# define debug_log(format, args...) fprintf(stderr, format, ## args)
#else

View File

@ -2,7 +2,7 @@
.\" First parameter, NAME, should be all caps
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
.\" other parameters are allowed: see man(7), man(1)
.TH MINIMODEM 1 "August 12, 2011"
.TH MINIMODEM 1 "August 19, 2012"
.\" Please adjust this date whenever revising the manpage.
.\"
.\" Some roff macros, for reference:
@ -48,8 +48,19 @@ receive mode: decode audio tones
.B \-a, \-\-auto-carrier
automatically detect mark and space frequences from carrier
.TP
.B \-c, \-\-confidence threshold
set receive confidence (minimum SNR) threshold (default 2.0)
.B \-c, \-\-confidence min-snr-threshold
Set receive confidence minimum SNR threshold (default 2.0).
This value acts as an FSK decoder "squelch" control.
Increase to accept only very clean signals (up to INFINITY, but
a value around 5.0 is more practical). Decrease to accept partial
decoding of noisy signals (down to 1.0).
.TP
.B \-l, \-\-limit max-snr-search-limit
Set receive confidence maximum SNR search limit (default 2.3).
This value acts as a performance vs. analysis quality control.
Increase (up to INFINITY) for a more pedantic analysis
and higher CPU usage. Decrease (down to the min-snr-threshold)
for a sloppier analysis, with lower CPU usage.
.TP
.B \-8, \-\-ascii
ASCII 8\-N\-1
@ -143,7 +154,7 @@ The latest version is available at <http://www.whence.com/minimodem>.
.B minimodem
was written by Kamal Mostafa <kamal@whence.com>.
.SH COPYRIGHT
Copyright \(co 2011 by Kamal Mostafa <kamal@whence.com>.
Copyright \(co 2011-2012 by Kamal Mostafa <kamal@whence.com>.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
.br
This is free software: you are free to change and redistribute it.

View File

@ -322,6 +322,7 @@ usage()
" [options]\n"
" -a, --auto-carrier\n"
" -c, --confidence {min-snr-threshold}\n"
" -l, --limit {max-snr-search-limit}\n"
" -8, --ascii ASCII 8-N-1\n"
" -5, --baudot Baudot 5-N-1\n"
" -f, --file {filename.flac}\n"
@ -360,7 +361,20 @@ main( int argc, char*argv[] )
char *filename = NULL;
float carrier_autodetect_threshold = 0.0;
float bfsk_confidence_threshold = 2.0;
// fsk_confidence_threshold : signal-to-noise squelch control
//
// The minimum SNR confidence level seen as "a signal".
float fsk_confidence_threshold = 2.0;
// fsk_confidence_search_limit : performance vs. quality
//
// If we find a frame with SNR confidence > confidence_search_limit,
// quit searching for a better frame. confidence_search_limit has a
// dramatic effect on peformance (high value yields low performance, but
// higher decode quality, for noisy or hard-to-discern signals (Bell 103).
float fsk_confidence_search_limit = 2.3f;
// float fsk_confidence_search_limit = INFINITY; /* for test */
sa_backend_t sa_backend = SA_BACKEND_SYSDEFAULT;
sa_format_t sample_format = SA_SAMPLE_FORMAT_S16;
@ -403,6 +417,7 @@ main( int argc, char*argv[] )
{ "receive", 0, 0, 'r' },
{ "read", 0, 0, 'r' },
{ "confidence", 1, 0, 'c' },
{ "limit", 1, 0, 'l' },
{ "auto-carrier", 0, 0, 'a' },
{ "ascii", 0, 0, '8' },
{ "baudot", 0, 0, '5' },
@ -438,7 +453,10 @@ main( int argc, char*argv[] )
TX_mode = 0;
break;
case 'c':
bfsk_confidence_threshold = atof(optarg);
fsk_confidence_threshold = atof(optarg);
break;
case 'l':
fsk_confidence_search_limit = atof(optarg);
break;
case 'a':
carrier_autodetect_threshold = 0.001;
@ -607,6 +625,9 @@ main( int argc, char*argv[] )
if ( band_width > bfsk_data_rate )
band_width = bfsk_data_rate;
// sanitize confidence search limit
if ( fsk_confidence_search_limit < fsk_confidence_threshold )
fsk_confidence_search_limit = fsk_confidence_threshold;
char *stream_name = NULL;;
@ -842,9 +863,25 @@ main( int argc, char*argv[] )
* prev_stop bit begins (since the "frame" includes the prev_stop). */
unsigned int frame_start_sample = 0;
// If we don't have carrier, then set this try_confidence_search_limit
// to infinity (search for best possible frame) so to get the decoder
// into phase with the signal, so the next try_first_sample will match
// up with where the next frame should be.
unsigned int try_first_sample;
float try_confidence_search_limit;
if ( carrier ) {
try_first_sample = nsamples_overscan;
try_confidence_search_limit = fsk_confidence_search_limit;
} else {
try_first_sample = 0;
try_confidence_search_limit = INFINITY;
}
confidence = fsk_find_frame(fskp, samplebuf, frame_nsamples,
try_first_sample,
try_max_nsamples,
try_step_nsamples,
try_confidence_search_limit,
&bits,
&frame_start_sample
);
@ -857,7 +894,7 @@ main( int argc, char*argv[] )
#define FSK_MAX_NOCONFIDENCE_BITS 20
if ( confidence <= bfsk_confidence_threshold ) {
if ( confidence <= fsk_confidence_threshold ) {
// FIXME: explain
if ( ++noconfidence > FSK_MAX_NOCONFIDENCE_BITS )