Skip to content

ps_start_stream() returns -1 when remove_noise is false #496

Description

@lenzo-ka

User-visible symptom

A decoder can initialize successfully with remove_noise=false, but the exported compatibility function ps_start_stream() then returns -1. A binding or application that treats a negative return as a stream-start failure can therefore reject an otherwise valid decoder configuration.

This is especially surprising because remove_noise=false is the default, and the API documentation describes ps_start_stream() as retained for compatibility with the sole effect of resetting noise-removal statistics.

Mechanism in v5.1.1

These references are to commit 511126b492dcb267cf30d49d631946d7b61a9530 (v5.1.1).

  • src/fe/fe_interface.c:278-281 allocates fe->noise_stats only when remove_noise is true.
  • src/pocketsphinx.c:1072-1082 implements ps_start_stream() and returns -1 when noise_stats is null, at lines 1079-1080.
  • src/fe/fe_noise.c:253-258 shows that fe_reset_noisestats() is already null-safe.
  • src/config_macro.h:487-490 defines remove_noise with the default no.
  • include/pocketsphinx.h:769-780 documents the compatibility function and its return convention without stating that noise removal must be enabled.

The failure is therefore caused by a precondition that the reset helper itself does not require.

Minimal reproduction

Build PocketSphinx v5.1.1, copy the shipped English acoustic model, and make the effective model configuration disable noise removal (this avoids the shipped model's feat.params overriding the caller setting):

cp -R model/en-us/en-us /tmp/ps-no-noise-model
sed -i.bak 's/^-remove_noise .*/-remove_noise no/' /tmp/ps-no-noise-model/feat.params

Compile and run:

#include <pocketsphinx.h>
#include <stdio.h>

int main(void)
{
    ps_config_t *config = ps_config_init(NULL);
    ps_config_set_str(config, "hmm", "/tmp/ps-no-noise-model");
    ps_config_set_str(config, "dict", "model/en-us/cmudict-en-us.dict");
    ps_config_set_str(config, "lm", "model/en-us/en-us.lm.bin");

    ps_decoder_t *ps = ps_init(config);
    if (ps == NULL)
        return 2;

    printf("remove_noise=%d ps_start_stream=%d\n",
           ps_config_bool(ps_get_config(ps), "remove_noise"),
           ps_start_stream(ps));

    ps_free(ps);
    ps_config_free(config);
    return 0;
}

With the pinned implementation, the expected output is:

remove_noise=0 ps_start_stream=-1

Changing the copied model's value to -remove_noise yes makes ps_start_stream() return 0.

What this does and does not establish

The allocation condition, failing branch, null-safe reset, default, and public API wording are directly established in the pinned source. The finding arose in application usage, not in PocketSphinx's test suite.

The standalone snippet above was not executed as part of this report; its result follows directly from the cited branches. ps_start_stream() is deprecated and is unnecessary for ordinary utterance processing, which limits the impact. This report does not claim that every caller invokes it or that disabling noise removal otherwise prevents decoding.

Smallest addressing change

Remove the noise_stats == NULL error return and call the already null-safe fe_reset_noisestats() unconditionally, or return 0 when the pointer is null. A focused regression test can initialize with an effective remove_noise=false configuration and assert that ps_start_stream() returns zero.

If the failure is intentional, the smaller alternative is to document the precondition explicitly, though that would make the compatibility function fail under the generic default.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions