From 6594bf209ee827c75f1c597e77ae5c1da7c549b2 Mon Sep 17 00:00:00 2001 From: f4exb Date: Sun, 8 Jan 2023 21:41:43 +0100 Subject: [PATCH] FT8 demod: restore double precision for time variables --- ft8/fft.cpp | 18 ++--- ft8/ft8.cpp | 164 ++++++++++++++++++++++++++---------------- ft8/ft8.h | 5 +- ft8/util.cpp | 2 +- ft8/util.h | 2 +- sdrbench/test_ft8.cpp | 22 ++---- 6 files changed, 122 insertions(+), 91 deletions(-) diff --git a/ft8/fft.cpp b/ft8/fft.cpp index 5e3bbdd89..9244ef00f 100644 --- a/ft8/fft.cpp +++ b/ft8/fft.cpp @@ -62,7 +62,7 @@ public: // how much CPU time spent in FFTs that use this plan. #if TIMING - float time_; + double time_; #endif const char *why_; int uses_; @@ -100,7 +100,7 @@ Plan *get_plan(int n, const char *why) } } - float t0 = now(); + double t0 = now(); // fftw_make_planner_thread_safe(); @@ -172,7 +172,7 @@ Plan *get_plan(int n, const char *why) if (0 && getpid() == plan_master_pid) { - float t1 = now(); + double t1 = now(); fprintf(stderr, "miss pid=%d master=%d n=%d t=%.3f total=%d type=%d, %s\n", getpid(), plan_master_pid, n, t1 - t0, nplans, type, why); } @@ -213,7 +213,7 @@ std::vector> one_fft( fftwf_plan m_plan = p->fwd_; #if TIMING - float t0 = now(); + double t0 = now(); #endif assert((int)samples.size() - i0 >= block); @@ -287,7 +287,7 @@ ffts_t ffts(const std::vector &samples, int i0, int block, const char *wh fftwf_plan m_plan = p->fwd_; #if TIMING - float t0 = now(); + double t0 = now(); #endif // allocate our own b/c using p->m_in and p->m_out isn't thread-safe. @@ -356,7 +356,7 @@ std::vector> one_fft_c( fftwf_plan m_plan = p->cfwd_; #if TIMING - float t0 = now(); + double t0 = now(); #endif fftwf_complex *m_in = (fftwf_complex *)fftwf_malloc(block * sizeof(fftwf_complex)); @@ -416,7 +416,7 @@ std::vector> one_fft_cc( fftwf_plan m_plan = p->cfwd_; #if TIMING - float t0 = now(); + double t0 = now(); #endif fftwf_complex *m_in = (fftwf_complex *)fftwf_malloc(block * sizeof(fftwf_complex)); @@ -472,7 +472,7 @@ std::vector> one_ifft_cc( fftwf_plan m_plan = p->crev_; #if TIMING - float t0 = now(); + double t0 = now(); #endif fftwf_complex *m_in = (fftwf_complex *)fftwf_malloc(block * sizeof(fftwf_complex)); @@ -519,7 +519,7 @@ std::vector one_ifft(const std::vector> &bins, const fftwf_plan m_plan = p->rev_; #if TIMING - float t0 = now(); + double t0 = now(); #endif fftwf_complex *m_in = (fftwf_complex *)fftwf_malloc(sizeof(fftwf_complex) * ((p->n_ / 2) + 1)); diff --git a/ft8/ft8.cpp b/ft8/ft8.cpp index aeff70b45..d855ceea4 100644 --- a/ft8/ft8.cpp +++ b/ft8/ft8.cpp @@ -595,8 +595,8 @@ public: int start_; // sample number of 0.5 seconds into samples[] int rate_; // samples/second - float deadline_; // start time + budget - float final_deadline_; // keep going this long if no decodes + double deadline_; // start time + budget + double final_deadline_; // keep going this long if no decodes std::vector hints1_; std::vector hints2_; int pass_; @@ -617,13 +617,19 @@ public: Plan *plan32_; - FT8(const std::vector &samples, + FT8( + const std::vector &samples, float min_hz, float max_hz, - int start, int rate, - int hints1[], int hints2[], float deadline, - float final_deadline, cb_t cb, - std::vector prevdecs) + int start, + int rate, + int hints1[], + int hints2[], + double deadline, + double final_deadline, + cb_t cb, + std::vector prevdecs + ) { samples_ = samples; min_hz_ = min_hz; @@ -636,12 +642,11 @@ public: cb_ = cb; down_hz_ = 0; - for (int i = 0; hints1[i]; i++) - { + for (int i = 0; hints1[i]; i++) { hints1_.push_back(hints1[i]); } - for (int i = 0; hints2[i]; i++) - { + + for (int i = 0; hints2[i]; i++) { hints2_.push_back(hints2[i]); } @@ -676,6 +681,7 @@ public: float mx; int mxi = -1; float sum = 0; + for (int i = 0; i < 8; i++) { float x = std::abs(bins[si0 + si][bi0 + i]); @@ -686,6 +692,7 @@ public: mx = x; } } + if (si >= 0 && si < 7) { float x = std::abs(bins[si0 + si][bi0 + costas[si - 0]]); @@ -723,12 +730,10 @@ public: x += std::abs(bins[si0 + si][bi0 + bi]); x += std::abs(bins[si0 + 36 + si][bi0 + bi]); x += std::abs(bins[si0 + 72 + si][bi0 + bi]); - if (bi == costas[si]) - { + + if (bi == costas[si]) { sig += x; - } - else - { + } else { noise += x; } } @@ -952,17 +957,19 @@ public: 144000, 145800, 216000, 218700, 0}; int nice = -1; + for (int i = 0; nice_sizes[i]; i++) { int sz = nice_sizes[i]; + if (fabs(samples_.size() - sz) < 0.05 * samples_.size()) { nice = sz; break; } } - if (nice != -1) - { + + if (nice != -1) { samples_.resize(nice); } @@ -986,16 +993,21 @@ public: { // filter and reduce the sample rate from rate_ to nrate. - float t0 = now(); + double t0 = now(); int osize = samples_.size(); float delta_hz; // how much it moved down - samples_ = reduce_rate(samples_, - min_hz_ - 3.1 - go_extra, - max_hz_ + 50 - 3.1 + go_extra, - rate_, nrate, delta_hz); + samples_ = reduce_rate( + samples_, + min_hz_ - 3.1 - go_extra, + max_hz_ + 50 - 3.1 + go_extra, + rate_, + nrate, + delta_hz + ); + + double t1 = now(); - float t1 = now(); if (t1 - t0 > 0.1) { fprintf(stderr, "reduce oops, size %d -> %d, rate %d -> %d, took %.2f\n", @@ -1005,6 +1017,7 @@ public: nrate, t1 - t0); } + if (0) { fprintf(stderr, "%.0f..%.0f, range %.0f, rate %d -> %d, delta hz %.0f, %.6f sec\n", @@ -1024,6 +1037,7 @@ public: prevdecs_[i].hz1 -= delta_hz; } } + assert(max_hz_ + 50 < nrate / 2); assert(min_hz_ >= 0); @@ -1055,21 +1069,26 @@ public: // v[i] = 0; v[i] = samples_[rnd()]; } + samples_.insert(samples_.end(), v.begin(), v.end()); } int si0 = (start_ - tminus * rate_) / block; - if (si0 < 0) + + if (si0 < 0) { si0 = 0; + } + int si1 = (start_ + tplus * rate_) / block; // a copy from which to subtract. nsamples_ = samples_; - int any = 0; + for (int i = 0; i < (int)prevdecs_.size(); i++) { auto d = prevdecs_[i]; + if (d.hz0 >= min_hz_ && d.hz0 <= max_hz_) { // reconstruct correct 79 symbols from LDPC output. @@ -1088,21 +1107,21 @@ public: any += 1; } } - if (any) - { + + if (any) { samples_ = nsamples_; } for (pass_ = 0; pass_ < npasses; pass_++) { - float total_remaining = deadline_ - now(); - float remaining = total_remaining / (npasses - pass_); - if (pass_ == 0) - { + double total_remaining = deadline_ - now(); + double remaining = total_remaining / (npasses - pass_); + + if (pass_ == 0) { remaining *= pass0_frac; } - float deadline = now() + remaining; + double deadline = now() + remaining; int new_decodes = 0; samples_ = nsamples_; @@ -1154,35 +1173,42 @@ public: { return a.strength_ > b.strength_; }); char already[2000]; // XXX - for (int i = 0; i < (int)(sizeof(already) / sizeof(already[0])); i++) + + for (int i = 0; i < (int)(sizeof(already) / sizeof(already[0])); i++) { already[i] = 0; + } for (int ii = 0; ii < (int)order.size(); ii++) { - float tt = now(); + double tt = now(); + if (ii > 0 && tt > deadline && (tt > deadline_ || new_decodes >= pass_threshold) && - (pass_ < npasses - 1 || tt > final_deadline_)) - { + (pass_ < npasses - 1 || tt > final_deadline_) + ) { break; } float hz = order[ii].hz_; - if (already[(int)round(hz / already_hz)]) + + if (already[(int)round(hz / already_hz)]) { continue; + } + int off = order[ii].off_; int ret = one(bins, samples_.size(), hz, off); + if (ret) { - if (ret == 2) - { + if (ret == 2) { new_decodes++; } + already[(int)round(hz / already_hz)] = 1; } } - } + } // pass } // @@ -3598,12 +3624,9 @@ public: int correct_bits = 0; for (int i = 0; i < 174; i++) { - if (ll174[i] < 0 && a174[i] == 1) - { + if (ll174[i] < 0 && a174[i] == 1) { correct_bits += 1; - } - else if (ll174[i] > 0 && a174[i] == 0) - { + } else if (ll174[i] > 0 && a174[i] == 0) { correct_bits += 1; } } @@ -3615,9 +3638,15 @@ public: { // fine-tune offset and hz for better subtraction. float best_off = best_off_samples / 200.0; - search_both_known(samples200, 200, re79, - best_hz, best_off, - best_hz, best_off); + search_both_known( + samples200, + 200, + re79, + best_hz, + best_off, + best_hz, + best_off + ); best_off_samples = round(best_off * 200.0); } @@ -3629,9 +3658,15 @@ public: if (do_third == 2) { // fine-tune offset and hz for better subtraction. - search_both_known(samples_, rate_, re79, - best_hz, best_off, - best_hz, best_off); + search_both_known( + samples_, + rate_, + re79, + best_hz, + best_off, + best_hz, + best_off + ); } float snr = guess_snr(m79); @@ -3639,9 +3674,18 @@ public: if (cb_ != 0) { cb_mu_.lock(); - int ret = cb_(a174, best_hz + down_hz_, best_hz + down_hz_, - best_off, comment.c_str(), snr, pass_, correct_bits); + int ret = cb_( + a174, + best_hz + down_hz_, + best_off, + comment.c_str(), + snr, + pass_, + correct_bits + ); + cb_mu_.unlock(); + if (ret == 2) { // a new decode. subtract it from nsamples_. @@ -3650,6 +3694,7 @@ public: return ret; } + return 1; } else @@ -3714,16 +3759,16 @@ void entry( float max_hz, int hints1[], int hints2[], - float time_left, - float total_time_left, + double time_left, + double total_time_left, cb_t cb, int nprevdecs, struct cdecode *xprevdecs ) { - float t0 = now(); - float deadline = t0 + time_left; - float final_deadline = t0 + total_time_left; + double t0 = now(); + double deadline = t0 + time_left; + double final_deadline = t0 + total_time_left; // decodes from previous runs, for subtraction. std::vector prevdecs; @@ -3778,7 +3823,6 @@ void entry( ); int npasses = nprevdecs > 0 ? npasses_two : npasses_one; - printf("FT8::entry: npasses: %d\n", npasses); ft8->th_ = new std::thread([ft8, npasses] () { ft8->go(npasses); }); diff --git a/ft8/ft8.h b/ft8/ft8.h index 5960a250a..fe2a767cf 100644 --- a/ft8/ft8.h +++ b/ft8/ft8.h @@ -26,7 +26,6 @@ namespace FT8 { typedef int (*cb_t)( int *a91, float hz0, - float hz1, float off, const char *, float snr, @@ -52,8 +51,8 @@ void entry( float max_hz, int hints1[], int hints2[], - float time_left, - float total_time_left, + double time_left, + double total_time_left, cb_t cb, int, struct cdecode * diff --git a/ft8/util.cpp b/ft8/util.cpp index 2bd00fdca..fe9112a6d 100644 --- a/ft8/util.cpp +++ b/ft8/util.cpp @@ -30,7 +30,7 @@ namespace FT8 { -float now() +double now() { struct timeval tv; gettimeofday(&tv, 0); diff --git a/ft8/util.h b/ft8/util.h index f1807325f..d56ee88b4 100644 --- a/ft8/util.h +++ b/ft8/util.h @@ -26,7 +26,7 @@ namespace FT8 { -float now(); +double now(); void writewav(const std::vector &samples, const char *filename, int rate); std::vector readwav(const char *filename, int &rate_out); void writetxt(std::vector v, const char *filename); diff --git a/sdrbench/test_ft8.cpp b/sdrbench/test_ft8.cpp index 0c2324d4e..5683b56a7 100644 --- a/sdrbench/test_ft8.cpp +++ b/sdrbench/test_ft8.cpp @@ -32,24 +32,17 @@ void MainBench::testFT8() #else QMutex cycle_mu; -volatile int cycle_count; -time_t saved_cycle_start; std::map cycle_already; int hcb( int *a91, float hz0, - float hz1, float off, const char *comment, float snr, int pass, int correct_bits) { - (void) hz1; - (void) comment; - (void) pass; - std::string msg = FT8::unpack(a91); cycle_mu.lock(); @@ -62,22 +55,17 @@ int hcb( } cycle_already[msg] = true; - cycle_count += 1; cycle_mu.unlock(); - struct tm result; - gmtime_r(&saved_cycle_start, &result); - - printf("%02d%02d%02d %3d %3d %5.2f %6.1f %s\n", - result.tm_hour, - result.tm_min, - result.tm_sec, + printf("%d %3d %3d %5.2f %6.1f %s, %s\n", + pass, (int)snr, correct_bits, off - 0.5, hz0, - msg.c_str()); + msg.c_str(), + comment); fflush(stdout); return 2; // 2 => new decode, do subtract. @@ -87,7 +75,7 @@ void MainBench::testFT8() { qDebug("MainBench::testFT8: start"); int hints[2] = { 2, 0 }; // CQ - double budget = 5; // compute for this many seconds per cycle + double budget = 2.5; // compute for this many seconds per cycle int rate; std::vector s = FT8::readwav("/home/f4exb/.local/share/WSJT-X/save/230105_091630.wav", rate); // FIXME: download file