Skip to content

v0.0.8

Choose a tag to compare

@MagicalTux MagicalTux released this 30 May 02:35
· 58 commits to master since this release
c434606

Other

  • parse plst (Playlist) chunk per Microsoft RIFF MCI §3
  • parse smpl (Sampler) + inst (Instrument) chunks
  • parse cue + LIST adtl per Microsoft RIFF MCI §3
  • parse bext Broadcast Audio Extension chunk (EBU Tech 3285)
  • fix intra-doc links to WavMuxOptions / WavDemuxer methods
  • A-law/μ-law tag 6/7 + WAVEFORMATEXTENSIBLE end-to-end

Added

  • WAV demuxer parses the plst (Playlist) chunk per
    docs/container/riff/metadata/microsoft-riffmci.pdf §3 ("Playlist
    Chunk"). The 4-byte dwSegments count is followed by N × 12-byte
    <play-segment> records (dwName, dwLength, dwLoops). Each
    segment surfaces under wav:plst.count plus per-segment
    wav:plst.<n>.cue_id / .length / .loops keys. Unlike the cue
    chunk which keys by dwName, the playlist is keyed by zero-based
    segment position because the spec explicitly allows a single cue
    id to appear in multiple segments (a cue replayed N times = N
    segments with identical dwName), so a dwName-indexed key would
    collide. A dwSegments count that exceeds the chunk body is
    clamped to the records that actually fit; bodies shorter than the
    4-byte segment-count header are treated as opaque and skipped.
  • WAV demuxer parses the smpl (Sampler) and inst (Instrument)
    chunks per docs/container/riff/metadata/exiftool-riff-tags.html §
    "RIFF Sampler Tags" / "RIFF Instrument Tags" and summarised in
    docs/container/riff/metadata/README.md § "Sampler / Instrument
    chunks". smpl is a 36-byte fixed header (Manufacturer,
    Product, SamplePeriod, MIDIUnityNote, MIDIPitchFraction,
    SMPTEFormat, SMPTEOffset, cSampleLoops, cbSamplerData)
    followed by N × 24-byte loop records (dwCuePointID, dwType,
    dwStart, dwEnd, dwFraction, dwPlayCount). inst is a
    7-byte fixed struct (UnshiftedNote, FineTune, Gain, LowNote,
    HighNote, LowVelocity, HighVelocity). Both surface through
    Demuxer::metadata under wav:smpl.* / wav:inst.* keys; the
    SMPTEOffset DWORD is rendered as canonical HH:MM:SS:FF, and
    FineTune / Gain are decoded as signed i8 (so -3 cents shows
    as -3, not 253). A cSampleLoops count exceeding what the chunk
    body actually carries is clamped to the records that fit; bodies
    shorter than the 36-byte (smpl) or 7-byte (inst) fixed header
    are treated as opaque and skipped.
  • WAV demuxer parses the cue chunk and the LIST adtl (Associated
    Data List) sub-chunks per
    docs/container/riff/metadata/microsoft-riffmci.pdf §3
    ("Cue-Points Chunk" + "Playlist Chunk" + "Associated Data Chunk").
    The cue-point table surfaces under wav:cue.count plus per-point
    wav:cue.<dwName>.position / .fcc_chunk / .chunk_start /
    .block_start / .sample_offset (all values as decimal strings;
    fcc_chunk rendered as a 4-byte ASCII FOURCC when printable). The
    LIST adtl body's labl / note / ltxt sub-chunks surface
    under wav:adtl.labl.<dwName> / wav:adtl.note.<dwName> /
    wav:adtl.ltxt.<dwName>.{length,purpose,text}. file sub-chunks
    (embedded media files) are skipped — their bytes do not fit the
    string-typed metadata API. A dwCuePoints count that exceeds the
    chunk body is clamped to the records that actually fit so a writer
    that lies about the count cannot panic the parser; labl / note
    shorter than the 4-byte dwName header and ltxt shorter than the
    20-byte fixed header are treated as opaque and skipped.
  • WAV demuxer parses the bext Broadcast Audio Extension chunk per
    docs/container/riff/metadata/ebu-tech3285-bwf.pdf (EBU Tech 3285 v2
    §2.3 BROADCAST_EXT). The 602-byte fixed struct plus variable
    CodingHistory is surfaced through Demuxer::metadata under
    wav:bext.description / .originator / .originator_reference /
    .origination_date / .origination_time / .time_reference (64-bit
    sample count reassembled from the low/high DWORDs) / .version /
    .umid (hex-encoded SMPTE-330M UMID, v1+ only when non-zero) /
    .coding_history. For BWF v2 the five loudness WORDs are decoded
    from the §2.4 round(100 × value) fixed-point to two decimals under
    .loudness_value / .loudness_range / .max_true_peak_level /
    .max_momentary_loudness / .max_short_term_loudness. Loudness and
    UMID keys are omitted for v0/v1 streams that leave those fields zero;
    a bext chunk shorter than 602 bytes is skipped as opaque.
  • WAV demuxer dispatches WAVE_FORMAT_ALAW (0x0006) and
    WAVE_FORMAT_MULAW (0x0007) streams to the pcm_alaw / pcm_mulaw
    codecs (host runtime applies G.711 decode through oxideav-g711).
    Decoded SampleFormat hint surfaces as S16; bit_rate reflects
    the on-wire 8-bit rate (not the post-decode S16 rate).
  • WAV WAVE_FORMAT_EXTENSIBLE (0xFFFE) end-to-end handling per
    docs/container/riff/waveformatextensible/README.md: the 22-byte
    extension's wValidBitsPerSample, dwChannelMask and SubFormat
    GUID are parsed and exposed both through typed accessors on
    WavDemuxer (format_tag, valid_bits_per_sample, channel_mask,
    subformat, subformat_text) and through Demuxer::metadata
    under the keys wav:fmt.valid_bits_per_sample /
    wav:fmt.channel_mask / wav:fmt.subformat. Well-known
    KSDATAFORMAT_SUBTYPE_* GUIDs (PCM, IEEE_FLOAT, ALAW, MULAW)
    resolve to the legacy codec ids; unknown GUIDs synthesise a
    wav:guid_<canonical-text> id so downstream make_decoder
    failures name the actual GUID rather than the opaque 0xFFFE tag.
  • WAV muxer open_muxer_with + WavMuxOptions::with_extensible(mask)
    emits a 40-byte WAVEFORMATEXTENSIBLE fmt chunk with caller-
    supplied dwChannelMask. wValidBitsPerSample defaults to the
    container wBitsPerSample and SubFormat defaults to the well-known
    GUID for the codec; both can be overridden via
    with_valid_bits_per_sample / with_subformat.
  • New public constants WAVE_FORMAT_PCM / WAVE_FORMAT_IEEE_FLOAT /
    WAVE_FORMAT_ALAW / WAVE_FORMAT_MULAW / WAVE_FORMAT_EXTENSIBLE
    in the wav module for muxer callers.

Fixed

  • WAV demuxer rejects WAVE_FORMAT_EXTENSIBLE streams whose
    cbSize < 22 (the spec mandates a 22-byte extension; previously
    the demuxer silently dropped the extension fields).
  • WAV demuxer stamps the on-wire wFormatTag onto
    CodecParameters.tag so consumers can distinguish legacy
    WAVEFORMATEX from EXTENSIBLE round-trips without reparsing.