diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index db054c2f..d016c134 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,7 +4,7 @@ on: push: branches: [dev, main, STL_2026_itu_submission] pull_request: - branches: [dev, main] + branches: [dev, main, STL_2026_itu_submission] jobs: build-and-test: @@ -58,7 +58,7 @@ jobs: run: | # Exclude build directory from Windows Defender to avoid scan delays powershell -Command "Add-MpPreference -ExclusionPath '${{ github.workspace }}'" - cmake . + cmake . -DCMAKE_C_FLAGS="/we4700" - name: Build (Unix) if: runner.os != 'Windows' diff --git a/CMakeLists.txt b/CMakeLists.txt index fcf6c233..c6f06c16 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.10...3.31) -project(STL2023 VERSION 2023) +project(STL2026 VERSION 2026) add_definitions( -DVERSION_STL="${CMAKE_PROJECT_NAME}" -DCMAKE_POLICY_VERSION_MINIMUM=3.5 ) @@ -22,7 +22,6 @@ add_subdirectory(src/basop/test_framework) add_subdirectory(src/basop/flc) add_subdirectory(src/bs1770demo) add_subdirectory(src/eid) -add_subdirectory(src/eid-amr) add_subdirectory(src/esdru) add_subdirectory(src/fir) add_subdirectory(src/freqresp) diff --git a/cmake/CompareTextFiles.cmake b/cmake/CompareTextFiles.cmake index 52e39133..562ca046 100644 --- a/cmake/CompareTextFiles.cmake +++ b/cmake/CompareTextFiles.cmake @@ -18,3 +18,8 @@ function(compare_text_files) message(FATAL_ERROR "Text file mismatch: ${_CTF_LABEL}\n--- got ---\n${_got}\n--- expected ---\n${_want}") endif() endfunction() + +# Auto-invoke when called via cmake -P with -D variables +if(DEFINED GOT AND DEFINED EXPECTED) + compare_text_files(GOT "${GOT}" EXPECTED "${EXPECTED}" LABEL "${LABEL}") +endif() diff --git a/doc/g191.md b/doc/g191.md index 58cab3b7..0e1b76e1 100644 --- a/doc/g191.md +++ b/doc/g191.md @@ -12,27 +12,23 @@ Please refer to the official Recommendation ITU-T G.191 for the complete text: [ Recommendation ITU-T G.191 provides source code for speech and audio processing modules for narrowband, wideband and super-wideband telephony applications. The set includes codecs, filters, noise generators. -This edition introduces changes to Annex A, which describes the ITU-T Software Tools (STL) containing a high-quality, portable C code library for speech processing applications. This release of the STL, also known as STL2024, incorporates: +This edition introduces changes to Annex A, which describes the ITU-T Software Tools (STL) containing a high-quality, portable C code library for speech processing applications. This release of the STL, also known as STL2026, incorporates: -* BS1770demo improvements: +* WAV file I/O support with multi-bit-depth (16/24/32-bit) processing for all tools - - a new RMS option disabling the gating function for background noise measurement, +* Extensions to the speech voltmeter (sv56) for arbitrary bit-depth processing - - the handling of the edge case where all gating blacks are below -70 LKFS, +* A delay-and-error profile to frame-erasure pattern conversion tool (dlyerr\_2\_errpat) for jitter buffer emulation (3GPP S4-121077) - - improved reporting with scaling factor being reported in the linear and log domains. +* An EID for 3GPP AMR bitstreams (eid-amr) -* WMC Tool updates: +* A pseudo-random selection tool (random) for EVS processing scripts (3GPP S4-121078) - - New command line parameter to allow control on the number of frames per second (default still 50) +* SHQ2/SHQ3 half-band and HP50 high-pass FIR filters - - Export information on all memory allocations occurring during runtime - - - Example script for graphical analysis and profiling of dymanic memory allocation +* Cross-platform portability fixes with expanded CTest regression coverage - - Bugs fixes and code improvements - -Recommendation ITU-T G.191 includes an electronic attachment containing STL2024 and manual. +Recommendation ITU-T G.191 includes an electronic attachment containing STL2026 and manual. ## Keywords diff --git a/doc/g191_Annex_A.md b/doc/g191_Annex_A.md index 68ea05c1..925496df 100644 --- a/doc/g191_Annex_A.md +++ b/doc/g191_Annex_A.md @@ -40,6 +40,9 @@ The following programs are examples of the use of the modules: | `stereoop.c` | on the use of stereo file operations. | | `esdru.c` | on the use of energy-based spatial distortion reference unit [ITU-T P.811]. | | `wmc_tool.cpp` | on the use of WMC tool for speech and audio codecs complexity and memory measurement. | +| `dlyerr_2_errpat.c` | on the use of the delay/error profile to frame-erasure pattern conversion tool for jitter buffer emulation. | +| `eid-amr.c` | on the use of the EID for 3GPP AMR codec frame erasure simulation using G.192 error patterns. | +| `random.c` | on the use of the pseudo-random selection tool for deterministic item selection or range drawing. | || @@ -85,6 +88,12 @@ The functions included are as follows: | `LP12_48kHz_init` | initialize a low-pass filter with a cut-off frequency of 12 kHz at (48-kHz sampling). | | `LP14_48kHz_init` | initialize a low-pass filter with a cut-off frequency of 14 kHz at 48-kHz sampling). | | `LP20_48kHz_init` | initialize a low-pass filter with a cut-off frequency of 20 kHz (48-kHz sampling). | +| `shq_up_1_to_2_init` | initialize 1:2 SHQ half-band up-sampling filter. | +| `shq_up_1_to_3_init` | initialize 1:3 SHQ up-sampling filter. | +| `shq_down_2_to_1_init` | initialize 2:1 SHQ half-band down-sampling filter. | +| `shq_down_3_to_1_init` | initialize 3:1 SHQ down-sampling filter. | +| `hp50_32khz_init` | initialize 50-Hz high-pass filter (32-kHz sampling). | +| `hp50_48khz_init` | initialize 50-Hz high-pass filter (48-kHz sampling). | | `hq_kernel` | FIR filtering function. | | `hq_reset` | clear state variables. | | `hq_free` | deallocate FIR-filter memory. | @@ -710,4 +719,22 @@ The main program for WMC Tool. Depends on: `wmc_auto_c.txt` Auto-generated C source file for inclusion in projects. ------------------------------------------------------------------------------------------ +## u) Delay/error profile to frame-erasure pattern conversion + +Name: `dlyerr_2_errpat.c` + +Converts a delay-and-error profile (one entry per packet with network delay in ms and a loss flag) into a frame-erasure error pattern suitable for use with the `eid-xor` tool. Supports fixed-delay and bounded-loss-rate jitter buffer emulation modes. Output formats include G.192 word, G.192 byte, and text. + +## v) EID for 3GPP AMR codec + +Name: `eid-amr.c` + +Applies G.192 frame erasure patterns to 3GPP AMR bitstreams. The standard `eid-xor` tool cannot be used directly with AMR because the AMR bitstream follows the ETSI/3GPP format rather than ITU-T G.192. Lost frames are signalled with frame type NO\_DATA and all data bits are forced to zero. + +## w) Pseudo-random selection tool + +Name: `random.c` + +Provides deterministic pseudo-random selection of items from a list or drawing of integers from a numeric range. Uses the EID linear congruential generator for cross-platform reproducibility. Supports configurable seed, dummy pre-runs, and multi-item selection. + -=Pagebreak=- diff --git a/doc/manual/STLmanual.tex b/doc/manual/STLmanual.tex index 6d93605c..ac628910 100644 --- a/doc/manual/STLmanual.tex +++ b/doc/manual/STLmanual.tex @@ -18,7 +18,7 @@ \addtolength{\itemsep}{-20pt} % Define headers -\def\ugst_title{ ITU-T Software Tool Library, release 2024} +\def\ugst_title{ ITU-T Software Tool Library, release 2026} \def\us{$\mu$s} \markboth{ \hspace{1cm} \hfill \ugst_title }% { Version: \today \hfill \hspace{1cm} } @@ -61,7 +61,7 @@ \pagenumbering{roman} %============================================================================== -\title{ITU-T Software Tool Library 2024 User's Manual} +\title{ITU-T Software Tool Library 2026 User's Manual} \author{ITU-T Users' Group on Software Tools} %------------------------------------------------------------------------------ @@ -71,7 +71,7 @@ \ruley{100mm} - Copyright \copyright~ 2005, 2006, 2009, 2019, 2022, 2023 and 2024 by the International + Copyright \copyright~ 2005, 2006, 2009, 2019, 2022, 2023, 2024 and 2026 by the International Telecommunication Union (ITU) \ruley{15mm} diff --git a/doc/manual/intro.tex b/doc/manual/intro.tex index 07eadbe2..ea4e0868 100644 --- a/doc/manual/intro.tex +++ b/doc/manual/intro.tex @@ -31,6 +31,8 @@ \chapter{Introduction} In 2024, the revision of the STL offers additional features and bug fixes to the BS.1770 demo and WMC tool. +In 2026, the proposed revision of the STL adds: WAV file I/O support with multi-bit-depth (16/24/32-bit) processing for all tools; extensions to the speech voltmeter (sv56) for arbitrary bit-depth processing; a delay-and-error profile to frame-erasure pattern conversion tool (dlyerr\_2\_errpat) for jitter buffer emulation (3GPP S4-121077); an EID for 3GPP AMR bitstreams (eid-amr); a pseudo-random selection tool (random) for EVS processing scripts (3GPP S4-121078); SHQ2/SHQ3 half-band and HP50 high-pass FIR filters; and cross-platform portability fixes with expanded CTest regression coverage. + Since STL2019, the build toolchain uses CMake to generate platform-dependent and tool-dependent build scripts as well as to execute regression tests for each module in the STL. Modules have been tested on Windows, MacOS and several Linux flavors. @@ -195,6 +197,8 @@ \section{Acknowledgements} For the STL2024, the improvements to BS.1770 demo and WMC Tool were kindly provided by Mr Erik Norvell from Ericsson and Mr Vladimir Malenovsky from VoiceAge Corporation respectively. +For the STL2026, the dlyerr\_2\_errpat tool (delay/error profile to frame-erasure pattern converter) and the random tool were kindly contributed by Mr Stefan Doehla from Fraunhofer IIS via 3GPP SA4. The SHQ2/SHQ3 and HP50 FIR filters and the eid-amr tool (EID for 3GPP AMR bitstreams) were contributed by Mr St\'{e}phane Ragot. Mr Markus Multrus from Fraunhofer IIS contributed bug fixes to the basic operators documentation. The sv56 updates were provided by Mr Jan Reimes from HEAD acoustics. The WAV I/O support, integration of contributions, and maintenance of the GitHub repository were performed by Mr Ludovic Malfait (BT Group). + Above all, special thank goes to ITU-T SG16 Counselor Mr~Sim\~ao Ferraz de Campos Neto, the ``father'' of the STL. %============================================================================= @@ -236,6 +240,7 @@ \chapter{Tutorial} \item[STL2022] ITU-T Software Tools Library, release 2022. \item[STL2023] ITU-T Software Tools Library, release 2023. \item[STL2024] ITU-T Software Tools Library, release 2024. +\item[STL2026] ITU-T Software Tools Library, release 2026. \item[UGST] Users' Group on Software Tools, of ITU-T Study Group 16. \end{Descr} diff --git a/doc/manual/unsup.tex b/doc/manual/unsup.tex index 06e07862..bb6d6b7c 100644 --- a/doc/manual/unsup.tex +++ b/doc/manual/unsup.tex @@ -69,7 +69,7 @@ \section{Source code} level. For Unix/MSDOS. \item[random.c:] - randomization tool for selecting items from a list or + randomization tool for selecting items from a list or drawing numbers from a range. Reuses the EID linear congruential generator from eid.c. For Unix/MSDOS. diff --git a/src/eid/bs-stats.c b/src/eid/bs-stats.c index be380291..7de91771 100644 --- a/src/eid/bs-stats.c +++ b/src/eid/bs-stats.c @@ -213,7 +213,7 @@ int main (int argc, char *argv[]) { /* Command line parameters */ char bs_format = g192; /* Generic Speech bitstream format */ char ibs_file[MAX_STRLEN]; /* Input bitstream file */ - char out_file[MAX_STRLEN]; /* Output ASCII file */ + char out_file[MAX_STRLEN] = "-"; /* Output ASCII file */ char log = 1; /* Flag for en/dis-abling output file */ long fr_len = 0; /* Frame length in bits */ long bs_len; /* BS frame length, with headers */ diff --git a/src/fir/CMakeLists.txt b/src/fir/CMakeLists.txt index 9a3aeeb0..904150a3 100644 --- a/src/fir/CMakeLists.txt +++ b/src/fir/CMakeLists.txt @@ -173,7 +173,7 @@ add_test(filter29 ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/filter -q SHQ3 test_data/tes add_test(filter29-verify ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/signal-diff -q -equiv 1 test_data/test-shq3.flt test_data/tst-shq3.ref) add_test(filter30 ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/filter -q HP50_32KHZ test_data/test.src test_data/test-hp50-32khz.flt) -add_test(filter30-verify ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/signal-diff -q test_data/test-hp50-32khz.flt test_data/test-hp50-32khz.ref) +add_test(filter30-verify ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/signal-diff -q -equiv 1 test_data/test-hp50-32khz.flt test_data/test-hp50-32khz.ref) add_test(filter31 ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/filter -q HP50_48KHZ test_data/test.src test_data/test-hp50-48khz.flt) -add_test(filter31-verify ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/signal-diff -q test_data/test-hp50-48khz.flt test_data/test-hp50-48khz.ref) +add_test(filter31-verify ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/signal-diff -q -equiv 1 test_data/test-hp50-48khz.flt test_data/test-hp50-48khz.ref) diff --git a/src/g728/g728fixed/g728fpdec.c b/src/g728/g728fixed/g728fpdec.c index 31f2fd5d..caa9497b 100644 --- a/src/g728/g728fixed/g728fpdec.c +++ b/src/g728/g728fixed/g728fpdec.c @@ -111,6 +111,7 @@ void g728fp_decinit (G728FpDecData * d) { d->ferased = 0; d->fecount = 0; d->ofecount = 0; + d->ogaindb = 0; d->tap = 0; g728fp_zerof (d->etpast, KPMAX); d->feframesz = 4; /* 10. msec */ @@ -137,7 +138,7 @@ void g728fp_decode (Short * speech, /* output speech */ Float *aptr; /* For attenuating a or atmp */ Float gptmp[LPCLG]; Gain gain; - Float gaindb; + Float gaindb = 0; Statelpc et; Float multfac; Float rc; diff --git a/src/is54/g_quant.c b/src/is54/g_quant.c index 3ebf028c..5d3f6225 100644 --- a/src/is54/g_quant.c +++ b/src/is54/g_quant.c @@ -39,18 +39,18 @@ Motorola Inc. static FTYPE corr (FTYPE *vec1Ptr, FTYPE *vec2Ptr); int G_QUANT (int lag, FTYPE rs00, FTYPE rs11, FTYPE rs22) { - FTYPE Rpc0; /* correlation between the weighted speech and the */ + FTYPE Rpc0 = 0.0; /* correlation between the weighted speech and the */ /* weighted pitch excitation vector */ FTYPE Rpc1; /* correlation between the weighted speech and the */ /* weighted 1st codebook excitation vector */ FTYPE Rpc2; /* correlation between the weighted speech and the */ /* weighted 2nd codebook excitation vector */ - FTYPE Rcc00; /* Rcc(mn) -- correlation between excitation vector */ + FTYPE Rcc00 = 0.0; /* Rcc(mn) -- correlation between excitation vector */ /* m and n, where vector 0 is the pitch excitation, */ /* vector 1 is the 1st codebook excitation, and */ /* vector 2 is the 2nd codebook excitation */ - FTYPE Rcc01; /* */ - FTYPE Rcc02; /* */ + FTYPE Rcc01 = 0.0; /* */ + FTYPE Rcc02 = 0.0; /* */ FTYPE Rcc11; /* */ FTYPE Rcc12; /* */ FTYPE Rcc22; /* */ @@ -63,7 +63,7 @@ int G_QUANT (int lag, FTYPE rs00, FTYPE rs11, FTYPE rs22) { FTYPE maxVal; /* the current best (maximum) error value */ int code; /* the best GSP0 centroid, returned to T_SUB() */ - FTYPE *savePtr, *tmpPtr, *tmpPtr2, *endPtr, *endPtr2; + FTYPE *savePtr = NULL, *tmpPtr, *tmpPtr2, *endPtr, *endPtr2; errCoefs = (FTYPE *) malloc (GSP0_TERMS * sizeof (FTYPE)); diff --git a/src/is54/init.c b/src/is54/init.c index d96f72a2..06f6dcf0 100644 --- a/src/is54/init.c +++ b/src/is54/init.c @@ -88,13 +88,13 @@ void initTables () { FILE *fptmp; char *line; - line = (char *) malloc (MAXLINE * sizeof (char)); + line = (char *) calloc (MAXLINE, sizeof (char)); /* allocate input speech buffer, interpolated coef buffer, and residual */ /* energy estimate buffer */ - inBuf = (FTYPE *) malloc (INBUFSIZ * sizeof (FTYPE)); - I_CBUFF = (FTYPE *) malloc ((NP * 3 * N_SUB) * sizeof (FTYPE)); - RS_BUFF = (FTYPE *) malloc ((2 * N_SUB) * sizeof (FTYPE)); + inBuf = (FTYPE *) calloc (INBUFSIZ, sizeof (FTYPE)); + I_CBUFF = (FTYPE *) calloc (NP * 3 * N_SUB, sizeof (FTYPE)); + RS_BUFF = (FTYPE *) calloc (2 * N_SUB, sizeof (FTYPE)); /* initialize codes to zero (in case 1st denominator in FLAT is zero) */ codeBuf = (int *) calloc (numCodes, sizeof (int)); @@ -109,29 +109,29 @@ void initTables () { /* (1<<(K_BITS_8+1))-1 + (1<<(K_BITS_9+1))-1 + */ /* (1<<(K_BITS_10+1))-1; */ numDecisionVals = 445; - *r0kAddr = (FTYPE *) malloc (numDecisionVals * sizeof (FTYPE)); - sst = (FTYPE *) malloc ((NP + 1) * sizeof (FTYPE)); + *r0kAddr = (FTYPE *) calloc (numDecisionVals, sizeof (FTYPE)); + sst = (FTYPE *) calloc ((NP + 1), sizeof (FTYPE)); /* T_SUB() and R_SUB() allocations */ - T_STATE = (FTYPE *) malloc (NP * sizeof (FTYPE)); - T_VEC = (FTYPE *) malloc (S_LEN * sizeof (FTYPE)); - P = (FTYPE *) malloc (S_LEN * sizeof (FTYPE)); - P_VEC = (FTYPE *) malloc (S_LEN * sizeof (FTYPE)); - W_P_VEC = (FTYPE *) malloc (S_LEN * sizeof (FTYPE)); - BASIS = (FTYPE *) malloc (S_LEN * C_BITS * sizeof (FTYPE)); - BASIS_A = (FTYPE *) malloc (S_LEN * C_BITS_A * sizeof (FTYPE)); - W_BASIS = (FTYPE *) malloc (S_LEN * C_BITS * sizeof (FTYPE)); - BITS = (FTYPE *) malloc (C_BITS * sizeof (FTYPE)); - X_VEC = (FTYPE *) malloc (S_LEN * sizeof (FTYPE)); - W_X_VEC = (FTYPE *) malloc (S_LEN * sizeof (FTYPE)); - X_A_VEC = (FTYPE *) malloc (S_LEN * sizeof (FTYPE)); - W_X_A_VEC = (FTYPE *) malloc (S_LEN * sizeof (FTYPE)); + T_STATE = (FTYPE *) calloc (NP, sizeof (FTYPE)); + T_VEC = (FTYPE *) calloc (S_LEN, sizeof (FTYPE)); + P = (FTYPE *) calloc (S_LEN, sizeof (FTYPE)); + P_VEC = (FTYPE *) calloc (S_LEN, sizeof (FTYPE)); + W_P_VEC = (FTYPE *) calloc (S_LEN, sizeof (FTYPE)); + BASIS = (FTYPE *) calloc (S_LEN * C_BITS, sizeof (FTYPE)); + BASIS_A = (FTYPE *) calloc (S_LEN * C_BITS_A, sizeof (FTYPE)); + W_BASIS = (FTYPE *) calloc (S_LEN * C_BITS, sizeof (FTYPE)); + BITS = (FTYPE *) calloc (C_BITS, sizeof (FTYPE)); + X_VEC = (FTYPE *) calloc (S_LEN, sizeof (FTYPE)); + W_X_VEC = (FTYPE *) calloc (S_LEN, sizeof (FTYPE)); + X_A_VEC = (FTYPE *) calloc (S_LEN, sizeof (FTYPE)); + W_X_A_VEC = (FTYPE *) calloc (S_LEN, sizeof (FTYPE)); T_P_STATE = (FTYPE *) calloc (LMAX, sizeof (FTYPE)); xmtExPtr = T_P_STATE + LMAX - S_LEN; - TABLE = (int *) malloc (((1 << C_BITS) - 2) * sizeof (int)); - GSP0_TABLE = (FTYPE *) malloc (GSP0_TERMS * GSP0_NUM * sizeof (FTYPE)); + TABLE = (int *) calloc (((1 << C_BITS) - 2), sizeof (int)); + GSP0_TABLE = (FTYPE *) calloc (GSP0_TERMS * GSP0_NUM, sizeof (FTYPE)); R_P_STATE = (FTYPE *) calloc (LMAX, sizeof (FTYPE)); - outBuf = (FTYPE *) malloc (S_LEN * sizeof (FTYPE)); + outBuf = (FTYPE *) calloc (S_LEN, sizeof (FTYPE)); /* fill r0 quantization table */ temp = sqrt ((double) S_LEN); /* sqrt (S_LEN * max amplitude squared) */ @@ -229,7 +229,7 @@ void initTables () { #include "gray.i" /* gray-code table */ /* store SST bandwidth widening factors for A_SST() */ - P_SST = (FTYPE *) malloc ((NP + 1) * sizeof (FTYPE)); + P_SST = (FTYPE *) calloc ((NP + 1), sizeof (FTYPE)); nb = log (0.5) / (2.0 * log (cos ((4.0 * atan (1.0) * POST_BEQ_N) / (2.0 * SRATE)))); temp = 1.0; diff --git a/src/is54/lag.c b/src/is54/lag.c index a022700d..e924f782 100644 --- a/src/is54/lag.c +++ b/src/is54/lag.c @@ -50,7 +50,7 @@ int LAG_SEARCH () { FTYPE Cl; /* Holds the cross correlation between bl and P, the */ /* weighted speech, for lag l */ FTYPE Gl; /* Holds the energy in bl */ - FTYPE E; /* Holds the partial energy of bl for lags greater */ + FTYPE E = 0.0; /* Holds the partial energy of bl for lags greater */ /* than S_LEN */ FTYPE ClBest = 0.0; /* Holds the value of Cl for the current best */ /* Cl**2 / Gl */ diff --git a/src/mnru/CMakeLists.txt b/src/mnru/CMakeLists.txt index 26dba2a7..23b587de 100644 --- a/src/mnru/CMakeLists.txt +++ b/src/mnru/CMakeLists.txt @@ -88,7 +88,7 @@ add_test(p50fbmnru_Q0_clipping_clamp ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/p50fbmnru add_test(p50fbmnru_Q0_clipping_clamp-verify ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/cf -q test_data/P501_D_AM_fm_FB_48k_Q0_clamp.ref test_data/P501_D_AM_fm_FB_48k_Q0_clamp.pcm) add_test(p50fbmnru_Q0_clipping_overflow ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/p50fbmnru test_data/P501_D_AM_fm_FB_48k.pcm test_data/P501_D_AM_fm_FB_48k_Q0_overflow.pcm 0 M --overflow) -add_test(p50fbmnru_Q0_clipping_overflow-verify ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/cf -q test_data/P501_D_AM_fm_FB_48k_Q0_overflow.ref test_data/P501_D_AM_fm_FB_48k_Q0_overflow.pcm) +add_test(p50fbmnru_Q0_clipping_overflow-verify ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/signal-diff -q -equiv 1 test_data/P501_D_AM_fm_FB_48k_Q0_overflow.ref test_data/P501_D_AM_fm_FB_48k_Q0_overflow.pcm) #TEST: Compute SNR for MNRU files #TODO: no automatic verification data available diff --git a/src/mnru/p50fbmnru.c b/src/mnru/p50fbmnru.c index e21cd6fb..5d58e51b 100644 --- a/src/mnru/p50fbmnru.c +++ b/src/mnru/p50fbmnru.c @@ -45,7 +45,7 @@ int main(int argc, char *argv[]) { MNRU_state state; FILE *In, *Out; - char dcFilterMode ; + char dcFilterMode = 0; short B_Len, BuffLen; long lFileLen = 0; int i, B_Max; diff --git a/src/mnru/snr.c b/src/mnru/snr.c index c90beb9c..0f975a37 100644 --- a/src/mnru/snr.c +++ b/src/mnru/snr.c @@ -54,6 +54,7 @@ float get_SNR (int mode, short *a, short *b, long N, long N2, SNR_state * s) { s->tot_smpno = 0; s->total_err = 0; s->total_sqr = 0; + s->total_snr_dB = 0; } diff --git a/src/sv56/CMakeLists.txt b/src/sv56/CMakeLists.txt index 9ef94bda..dac870a9 100644 --- a/src/sv56/CMakeLists.txt +++ b/src/sv56/CMakeLists.txt @@ -22,35 +22,125 @@ set_tests_properties(sv56demo2-verify PROPERTIES WORKING_DIRECTORY ${CMAKE_CURRE add_test(sv56demo3 ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/actlev -q test_data/voice.src test_data/voice.nrm test_data/voice.prc test_data/voice.ltl test_data/voice.rms) set_tests_properties(sv56demo3 PROPERTIES WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) -add_executable(sv56test sv56test.c sv-p56.c) -target_link_libraries(sv56test ${M_LIBRARY}) +# 12-bit backward compatibility test +add_test(sv56demo4 ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/sv56demo -q -log test_data/voice_12bit.log test_data/voice.src test_data/voice_12bit.prc 256 1 0 -30 16000 12) +set_tests_properties(sv56demo4 PROPERTIES WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) +add_test(sv56demo4-verify ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/cf -q test_data/voice_12bit.nrm test_data/voice_12bit.prc) +set_tests_properties(sv56demo4-verify PROPERTIES WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} DEPENDS sv56demo4) +add_test(sv56demo4-log-verify ${CMAKE_COMMAND} + -DGOT=${CMAKE_CURRENT_SOURCE_DIR}/test_data/voice_12bit.log + -DEXPECTED=${CMAKE_CURRENT_SOURCE_DIR}/test_data/voice_12bit.log.ref + -DLABEL=sv56demo4-log + -P ${CMAKE_SOURCE_DIR}/cmake/CompareTextFiles.cmake) +set_tests_properties(sv56demo4-log-verify PROPERTIES DEPENDS sv56demo4) + +# WAV integration tests +add_test(sv56demo-wav-24bit-normal ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/sv56demo -q test_data/speech_normal_24bit.wav test_data/speech_normal_24bit.out) +set_tests_properties(sv56demo-wav-24bit-normal PROPERTIES WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) + +add_test(sv56demo-wav-24bit-normal-verify ${CMAKE_COMMAND} -E compare_files test_data/speech_normal_24bit.ref test_data/speech_normal_24bit.out) +set_tests_properties(sv56demo-wav-24bit-normal-verify PROPERTIES WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) + +add_test(sv56demo-wav-32bit ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/sv56demo -q test_data/speech_normal_32bit.wav test_data/speech_normal_32bit.out) +set_tests_properties(sv56demo-wav-32bit PROPERTIES WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) + +add_test(sv56demo-wav-32bit-verify ${CMAKE_COMMAND} -E compare_files test_data/speech_normal_32bit.ref test_data/speech_normal_32bit.out) +set_tests_properties(sv56demo-wav-32bit-verify PROPERTIES WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) + +add_test(sv56demo-wav-24bit ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/sv56demo -q test_data/speech_quiet_24bit.wav test_data/speech_quiet_24bit.out) +set_tests_properties(sv56demo-wav-24bit PROPERTIES WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) + +add_test(sv56demo-wav-24bit-verify ${CMAKE_COMMAND} -E compare_files test_data/speech_quiet_24bit.ref test_data/speech_quiet_24bit.out) +set_tests_properties(sv56demo-wav-24bit-verify PROPERTIES WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) + +add_test(sv56demo-wav-float ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/sv56demo -q test_data/speech_quiet_32bit_float.wav test_data/speech_quiet_32bit_float.out) +set_tests_properties(sv56demo-wav-float PROPERTIES WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) + +add_test(sv56demo-wav-float-verify ${CMAKE_COMMAND} -E compare_files test_data/speech_quiet_32bit_float.ref test_data/speech_quiet_32bit_float.out) +set_tests_properties(sv56demo-wav-float-verify PROPERTIES WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) + +add_test(sv56demo-wav-vquiet-32bit ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/sv56demo -q test_data/speech_vquiet_32bit.wav test_data/speech_vquiet_32bit.out) +set_tests_properties(sv56demo-wav-vquiet-32bit PROPERTIES WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) + +add_test(sv56demo-wav-vquiet-32bit-verify ${CMAKE_COMMAND} -E compare_files test_data/speech_vquiet_32bit.ref test_data/speech_vquiet_32bit.out) +set_tests_properties(sv56demo-wav-vquiet-32bit-verify PROPERTIES WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) + +add_test(sv56demo-wav-vquiet-16bit-adc ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/sv56demo -q -bits 16 test_data/speech_vquiet_32bit.wav test_data/speech_vquiet_32bit_16bit.out) +set_tests_properties(sv56demo-wav-vquiet-16bit-adc PROPERTIES WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) + +add_test(sv56demo-wav-vquiet-16bit-adc-verify ${CMAKE_COMMAND} -E compare_files test_data/speech_vquiet_32bit_16bit.ref test_data/speech_vquiet_32bit_16bit.out) +set_tests_properties(sv56demo-wav-vquiet-16bit-adc-verify PROPERTIES WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) + +# WAV text output (statistics) verification tests +add_test(sv56demo-wav-24bit-normal-log ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/sv56demo -q -log test_data/speech_normal_24bit.log test_data/speech_normal_24bit.wav test_data/speech_normal_24bit.out) +set_tests_properties(sv56demo-wav-24bit-normal-log PROPERTIES WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) -add_executable(sv56-convert sv56-convert.c) -target_link_libraries(sv56-convert ${M_LIBRARY}) +add_test(sv56demo-wav-24bit-normal-log-verify ${CMAKE_COMMAND} + -DGOT=${CMAKE_CURRENT_SOURCE_DIR}/test_data/speech_normal_24bit.log + -DEXPECTED=${CMAKE_CURRENT_SOURCE_DIR}/test_data/speech_normal_24bit.log.ref + -DLABEL=sv56demo-wav-24bit-normal-log + -P ${CMAKE_SOURCE_DIR}/cmake/CompareTextFiles.cmake) + +add_test(sv56demo-wav-32bit-log ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/sv56demo -q -log test_data/speech_normal_32bit.log test_data/speech_normal_32bit.wav test_data/speech_normal_32bit.out) +set_tests_properties(sv56demo-wav-32bit-log PROPERTIES WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) + +add_test(sv56demo-wav-32bit-log-verify ${CMAKE_COMMAND} + -DGOT=${CMAKE_CURRENT_SOURCE_DIR}/test_data/speech_normal_32bit.log + -DEXPECTED=${CMAKE_CURRENT_SOURCE_DIR}/test_data/speech_normal_32bit.log.ref + -DLABEL=sv56demo-wav-32bit-log + -P ${CMAKE_SOURCE_DIR}/cmake/CompareTextFiles.cmake) + +add_test(sv56demo-wav-vquiet-32bit-log ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/sv56demo -q -log test_data/speech_vquiet_32bit.log test_data/speech_vquiet_32bit.wav test_data/speech_vquiet_32bit.out) +set_tests_properties(sv56demo-wav-vquiet-32bit-log PROPERTIES WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) + +add_test(sv56demo-wav-vquiet-32bit-log-verify ${CMAKE_COMMAND} + -DGOT=${CMAKE_CURRENT_SOURCE_DIR}/test_data/speech_vquiet_32bit.log + -DEXPECTED=${CMAKE_CURRENT_SOURCE_DIR}/test_data/speech_vquiet_32bit.log.ref + -DLABEL=sv56demo-wav-vquiet-32bit-log + -P ${CMAKE_SOURCE_DIR}/cmake/CompareTextFiles.cmake) + +add_test(sv56demo-wav-vquiet-16bit-adc-log ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/sv56demo -q -log test_data/speech_vquiet_32bit_16bit.log -bits 16 test_data/speech_vquiet_32bit.wav test_data/speech_vquiet_32bit_16bit.out) +set_tests_properties(sv56demo-wav-vquiet-16bit-adc-log PROPERTIES WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) + +add_test(sv56demo-wav-vquiet-16bit-adc-log-verify ${CMAKE_COMMAND} + -DGOT=${CMAKE_CURRENT_SOURCE_DIR}/test_data/speech_vquiet_32bit_16bit.log + -DEXPECTED=${CMAKE_CURRENT_SOURCE_DIR}/test_data/speech_vquiet_32bit_16bit.log.ref + -DLABEL=sv56demo-wav-vquiet-16bit-adc-log + -P ${CMAKE_SOURCE_DIR}/cmake/CompareTextFiles.cmake) + +# actlev WAV integration tests +add_test(actlev-wav-24bit ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/actlev -q -log test_data/actlev_normal_24bit.log test_data/speech_normal_24bit.wav) +set_tests_properties(actlev-wav-24bit PROPERTIES WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) + +add_test(actlev-wav-24bit-verify ${CMAKE_COMMAND} + -DGOT=${CMAKE_CURRENT_SOURCE_DIR}/test_data/actlev_normal_24bit.log + -DEXPECTED=${CMAKE_CURRENT_SOURCE_DIR}/test_data/actlev_normal_24bit.log.ref + -DLABEL=actlev-wav-24bit + -P ${CMAKE_SOURCE_DIR}/cmake/CompareTextFiles.cmake) -add_test(sv56test-16bit ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/sv56test 16 test_data/voice.src test_data/voice_16bit.out) -set_tests_properties(sv56test-16bit PROPERTIES WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) +add_test(actlev-wav-vquiet-32bit ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/actlev -q -log test_data/actlev_vquiet_32bit.log test_data/speech_vquiet_32bit.wav) +set_tests_properties(actlev-wav-vquiet-32bit PROPERTIES WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) -add_test(sv56test-16bit-verify ${CMAKE_COMMAND} - -DGOT=${CMAKE_CURRENT_SOURCE_DIR}/test_data/voice_16bit.out - -DEXPECTED=${CMAKE_CURRENT_SOURCE_DIR}/test_data/voice_16bit.ref - -DLABEL=sv56test-16bit +add_test(actlev-wav-vquiet-32bit-verify ${CMAKE_COMMAND} + -DGOT=${CMAKE_CURRENT_SOURCE_DIR}/test_data/actlev_vquiet_32bit.log + -DEXPECTED=${CMAKE_CURRENT_SOURCE_DIR}/test_data/actlev_vquiet_32bit.log.ref + -DLABEL=actlev-wav-vquiet-32bit -P ${CMAKE_SOURCE_DIR}/cmake/CompareTextFiles.cmake) -add_test(sv56test-24bit ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/sv56test 24 test_data/voice_24.src test_data/voice_24bit.out) -set_tests_properties(sv56test-24bit PROPERTIES WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) +add_test(actlev-wav-vquiet-16bit-adc ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/actlev -q -bits 16 -log test_data/actlev_vquiet_32bit_16bit.log test_data/speech_vquiet_32bit.wav) +set_tests_properties(actlev-wav-vquiet-16bit-adc PROPERTIES WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) -add_test(sv56test-24bit-verify ${CMAKE_COMMAND} - -DGOT=${CMAKE_CURRENT_SOURCE_DIR}/test_data/voice_24bit.out - -DEXPECTED=${CMAKE_CURRENT_SOURCE_DIR}/test_data/voice_24bit.ref - -DLABEL=sv56test-24bit +add_test(actlev-wav-vquiet-16bit-adc-verify ${CMAKE_COMMAND} + -DGOT=${CMAKE_CURRENT_SOURCE_DIR}/test_data/actlev_vquiet_32bit_16bit.log + -DEXPECTED=${CMAKE_CURRENT_SOURCE_DIR}/test_data/actlev_vquiet_32bit_16bit.log.ref + -DLABEL=actlev-wav-vquiet-16bit-adc -P ${CMAKE_SOURCE_DIR}/cmake/CompareTextFiles.cmake) -add_test(sv56test-32bit ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/sv56test 32 test_data/voice_32.src test_data/voice_32bit.out) -set_tests_properties(sv56test-32bit PROPERTIES WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) +add_test(actlev-wav-multi ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/actlev -q -log test_data/actlev_multi.log test_data/speech_normal_24bit.wav test_data/speech_vquiet_32bit.wav) +set_tests_properties(actlev-wav-multi PROPERTIES WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) -add_test(sv56test-32bit-verify ${CMAKE_COMMAND} - -DGOT=${CMAKE_CURRENT_SOURCE_DIR}/test_data/voice_32bit.out - -DEXPECTED=${CMAKE_CURRENT_SOURCE_DIR}/test_data/voice_32bit.ref - -DLABEL=sv56test-32bit +add_test(actlev-wav-multi-verify ${CMAKE_COMMAND} + -DGOT=${CMAKE_CURRENT_SOURCE_DIR}/test_data/actlev_multi.log + -DEXPECTED=${CMAKE_CURRENT_SOURCE_DIR}/test_data/actlev_multi.log.ref + -DLABEL=actlev-wav-multi -P ${CMAKE_SOURCE_DIR}/cmake/CompareTextFiles.cmake) diff --git a/src/sv56/README.md b/src/sv56/README.md index 0cf60760..30dd6898 100644 --- a/src/sv56/README.md +++ b/src/sv56/README.md @@ -6,72 +6,73 @@ CODING STANDARDS". ============================================================= -The UGST P.56 speech voltmeter module, version 3.1 (21/Aug/95), needs the -following files: +# UGST P.56 Speech Voltmeter -# C program code -``` -sv-p56.c ........ the speech voltmeter (SV) module itself; needs the - prototypes in sv-p56.h -sv-p56.h ........ prototypes and definitions needed by the SV module. -``` +Measures and equalizes active speech levels according to ITU-T Recommendation +P.56. Includes `sv56demo` (measure + equalize) and `actlev` (measure only). -# Additional modules needed (see directory ../utl): -``` -ugst-utl.c ...... UGST utilities' module: conversion between float and short - data formats functions/macros and gain/loss function. -ugst-utl.h ...... prototypes and definitions needed by the UGST utilities' - module. -ugstdemo.h ...... prototypes and definitions needed by UGST demo programs. -``` +# WAV file support -# Demo -``` -sv56demo.c ...... Demonstration program for the SV module; needs the files - sv-p56.c, ugst-utl.c, ugst-utl.h, and ugstdemo.h in the - current directory. -actlevel.c ...... Demo program that only measures the level/min/max/etc for - all the files given in the command line. In MSDOS, needs - wildargs.obj when using Borland compilers, in order to - be able to automatically process commands like - actlev *.src - This is not a concern in Unix because wildcard expansion - is included in the shell. Wildcard expansion is *not* - implemented in VMS (sorry). Please mind that the -q option - gives a more compact listing of the file statistics. -``` +`sv56demo` transparently supports WAV files (8/16/24/32-bit PCM and 32-bit +IEEE float). The format is auto-detected from the RIFF header; raw PCM files +continue to work as before (assumed 16-bit, native byte order). + +When a WAV file is detected: +- Bit depth and sample rate are read from the header +- The `-bits` flag overrides the A/D resolution used by the P.56 algorithm + (must be ≤ file bit depth), simulating a lower-resolution ADC/DAC +- Output format matches the input (WAV output if filename ends in `.wav`) + +## Benefits of higher bit depths + +The P.56 speech voltmeter's ability to detect and measure speech depends on +the signal being above the quantization noise floor. Higher bit depths +provide more dynamic range: + +| Bit depth | Dynamic range | Noise floor | +|-----------|--------------|-------------| +| 16-bit | ~96 dB | -96 dBov | +| 24-bit | ~144 dB | -144 dBov | +| 32-bit | ~192 dB | -192 dBov | + +### Test results: very quiet speech (-91 dBov) + +| Resolution | Active level | Activity | Result | +|------------|-------------|----------|--------| +| 32-bit | -91.029 dBov | 90.2% | Speech correctly detected and measured | +| 16-bit ADC | — | 0% | **Signal below noise floor — undetectable** | + +With 32-bit resolution, the speech voltmeter correctly measures a signal at +-91 dBov with 90% activity. With a 16-bit ADC simulation (`-bits 16`), the +same signal falls below the quantization threshold and the algorithm reports +zero activity — it cannot distinguish speech from silence. + +For signals at normal levels (-26 dBov), all bit depths produce identical +measurements, confirming full backward compatibility. -# Makefiles +# Source files -Makefiles have been provided for automatic build-up of the executable program -and to process a test file. ``` -makefile.djc: ... make file for MSDOS port of gcc -makefile.tcc .... DOS make file, for tcc -makefile.unx .... make file for Unix machines. Set up for gcc, may be tailored +sv-p56.c ........ P.56 speech voltmeter module +sv-p56.h ........ prototypes and definitions for the SV module +sv56demo.c ...... demo program: measure active level and equalize +actlevel.c ...... demo program: measure level/min/max for multiple files ``` -# Test file +# Dependencies (from ../utl) -The file `voice.src`, also used for testing the IS54 VSELP, is needed -for testing the sv-p56 demo programs. A reference, normalized file, -is available in the ZIP-compatible archive sv56-tst.zip. [pk]unzip is -necessary to extract the reference processed file. The contents of this -archive file is, as reported by unzip: ``` - Length Method Size Ratio Date Time CRC-32 Name - ------ ------ ---- ----- ---- ---- ------ ---- - 105472 Deflate 79982 24% 01-12-95 10:23 66211f99 voice.nrm - 105472 Deflate 80086 24% 08-21-95 12:25 8d3c67bf voice.ltl - ------ ------ --- ------- - 210944 160068 24% 2 +ugst-utl.c ...... float/short conversion and gain/loss functions +ugst-utl.h ...... prototypes for UGST utilities +ugstdemo.h ...... macros for UGST demo programs +wav_io.c ........ WAV file I/O (auto-detect, read, write) +wav_io.h ........ WAV I/O prototypes ``` -NOTE! This file is in the big-endian (high-byte first) format. Therefore, - before using under MSDOS or VAX/VMS, the files need to be byte-swapped. - See unsupported program sb in the ../unsup directory. If testing is - done using the provided makefiles, they will attempt to carry out - the necessary byte-swapping for voice.nrm. For this, a version of - the utility awk (gawk is preferred) must be available in the path. +# Test data --- -- +The `test_data/` directory contains: +- `voice.src` — raw 16-bit PCM test signal +- `voice.nrm`, `voice.ltl` — reference outputs for regression tests +- `speech_*.wav` — WAV test files at various bit depths and levels +- `*.ref`, `*.log.ref` — reference outputs for binary and text comparison diff --git a/src/sv56/actlevel.c b/src/sv56/actlevel.c index 594b92c9..86dac198 100644 --- a/src/sv56/actlevel.c +++ b/src/sv56/actlevel.c @@ -155,7 +155,7 @@ /* ... Include of utilities ... */ #include "ugst-utl.h" -#include "sv56-util.h" +#include "wav_io.h" /* ... Local definitions ... */ #define DEF_BLK_LEN 256 /* samples per block */ @@ -424,17 +424,19 @@ int main (int argc, char *argv[]) { /* File-related variables */ char FileIn[150]; - FILE *Fi; /* input file pointer */ + AUDIO_FILE *Fi; /* input file pointer */ FILE *out = stdout; /* where to print the statistical results */ #ifdef VMS char mrs[15]; #endif /* Other variables */ - unsigned char raw_buf[4096 * 4]; + short short_buf[4096]; + long long_buf[4096]; float Buf[4096]; - int bps; - long start_byte, bitno = 16; + long start_byte, bitno = 16, k; + char user_set_bitno = 0; + int file_bitno, is_float; double sf = 16000; /* Hz */ double ActiveLeveldB, level = 0, gain = 0; static char funny[] = "|/-\\|/-\\", funny_size = sizeof (funny), quiet = 0; @@ -472,8 +474,9 @@ int main (int argc, char *argv[]) { argv++; argc--; } else if (strcmp (argv[1], "-bits") == 0) { - /* Change default sampling frequency */ + /* Change default A/D resolution */ bitno = atoi (argv[2]); + user_set_bitno = 1; /* Update argc/argv to next valid option/argument */ argv += 2; @@ -540,21 +543,11 @@ int main (int argc, char *argv[]) { /* ......... SOME INITIALIZATIONS ......... */ - /* Validate bitno */ - if (bitno < 8 || bitno > SVP56_MAX_NO_BITS) { - fprintf (stderr, "Error: bitno must be between 8 and %d\n", SVP56_MAX_NO_BITS); - exit (1); - } - bps = sv56_bytes_per_sample ((int) bitno); - /* funny_size = strlen(funny); */ start_byte = --N1; - start_byte *= N * bps; + start_byte *= N * sizeof (short); N2_ori = N2; - /* Overflow (saturation) point */ - Overflow = pow ((double) 2.0, (double) (bitno - 1)); - /* REPEAT FOR ALL FILES IN THE COMMAND LINE */ while (argc > 1) { @@ -563,30 +556,44 @@ int main (int argc, char *argv[]) { argv++; argc--; - /* Reset variables for speech level measurements */ - init_speech_voltmeter (&state, sf, (int)bitno); - /* ......... FILE PREPARATION ......... */ /* Opening input file; abort if there's any problem */ -#ifdef VMS - sprintf (mrs, "mrs=%d", bps * N); -#endif - if ((Fi = fopen (FileIn, RB)) == NULL) + if ((Fi = audio_open_read (FileIn, 0, 0, 0)) == NULL) KILL (FileIn, 2); + /* If WAV, derive file bit depth and sample rate from header */ + if (audio_is_wav (Fi)) { + file_bitno = Fi->bits_per_sample; + if (audio_get_sample_rate (Fi) > 0) + sf = (double) audio_get_sample_rate (Fi); + if (!user_set_bitno) + bitno = file_bitno; + } else { + file_bitno = 16; + } + is_float = (audio_is_wav (Fi) && Fi->audio_format == 3); + if (is_float && !user_set_bitno) + bitno = 32; + + /* Overflow (saturation) point */ + Overflow = is_float ? 1.0 : pow ((double) 2.0, (double) (file_bitno - 1)); + + /* Reset variables for speech level measurements */ + init_speech_voltmeter (&state, sf, (int)bitno); + /* Reinitialize number of blocks as specified initially */ N2 = N2_ori; /* Check if is to process the whole file */ if (N2 == 0) { - struct stat st; - stat (FileIn, &st); - N2 = ceil (st.st_size / (double) (N * bps)); + int bps = file_bitno / 8; + long data_size = audio_get_data_size (Fi); + N2 = ceil ((data_size - start_byte) / (double) (N * bps)); } /* Move pointer to 1st block of interest */ - if (fseek (Fi, start_byte, 0) < 0l) + if (audio_seek (Fi, start_byte) < 0) KILL (FileIn, 4); @@ -596,19 +603,27 @@ int main (int argc, char *argv[]) { if (!quiet) fprintf (stderr, " Processing \r"); for (i = 0; i < N2; i++) { - if ((l = fread (raw_buf, bps, N, Fi)) > 0) { - /* ... Convert samples to float */ - sv56_raw2fl ((long) l, raw_buf, Buf, (int) bitno); - - /* ... Get the active level */ - ActiveLeveldB = speech_voltmeter (Buf, (long) l, &state); - - /* Print progress flag */ - if (!quiet) - fprintf (stderr, "%c\r", funny[i % funny_size]); + if (is_float) { + if ((l = audio_read (Fi, Buf, N)) <= 0) + KILL (FileIn, 5); + } else if (file_bitno <= 16) { + if ((l = audio_read (Fi, short_buf, N)) <= 0) + KILL (FileIn, 5); + for (k = 0; k < l; k++) + Buf[k] = (float) ((double) short_buf[k] / Overflow); } else { - KILL (FileIn, 5); + if ((l = audio_read (Fi, long_buf, N)) <= 0) + KILL (FileIn, 5); + for (k = 0; k < l; k++) + Buf[k] = (float) ((double) long_buf[k] / Overflow); } + + /* ... Get the active level */ + ActiveLeveldB = speech_voltmeter (Buf, (long) l, &state); + + /* Print progress flag */ + if (!quiet) + fprintf (stderr, "%c\r", funny[i % funny_size]); } if (!quiet) fprintf (stderr, "\n"); @@ -690,7 +705,7 @@ int main (int argc, char *argv[]) { #endif /* LOCAL_PRINT */ /* Close current file */ - fclose (Fi); + audio_close (Fi); } /* FINALIZATIONS */ diff --git a/src/sv56/sv56-convert.c b/src/sv56/sv56-convert.c deleted file mode 100644 index 0f693f91..00000000 --- a/src/sv56/sv56-convert.c +++ /dev/null @@ -1,38 +0,0 @@ -#include -#include -#include "sv56-util.h" - -#define BLK_LEN 256 - -int main (int argc, char *argv[]) -{ - FILE *Fi, *Fo; - unsigned char in_buf[BLK_LEN * 2]; - unsigned char out_buf[BLK_LEN * 4]; - float Buf[BLK_LEN]; - long l; - int out_bitno, out_bps; - - if (argc < 4) { - fprintf (stderr, "Usage: %s \n", argv[0]); - return 1; - } - - out_bitno = atoi (argv[1]); - out_bps = sv56_bytes_per_sample (out_bitno); - - Fi = fopen (argv[2], "rb"); - if (!Fi) { fprintf (stderr, "Cannot open %s\n", argv[2]); return 1; } - Fo = fopen (argv[3], "wb"); - if (!Fo) { fprintf (stderr, "Cannot open %s\n", argv[3]); fclose (Fi); return 1; } - - while ((l = fread (in_buf, 2, BLK_LEN, Fi)) > 0) { - sv56_raw2fl (l, in_buf, Buf, 16); - sv56_fl2raw (l, Buf, out_buf, out_bitno); - fwrite (out_buf, out_bps, l, Fo); - } - - fclose (Fi); - fclose (Fo); - return 0; -} diff --git a/src/sv56/sv56-util.h b/src/sv56/sv56-util.h deleted file mode 100644 index c785aa2e..00000000 --- a/src/sv56/sv56-util.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - ============================================================================ - File: SV56-UTIL.H 28.May.2026 v2.0 - ============================================================================ - - UGST/ITU-T SPEECH VOLTMETER MODULE - - LOCAL UTILITY FUNCTIONS - - =============================================================== - COPYRIGHT NOTE: This source code, and all of its derivations, - is subject to the "ITU-T General Public License". Please have - it read in the distribution disk, or in the ITU-T - Recommendation G.191 on "SOFTWARE TOOLS FOR SPEECH AND AUDIO - CODING STANDARDS". - =============================================================== - - History: - 28.May.26 v1.0 Created: safe short-to-float conversion for sv56 - module that always assumes 16-bit PCM input. - 28.May.26 v2.0 Rewritten: variable bit-width I/O (8, 16, 24, 32 - bit) with native byte order. Legacy widths - (9-15 bit) supported via bit masking. - - ============================================================================ -*/ -#ifndef SV56_UTIL_defined -#define SV56_UTIL_defined 200 - -#include - -static int sv56_is_little_endian (void) -{ - unsigned int x = 1; - return *(unsigned char *) &x; -} - -static int sv56_bytes_per_sample (int bitno) -{ - if (bitno <= 8) - return 1; - if (bitno <= 16) - return 2; - if (bitno <= 24) - return 3; - return 4; -} - -static void sv56_raw2fl (long n, const unsigned char *raw, float *y, int bitno) -{ - long k; - int bps = sv56_bytes_per_sample (bitno); - int le = sv56_is_little_endian (); - double norm = (double) (1 << (bitno - 1)); - - for (k = 0; k < n; k++) - { - const unsigned char *p = raw + k * bps; - uint32_t uval = 0; - int32_t sval; - int j; - - for (j = 0; j < bps; j++) - uval |= (uint32_t) p[le ? j : (bps - 1 - j)] << (j * 8); - - sval = (int32_t) uval; - if (bitno < 32 && (uval & (1U << (bitno - 1)))) - sval -= (int32_t) (1U << bitno); - - y[k] = (float) ((double) sval / norm); - } -} - -static long sv56_fl2raw (long n, const float *x, unsigned char *raw, int bitno) -{ - long k; - int bps = sv56_bytes_per_sample (bitno); - int le = sv56_is_little_endian (); - int pad_bits = bps * 8 - bitno; - double scale = (double) (1U << (bitno - 1)); - long overflows = 0; - - for (k = 0; k < n; k++) - { - double val = (double) x[k] * scale; - int32_t ival; - uint32_t uval; - int j; - - if (val > scale - 1.0) - { - val = scale - 1.0; - overflows++; - } - else if (val < -scale) - { - val = -scale; - overflows++; - } - - ival = (int32_t) val; - if (pad_bits > 0) - ival &= ~((1 << pad_bits) - 1); - uval = (uint32_t) ival; - - for (j = 0; j < bps; j++) - raw[k * bps + (le ? j : (bps - 1 - j))] = - (unsigned char) ((uval >> (j * 8)) & 0xFF); - } - - return overflows; -} - -#endif /* SV56_UTIL_defined */ -/* ........................ End of SV56-UTIL.H .......................... */ diff --git a/src/sv56/sv56demo.c b/src/sv56/sv56demo.c index ac786de4..a2387698 100644 --- a/src/sv56/sv56demo.c +++ b/src/sv56/sv56demo.c @@ -185,7 +185,7 @@ /* ... Include of utilities ... */ #include "ugst-utl.h" -#include "sv56-util.h" +#include "wav_io.h" /* Local definitions */ #define MIN_LOG_OFFSET 1.0e-20 /* To avoid sigularity with log(0.0) */ @@ -425,7 +425,7 @@ int main (int argc, char *argv[]) { /* Parameters for operation */ double Overflow; /* Max.positive value for AD_resolution bits */ - long N = 256, N1 = 1, N2 = 0, i, l; + long N = 256, N1 = 1, N2 = 0, i, l, k; double NdB = -26; /* dBov */ /* Intermediate storage variables for speech voltmeter */ @@ -433,7 +433,7 @@ int main (int argc, char *argv[]) { /* File-related variables */ char FileIn[MAX_STRLEN], FileOut[MAX_STRLEN]; - FILE *Fi, *Fo; /* input/output file pointers */ + AUDIO_FILE *Fi, *Fo; /* input/output file pointers */ FILE *out = stdout; /* where to print the statistical results */ #ifdef VMS char mrs[15]; @@ -441,10 +441,13 @@ int main (int argc, char *argv[]) { /* Other variables */ char quiet = 0, use_active_level = 1, long_summary = 1; - unsigned char raw_buf[4096 * 4]; + short short_buf[4096]; /* for 8/16-bit reads */ + long long_buf[4096]; /* for 24/32-bit reads */ + int write_buf32[4096]; /* for 32-bit writes (4 bytes each) */ float Buf[4096]; long NrSat = 0, start_byte, bitno = 16; - int bps; + char user_set_bitno = 0, is_float = 0; + int bps, file_bitno; double sf = 16000, factor; double ActiveLeveldB, DesiredSpeechLeveldB; static char funny[5] = { '/', '-', '\\', '|', '-' }; @@ -472,8 +475,9 @@ int main (int argc, char *argv[]) { argv += 2; argc -= 2; } else if (strcmp (argv[1], "-bits") == 0) { - /* Change default sampling frequency */ + /* Change default A/D resolution */ bitno = atol (argv[2]); + user_set_bitno = 1; /* Update argc/argv to next valid option/argument */ argv += 2; @@ -559,11 +563,41 @@ int main (int argc, char *argv[]) { FIND_PAR_L (8, "_A/D resolution: ....................... ", bitno, bitno); /* Validate bitno */ - if (bitno < 8 || bitno > SVP56_MAX_NO_BITS) { - fprintf (stderr, "Error: bitno must be between 8 and %d\n", SVP56_MAX_NO_BITS); + if (bitno < 1 || bitno > 32) { + fprintf (stderr, "Error: bitno must be between 1 and 32\n"); exit (1); } - bps = sv56_bytes_per_sample ((int) bitno); + +/* + * ......... FILE PREPARATION ......... + */ + + /* Opening input file; auto-detects WAV vs raw */ + if ((Fi = audio_open_read (FileIn, 0, 0, 0)) == NULL) + KILL (FileIn, 2); + + /* If WAV, derive file bit depth and sample rate from header */ + if (audio_is_wav (Fi)) { + file_bitno = Fi->bits_per_sample; + if (audio_get_sample_rate (Fi) > 0) + sf = (double) audio_get_sample_rate (Fi); + if (!user_set_bitno) + bitno = file_bitno; + else if (bitno > file_bitno) { + fprintf (stderr, "Error: requested resolution (%ld bits) exceeds file bit depth (%d)\n", bitno, file_bitno); + exit (1); + } + } else { + file_bitno = 16; /* raw PCM is always 16-bit */ + } + + /* Check if input is IEEE float format */ + is_float = (audio_is_wav (Fi) && Fi->audio_format == 3); + if (is_float && !user_set_bitno) + bitno = 32; + + /* Bytes per sample for the file format */ + bps = file_bitno / 8; /* ......... SOME INITIALIZATIONS ......... */ start_byte = --N1; @@ -571,37 +605,22 @@ int main (int argc, char *argv[]) { /* Check if is to process the whole file */ if (N2 == 0) { - struct stat st; - - /* ... find the input file size ... */ - stat (FileIn, &st); - N2 = ceil ((st.st_size - start_byte) / (double) (N * bps)); + long data_size = audio_get_data_size (Fi); + N2 = ceil ((data_size - start_byte) / (double) (N * bps)); } - /* Overflow (saturation) point */ - Overflow = pow ((double) 2.0, (double) (bitno - 1)); + /* Overflow (saturation) point: file_overflow for normalization, Overflow for algorithm */ + Overflow = is_float ? 1.0 : pow ((double) 2.0, (double) (file_bitno - 1)); /* reset variables for speech level measurements */ init_speech_voltmeter (&state, sf, (int)bitno); - -/* - * ......... FILE PREPARATION ......... - */ - - /* Opening input file; abort if there's any problem */ -#ifdef VMS - sprintf (mrs, "mrs=%d", bps * N); -#endif - if ((Fi = fopen (FileIn, RB)) == NULL) - KILL (FileIn, 2); - /* Creates output file */ - if ((Fo = fopen (FileOut, WB)) == NULL) + if ((Fo = audio_open_write (FileOut, (long) sf, 1, file_bitno)) == NULL) KILL (FileOut, 3); /* Move pointer to 1st block of interest */ - if (fseek (Fi, start_byte, 0) < 0l) + if (audio_seek (Fi, start_byte) < 0) KILL (FileIn, 4); @@ -614,19 +633,27 @@ int main (int argc, char *argv[]) { /* Process selected blocks */ for (i = 0; i < N2; i++) { /* Read samples ... */ - if ((l = fread (raw_buf, bps, N, Fi)) > 0) { - /* ... Convert samples to float */ - sv56_raw2fl ((long) l, raw_buf, Buf, (int) bitno); - - /* ... Get the active level */ - ActiveLeveldB = speech_voltmeter (Buf, (long) l, &state); - - /* Print some preliminary information */ - if (!quiet) - printf ("%c\r", funny[i % 5]); + if (is_float) { + if ((l = audio_read (Fi, Buf, N)) <= 0) + KILL (FileIn, 5); + } else if (file_bitno <= 16) { + if ((l = audio_read (Fi, short_buf, N)) <= 0) + KILL (FileIn, 5); + for (k = 0; k < l; k++) + Buf[k] = (float) ((double) short_buf[k] / Overflow); } else { - KILL (FileIn, 5); + if ((l = audio_read (Fi, long_buf, N)) <= 0) + KILL (FileIn, 5); + for (k = 0; k < l; k++) + Buf[k] = (float) ((double) long_buf[k] / Overflow); } + + /* ... Get the active level */ + ActiveLeveldB = speech_voltmeter (Buf, (long) l, &state); + + /* Print some preliminary information */ + if (!quiet) + printf ("%c\r", funny[i % 5]); } /* Beautify screen ... */ @@ -652,26 +679,60 @@ int main (int argc, char *argv[]) { /* EQUALIZATION: hard clipping (with truncation) */ /* Move pointer to 1st desired block */ - if (fseek (Fi, start_byte, 0) < 0l) + if (audio_seek (Fi, start_byte) < 0) KILL (FileIn, 4); /* Get data of interest, equalize and de-normalize */ for (i = 0; i < N2; i++) { - if ((l = fread (raw_buf, bps, N, Fi)) > 0) { - /* convert samples to float */ - sv56_raw2fl ((long) l, raw_buf, Buf, (int) bitno); - - /* equalizes vector */ + if (is_float) { + if ((l = audio_read (Fi, Buf, N)) <= 0) + KILL (FileIn, 5); + /* equalizes vector and convert to 32-bit PCM */ + for (k = 0; k < l; k++) { + double val = (double) Buf[k] * factor; + if (val > 1.0 - (1.0 / 2147483648.0)) { val = 1.0 - (1.0 / 2147483648.0); NrSat++; } + else if (val < -1.0) { val = -1.0; NrSat++; } + write_buf32[k] = (int) (val * 2147483648.0); + } + if ((l = audio_write (Fo, write_buf32, l)) < 0) + KILL (FileOut, 6); + } else if (file_bitno <= 16) { + if ((l = audio_read (Fi, short_buf, N)) <= 0) + KILL (FileIn, 5); + /* Use float path for backward-compatible rounding */ + for (k = 0; k < l; k++) + Buf[k] = (float) ((double) short_buf[k] / Overflow); scale (Buf, (long) l, (double) factor); - - /* Convert from float to raw with hard clip and truncation */ - NrSat += sv56_fl2raw ((long) l, Buf, raw_buf, (int) bitno); - - /* write equalized, de-normalized and hard-clipped samples to file */ - if ((l = fwrite (raw_buf, bps, l, Fo)) < 0) + for (k = 0; k < l; k++) { + double val = (double) Buf[k] * Overflow; + if (val > Overflow - 1.0) { val = Overflow - 1.0; NrSat++; } + else if (val < -Overflow) { val = -Overflow; NrSat++; } + short_buf[k] = (short) val; + } + if ((l = audio_write (Fo, short_buf, l)) < 0) + KILL (FileOut, 6); + } else if (file_bitno == 24) { + if ((l = audio_read (Fi, long_buf, N)) <= 0) + KILL (FileIn, 5); + for (k = 0; k < l; k++) { + double val = (double) long_buf[k] * factor; + if (val > Overflow - 1.0) { val = Overflow - 1.0; NrSat++; } + else if (val < -Overflow) { val = -Overflow; NrSat++; } + long_buf[k] = (long) val; + } + if ((l = audio_write (Fo, long_buf, l)) < 0) KILL (FileOut, 6); } else { - KILL (FileIn, 5); + if ((l = audio_read (Fi, long_buf, N)) <= 0) + KILL (FileIn, 5); + for (k = 0; k < l; k++) { + double val = (double) long_buf[k] * factor; + if (val > Overflow - 1.0) { val = Overflow - 1.0; NrSat++; } + else if (val < -Overflow) { val = -Overflow; NrSat++; } + write_buf32[k] = (int) val; + } + if ((l = audio_write (Fo, write_buf32, l)) < 0) + KILL (FileOut, 6); } } @@ -687,8 +748,8 @@ int main (int argc, char *argv[]) { printf ("---> DONE \n"); /* Close files ... */ - fclose (Fi); - fclose (Fo); + audio_close (Fi); + audio_close (Fo); if (out != stdout) fclose (out); #if !defined(VMS) diff --git a/src/sv56/sv56test.c b/src/sv56/sv56test.c deleted file mode 100644 index 14b4f15e..00000000 --- a/src/sv56/sv56test.c +++ /dev/null @@ -1,113 +0,0 @@ -/* v2.0 28.May.26 - ============================================================================ - - SV56TEST.C - ~~~~~~~~~~ - - Description: - ~~~~~~~~~~~~ - - Minimal test program for the ITU-T P.56 speech voltmeter. - Reads a PCM input file with configurable bit width (8, 16, 24, 32), - measures the active speech level, and prints a one-line result. - - This program is intended for automated testing with different - bitno values against input data of the corresponding format. - - Usage: - ~~~~~~ - $ sv56test [sample_rate] - where: - bitno is the bit depth (8, 16, 24, or 32); - input_file is the input file (2's complement, native byte order); - output_file is the output text file for the measurement result; - sample_rate is the sampling rate in Hz (default: 16000). - - Output: - ~~~~~~~ - A single line to the output file (and stdout): - ActLev[dB]: RMSLev[dB]: Activity[%]: - - Original author - ~~~~~~~~~~~~~~~ - Jan Reimes - - Log of changes - ~~~~~~~~~~~~~~ - 28.May.26 v1.0 Creation. - 28.May.26 v2.0 Variable bit-width I/O (8, 16, 24, 32 bit). - - ============================================================================ -*/ - -#include -#include -#include - -#include "sv-p56.h" -#include "sv56-util.h" - -#define BLK_LEN 256 - -int main (int argc, char *argv[]) -{ - SVP56_state state; - FILE *Fi, *Fo; - unsigned char raw_buf[BLK_LEN * 4]; - float Buf[BLK_LEN]; - long l; - int bitno, bps; - double sf = 16000.0; - double ActiveLeveldB; - - if (argc < 4) { - fprintf (stderr, "Usage: %s [sample_rate]\n", argv[0]); - return 1; - } - - bitno = atoi (argv[1]); - if (bitno < 8 || bitno > SVP56_MAX_NO_BITS) { - fprintf (stderr, "Error: bitno must be between 8 and %d\n", SVP56_MAX_NO_BITS); - return 1; - } - - bps = sv56_bytes_per_sample (bitno); - - if (argc >= 5) - sf = atof (argv[4]); - - Fi = fopen (argv[2], "rb"); - if (Fi == NULL) { - fprintf (stderr, "Error: cannot open %s\n", argv[2]); - return 1; - } - - Fo = fopen (argv[3], "w"); - if (Fo == NULL) { - fprintf (stderr, "Error: cannot open %s for writing\n", argv[3]); - fclose (Fi); - return 1; - } - - init_speech_voltmeter (&state, sf, bitno); - - while ((l = fread (raw_buf, bps, BLK_LEN, Fi)) > 0) { - sv56_raw2fl (l, raw_buf, Buf, bitno); - ActiveLeveldB = speech_voltmeter (Buf, l, &state); - } - - fclose (Fi); - - fprintf (Fo, "ActLev[dB]: %10.3f RMSLev[dB]: %10.3f Activity[%%]: %8.3f\n", - ActiveLeveldB, SVP56_get_rms_dB (state), - SVP56_get_activity (state)); - fclose (Fo); - - printf ("ActLev[dB]: %10.3f RMSLev[dB]: %10.3f Activity[%%]: %8.3f\n", - ActiveLeveldB, SVP56_get_rms_dB (state), - SVP56_get_activity (state)); - - return 0; -} - -/* ....................... End of SV56TEST.C ....................... */ diff --git a/src/sv56/test_data/actlev_multi.log.ref b/src/sv56/test_data/actlev_multi.log.ref new file mode 100644 index 00000000..050558a9 --- /dev/null +++ b/src/sv56/test_data/actlev_multi.log.ref @@ -0,0 +1,2 @@ +Samples: 105472 Min: -5141930 Max: 8227312 DC: 2326.99 RMSLev[dB]: -25.478 ActLev[dB]: -25.023 %Active: 90.044 RMSPkF[dB]: 25.310 ActPkF[dB]: 24.854 test_data/speech_normal_24bit.wav +Samples: 105472 Min: -659712 Max: 1055232 DC: 298.53 RMSLev[dB]: -91.478 ActLev[dB]: -91.029 %Active: 90.181 RMSPkF[dB]: 25.306 ActPkF[dB]: 24.858 test_data/speech_vquiet_32bit.wav diff --git a/src/sv56/test_data/actlev_normal_24bit.log.ref b/src/sv56/test_data/actlev_normal_24bit.log.ref new file mode 100644 index 00000000..79982f46 --- /dev/null +++ b/src/sv56/test_data/actlev_normal_24bit.log.ref @@ -0,0 +1 @@ +Samples: 105472 Min: -5141930 Max: 8227312 DC: 2326.99 RMSLev[dB]: -25.478 ActLev[dB]: -25.023 %Active: 90.044 RMSPkF[dB]: 25.310 ActPkF[dB]: 24.854 test_data/speech_normal_24bit.wav diff --git a/src/sv56/test_data/actlev_vquiet_32bit.log.ref b/src/sv56/test_data/actlev_vquiet_32bit.log.ref new file mode 100644 index 00000000..9373737a --- /dev/null +++ b/src/sv56/test_data/actlev_vquiet_32bit.log.ref @@ -0,0 +1 @@ +Samples: 105472 Min: -659712 Max: 1055232 DC: 298.53 RMSLev[dB]: -91.478 ActLev[dB]: -91.029 %Active: 90.181 RMSPkF[dB]: 25.306 ActPkF[dB]: 24.858 test_data/speech_vquiet_32bit.wav diff --git a/src/sv56/test_data/actlev_vquiet_32bit_16bit.log.ref b/src/sv56/test_data/actlev_vquiet_32bit_16bit.log.ref new file mode 100644 index 00000000..5b2b193f --- /dev/null +++ b/src/sv56/test_data/actlev_vquiet_32bit_16bit.log.ref @@ -0,0 +1 @@ +Samples: 105472 Min: -659712 Max: 1055232 DC: 298.53 RMSLev[dB]: -91.478 ActLev[dB]: -100.000 %Active: 0.000 RMSPkF[dB]: 25.306 ActPkF[dB]: 33.828 test_data/speech_vquiet_32bit.wav diff --git a/src/sv56/test_data/speech_normal_16bit.wav b/src/sv56/test_data/speech_normal_16bit.wav new file mode 100644 index 00000000..a66436b6 Binary files /dev/null and b/src/sv56/test_data/speech_normal_16bit.wav differ diff --git a/src/sv56/test_data/speech_normal_24bit.log.ref b/src/sv56/test_data/speech_normal_24bit.log.ref new file mode 100644 index 00000000..fea652c8 --- /dev/null +++ b/src/sv56/test_data/speech_normal_24bit.log.ref @@ -0,0 +1,19 @@ + ------------------------------------------------------- + Input file: ................... test_data/speech_normal_24bit.wav, 24 bits, fs=16000 Hz + Block Length: ................. 256 [samples] + Starting Block: ............... 1 [] + Number of Blocks: ............. 412 [] + dBov desired for output: ...... -26.000 [dBov] + Norm factor desired is: ....... 0.894 [times] + Max norm WITHOUT saturation: .. -24.854 [dBov] + ------------------------------------------------------- + DC level: ..................... 2327 [PCM] + Maximum positive value: ....... 8227312 [PCM] + Maximum negative value: ....... -5141930 [PCM] + ------------------------------------------------------- + Long term energy (rms): ....... -25.478 [dBov] + Active speech level: .......... -25.023 [dBov] + RMS peak-factor found: ........ 25.310 [dB] + Active peak factor found: ..... 24.854 [dB] + Activity factor: .............. 90.044 [%] + ------------------------------------------------------- diff --git a/src/sv56/test_data/speech_normal_24bit.ref b/src/sv56/test_data/speech_normal_24bit.ref new file mode 100644 index 00000000..7d91f4a8 Binary files /dev/null and b/src/sv56/test_data/speech_normal_24bit.ref differ diff --git a/src/sv56/test_data/speech_normal_24bit.wav b/src/sv56/test_data/speech_normal_24bit.wav new file mode 100644 index 00000000..cdca0c79 Binary files /dev/null and b/src/sv56/test_data/speech_normal_24bit.wav differ diff --git a/src/sv56/test_data/speech_normal_32bit.log.ref b/src/sv56/test_data/speech_normal_32bit.log.ref new file mode 100644 index 00000000..0b7433fa --- /dev/null +++ b/src/sv56/test_data/speech_normal_32bit.log.ref @@ -0,0 +1,19 @@ + ------------------------------------------------------- + Input file: ................... test_data/speech_normal_32bit.wav, 32 bits, fs=16000 Hz + Block Length: ................. 256 [samples] + Starting Block: ............... 1 [] + Number of Blocks: ............. 412 [] + dBov desired for output: ...... -26.000 [dBov] + Norm factor desired is: ....... 0.894 [times] + Max norm WITHOUT saturation: .. -24.854 [dBov] + ------------------------------------------------------- + DC level: ..................... 595710 [PCM] + Maximum positive value: ....... 2106191744 [PCM] + Maximum negative value: ....... -1316334336 [PCM] + ------------------------------------------------------- + Long term energy (rms): ....... -25.478 [dBov] + Active speech level: .......... -25.023 [dBov] + RMS peak-factor found: ........ 25.310 [dB] + Active peak factor found: ..... 24.854 [dB] + Activity factor: .............. 90.044 [%] + ------------------------------------------------------- diff --git a/src/sv56/test_data/speech_normal_32bit.ref b/src/sv56/test_data/speech_normal_32bit.ref new file mode 100644 index 00000000..49c5ac17 Binary files /dev/null and b/src/sv56/test_data/speech_normal_32bit.ref differ diff --git a/src/sv56/test_data/speech_normal_32bit.wav b/src/sv56/test_data/speech_normal_32bit.wav new file mode 100644 index 00000000..7c203d03 Binary files /dev/null and b/src/sv56/test_data/speech_normal_32bit.wav differ diff --git a/src/sv56/test_data/speech_normal_32bit_float.wav b/src/sv56/test_data/speech_normal_32bit_float.wav new file mode 100644 index 00000000..a517054d Binary files /dev/null and b/src/sv56/test_data/speech_normal_32bit_float.wav differ diff --git a/src/sv56/test_data/speech_quiet_16bit.wav b/src/sv56/test_data/speech_quiet_16bit.wav new file mode 100644 index 00000000..419b344e Binary files /dev/null and b/src/sv56/test_data/speech_quiet_16bit.wav differ diff --git a/src/sv56/test_data/speech_quiet_24bit.log.ref b/src/sv56/test_data/speech_quiet_24bit.log.ref new file mode 100644 index 00000000..76aa133c --- /dev/null +++ b/src/sv56/test_data/speech_quiet_24bit.log.ref @@ -0,0 +1,19 @@ + ------------------------------------------------------- + Input file: ................... test_data/speech_quiet_24bit.wav, 24 bits, fs=16000 Hz + Block Length: ................. 256 [samples] + Starting Block: ............... 1 [] + Number of Blocks: ............. 412 [] + dBov desired for output: ...... -26.000 [dBov] + Norm factor desired is: ....... 44.876 [times] + Max norm WITHOUT saturation: .. -24.871 [dBov] + ------------------------------------------------------- + DC level: ..................... 46 [PCM] + Maximum positive value: ....... 164155 [PCM] + Maximum negative value: ....... -102591 [PCM] + ------------------------------------------------------- + Long term energy (rms): ....... -59.478 [dBov] + Active speech level: .......... -59.040 [dBov] + RMS peak-factor found: ........ 25.310 [dB] + Active peak factor found: ..... 24.871 [dB] + Activity factor: .............. 90.403 [%] + ------------------------------------------------------- diff --git a/src/sv56/test_data/speech_quiet_24bit.ref b/src/sv56/test_data/speech_quiet_24bit.ref new file mode 100644 index 00000000..19e05473 Binary files /dev/null and b/src/sv56/test_data/speech_quiet_24bit.ref differ diff --git a/src/sv56/test_data/speech_quiet_24bit.wav b/src/sv56/test_data/speech_quiet_24bit.wav new file mode 100644 index 00000000..ad1029ad Binary files /dev/null and b/src/sv56/test_data/speech_quiet_24bit.wav differ diff --git a/src/sv56/test_data/speech_quiet_32bit.wav b/src/sv56/test_data/speech_quiet_32bit.wav new file mode 100644 index 00000000..86573363 Binary files /dev/null and b/src/sv56/test_data/speech_quiet_32bit.wav differ diff --git a/src/sv56/test_data/speech_quiet_32bit_float.log.ref b/src/sv56/test_data/speech_quiet_32bit_float.log.ref new file mode 100644 index 00000000..00ee7154 --- /dev/null +++ b/src/sv56/test_data/speech_quiet_32bit_float.log.ref @@ -0,0 +1,19 @@ + ------------------------------------------------------- + Input file: ................... test_data/speech_quiet_32bit_float.wav, 32 bits, fs=16000 Hz + Block Length: ................. 256 [samples] + Starting Block: ............... 1 [] + Number of Blocks: ............. 412 [] + dBov desired for output: ...... -26.000 [dBov] + Norm factor desired is: ....... 44.876 [times] + Max norm WITHOUT saturation: .. -24.872 [dBov] + ------------------------------------------------------- + DC level: ..................... 0 [PCM] + Maximum positive value: ....... 0 [PCM] + Maximum negative value: ....... -0 [PCM] + ------------------------------------------------------- + Long term energy (rms): ....... -59.478 [dBov] + Active speech level: .......... -59.040 [dBov] + RMS peak-factor found: ........ 25.310 [dB] + Active peak factor found: ..... 24.872 [dB] + Activity factor: .............. 90.403 [%] + ------------------------------------------------------- diff --git a/src/sv56/test_data/speech_quiet_32bit_float.ref b/src/sv56/test_data/speech_quiet_32bit_float.ref new file mode 100644 index 00000000..27fcc092 Binary files /dev/null and b/src/sv56/test_data/speech_quiet_32bit_float.ref differ diff --git a/src/sv56/test_data/speech_quiet_32bit_float.wav b/src/sv56/test_data/speech_quiet_32bit_float.wav new file mode 100644 index 00000000..f3aac555 Binary files /dev/null and b/src/sv56/test_data/speech_quiet_32bit_float.wav differ diff --git a/src/sv56/test_data/speech_vquiet_32bit.log.ref b/src/sv56/test_data/speech_vquiet_32bit.log.ref new file mode 100644 index 00000000..e2284e77 --- /dev/null +++ b/src/sv56/test_data/speech_vquiet_32bit.log.ref @@ -0,0 +1,19 @@ + ------------------------------------------------------- + Input file: ................... test_data/speech_vquiet_32bit.wav, 32 bits, fs=16000 Hz + Block Length: ................. 256 [samples] + Starting Block: ............... 1 [] + Number of Blocks: ............. 412 [] + dBov desired for output: ...... -26.000 [dBov] + Norm factor desired is: ....... 1784.261 [times] + Max norm WITHOUT saturation: .. -24.858 [dBov] + ------------------------------------------------------- + DC level: ..................... 299 [PCM] + Maximum positive value: ....... 1055232 [PCM] + Maximum negative value: ....... -659712 [PCM] + ------------------------------------------------------- + Long term energy (rms): ....... -91.478 [dBov] + Active speech level: .......... -91.029 [dBov] + RMS peak-factor found: ........ 25.306 [dB] + Active peak factor found: ..... 24.858 [dB] + Activity factor: .............. 90.181 [%] + ------------------------------------------------------- diff --git a/src/sv56/test_data/speech_vquiet_32bit.ref b/src/sv56/test_data/speech_vquiet_32bit.ref new file mode 100644 index 00000000..757bd5c5 Binary files /dev/null and b/src/sv56/test_data/speech_vquiet_32bit.ref differ diff --git a/src/sv56/test_data/speech_vquiet_32bit.wav b/src/sv56/test_data/speech_vquiet_32bit.wav new file mode 100644 index 00000000..310fe13f Binary files /dev/null and b/src/sv56/test_data/speech_vquiet_32bit.wav differ diff --git a/src/sv56/test_data/speech_vquiet_32bit_16bit.log.ref b/src/sv56/test_data/speech_vquiet_32bit_16bit.log.ref new file mode 100644 index 00000000..1e4e978a --- /dev/null +++ b/src/sv56/test_data/speech_vquiet_32bit_16bit.log.ref @@ -0,0 +1,18 @@ + ------------------------------------------------------- + Input file: ................... test_data/speech_vquiet_32bit.wav, 16 bits, fs=16000 Hz + Block Length: ................. 256 [samples] + Starting Block: ............... 1 [] + Number of Blocks: ............. 412 [] + dBov desired for output: ...... -26.000 [dBov] + Activity factor is ZERO -- the file is silence or idle noise + ------------------------------------------------------- + DC level: ..................... 299 [PCM] + Maximum positive value: ....... 1055232 [PCM] + Maximum negative value: ....... -659712 [PCM] + ------------------------------------------------------- + Noise/silence energy (rms): ... -91.478 [dB] + ------------------------------------------------------- +%SV-W-SAT, the dB level chosen causes SATURATION: old max=1055232; new max=5288688069 +%SV-I-MAXLEVDB, the maximum norm factor to PREVENT clipping is -33.828dB; + ------------------------------------------------------- + Number of clippings: .......... 81 [] diff --git a/src/sv56/test_data/speech_vquiet_32bit_16bit.ref b/src/sv56/test_data/speech_vquiet_32bit_16bit.ref new file mode 100644 index 00000000..19994da3 Binary files /dev/null and b/src/sv56/test_data/speech_vquiet_32bit_16bit.ref differ diff --git a/src/sv56/test_data/voice_12bit.log.ref b/src/sv56/test_data/voice_12bit.log.ref new file mode 100644 index 00000000..74d3e0da --- /dev/null +++ b/src/sv56/test_data/voice_12bit.log.ref @@ -0,0 +1,19 @@ + ------------------------------------------------------- + Input file: ................... test_data/voice.src, 12 bits, fs=16000 Hz + Block Length: ................. 256 [samples] + Starting Block: ............... 1 [] + Number of Blocks: ............. 206 [] + dBov desired for output: ...... -30.000 [dBov] + Norm factor desired is: ....... 0.584 [times] + Max norm WITHOUT saturation: .. -24.408 [dBov] + ------------------------------------------------------- + DC level: ..................... 9 [PCM] + Maximum positive value: ....... 29472 [PCM] + Maximum negative value: ....... -19874 [PCM] + ------------------------------------------------------- + Long term energy (rms): ....... -25.478 [dBov] + Active speech level: .......... -25.329 [dBov] + RMS peak-factor found: ........ 24.557 [dB] + Active peak factor found: ..... 24.408 [dB] + Activity factor: .............. 96.625 [%] + ------------------------------------------------------- diff --git a/src/sv56/test_data/voice_12bit.nrm b/src/sv56/test_data/voice_12bit.nrm new file mode 100644 index 00000000..f4271d78 Binary files /dev/null and b/src/sv56/test_data/voice_12bit.nrm differ diff --git a/src/unsup/CMakeLists.txt b/src/unsup/CMakeLists.txt old mode 100644 new mode 100755 index 56186f90..942cbeaf --- a/src/unsup/CMakeLists.txt +++ b/src/unsup/CMakeLists.txt @@ -39,6 +39,9 @@ add_executable(sh2chr sh2chr.c) add_executable(crc getcrc32.c) +add_executable(random random.c) +target_link_libraries(random ${M_LIBRARY}) + add_test(astrip1 ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/astrip -q -smooth -wlen 145 -sample test_data/cftest1.dat test_data/astrip.smp) add_test(astrip1-verify ${CMAKE_COMMAND} -E compare_files test_data/astrip.smp test_data/astrip.ref) @@ -83,3 +86,12 @@ add_test(fdelay5-verify ${CMAKE_COMMAND} -E compare_files test_data/delay-15.tst add_test(fdelay6 ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/fdelay -hex 0xF test_data/litend.src test_data/delay-0f.tst) add_test(fdelay6-verify ${CMAKE_COMMAND} -E compare_files test_data/delay-0f.tst test_data/delay-15.ref) + +add_test(random1 ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/random -s 12345 -r 10 20 -n 5) +set_tests_properties(random1 PROPERTIES PASS_REGULAR_EXPRESSION "12 19 12 14 14") + +add_test(random2 ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/random -s 42 alpha bravo charlie delta echo) +set_tests_properties(random2 PROPERTIES PASS_REGULAR_EXPRESSION "^alpha ") + +add_test(random3 ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/random -s 42 -d 3 -n 3 alpha bravo charlie delta echo) +set_tests_properties(random3 PROPERTIES PASS_REGULAR_EXPRESSION "bravo delta charlie") diff --git a/src/unsup/README.md b/src/unsup/README.md index 4a414471..5a58be27 100644 --- a/src/unsup/README.md +++ b/src/unsup/README.md @@ -56,6 +56,10 @@ oper.c: implement arithmetic operation on two files: add, subtract, multiply or divide two files applying scaling factors (linear or dB), and adding a DC level. +random.c: randomization tool for selecting items from a list or drawing + numbers from a range. Reuses the EID linear congruential + generator from eid.c. + sb.c swap bytes for word-oriented files. For VMS/Unix/MSDOS. sh2chr.c: convert short-oriented (16-bit words) files to char-oriented diff --git a/src/unsup/compfile.c b/src/unsup/compfile.c index bde37e7e..422bcf4f 100644 --- a/src/unsup/compfile.c +++ b/src/unsup/compfile.c @@ -461,7 +461,7 @@ int main (int argc, char *argv[]) { long k, l, s1, s2; char *abstol; - double reltol; + double reltol = 0.0; double abstol_double; float abstol_float; long abstol_long; diff --git a/src/unsup/random.c b/src/unsup/random.c new file mode 100644 index 00000000..d15e626a --- /dev/null +++ b/src/unsup/random.c @@ -0,0 +1,225 @@ +/*---------------------------------------------------------------------------* + * Randomization tool, V1.1 * + * ------------------------------------------ * + * (C) 2012 Fraunhofer IIS. All rights reserved. * + * * + * =============================================================== * + * COPYRIGHT NOTE: This source code, and all of its derivations, * + * is subject to the "ITU-T General Public License". Please have * + * it read in the distribution disk, or in the ITU-T Recommendation * + * G.191 on "SOFTWARE TOOLS FOR SPEECH AND AUDIO CODING STANDARDS". * + * See LICENSE.md in the top-level directory for terms. * + * =============================================================== * + * * + * The LCS generator is copied from ITU-T G.191, file STL/eid.c. * + * * + * Fraunhofer IIS makes no representation nor warranty in regard to * + * the accuracy, completeness or sufficiency of The Software, nor * + * shall Fraunhofer IIS be held liable for any damages whatsoever * + * relating to use of said Software. * + *---------------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include + +#define MAX_ITEMS 1000 +#define VERBOSE 0 +#define DEFAULT_SEED 3141592653U + +typedef enum { + SUBSET = 0, + FROM_RANGE = 1 +} MODE; + +/* +============================================================================ + double EID_random (unsigned long *seed); inherited from STL/eid.c, + ~~~~~~~~~~~~~~~~~ + + Description: + ~~~~~~~~~~~~ + Returns a new random number, generated a linear congruential + sequence (LCS) generator. See: Knuth, D.E. 1981: "Seminumerical + Algorithms" vol.2 of The Art of Computer Programming; Reading, + Mass.; Addison-Wesley. + + Parameters: + ~~~~~~~~~~~ + seed: ... long seed. + + Return value: + ~~~~~~~~~~~~~ + Returns a random number as double in the range 0..1. + + Author: + ~~~~~~~ + History: + ~~~~~~~~ + 28.Feb.92 v1.0 Release of 1st version + 20.Apr.92 v2.0 Change of polinomial generator to LCG + + 26.Jan.98 v3.0 Corrected bug for 64-bit operating systems (where + longs have 64, not 32 bits). Implemented by + , after bug reported + by + 12.Aug.12 v4.0 Changed unsigned long to unsigned int to have identical + behavior on at least Windows, Linux, OSX +============================================================================ */ + +static double EID_random(seed) +unsigned int *seed; +{ + /* Size in bits (=size in bytes * 8) for int variables*/ + static double bits_in_int = sizeof(unsigned int) * 8; + /* Update RNG */ + *seed = ((unsigned int)69069L * (*seed) +1L); + /* Return random number as a double */ +#ifdef WAS + return(pow((double)2.0, (double)-32.0) * (double)(*seed)); +#else + return(pow((double)2.0, -bits_in_int) * (double)(*seed)); +#endif +} + +static void usage() +{ + fprintf( stdout,"usage: random [OPTIONS] [ITEM_LIST]\n" ); + fprintf( stdout," OPTIONS:\n" ); + fprintf( stdout," -s SEED any number in between 0 and %u: as a seed for the RNG, default: %u\n", UINT_MAX, DEFAULT_SEED ); + fprintf( stdout," -d PRERUNS number of dummy pre-runs to alter the seed, default: 0\n" ); + fprintf( stdout," -r START STOP range mode, values define lowest and highest allowed value, not set by default\n" ); + fprintf( stdout," -n NUM_ITEMS select more than one item from the provided item list, default: 1\n" ); + exit(-1); +} + +int main( int argc, char** argv ) +{ + unsigned int seed = DEFAULT_SEED; + MODE mode = SUBSET; + unsigned int num_items = 1; + unsigned int num_dummyruns = 0; + unsigned int items_in_list = 0; + unsigned int selected_item = 0; + unsigned int verbose = 0; + unsigned int i = 0, j = 0; + unsigned int range_start = 0, range_stop = 1; + double rand_f = 0.0f; + char * item_list [MAX_ITEMS] = {0}; + + for(i=1; i= argc) usage(); + seed = atoi(argv[i]); + continue; + } + /* num items to select */ + if(!strcmp(argv[i],"-n")) { + if(++i >= argc) usage(); + num_items = atoi(argv[i]); + continue; + } + /* num dummy runs before the item selection is started - similar to different seed */ + if(!strcmp(argv[i],"-d")) { + if(++i >= argc) usage(); + num_dummyruns = atoi(argv[i]); + continue; + } + /* select item within given range instead of a subset */ + if(!strcmp(argv[i],"-r")) { + mode = FROM_RANGE; + if(++i >= argc) usage(); + range_start = atoi(argv[i]); + if(++i >= argc) usage(); + range_stop = atoi(argv[i]); + continue; + } + break; + } + + if(mode == SUBSET) { + /* list items are the last */ + if(i == (argc)) usage(); + items_in_list = argc - i; + if(items_in_list > MAX_ITEMS) + { + fprintf(stderr, "only up to %u items are supported by this tool\n", MAX_ITEMS); + exit(-2); + } + } + + for(i=0; i items_in_list) + { + fprintf(stderr, "requested %u items, but only %u in list\n", num_items, items_in_list); + exit (-1); + } + + for(i=0; iselected_item && iis_wav && ch <= 1 && bps <= 2) { return (long) fread (buffer, (size_t) sample_bytes, (size_t) nsamples, af->fp); } - /* Multi-channel extraction or 24-bit unpacking */ + /* WAV (little-endian) and multi-channel: extract with byte-order handling */ { unsigned char *raw_buf; @@ -337,10 +337,39 @@ long audio_write (AUDIO_FILE * af, void *buffer, long nsamples) { sample_bytes = (bps == 24) ? 3 : (bps / 8); if (bps != 24) { - /* 8, 16, 32-bit or float: direct fwrite */ - n = (long) fwrite (buffer, (size_t) sample_bytes, (size_t) nsamples, af->fp); - af->data_size += n * sample_bytes; - return n; + /* For raw or 8-bit: direct fwrite (native endian or single byte) */ + if (!af->is_wav || bps == 8) { + n = (long) fwrite (buffer, (size_t) sample_bytes, (size_t) nsamples, af->fp); + af->data_size += n * sample_bytes; + return n; + } + /* WAV 16-bit: write little-endian */ + if (bps == 16) { + short *in = (short *) buffer; + for (i = 0; i < nsamples; i++) { + unsigned char b[2]; + b[0] = (unsigned char) (in[i] & 0xFF); + b[1] = (unsigned char) ((in[i] >> 8) & 0xFF); + if (fwrite (b, 1, 2, af->fp) != 2) break; + } + af->data_size += i * 2; + return i; + } + /* WAV 32-bit: write little-endian */ + { + int *in = (int *) buffer; + for (i = 0; i < nsamples; i++) { + unsigned char b[4]; + unsigned int val = (unsigned int) in[i]; + b[0] = (unsigned char) (val & 0xFF); + b[1] = (unsigned char) ((val >> 8) & 0xFF); + b[2] = (unsigned char) ((val >> 16) & 0xFF); + b[3] = (unsigned char) ((val >> 24) & 0xFF); + if (fwrite (b, 1, 4, af->fp) != 4) break; + } + af->data_size += i * 4; + return i; + } } /* 24-bit: pack from long */ diff --git a/src/utl/wav_io.h b/src/utl/wav_io.h index 45752764..63c2f64c 100644 --- a/src/utl/wav_io.h +++ b/src/utl/wav_io.h @@ -3,7 +3,7 @@ * Provides transparent reading/writing of WAV and raw PCM files. * Input format is auto-detected (RIFF header check). * Output format is determined by filename extension (.wav = WAV, else raw). - * Only 16-bit PCM WAV is supported. + * Supports 8/16/24/32-bit PCM and 32-bit IEEE float WAV. */ #ifndef WAV_IO_H #define WAV_IO_H diff --git a/src/wmc_tool/CMakeLists.txt b/src/wmc_tool/CMakeLists.txt index 3ee0f58c..33df6e17 100644 --- a/src/wmc_tool/CMakeLists.txt +++ b/src/wmc_tool/CMakeLists.txt @@ -20,6 +20,8 @@ file(TO_CMAKE_PATH ${TEST_DIR}/test_wmc_tool.py TEST_WMC_TOOL_SCRIPT) add_test(NAME wmc_tool_dry_run COMMAND wmc_tool -h) add_test(NAME wmc_tool_dry_run2 COMMAND wmc_tool -i) + +if(Python3_FOUND) add_test(NAME wmc_tool_test_single_file COMMAND ${PYTHON_EXECUTABLE} ${TEST_WMC_TOOL_SCRIPT} -e $ -s src -r ref -o out -v test_file1.c WORKING_DIRECTORY ${TEST_DIR}) add_test(NAME wmc_tool_test_single_file2 COMMAND ${PYTHON_EXECUTABLE} ${TEST_WMC_TOOL_SCRIPT} -e $ test_file2.c WORKING_DIRECTORY ${TEST_DIR}) add_test(NAME wmc_tool_test_multiple_files COMMAND ${PYTHON_EXECUTABLE} ${TEST_WMC_TOOL_SCRIPT} -e $ -v "test_file*.c" test_g728durb.c WORKING_DIRECTORY ${TEST_DIR}) @@ -30,3 +32,6 @@ add_test(NAME wmc_tool_test_rom_file2 COMMAND ${PYTHON_EXECUTABLE} ${TEST_WMC_TO add_test(NAME wmc_tool_test_desinstrument_file COMMAND ${PYTHON_EXECUTABLE} ${TEST_WMC_TOOL_SCRIPT} -e $ -v -d di_test_file1.c WORKING_DIRECTORY ${TEST_DIR}) add_test(NAME wmc_tool_test_desinstrument_rom_file COMMAND ${PYTHON_EXECUTABLE} ${TEST_WMC_TOOL_SCRIPT} -e $ -v -d di_test_rom.c WORKING_DIRECTORY ${TEST_DIR}) add_test(NAME wmc_tool_test_wmc_auto_files COMMAND ${PYTHON_EXECUTABLE} ${TEST_WMC_TOOL_SCRIPT} -e $ -c ${TEST_DIR} test_file3.c WORKING_DIRECTORY ${TEST_DIR}) +else() + message(STATUS "Python3 not found -- skipping wmc_tool Python tests") +endif() diff --git a/src/wmc_tool/c_parser.cpp b/src/wmc_tool/c_parser.cpp index 79f11010..6feb79b2 100644 --- a/src/wmc_tool/c_parser.cpp +++ b/src/wmc_tool/c_parser.cpp @@ -805,7 +805,8 @@ static TOOL_ERROR Allocate_Insertion( Insert_Tbl_def *InsertTbl_ptr ) /* Calculate Bigger Size */ size = InsertTbl_ptr->MaxSize + INSERT_TBL_MEM_INCREMENT; /* Allocate Memory */ - if ( ( ptr = (Insert_Rec_def *) malloc( nbytes = INSERT_REC_SIZE * size ) ) == NULL ) + nbytes = INSERT_REC_SIZE * size; + if ( ( ptr = (Insert_Rec_def *) calloc( size, INSERT_REC_SIZE ) ) == NULL ) { ErrCode = ERR_MEM_PARSING; Error( ERROR_MSG_MEM_PARSING, ErrCode, itos( temp, nbytes ) ); @@ -882,6 +883,7 @@ static TOOL_ERROR Add_Insertion( } InsertRec_ptr = InsertTbl_ptr->Data + InsertTbl_ptr->Size; /* Fill Record */ + memset(InsertRec_ptr, 0, sizeof(*InsertRec_ptr)); InsertRec_ptr->Ptr = (char *)ptr; /* Reset # of Chars Stored */ nChars = 0; @@ -1679,7 +1681,7 @@ static TOOL_ERROR Find_Enclosed_Text( char *ptr; char *last_ptr; - Item_Type item_type; + Item_Type item_type = ITEM_NONE; char chr; /* Start at Beginning */ @@ -2471,7 +2473,7 @@ static TOOL_ERROR Find_Keywords( char kw_name[16]; size_t kw_name_len; char *ns, *ne; /* Name Start/End */ - char *ps, *pe; /* Params Start/End */ + char *ps = NULL, *pe; /* Params Start/End */ char *dp; Item_Type item_type; Parse_Tbl_def *ParseTbl_ptr; @@ -5440,6 +5442,7 @@ static TOOL_ERROR Instrument_Operators( /* Initialize (No Memory Allocated by Default) */ OperInsTbl.MaxSize = 0; + OperInsTbl.Data = NULL; /* Get Parse Table Address (for clarity) */ ParseTbl_ptr = &ParseCtx_ptr->ParseTbl; diff --git a/src/wmc_tool/wmc_tool.cpp b/src/wmc_tool/wmc_tool.cpp index dac4c482..23f3e37b 100644 --- a/src/wmc_tool/wmc_tool.cpp +++ b/src/wmc_tool/wmc_tool.cpp @@ -1161,11 +1161,7 @@ int main( int argc, char *argv[] ) TOOL_ERROR ErrCode = NO_ERR; /* Initialization */ - ParseContext.File.MaxSize = 0; - ParseContext.ParseTbl.MaxSize = 0; - ParseContext.InsertTbl.MaxSize = 0; - ParseContext.FctCallTbl.MaxSize = 0; - ParseContext.PointerTbl.MaxSize = 0; + memset(&ParseContext, 0, sizeof(ParseContext)); ParseContext.PROMOpsWeightsSet = 1; /* Set PROM Ops Weighting Set in Context (0 = Std, 1 = STL 2009) */ /* Skip the Executable's Name */