From 4a98772d5ed1c673fe1e686ebddb943b5e9055da Mon Sep 17 00:00:00 2001 From: Kevin Lenzo Date: Sat, 15 Aug 2026 11:19:51 -0400 Subject: [PATCH] Add a stream_reset option to pocketsphinx_batch With noise removal enabled, batch results depend on control-file order: one shared decoder processes every entry, and the spectral-subtraction noise estimate persists across entries because ps_start_utt() does not reset it. Only ps_start_stream() resets it, and the batch tool never called it. Retention is correct when a control file addresses segments of one continuous recording, but batch entries are routinely independent recordings, and the tool offered no way to choose. The same audio file listed twice in one control file can report two different scores in a single run. The new stream_reset option (default no, preserving current behavior) calls ps_start_stream() before each control-file entry when noise removal is effectively enabled. test-batch-stream-reset.sh decodes a control file that lists the same recording twice, with other audio between, under -stream_reset yes, and asserts the repeated entries report identical hypothesis and score. It fails when the reset is not performed. --- doxygen/pocketsphinx_batch.1 | 3 ++ programs/pocketsphinx_batch.c | 7 ++++ test/regression/CMakeLists.txt | 1 + test/regression/test-batch-stream-reset.sh | 39 ++++++++++++++++++++++ 4 files changed, 50 insertions(+) create mode 100644 test/regression/test-batch-stream-reset.sh diff --git a/doxygen/pocketsphinx_batch.1 b/doxygen/pocketsphinx_batch.1 index 8e660af81..ba59fa6db 100644 --- a/doxygen/pocketsphinx_batch.1 +++ b/doxygen/pocketsphinx_batch.1 @@ -369,6 +369,9 @@ Silence word transition probability .B \-smoothspec Write out cepstral-smoothed logspectral files .TP +.B \-stream_reset +Reset noise-removal statistics before each control-file entry, for control files whose entries are independent recordings +.TP .B \-svspec specification (e.g., 24,0-11/25,12-23/26-38 or 0-12/13-25/26-38) .TP diff --git a/programs/pocketsphinx_batch.c b/programs/pocketsphinx_batch.c index 3a1ae210f..d904d3fcf 100644 --- a/programs/pocketsphinx_batch.c +++ b/programs/pocketsphinx_batch.c @@ -79,6 +79,10 @@ static const ps_arg_t ps_args_def[] = { ARG_INTEGER, "1", "Do every Nth line in the control file" }, + { "stream_reset", + ARG_BOOLEAN, + "no", + "Reset noise-removal statistics before each control-file entry, for control files whose entries are independent recordings" }, { "mllrctl", ARG_STRING, NULL, @@ -836,6 +840,9 @@ process_ctl(ps_decoder_t *ps, cmd_ln_t *config, FILE *ctlfh) E_INFO("Decoding '%s'\n", uttid); /* Do actual decoding. */ + if (ps_config_bool(config, "stream_reset") + && ps_config_bool(config, "remove_noise")) + ps_start_stream(ps); if(process_mllrctl_line(ps, config, mllrfile) < 0) continue; if(process_lmnamectl_line(ps, config, lmname) < 0) diff --git a/test/regression/CMakeLists.txt b/test/regression/CMakeLists.txt index 4ef434d58..56ca37fa6 100644 --- a/test/regression/CMakeLists.txt +++ b/test/regression/CMakeLists.txt @@ -3,6 +3,7 @@ set(TESTS test-lm.sh test-lm-convert.sh test-main.sh + test-batch-stream-reset.sh test-main-align.sh test-align.sh test-tidigits-fsg.sh diff --git a/test/regression/test-batch-stream-reset.sh b/test/regression/test-batch-stream-reset.sh new file mode 100644 index 000000000..7dcfde169 --- /dev/null +++ b/test/regression/test-batch-stream-reset.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +: ${CMAKE_BINARY_DIR:=$(pwd)} +. ${CMAKE_BINARY_DIR}/test/testfuncs.sh + +bn=`basename $0 .sh` +ctl=$bn.ctl + +echo "Test: $bn" + +printf 'goforward 0 -1 gof_first\nnumbers 0 -1 num\nsomething 0 -1 som\ngoforward 0 -1 gof_again\n' >$ctl +rm -f $bn.hyp + +run_program pocketsphinx_batch \ + -hmm $model/en-us/en-us \ + -lm $model/en-us/en-us.lm.bin \ + -dict $model/en-us/cmudict-en-us.dict \ + -ctl $ctl \ + -cepdir $data \ + -cepext .raw \ + -adcin yes \ + -stream_reset yes \ + -hyp $bn.hyp \ + 2>$bn.log + +if [ $? = 0 ]; then + pass "run" +else + fail "run" +fi + +first=`grep ' (gof_first ' $bn.hyp 2>/dev/null | sed 's/ (gof_first / (gof /'` +again=`grep ' (gof_again ' $bn.hyp 2>/dev/null | sed 's/ (gof_again / (gof /'` + +if test -n "$first" && test "$first" = "$again"; then + pass "repeated entry" +else + fail "repeated entry" +fi