Commit 284029c0 for whisper.cpp
commit 284029c07012d2000941a08d38a31ffb71f4734e
Author: Lucius <37386791+luciusacarr@users.noreply.github.com>
Date: Wed Oct 28 01:07:30 2026 -0700
whisper : clear VAD state when VAD is disabled (#4122)
* whisper : clear VAD state when VAD is disabled
* test hardening
diff --git a/src/whisper.cpp b/src/whisper.cpp
index 6e0fbf4a..112e7078 100644
--- a/src/whisper.cpp
+++ b/src/whisper.cpp
@@ -6814,6 +6814,12 @@ static void whisper_sequence_score(
}
}
+static void whisper_state_clear_vad(struct whisper_state * state) {
+ state->vad_segments.clear();
+ state->vad_mapping_table.clear();
+ state->has_vad_segments = false;
+}
+
static bool whisper_vad(
struct whisper_context * ctx,
struct whisper_state * state,
@@ -6824,9 +6830,8 @@ static bool whisper_vad(
WHISPER_LOG_INFO("%s: VAD is enabled, processing speech segments only\n", __func__);
int filtered_n_samples = 0;
- // Clear any existing mapping table
- state->vad_mapping_table.clear();
- state->has_vad_segments = false;
+ // Clear any existing VAD state
+ whisper_state_clear_vad(state);
if (state->vad_context == nullptr) {
struct whisper_vad_context_params vad_ctx_params = whisper_vad_default_context_params();
@@ -7968,6 +7973,8 @@ int whisper_full(
}
samples = vad_samples.data();
n_samples = vad_samples.size();
+ } else {
+ whisper_state_clear_vad(ctx->state);
}
return whisper_full_with_state(ctx, ctx->state, params, samples, n_samples);
}
@@ -7995,6 +8002,8 @@ int whisper_full_parallel(
}
samples = vad_samples.data();
n_samples = vad_samples.size();
+ } else {
+ whisper_state_clear_vad(ctx->state);
}
int ret = 0;
diff --git a/tests/test-vad-full.cpp b/tests/test-vad-full.cpp
index f033e058..6452b05d 100644
--- a/tests/test-vad-full.cpp
+++ b/tests/test-vad-full.cpp
@@ -81,6 +81,35 @@ int main() {
vad_prev_end = t1;
}
+ // non-VAD call after a VAD call on the same context must not use stale VAD state.
+ // ref: https://github.com/ggml-org/whisper.cpp/issues/4113
+ struct whisper_full_params wparams_novad = wparams;
+ wparams_novad.vad = false;
+
+ struct whisper_context * wctx_ref = whisper_init_from_file_with_params(
+ whisper_model_path.c_str(),
+ cparams);
+
+ assert(wctx_ref);
+
+ for (int processors = 1; processors <= 2; ++processors) {
+ assert(whisper_full_parallel(wctx_ref, wparams_novad, pcmf32.data(), pcmf32.size(), processors) == 0);
+
+ assert(whisper_full_parallel(wctx, wparams, pcmf32.data(), pcmf32.size(), 1) == 0);
+ assert(whisper_full_parallel(wctx, wparams_novad, pcmf32.data(), pcmf32.size(), processors) == 0);
+ assert(whisper_full_n_vad_segments(wctx) == 0);
+
+ const int n_segments_ref = whisper_full_n_segments(wctx_ref);
+ assert(n_segments_ref > 0);
+ assert(whisper_full_n_segments(wctx) == n_segments_ref);
+
+ for (int i = 0; i < n_segments_ref; ++i) {
+ assert(whisper_full_get_segment_t0(wctx, i) == whisper_full_get_segment_t0(wctx_ref, i));
+ assert(whisper_full_get_segment_t1(wctx, i) == whisper_full_get_segment_t1(wctx_ref, i));
+ }
+ }
+
+ whisper_free(wctx_ref);
whisper_free(wctx);
return 0;