aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--etisnoop.cpp26
-rw-r--r--repetitionrate.cpp135
-rw-r--r--repetitionrate.hpp13
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);