xiaonan.dev / open-source / llama-cpp

llama.cpp contributions

A cross-platform C/C++ inference project whose multimodal layer turns image and audio inputs into model-ready chunks.

Issue and pull-request links are the public record. Statuses are snapshots, not release claims.

View contribution records

In this repository

01 / 01
Choose a record below. The strip grows sideways as this repository gains more contributions, while the reader keeps one case study in focus.

tools/mtmd · libmtmd audio tokenization

Contribution roleParticipating investigator — not the primary owner; no implementation submitted

Investigating a recoverable boundary for one-sample audio

A provisional, non-primary investigation of an audio boundary in libmtmd: a structurally valid one-sample PCM bitmap can reach a process-level assertion, turning a malformed request into a server availability failure.

Upstream progressDRAFT / PROVISIONAL. The issue is open and no PR exists. Static root-cause evidence and a candidate boundary are recorded, but this is a non-primary investigation: runtime reproduction, implementation, tests, review, and adoption remain open.
Issue
#27693
Pull request
Not opened
Module
tools/mtmd · libmtmd audio tokenization

System context

llama.cpp is a cross-platform C/C++ inference project with model loading, local/server inference, CPU and GPU backends, and multimodal inputs. The issue is in libmtmd, the layer that prepares media before it enters a model; it is not in a backend kernel or text generation loop.

For audio, llama-server accepts an OpenAI-compatible input_audio file, mtmd_helper decodes WAV/MP3/FLAC through miniaudio into mono F32 PCM, and libmtmd creates an audio bitmap. mtmd_tokenize then selects a model-specific preprocessor and turns the media into multimodal chunks and audio tokens.

Audio input is experimental and the shared tokenizer can select several preprocessors. That matters because a shared boundary check must not silently expand the accepted input domain for every audio-capable model just because one model may pad a very short signal.

Trigger and impact

The issue report describes a 16 kHz mono WAV with exactly one decoded sample on the Voxtral path. One mono F32 sample is a legitimate four-byte buffer: nx == 1, buf.size() == sizeof(float), and the buffer remains correctly aligned.

The current tokenizer treats nx == 0 as a recoverable empty-input error, but a later check requires buf.size() > sizeof(float). For one sample, 4 > 4 is false, so GGML_ASSERT reaches ggml_abort rather than returning a request error.

The reported CLI exits and the reported server loses /health after one request. Those runtime results are reported upstream, not reproduced locally: my contribution currently confirms the static path and the remaining acceptance gates, not a Windows reproduction or a fix.

Root cause

The underlying bitmap is not corrupt. Its byte size is nx * sizeof(float), so a one-sample object satisfies the representation and alignment invariants. The fault is that a user-controlled minimum-length question was expressed as an internal, process-terminating memory assertion.

Simply changing > to >= would stop this specific assertion, but it would also send a one-sample signal into every model-specific preprocessor. Whisper-style processing may pad it; Conformer, Parakeet, Granite Speech, Qwen3 TTS, and other paths have different frame, normalisation, or minimum-length semantics. Static evidence does not justify globally accepting it.

The error boundary also has to account for placeholder bitmaps used by /input_tokens. A fix based only on the real buffer could make token-count and normal completion paths disagree for the same sample count.

Fix and boundary

No source change has been made. The provisional direction is to reject nx < 2 at the shared audio-tokenization boundary with the existing LOG_ERR + return-error contract, before real-buffer and placeholder paths split. That would turn the abnormal input into a recoverable request failure instead of allowing it to reach an abort.

The existing alignment assertion would remain an internal invariant. Normal nx >= 2 audio would still enter exactly the same preprocessor path, while the patch would avoid defining one-sample numerical behaviour across every audio model.

This is a design candidate, not an implementation claim. Before any code, it needs a baseline reproduction, an explicit choice about zero-sample error wording, real-buffer and placeholder checks, and a regression test that fails before the change and passes afterward.

Why this boundary

This record is intentionally marked as a non-primary contribution. The primary contribution candidate moved to Issue #27697; #27693 remains a documented investigation and planning contribution, not a claimed ownership of the bug or its future patch.

I did not collapse the proposal into a one-character >= change because the shared boundary serves multiple preprocessors with different semantics. The safer scope is to make a bad external request recoverable without asserting a new, unverified minimum-audio policy for all models.

The page preserves the distinction between reported behaviour, static source evidence, and open runtime gates. There is no implementation, local commit, PR, CI result, maintainer review, or merge to claim at this stage.

Verification

  1. 01

    As of 27 Aug 2026 11:40 AEST, the upstream Issue was open and labelled bug-unconfirmed, with no linked Development branch or PR. The reported macOS abort remains a source report, not a locally reproduced result.

  2. 02

    Static source review at local baseline 11cd988 confirms the reachable path: decoded mono F32 PCM becomes an audio bitmap; nx == 1 produces four bytes; tools/mtmd/mtmd.cpp still uses the strict > sizeof(float) assertion after the recoverable nx == 0 branch.

  3. 03

    No fetch, build, model run, code edit, regression test, commit, push, PR, or CI run has been performed for this record. Windows baseline reproduction, server survival checks, placeholder coverage, and the full 0/1/2/normal-audio matrix remain open gates.

Upstream progress

  1. Static source path

    Confirmed at local baseline 11cd988

  2. Local reproduction

    Not run

  3. Implementation and regression

    Candidate design only

  4. Pull request

    Not created