Skip to content

Codec and format negotiation: default codec order, PCM byte-layout docs #90

@balloob

Description

@balloob

This issue comes out of a cross-SDK conformance audit comparing every Sendspin client/server implementation (aiosendspin, sendspin-cli, sendspin-cpp, sendspin-dotnet, sendspin-go, sendspin-js, sendspin-jvm, sendspin-rs, SendspinKit) against the spec. sendspin-cpp is treated as the reference implementation throughout — it most closely matches the spec's language and is the only SDK that runs on the constrained-embedded target the spec was originally written for.

The spec is detailed about codec negotiation, but the audit surfaced
two spec-text issues (plus a universal stream/request-format gap
that's better solved by a conformance scenario — filed separately
against Sendspin/conformance). sendspin-cpp is the reference for
codec handling: textbook 24-bit unpack with sign-extension in
audio_utils.h:29-47, FLAC codec_header Base64-decode in
player_role.cpp:270-282, and embedder-supplied codec order with no
hardcoded preference.

1. Specify a default codec ordering

Clients SHOULD list supported_formats in descending preference,
with compressed codecs (opus, flac) listed before pcm unless
the client has a specific reason to prefer uncompressed (e.g. a
battery-powered device avoiding CPU-heavy decoding).

sendspin-js advertises [pcm, opus, flac] (PCM first), which means
servers will choose uncompressed over Opus by default and waste
bandwidth. sendspin-cpp's conformance harness uses opus, flac, pcm
which is the more defensible default.

2. Document the PCM byte-layout convention more visibly

The current PCM encoding note is one line buried in the player
support object section. Promote it to its own subsection — PCM byte
layout
— with worked examples for 16-, 24-, and 32-bit. The full
text we have today:

Samples are encoded as little-endian signed integers (two's complement).
24-bit samples are packed as 3 bytes per sample.

This matters: sendspin-go has no explicit 24-bit code path at all,
and the bug is latent precisely because the spec text is so easy to
miss. Worked-example code would make conformance audit-able by
inspection.


Source audit doc: docs/codec-format-negotiation.md
Full audit branch: claude/stream-sync-correction-sdks-AWoNC
Per-SDK digest: sdk-issues digest

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions