diff options
-rw-r--r-- | etisnoop.cpp | 26 | ||||
-rw-r--r-- | repetitionrate.cpp | 135 | ||||
-rw-r--r-- | repetitionrate.hpp | 13 |
3 files changed, 115 insertions, 59 deletions
diff --git a/etisnoop.cpp b/etisnoop.cpp index ed9a420..77ac799 100644 --- a/etisnoop.cpp +++ b/etisnoop.cpp @@ -156,6 +156,7 @@ struct eti_analyse_config_t { std::map<int, DabPlusSnoop> streams_to_decode; bool analyse_fic_carousel; bool analyse_fig_rates; + bool analyse_fig_rates_per_second; bool decode_watermark; }; @@ -187,15 +188,19 @@ const struct option longopts[] = { void usage(void) { fprintf(stderr, - "ETISnoop analyser\n\n" - "The ETSnoop analyser decodes and prints out a RAW ETI file in a\n" + "Opendigitalradio ETISnoop analyser\n\n" + "The ETISnoop analyser decodes and prints out a RAW ETI file in a\n" "form that makes analysis easier.\n" + "\n" + " http://www.opendigitalradio.org\n" + "\n" "Usage: etisnoop [-v] [-f] [-w] [-i filename] [-d stream_index]\n" "\n" " -v increase verbosity (can be given more than once)\n" " -d N decode subchannel N into .dabp and .wav files\n" " -f analyse FIC carousel\n" - " -r analyse FIG rates\n" + " -r analyse FIG rates in FIGs per second\n" + " -R analyse FIG rates in frames per FIG\n" " -w decode CRC-DABMUX and ODR-DabMux watermark.\n"); } @@ -208,7 +213,7 @@ int main(int argc, char *argv[]) eti_analyse_config_t config; while(ch != -1) { - ch = getopt_long(argc, argv, "d:efhrvwi:", longopts, &index); + ch = getopt_long(argc, argv, "d:efhrRvwi:", longopts, &index); switch (ch) { case 'd': { @@ -228,6 +233,11 @@ int main(int argc, char *argv[]) break; case 'r': config.analyse_fig_rates = true; + config.analyse_fig_rates_per_second = true; + break; + case 'R': + config.analyse_fig_rates = true; + config.analyse_fig_rates_per_second = false; break; case 'v': set_verbosity(get_verbosity() + 1); @@ -296,6 +306,10 @@ int eti_analyse(eti_analyse_config_t& config) WatermarkDecoder wm_decoder; + if (config.analyse_fig_rates) { + rate_display_header(config.analyse_fig_rates_per_second); + } + while (running) { int ret = get_eti_frame(config.etifd, stream_type, p); @@ -654,7 +668,7 @@ int eti_analyse(eti_analyse_config_t& config) } if (config.analyse_fig_rates and (fct % 250) == 0) { - rate_display_analysis(true); + rate_display_analysis(false, config.analyse_fig_rates_per_second); } } @@ -672,7 +686,7 @@ int eti_analyse(eti_analyse_config_t& config) } if (config.analyse_fig_rates) { - rate_display_analysis(false); + rate_display_analysis(false, config.analyse_fig_rates_per_second); } figs_cleardb(); diff --git a/repetitionrate.cpp b/repetitionrate.cpp index c407c18..970bcfc 100644 --- a/repetitionrate.cpp +++ b/repetitionrate.cpp @@ -23,10 +23,12 @@ #include <vector> #include <map> #include <set> +#include <cmath> +#include <limits> using namespace std; -const double frame_duration = 24e-3; +const double FRAME_DURATION = 24e-3; struct FIGTypeExt { int figtype; @@ -77,71 +79,102 @@ void rate_announce_fig(int figtype, int figextension, bool complete) rate.in_fib.insert(current_fib); } -void rate_display_analysis(bool clear) +// Calculate the minimal, maximum and average repetition rate (FIGs per +// second). +void rate_min_max_avg( + const std::vector<int>& fig_positions, + double* min, + double* max, + double* avg, + bool per_second) +{ + double avg_interval = + (double)(fig_positions.back() - fig_positions.front()) / + (double)(fig_positions.size() - 1); + + int min_delta = std::numeric_limits<int>::max(); + int max_delta = 0; + for (size_t i = 1; i < fig_positions.size(); i++) { + const int delta = fig_positions[i] - fig_positions[i-1]; + + // Min + if (min_delta > delta) { + min_delta = delta; + } + + // Max + if (max_delta < delta) { + max_delta = delta; + } + } + + *avg = avg_interval; + *min = min_delta; + *max = max_delta; + + if (per_second) { + *avg = 1.0 / + (*avg * FRAME_DURATION); + *min = 1.0 / (*min * FRAME_DURATION); + *max = 1.0 / (*min * FRAME_DURATION); + } + +} + +void rate_display_header(bool per_second) +{ + if (per_second) { + printf("FIG carousel analysis. Format:\n" + " min, average, max FIGs per second (total count) - \n" + " min, average, max complete FIGs per second (total count)\n"); + } + else { + printf("FIG carousel analysis. Format:\n" + " min, average, max frames per FIG (total count) - \n" + " min, average, max frames per complete FIGs (total count)\n"); + } +} + +void rate_display_analysis(bool clear, bool per_second) { - printf("FIG carousel analysis. Format:\n" - " average FIGs per second (total count, delta variance in frames)\n" - " average complete FIGs per second (total count, delta variance in frames)\n"); for (auto& fig_rate : fig_rates) { auto& frames_present = fig_rate.second.frames_present; auto& frames_complete = fig_rate.second.frames_complete; - const size_t n_present = frames_present.size(); - if (n_present) { - double average_present_interval = - (double)(frames_present.back() - frames_present.front()) / - (double)(frames_present.size() - 1); - - double variance_of_delta_present = 0; - for (size_t i = 1; i < frames_present.size(); i++) { - double s = - (double)(frames_present[i] - frames_present[i-1]) - - average_present_interval; - - variance_of_delta_present += s * s; - } - variance_of_delta_present /= frames_present.size(); - - const double n_present_per_second = 1 / - (average_present_interval * frame_duration); - - printf("FIG%2d/%2d %2.2f (%6zu %2.2f)", - fig_rate.first.figtype, fig_rate.first.figextension, - n_present_per_second, n_present, variance_of_delta_present); - } - else { - printf("FIG%2d/%2d 0\n", - fig_rate.first.figtype, fig_rate.first.figextension); - } + double min = 0.0; + double max = 0.0; + double avg = 0.0; + const size_t n_present = frames_present.size(); const size_t n_complete = frames_complete.size(); - if (n_present and n_complete) { + if (n_present >= 2) { - double average_complete_interval = - (double)(frames_complete.back() - frames_complete.front()) / - (double)(frames_complete.size() - 1); + rate_min_max_avg(frames_present, &min, &max, &avg, per_second); + printf("FIG%2d/%2d %4.2f %4.2f %4.2f (%5zu)", + fig_rate.first.figtype, fig_rate.first.figextension, + min, avg, max, + n_present); - double variance_of_delta_complete = 0; - for (size_t i = 1; i < frames_complete.size(); i++) { - double s = - (double)(frames_complete[i] - frames_complete[i-1]) - - average_complete_interval; + if (n_complete >= 2) { + rate_min_max_avg(frames_complete, &min, &max, &avg, per_second); - variance_of_delta_complete += s * s; + printf(" - %4.2f %4.2f %4.2f (%5zu)", + min, avg, max, + n_present); } - variance_of_delta_complete /= frames_complete.size(); - - const double n_complete_per_second = 1 / - (average_complete_interval * frame_duration); - - printf(" %2.2f (%6zu %2.2f)", - n_complete_per_second, n_complete, variance_of_delta_complete); + else { + printf(" - None complete"); + } + } + else { + printf("FIG%2d/%2d 0", + fig_rate.first.figtype, fig_rate.first.figextension); } - printf(" in FIB(s): "); + printf(" - in FIB(s):"); for (auto& fib : fig_rate.second.in_fib) { - printf("%d ", fib); + printf(" %d", fib); } printf("\n"); diff --git a/repetitionrate.hpp b/repetitionrate.hpp index a779c3d..41b5b40 100644 --- a/repetitionrate.hpp +++ b/repetitionrate.hpp @@ -32,7 +32,16 @@ void rate_announce_fig(int figtype, int figextension, bool complete); */ void rate_new_fib(int fib); -/* Print analysis, optionally clear all statistics +/* Print small header to explain rate display + * per_second: if true, rates are calculated in FIGs per second. + * If false, rate is given in frames per FIG */ -void rate_display_analysis(bool clear); +void rate_display_header(bool per_second); + +/* Print analysis. + * optionally clear all statistics + * per_second: if true, rates are calculated in FIGs per second. + * If false, rate is given in frames per FIG + */ +void rate_display_analysis(bool clear, bool per_second); |