aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.faadalyse7
-rw-r--r--README.md97
-rw-r--r--configure.ac4
-rw-r--r--src/etianalyse.cpp42
-rw-r--r--src/fig0_1.cpp5
-rw-r--r--src/fig0_11.cpp5
-rw-r--r--src/fig0_13.cpp5
-rw-r--r--src/fig0_14.cpp5
-rw-r--r--src/fig0_16.cpp5
-rw-r--r--src/fig0_17.cpp5
-rw-r--r--src/fig0_18.cpp5
-rw-r--r--src/fig0_19.cpp5
-rw-r--r--src/fig0_2.cpp5
-rw-r--r--src/fig0_21.cpp5
-rw-r--r--src/fig0_22.cpp5
-rw-r--r--src/fig0_24.cpp5
-rw-r--r--src/fig0_25.cpp5
-rw-r--r--src/fig0_26.cpp5
-rw-r--r--src/fig0_27.cpp5
-rw-r--r--src/fig0_28.cpp5
-rw-r--r--src/fig0_3.cpp6
-rw-r--r--src/fig0_31.cpp6
-rw-r--r--src/fig0_5.cpp5
-rw-r--r--src/fig0_6.cpp5
-rw-r--r--src/fig0_8.cpp6
-rw-r--r--src/fig1.cpp24
-rw-r--r--src/repetitionrate.cpp130
-rw-r--r--src/repetitionrate.hpp15
-rw-r--r--src/utils.cpp18
-rw-r--r--src/utils.hpp13
30 files changed, 251 insertions, 207 deletions
diff --git a/Makefile.faadalyse b/Makefile.faadalyse
index f73a8f4..723f204 100644
--- a/Makefile.faadalyse
+++ b/Makefile.faadalyse
@@ -1,5 +1,6 @@
CC=gcc
CXX=g++
+FAADVERSION = faad2-2.8.8
CFLAGS = -Wall -g --std=c99
CXXFLAGS = -Wall -g --std=c++11 -DDPS_DEBUG=1
SOURCES = src/dabplussnoop.cpp \
@@ -31,12 +32,12 @@ HEADERS = src/dabplussnoop.hpp \
all: faadalyse
faadalyse: libfaad $(SOURCES) $(CSOURCES) $(HEADERS)
- $(CXX) $(CXXFLAGS) $(SOURCES) -Ifaad2-2.7/include -c
+ $(CXX) $(CXXFLAGS) $(SOURCES) -I$(FAADVERSION)/include -c
$(CC) $(CFLAGS) $(CSOURCES) -c
- $(CXX) *.o faad2-2.7/libfaad/.libs/libfaad.a -o faadalyse
+ $(CXX) *.o $(FAADVERSION)/libfaad/.libs/libfaad.a -o faadalyse
libfaad:
- make -C ./faad2-2.7
+ make -C ./$(FAADVERSION)
clean:
rm -f faadalyse *.o
diff --git a/README.md b/README.md
index 2179371..bad8708 100644
--- a/README.md
+++ b/README.md
@@ -1,21 +1,21 @@
ETISnoop analyser
=================
-The ETISnoop analyser decodes a RAW ETI (see https://wiki.opendigitalradio.org/Ensemble_Transport_Interface ) file and prints out
-its contents in YAML for easier analysis.
+The **ETISnoop analyser** decodes a RAW ETI (see https://wiki.opendigitalradio.org/Ensemble_Transport_Interface ) file and prints out
+its contents in [YAML](https://en.wikipedia.org/wiki/YAML) for easier analysis.
It can show information about the signalling, details about the FIGs,
and extract a DAB+ subchannel into a file.
-Build
------
+Building
+--------
-etisnoop is using autotools. If you do not have a release containing a ./configure script,
-run ./bootstrap.sh
+**etisnoop** is using autotools. If you do not have a release containing a `./configure` script,
+run `./bootstrap.sh` before.
Install prerequisites: A C++ compiler with complete C++11 support and `libfaad-dev`
-Then do
+Then run
./configure
make
@@ -52,6 +52,32 @@ You can open the stream-N.dab file in https://www.basicmaster.de/xpadxpert/
Hint: subchannel N means the (N+1)th subchannel in a mux (including data subchannels!)
+Example FIG carousel statistic output
+-------------------------------------
+
+Using `-r` parameter a FIG statistic will be printed at the end of a file.
+
+```
+CAROUSEL FIG T/EXT AVG (COUNT) - AVG (COUNT) - LEN - LENGTH HISTOGRAM IN FIB(S)
+CAROUSEL FIG 0/ 0 10.42 ( 237) - 10.42 ( 237) - 5.0 [▁▁▁▁▁▇▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁] - 0
+CAROUSEL FIG 0/ 1 31.34 ( 714) - 10.42 ( 237) - 23.7 [▁▁▁▁▁▁▁▁▁▁▁▁▁▄▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▇] - 0 1 2
+CAROUSEL FIG 0/ 2 62.54 ( 1424) - 10.42 ( 237) - 15.5 [▁▁▁▁▁▁▄▁▄▁▁▄▁▁▁▁▄▁▁▁▁▁▁▁▁▁▇▁▁▁] - 0 1 2
+CAROUSEL FIG 0/ 3 10.42 ( 237) - 10.42 ( 236) - 6.0 [▁▁▁▁▁▁▇▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁] - 0
+CAROUSEL FIG 0/ 5 16.07 ( 365) - 1.01 ( 22) - 3.2 [▁▁▁▇▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁] - 0 1 2
+CAROUSEL FIG 0/ 6 3.12 ( 69) - 1.27 ( 28) - 7.0 [▁▁▁▇▁▁▁▇▄▁▂▁▁▁▁▁▁▁▁▁▂▁▁▁▁▁▁▁▁▁] - 0 1 2
+CAROUSEL FIG 0/ 7 10.42 ( 237) - 10.42 ( 237) - 3.0 [▁▁▁▇▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁] - 0
+CAROUSEL FIG 0/ 8 10.36 ( 230) - 1.01 ( 22) - 8.1 [▁▁▁▁▁▂▁▁▁▇▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁] - 0 2
+CAROUSEL FIG 0/ 9 1.01 ( 23) - 1.01 ( 23) - 4.0 [▁▁▁▁▇▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁] - 0 1 2
+CAROUSEL FIG 0/10 1.01 ( 23) - 1.01 ( 23) - 7.0 [▁▁▁▁▁▁▁▇▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁] - 0 1 2
+CAROUSEL FIG 0/13 17.35 ( 389) - 1.01 ( 22) - 8.1 [▁▁▁▁▁▁▁▁▇▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁] - 0 1 2
+CAROUSEL FIG 0/14 1.01 ( 22) - 1.01 ( 21) - 2.0 [▁▁▇▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁] - 0 2
+CAROUSEL FIG 0/17 9.55 ( 217) - 0.99 ( 22) - 7.7 [▁▁▁▁▁▇▁▁▁▅▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁] - 0 1 2
+CAROUSEL FIG 0/18 10.73 ( 244) - 0.99 ( 22) - 7.7 [▁▁▁▁▁▁▁▇▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁] - 0 1
+CAROUSEL FIG 1/ 0 0.99 ( 22) - 0.99 ( 22) - 21.0 [▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▇▁▁▁▁▁▁▁▁] - 1 2
+CAROUSEL FIG 1/ 1 15.93 ( 362) - 0.99 ( 22) - 21.0 [▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▇▁▁▁▁▁▁▁▁] - 1 2
+CAROUSEL FIG 1/ 5 0.99 ( 22) - 0.99 ( 22) - 23.0 [▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▇▁▁▁▁▁▁] - 1 2
+```
+
About
-----
@@ -63,17 +89,66 @@ See LICENCE for more information.
Faadalyse
=========
-faadalyse can extract the audio from .dabp files created with ODR-AudioEnc,
+**faadalyse** can extract the audio from `.dabp` files created with [ODR-AudioEnc](https://github.com/Opendigitalradio/ODR-AudioEnc),
and is designed to do more in-depth analysis of the AAC encoding using a modified
libfaad.
-To install:
+Installation
+------------
+
+To install, download (latest) [faad2-2.8.8](https://sourceforge.net/projects/faac/files/faad2-src/faad2-2.8.0/), extract it into the etisnoop-folder and run
+
+ cd faad2-2.8.8/
+ ./configure
+ make
-download and extract faad2-2.7 to a folder of the same name, and configure and compile it.
You can patch that faad library to display additional information you need.
-Do not run make install.
+
+Remark: Do **not** run make install.
Then run
make -f Makefile.faadalyse
./faadalyse
+
+Example output
+--------------
+
+```
+./faadalyse /tmp/file.dabp 96 | head -30
+Faadalyse -- A .dabp file analyser
+ www.opendigitalradio.org
+ compiled at Dec 3 2024 21:23:42
+Analysing /tmp/file.dabp 96kbps
+DAB+ decode: Found valid FireCode at 0
+DAB+ decode: We have 1024 bytes of data
+DAB+ decode: Found valid FireCode at 0
+DAB+ decode: We have 2048 bytes of data
+ DAB+ decode:
+ firecode 0x30b0
+ rfa 0
+ dac_rate 1
+ sbr_flag 0
+ aac_channel_mode 1
+ ps_flag 0
+ mpeg_surround_config 0
+ num_aus 6
+ DAB+ decode: AU start
+ AU[0] 11 0xb
+ AU[1] 216 0xd8
+ AU[2] 432 0x1b0
+ AU[3] 648 0x288
+ AU[4] 864 0x360
+ AU[5] 1080 0x438
+DAB+ decode: Copy au 0 of size 203
+DAB+ decode: Copy au 1 of size 214
+DAB+ decode: Copy au 2 of size 214
+DAB+ decode: Copy au 3 of size 214
+DAB+ decode: Copy au 4 of size 214
+DAB+ decode: Copy au 5 of size 238
+DAB+ decode: Found valid FireCode at 0
+DAB+ decode: We have 608 bytes of data
+DAB+ decode: Found valid FireCode at 0
+DAB+ decode: We have 1632 bytes of data
+
+```
diff --git a/configure.ac b/configure.ac
index 10e622a..7b6c613 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,7 +1,7 @@
dnl -*- Autoconf -*-
dnl Process this file with autoconf to produce a configure script.
-AC_INIT([etisnoop], [2.1.0], [http://opendigitalradio.org/])
+AC_INIT([etisnoop], [2.2.0], [http://opendigitalradio.org/])
AC_CONFIG_AUX_DIR(.)
AC_CONFIG_MACRO_DIR([m4])
AM_INIT_AUTOMAKE([-Wall tar-ustar foreign subdir-objects])
@@ -14,7 +14,7 @@ AC_PROG_CXX
AC_PROG_INSTALL
AC_PROG_MKDIR_P
-AX_CXX_COMPILE_STDCXX(11,noext,mandatory)
+AX_CXX_COMPILE_STDCXX(17,noext,mandatory)
AC_PROG_CC_STDC
# Added for automake 1.13 on CentOS 7, obsolecent starting with automake 1.14
diff --git a/src/etianalyse.cpp b/src/etianalyse.cpp
index dbd9adc..1104156 100644
--- a/src/etianalyse.cpp
+++ b/src/etianalyse.cpp
@@ -137,10 +137,6 @@ void ETI_Analyser::eti_analyse()
fprintf(stderr, "?\n");
}
- if (config.analyse_fig_rates) {
- rate_display_header(config.analyse_fig_rates_per_second);
- }
-
FILE *stat_fd = nullptr;
if (not config.statistics_filename.empty()) {
stat_fd = fopen(config.statistics_filename.c_str(), "w");
@@ -226,7 +222,7 @@ void ETI_Analyser::eti_analyse()
printbuf("FSYNC", 1, p + 1, 3, "", desc);
// LIDATA
- printbuf("LIDATA");
+ printbuf("LIDATA", 0);
// LIDATA - FC
printbuf("FC", 1, p+4, 4, "Frame Characterization field");
// LIDATA - FC - FCT
@@ -507,9 +503,7 @@ void ETI_Analyser::eti_analyse()
}
printvalue("Selected for decoding", 3, "", (subchid == -1 ? "false" : "true"));
- if (get_verbosity() > 1) {
- printbuf("Data", 3, streamdata, stl[i]*8);
- }
+ printbuf("Data", 3, streamdata, stl[i]*8);
if (subchid != -1) {
config.streams_to_decode.at(subchid).push(streamdata, stl[i]*8);
@@ -548,7 +542,7 @@ void ETI_Analyser::eti_analyse()
printbuf("TIST", 1, p + tist_ix, 4, "Time Stamp (ms)", sdesc);
if (config.analyse_fig_rates and (fct % 250) == 0) {
- rate_display_analysis(false, config.analyse_fig_rates_per_second);
+ rate_display_analysis(config.analyse_fig_rates_per_second);
}
num_frames++;
@@ -648,7 +642,7 @@ void ETI_Analyser::eti_analyse()
}
if (config.analyse_fig_rates) {
- rate_display_analysis(false, config.analyse_fig_rates_per_second);
+ rate_display_analysis(config.analyse_fig_rates_per_second);
}
figs_cleardb();
@@ -656,10 +650,6 @@ void ETI_Analyser::eti_analyse()
void ETI_Analyser::fic_analyse()
{
- if (config.analyse_fig_rates) {
- rate_display_header(config.analyse_fig_rates_per_second);
- }
-
FILE *stat_fd = nullptr;
if (not config.statistics_filename.empty()) {
stat_fd = fopen(config.statistics_filename.c_str(), "w");
@@ -754,9 +744,7 @@ void ETI_Analyser::decodeFIG(
const display_settings_t disp(config.is_fig_to_be_printed(figtype, fig0.ext()), indent);
printvalue("FIG", disp, "", strprintf("0/%d", fig0.ext()));
- if (get_verbosity() > 0) {
- printbuf("Data", disp, f, figlen);
- }
+ printbuf("Data", disp, f, figlen);
if (disp.print) {
printvalue("Length", disp, "", to_string(figlen));
@@ -773,7 +761,7 @@ void ETI_Analyser::decodeFIG(
printvalue("Decoding", disp);
print_fig_result(fig_result, disp+1);
- rate_announce_fig(figtype, fig0.ext(), fig_result.complete);
+ rate_announce_fig(figtype, fig0.ext(), fig_result.complete, figlen);
}
break;
@@ -785,9 +773,7 @@ void ETI_Analyser::decodeFIG(
const display_settings_t disp(config.is_fig_to_be_printed(figtype, fig1.ext()), indent);
printvalue("FIG", disp, "", strprintf("1/%d", fig1.ext()));
- if (get_verbosity() > 0) {
- printbuf("Data", disp, f, figlen);
- }
+ printbuf("Data", disp, f, figlen);
if (disp.print) {
printvalue("Length", disp, "", to_string(figlen));
@@ -801,7 +787,7 @@ void ETI_Analyser::decodeFIG(
fig_result.figext = fig1.ext();
printvalue("Decoding", disp);
print_fig_result(fig_result, disp+1);
- rate_announce_fig(figtype, fig1.ext(), fig_result.complete);
+ rate_announce_fig(figtype, fig1.ext(), fig_result.complete, figlen);
}
break;
case 2:
@@ -812,9 +798,7 @@ void ETI_Analyser::decodeFIG(
printvalue("FIG", disp, "", strprintf("2/%d", fig2.ext()));
- if (get_verbosity() > 0) {
- printbuf("Data", disp, f, figlen);
- }
+ printbuf("Data", disp, f, figlen);
if (disp.print) {
printvalue("Length", disp, "", to_string(figlen));
@@ -824,7 +808,7 @@ void ETI_Analyser::decodeFIG(
printvalue("Decoding", disp);
print_fig_result(fig_result, disp+1);
- rate_announce_fig(figtype, fig2.ext(), fig_result.complete);
+ rate_announce_fig(figtype, fig2.ext(), fig_result.complete, figlen);
}
break;
case 5:
@@ -840,9 +824,7 @@ void ETI_Analyser::decodeFIG(
printvalue("FIG", disp, "", strprintf("5/%d", ext));
- if (get_verbosity() > 0) {
- printbuf("Data", disp, f, figlen);
- }
+ printbuf("Data", disp, f, figlen);
if (disp.print) {
printvalue("Length", disp, "", to_string(figlen));
@@ -854,7 +836,7 @@ void ETI_Analyser::decodeFIG(
figs.push_back(figtype, ext, figlen);
bool complete = true; // TODO verify
- rate_announce_fig(figtype, ext, complete);
+ rate_announce_fig(figtype, ext, complete, figlen);
}
break;
case 6:
diff --git a/src/fig0_1.cpp b/src/fig0_1.cpp
index db2250c..58fd55b 100644
--- a/src/fig0_1.cpp
+++ b/src/fig0_1.cpp
@@ -39,9 +39,8 @@ bool fig0_1_is_complete(fig0_common_t& fig0, int subch_id)
fig0.wm_decoder.push_fig0_1_bit(subchannels_seen.front() < subchannels_seen.back());
subchannels_seen.clear();
}
- else {
- subchannels_seen.push_back(subch_id);
- }
+
+ subchannels_seen.push_back(subch_id);
return complete;
}
diff --git a/src/fig0_11.cpp b/src/fig0_11.cpp
index 196dd37..1c76ec8 100644
--- a/src/fig0_11.cpp
+++ b/src/fig0_11.cpp
@@ -39,9 +39,8 @@ bool fig0_11_is_complete(int region_id)
if (complete) {
region_ids_seen.clear();
}
- else {
- region_ids_seen.insert(region_id);
- }
+
+ region_ids_seen.insert(region_id);
return complete;
}
diff --git a/src/fig0_13.cpp b/src/fig0_13.cpp
index dd053b7..de1eda9 100644
--- a/src/fig0_13.cpp
+++ b/src/fig0_13.cpp
@@ -46,9 +46,8 @@ bool fig0_13_is_complete(SId_t SId, SCIdS_t SCIdS)
if (complete) {
components_ids_seen.clear();
}
- else {
- components_ids_seen.insert(key);
- }
+
+ components_ids_seen.insert(key);
return complete;
}
diff --git a/src/fig0_14.cpp b/src/fig0_14.cpp
index de32820..97ef9a9 100644
--- a/src/fig0_14.cpp
+++ b/src/fig0_14.cpp
@@ -39,9 +39,8 @@ bool fig0_14_is_complete(int subch_id)
if (complete) {
subch_ids_seen.clear();
}
- else {
- subch_ids_seen.insert(subch_id);
- }
+
+ subch_ids_seen.insert(subch_id);
return complete;
}
diff --git a/src/fig0_16.cpp b/src/fig0_16.cpp
index 0f47533..59a6cd9 100644
--- a/src/fig0_16.cpp
+++ b/src/fig0_16.cpp
@@ -44,9 +44,8 @@ bool fig0_16_is_complete(SId_t SId, PNum_t PNum)
if (complete) {
components_seen.clear();
}
- else {
- components_seen.insert(key);
- }
+
+ components_seen.insert(key);
return complete;
}
diff --git a/src/fig0_17.cpp b/src/fig0_17.cpp
index 247e79e..9cee795 100644
--- a/src/fig0_17.cpp
+++ b/src/fig0_17.cpp
@@ -39,9 +39,8 @@ bool fig0_17_is_complete(int services_id)
if (complete) {
services_ids_seen.clear();
}
- else {
- services_ids_seen.insert(services_id);
- }
+
+ services_ids_seen.insert(services_id);
return complete;
}
diff --git a/src/fig0_18.cpp b/src/fig0_18.cpp
index ecbf7ba..2927a20 100644
--- a/src/fig0_18.cpp
+++ b/src/fig0_18.cpp
@@ -39,9 +39,8 @@ bool fig0_18_is_complete(int services_id)
if (complete) {
services_seen.clear();
}
- else {
- services_seen.insert(services_id);
- }
+
+ services_seen.insert(services_id);
return complete;
}
diff --git a/src/fig0_19.cpp b/src/fig0_19.cpp
index 0e6c25e..8ce0470 100644
--- a/src/fig0_19.cpp
+++ b/src/fig0_19.cpp
@@ -39,9 +39,8 @@ bool fig0_19_is_complete(int clusters_id)
if (complete) {
clusters_seen.clear();
}
- else {
- clusters_seen.insert(clusters_id);
- }
+
+ clusters_seen.insert(clusters_id);
return complete;
}
diff --git a/src/fig0_2.cpp b/src/fig0_2.cpp
index 6d309c9..777fea2 100644
--- a/src/fig0_2.cpp
+++ b/src/fig0_2.cpp
@@ -39,9 +39,8 @@ bool fig0_2_is_complete(int services_id)
if (complete) {
services_seen.clear();
}
- else {
- services_seen.insert(services_id);
- }
+
+ services_seen.insert(services_id);
return complete;
}
diff --git a/src/fig0_21.cpp b/src/fig0_21.cpp
index fbd1b13..ef93c74 100644
--- a/src/fig0_21.cpp
+++ b/src/fig0_21.cpp
@@ -39,9 +39,8 @@ bool fig0_21_is_complete(int region_id)
if (complete) {
regions_seen.clear();
}
- else {
- regions_seen.insert(region_id);
- }
+
+ regions_seen.insert(region_id);
return complete;
}
diff --git a/src/fig0_22.cpp b/src/fig0_22.cpp
index a76de31..c893cf0 100644
--- a/src/fig0_22.cpp
+++ b/src/fig0_22.cpp
@@ -41,9 +41,8 @@ bool fig0_22_is_complete(int M_S, int MainId)
if (complete) {
identifiers_seen.clear();
}
- else {
- identifiers_seen.insert(identifier);
- }
+
+ identifiers_seen.insert(identifier);
return complete;
}
diff --git a/src/fig0_24.cpp b/src/fig0_24.cpp
index 690979d..1c697ba 100644
--- a/src/fig0_24.cpp
+++ b/src/fig0_24.cpp
@@ -39,9 +39,8 @@ bool fig0_24_is_complete(int services_id)
if (complete) {
services_seen.clear();
}
- else {
- services_seen.insert(services_id);
- }
+
+ services_seen.insert(services_id);
return complete;
}
diff --git a/src/fig0_25.cpp b/src/fig0_25.cpp
index bf02d13..bc0a87f 100644
--- a/src/fig0_25.cpp
+++ b/src/fig0_25.cpp
@@ -39,9 +39,8 @@ bool fig0_25_is_complete(int services_id)
if (complete) {
services_seen.clear();
}
- else {
- services_seen.insert(services_id);
- }
+
+ services_seen.insert(services_id);
return complete;
}
diff --git a/src/fig0_26.cpp b/src/fig0_26.cpp
index 0568b60..1508814 100644
--- a/src/fig0_26.cpp
+++ b/src/fig0_26.cpp
@@ -39,9 +39,8 @@ bool fig0_26_is_complete(int cluster_id)
if (complete) {
clusters_seen.clear();
}
- else {
- clusters_seen.insert(cluster_id);
- }
+
+ clusters_seen.insert(cluster_id);
return complete;
}
diff --git a/src/fig0_27.cpp b/src/fig0_27.cpp
index fdcb5f5..d00391f 100644
--- a/src/fig0_27.cpp
+++ b/src/fig0_27.cpp
@@ -39,9 +39,8 @@ bool fig0_27_is_complete(int services_id)
if (complete) {
services_seen.clear();
}
- else {
- services_seen.insert(services_id);
- }
+
+ services_seen.insert(services_id);
return complete;
}
diff --git a/src/fig0_28.cpp b/src/fig0_28.cpp
index 3a95c5c..e86c676 100644
--- a/src/fig0_28.cpp
+++ b/src/fig0_28.cpp
@@ -39,9 +39,8 @@ bool fig0_28_is_complete(int cluster_id)
if (complete) {
clusters_seen.clear();
}
- else {
- clusters_seen.insert(cluster_id);
- }
+
+ clusters_seen.insert(cluster_id);
return complete;
}
diff --git a/src/fig0_3.cpp b/src/fig0_3.cpp
index 6c424b8..1da959d 100644
--- a/src/fig0_3.cpp
+++ b/src/fig0_3.cpp
@@ -38,9 +38,9 @@ bool fig0_3_is_complete(int components_id)
if (complete) {
components_ids_seen.clear();
}
- else {
- components_ids_seen.insert(components_id);
- }
+
+ components_ids_seen.insert(components_id);
+
return complete;
}
diff --git a/src/fig0_31.cpp b/src/fig0_31.cpp
index c869bf4..d6ede22 100644
--- a/src/fig0_31.cpp
+++ b/src/fig0_31.cpp
@@ -39,9 +39,9 @@ bool fig0_31_is_complete(uint64_t figtype_flags)
if (complete) {
figtype_flags_seen.clear();
}
- else {
- figtype_flags_seen.insert(figtype_flags);
- }
+
+ figtype_flags_seen.insert(figtype_flags);
+
return complete;
}
diff --git a/src/fig0_5.cpp b/src/fig0_5.cpp
index 2243539..cee9e5d 100644
--- a/src/fig0_5.cpp
+++ b/src/fig0_5.cpp
@@ -39,9 +39,8 @@ bool fig0_5_is_complete(int components_id)
if (complete) {
components_seen.clear();
}
- else {
- components_seen.insert(components_id);
- }
+
+ components_seen.insert(components_id);
return complete;
}
diff --git a/src/fig0_6.cpp b/src/fig0_6.cpp
index 0ba4132..6c527ae 100644
--- a/src/fig0_6.cpp
+++ b/src/fig0_6.cpp
@@ -39,9 +39,8 @@ bool fig0_6_is_complete(int link_key)
if (complete) {
links_seen.clear();
}
- else {
- links_seen.insert(link_key);
- }
+
+ links_seen.insert(link_key);
return complete;
}
diff --git a/src/fig0_8.cpp b/src/fig0_8.cpp
index 8a651ad..3ac4636 100644
--- a/src/fig0_8.cpp
+++ b/src/fig0_8.cpp
@@ -46,9 +46,9 @@ bool fig0_8_is_complete(SId_t SId, SCIdS_t SCIdS)
if (complete) {
components_seen.clear();
}
- else {
- components_seen.insert(key);
- }
+
+ components_seen.insert(key);
+
return complete;
}
diff --git a/src/fig1.cpp b/src/fig1.cpp
index 71e4508..89a54f1 100644
--- a/src/fig1.cpp
+++ b/src/fig1.cpp
@@ -25,6 +25,7 @@
*/
#include "figs.hpp"
+#include <algorithm>
#include <cstdio>
#include <string>
#include <cstring>
@@ -48,6 +49,21 @@ static ensemble_database::charset_e charset_to_charset(uint8_t charset)
}
}
+static std::vector<uint16_t> service_labels_seen;
+
+bool fig1_1_is_complete(uint16_t sid)
+{
+ bool complete = std::count(service_labels_seen.begin(), service_labels_seen.end(), sid) > 0;
+
+ if (complete) {
+ service_labels_seen.clear();
+ }
+
+ service_labels_seen.push_back(sid);
+
+ return complete;
+}
+
// SHORT LABELS
fig_result_t fig1_select(fig1_common_t& fig1, const display_settings_t &disp)
{
@@ -78,6 +94,7 @@ fig_result_t fig1_select(fig1_common_t& fig1, const display_settings_t &disp)
r.msgs.push_back(strprintf("Label=\"%s\"", fig1.ensemble.label.label().c_str()));
r.msgs.push_back(strprintf("Short label mask=0x%04X", flag));
r.msgs.push_back(strprintf("Short label=\"%s\"", fig1.ensemble.label.shortlabel().c_str()));
+ r.complete = true;
}
}
break;
@@ -97,6 +114,8 @@ fig_result_t fig1_select(fig1_common_t& fig1, const display_settings_t &disp)
r.msgs.push_back(strprintf("Label=\"%s\"", service.label.label().c_str()));
r.msgs.push_back(strprintf("Short label mask=0x%04X", flag));
r.msgs.push_back(strprintf("Short label=\"%s\"", service.label.shortlabel().c_str()));
+
+ r.complete = fig1_1_is_complete(sid);
}
catch (ensemble_database::not_found &e) {
r.errors.push_back("Not yet in DB");
@@ -122,6 +141,7 @@ fig_result_t fig1_select(fig1_common_t& fig1, const display_settings_t &disp)
// TODO put label into ensembledatabase
r.msgs.push_back(strprintf("Label bytes=\"%s\"", string(label.begin(), label.end()).c_str()));
r.msgs.push_back(strprintf("Short label mask=0x%04X", flag));
+ r.complete = true; // TODO wrong
}
break;
@@ -134,6 +154,7 @@ fig_result_t fig1_select(fig1_common_t& fig1, const display_settings_t &disp)
// TODO put label into ensembledatabase
r.msgs.push_back(strprintf("Label bytes=\"%s\"", string(label.begin(), label.end()).c_str()));
r.msgs.push_back(strprintf("Short label mask=0x%04X", flag));
+ r.complete = true; // TODO wrong
}
break;
@@ -172,12 +193,11 @@ fig_result_t fig1_select(fig1_common_t& fig1, const display_settings_t &disp)
// TODO put label into ensembledatabase
r.msgs.push_back(strprintf("Label bytes=\"%s\"", string(label.begin(), label.end()).c_str()));
r.msgs.push_back(strprintf("Short label mask=0x%04X", flag));
+ r.complete = true; // TODO wrong
}
break;
}
- // FIG1s always contain a complete set of information
- r.complete = true;
return r;
}
diff --git a/src/repetitionrate.cpp b/src/repetitionrate.cpp
index 970bcfc..81a50e1 100644
--- a/src/repetitionrate.cpp
+++ b/src/repetitionrate.cpp
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2016 Matthias P. Braendli (http://www.opendigitalradio.org)
+ Copyright (C) 2024 Matthias P. Braendli (http://www.opendigitalradio.org)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -20,11 +20,15 @@
*/
#include "repetitionrate.hpp"
+#include <algorithm>
+#include <cmath>
+#include <cstdio>
+#include <sstream>
+#include <string>
#include <vector>
+#include <array>
#include <map>
#include <set>
-#include <cmath>
-#include <limits>
using namespace std;
@@ -53,6 +57,8 @@ struct FIGRateInfo {
// Which FIBs this FIG was seen in
set<int> in_fib;
+
+ vector<uint8_t> lengths;
};
@@ -61,7 +67,7 @@ static map<FIGTypeExt, FIGRateInfo> fig_rates;
static int current_frame_number = 0;
static int current_fib = 0;
-void rate_announce_fig(int figtype, int figextension, bool complete)
+void rate_announce_fig(int figtype, int figextension, bool complete, uint8_t figlen)
{
FIGTypeExt f = {.figtype = figtype, .figextension = figextension};
@@ -77,112 +83,112 @@ void rate_announce_fig(int figtype, int figextension, bool complete)
rate.frames_complete.push_back(current_frame_number);
}
rate.in_fib.insert(current_fib);
+ rate.lengths.push_back(figlen);
}
-// Calculate the minimal, maximum and average repetition rate (FIGs per
-// second).
-void rate_min_max_avg(
+static double rate_avg(
const std::vector<int>& fig_positions,
- double* min,
- double* max,
- double* avg,
bool per_second)
{
- double avg_interval =
+ // Average interval is 1/N \sum_{i} pos_{i+1} - pos_{i}
+ // but this sums out all the intermediate pos_{i}, leaving us
+ // with 1/N (pos_{last} - pos_{first})
+ //
+ // N = size - 1 because we sum intervals, not points in time,
+ // and there's one less interval than there are points.
+
+ double avg =
(double)(fig_positions.back() - fig_positions.front()) /
(double)(fig_positions.size() - 1);
+ if (per_second) {
+ avg = 1.0 / (avg * FRAME_DURATION);
+ }
+ return avg;
+}
- 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];
+static double length_avg(const std::vector<uint8_t>& lengths)
+{
+ double avg = 0.0;
+ for (const uint8_t l : lengths) {
+ avg += l;
+ }
+ return avg / (double)lengths.size();
+}
- // Min
- if (min_delta > delta) {
- min_delta = delta;
- }
+static string length_histogram(const std::vector<uint8_t>& lengths)
+{
+ const array<const char*, 7> hist_chars({"▁", "▂", "▃", "▄", "▅", "▆", "▇"});
- // Max
- if (max_delta < delta) {
- max_delta = delta;
- }
+ // FIB length is 30
+ vector<size_t> histogram(30);
+ for (const uint8_t l : lengths) {
+ histogram.at(l)++;
}
- *avg = avg_interval;
- *min = min_delta;
- *max = max_delta;
+ const double max_hist = *std::max_element(histogram.cbegin(), histogram.cend());
- if (per_second) {
- *avg = 1.0 /
- (*avg * FRAME_DURATION);
- *min = 1.0 / (*min * FRAME_DURATION);
- *max = 1.0 / (*min * FRAME_DURATION);
+ stringstream ss;
+ ss << "[";
+ for (const size_t h : histogram) {
+ uint8_t char_ix = floor((double)h / (max_hist+1) * hist_chars.size());
+ ss << hist_chars.at(char_ix);
}
+ ss << "]";
+ return ss.str();
}
-void rate_display_header(bool per_second)
+
+void rate_display_analysis(bool per_second)
{
+
+#define GREPPABLE_PREFIX "CAROUSEL "
+
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");
+ printf(GREPPABLE_PREFIX
+ "FIG T/EXT AVG (COUNT) - AVG (COUNT) - LEN - LENGTH HISTOGRAM IN FIB(S)\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)
-{
for (auto& fig_rate : fig_rates) {
auto& frames_present = fig_rate.second.frames_present;
auto& frames_complete = fig_rate.second.frames_complete;
- 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 >= 2) {
+ printf(GREPPABLE_PREFIX);
- rate_min_max_avg(frames_present, &min, &max, &avg, per_second);
+ if (n_present >= 2) {
+ double avg = rate_avg(frames_present, per_second);
- printf("FIG%2d/%2d %4.2f %4.2f %4.2f (%5zu)",
+ printf("FIG%2d/%2d %6.2f (%5zu)",
fig_rate.first.figtype, fig_rate.first.figextension,
- min, avg, max,
+ avg,
n_present);
if (n_complete >= 2) {
- rate_min_max_avg(frames_complete, &min, &max, &avg, per_second);
+ double avg = rate_avg(frames_complete, per_second);
- printf(" - %4.2f %4.2f %4.2f (%5zu)",
- min, avg, max,
- n_present);
+ printf(" - %6.2f (%5zu)", avg, n_complete);
}
else {
- printf(" - None complete");
+ printf(" - None complete ");
}
}
else {
- printf("FIG%2d/%2d 0",
+ printf("FIG%2d/%2d ",
fig_rate.first.figtype, fig_rate.first.figextension);
}
- printf(" - in FIB(s):");
+ printf(" - %4.1f %s - ",
+ length_avg(fig_rate.second.lengths),
+ length_histogram(fig_rate.second.lengths).c_str());
+
for (auto& fib : fig_rate.second.in_fib) {
printf(" %d", fib);
}
printf("\n");
}
-
- if (clear) {
- fig_rates.clear();
- }
}
void rate_new_fib(int fib)
diff --git a/src/repetitionrate.hpp b/src/repetitionrate.hpp
index 41b5b40..b795351 100644
--- a/src/repetitionrate.hpp
+++ b/src/repetitionrate.hpp
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2016 Matthias P. Braendli (http://www.opendigitalradio.org)
+ Copyright (C) 2024 Matthias P. Braendli (http://www.opendigitalradio.org)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -20,28 +20,21 @@
*/
#pragma once
-#include "utils.hpp"
+#include <cstdint>
/* Tell the repetition rate analyser that we have received a given FIG.
* The complete flag should be set to true every time a complete
* set of information for that FIG has been received
*/
-void rate_announce_fig(int figtype, int figextension, bool complete);
+void rate_announce_fig(int figtype, int figextension, bool complete, uint8_t figlen);
/* Tell the repetition rate analyser that a new FIB starts.
*/
void rate_new_fib(int fib);
-/* 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_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);
+void rate_display_analysis(bool per_second);
diff --git a/src/utils.cpp b/src/utils.cpp
index e7420bd..6707b90 100644
--- a/src/utils.cpp
+++ b/src/utils.cpp
@@ -160,7 +160,7 @@ void printbuf(const std::string& header,
const std::string& desc,
const std::string& value)
{
- display_settings_t disp(true, indent);
+ display_settings_t disp(verbosity > 1, indent);
printyaml(header, disp, buffer, size, desc, value);
}
@@ -171,15 +171,7 @@ void printbuf(const string& header,
const std::string& desc,
const std::string& value)
{
- display_settings_t d = disp;
- d.print = (verbosity > 0);
- printyaml(header, d, buffer, size, desc, value);
-}
-
-void printbuf(const std::string& header, int indent)
-{
- display_settings_t disp(true, indent);
- return printyaml(header, disp);
+ printyaml(header, disp, buffer, size, desc, value);
}
void printfig(const string& header,
@@ -221,12 +213,6 @@ void printinfo(const string &header,
}
}
-void printinfo(const std::string &header, int min_verb)
-{
- const display_settings_t disp(true, 0);
- printinfo(header, min_verb);
-}
-
void printsequencestart(int indent)
{
for (int i = 0; i < indent; i++) {
diff --git a/src/utils.hpp b/src/utils.hpp
index ee5f7c9..23f767d 100644
--- a/src/utils.hpp
+++ b/src/utils.hpp
@@ -48,28 +48,27 @@ struct display_settings_t {
std::string strprintf(const char* fmt, ...);
-void printbuf(const std::string& header,
+void printfig(const std::string& header,
const display_settings_t &disp,
uint8_t* buffer,
size_t size,
const std::string& desc="",
const std::string& value="");
-void printfig(const std::string& header,
- const display_settings_t &disp,
- uint8_t* buffer,
- size_t size,
+void printbuf(const std::string& header,
+ int indent,
+ uint8_t* buffer=nullptr,
+ size_t size=0,
const std::string& desc="",
const std::string& value="");
void printbuf(const std::string& header,
- int indent,
+ const display_settings_t &disp,
uint8_t* buffer,
size_t size,
const std::string& desc="",
const std::string& value="");
-void printbuf(const std::string& header, int indent = 0);
void printvalue(const std::string& header,
int indent = 0,