The one portable audio representation a capsule carries. More...
#include <pulp/authoring_capsule/status.hpp>#include <pulp/runtime/result.hpp>#include <cstddef>#include <cstdint>#include <span>#include <string>#include <vector>Go to the source code of this file.
Classes | |
| struct | pulp::authoring_capsule::CanonicalPcm |
Namespaces | |
| namespace | pulp |
| namespace | pulp::authoring_capsule |
Functions | |
| runtime::Result< CanonicalPcm, CapsuleError > | pulp::authoring_capsule::decode_to_canonical (std::span< const std::uint8_t > source) |
| Decode a source audio file into the canonical form. | |
| std::vector< std::uint8_t > | pulp::authoring_capsule::to_canonical_bytes (const CanonicalPcm &pcm) |
| Serialize to the exact member bytes a capsule stores: the fixed header documented at the top of this file, then the interleaved little-endian binary32 samples. | |
| runtime::Result< CanonicalPcm, CapsuleError > | pulp::authoring_capsule::from_canonical_bytes (std::span< const std::uint8_t > bytes) |
| Parse a canonical member from its bytes alone; no external metadata exists. | |
| std::string | pulp::authoring_capsule::canonical_pcm_digest (const CanonicalPcm &pcm) |
| SHA-256, bare lowercase hex, over to_canonical_bytes(pcm). | |
| runtime::Result< void, CapsuleError > | pulp::authoring_capsule::validate_canonical (const CanonicalPcm &pcm) |
| Reject NaN, infinity, and any frame count that disagrees with the buffer length. | |
Variables | |
| constexpr std::uint32_t | pulp::authoring_capsule::kMinCanonicalSampleRate = 8000 |
| constexpr std::uint32_t | pulp::authoring_capsule::kMaxCanonicalSampleRate = 192000 |
| constexpr std::uint32_t | pulp::authoring_capsule::kMaxCanonicalChannels = 2 |
| constexpr std::uint32_t | pulp::authoring_capsule::kCanonicalPcmDecoderVersion = 1 |
| The decoder's contract version, stored in every canonical member's header. | |
| constexpr char | pulp::authoring_capsule::kCanonicalPcmMagic [8] = {'p', 'u', 'l', 'p', '.', 'p', 'c', 'm'} |
| First eight bytes of every canonical member. | |
| constexpr std::size_t | pulp::authoring_capsule::kCanonicalPcmHeaderBytes = 28 |
| Fixed header size; sample data begins here. | |
The one portable audio representation a capsule carries.
A capsule that travelled with the author's original 96 kHz FLAC and nothing else would only play back where that decoder exists. So the capsule embeds a canonical rendition — a self-describing member of interleaved little-endian float32 with a fixed header — and treats the author's original as an optional source role. Machine B needs the canonical member bytes and nothing more.
Canonical member byte layout (frozen — every audio member's identity is the SHA-256 of exactly these bytes):
[0 .. 8) magic, the ASCII bytes "pulp.pcm" [8 .. 12) uint32 LE decoder_version [12 .. 16) uint32 LE channels, 1 or 2 [16 .. 20) uint32 LE sample_rate, in [8000, 192000] [20 .. 28) uint64 LE frame_count [28 .. ) frame_count * channels interleaved little-endian IEEE-754 binary32 samples, finite only, exactly to the end
The header travels inside the hashed bytes, which buys three properties at once: the member's plain SHA-256 is its identity, so an audio row obeys the same uniform "row digest = digest of member bytes" rule as every other row with no side channel; the member decodes from its bytes alone, so the decoder-version guard is enforced by the bytes rather than by metadata a consumer might drop; and two renditions differing only in declared rate have different identities, because the rate is inside the hash.