. "$BST_LIB" # libsndfile 1.2.2 (poky recipes-multimedia/libsndfile) -- the audio file I/O # library: one API over WAV, AIFF, AU, W64, CAF, FLAC and Ogg/Vorbis, plus the # ten sndfile-* command-line tools that drive it. # # WHY THIS PORT IS CHECKABLE TO A STANDARD MOST OF THE MEDIA TIER IS NOT. There # is no sound card on a browser guest, so a codec is normally only testable to # the "it ran and printed a banner" standard. libsndfile escapes that twice # over. First, MOST OF WHAT IT DOES IS EXACT: rewriting PCM from a RIFF wrapper # into an AIFF, AU, W64 or CAF one moves the same samples into a different # header and performs no arithmetic at all, so the output is a byte-for-byte # fact rather than a judgement. Second, IT SHIPS ITS OWN COMPARATOR -- # sndfile-cmp reads two files through the library and compares the DECODED PCM, # so "same audio, different container" is a question the subject answers about # itself, with no reference file involved. # # WHAT IS COMPARED AGAINST x86-64, AND WHY ONLY THOSE. Every reference under # data/ was produced by libsndfile 1.2.2's own sndfile-convert built natively on # the build host from the same tarball with the same five poky patches, against # the same libogg 1.3.5 / flac 1.4.3 / libvorbis 1.3.7 the image builds -- # reference and subject are one program built for two architectures. Which of # its outputs may be stored at all was MEASURED, not assumed (each conversion # run twice, seconds apart, and compared); see src/libsndfile1_mkfixtures.py. # aiff/au/w64/caf, ulaw/alaw/pcm24 and flac came back byte-identical. Two did # not, and both are handled rather than hidden: # # - float32 carries the WAV PEAK chunk, whose `timestamp` field is # "secs since 1/1/1970" (src/common.h:222). Four bytes at offset 60. Both # sides zero exactly those four, and the case below asserts the PEAK magic # really is where the zeroing assumes before doing it. # - Ogg/Vorbis is given NO stored reference: the Ogg bitstream serial number # is drawn at random per run -- the same upstream wart 57-speex.test # canonicalises around -- and the Vorbis encoder is float-heavy, the class # 57-libvorbis.test already refuses a cross-machine digest for. It is # covered structurally instead. # # THE ONE CASE HERE THAT IS A QUESTION RATHER THAN A REGRESSION GUARD is # `flac-exact`. libFLAC's LPC analysis runs in double precision, so a byte-exact # cross-architecture encode is not owed, and 57-flac.test next door declines a # stored digest for exactly that reason. This suite does not rest on it: FLAC's # real gate is `flac-lossless`, which needs no oracle at all. `flac-exact` is # asked anyway because the answer is worth knowing for an image whose whole # media tier sits on this arithmetic. A red there is a finding to attribute, not # a broken port -- and it would NOT indict the port, because a lossless # round-trip through the same encoder cannot be reconciled with a broken one. # # THE INVERSE TELL, so a later reader does not misread a sweep: the exact- # container cases (aiff/au/w64/caf/ulaw/alaw/pcm24) touch no floating point # whatsoever. If any of THOSE go red while the codec cases stay green, the fault # is in file I/O or the header writers, not in arithmetic -- and if they go red # together, suspect the fixture staging above them rather than seven independent # format bugs. require sndfile-info libsndfile1/present tmp=${TMPDIR:-/tmp}/bst-libsndfile1.$$ mkdir -p "$tmp" 2>/dev/null MONO=$BST_DATA/libsndfile1-mono8k.wav STEREO=$BST_DATA/libsndfile1-stereo8k.wav # ------------------------------------------------------------------ fixture --- # The fixtures ship rather than being generated in-shell: every case below is a # comparison against a reference made from these exact bytes, so a fixture that # drifted by one sample would redden the whole file for a reason that has # nothing to do with the port. if [ ! -f "$MONO" ] || [ ! -f "$STEREO" ]; then bst_notok libsndfile1/fixture "shipped fixtures missing under $BST_DATA -- remaining cases not run" rm -rf "$tmp" exit 0 fi check_eq libsndfile1/fixture-mono 16044 "$(wc -c < "$MONO" 2>/dev/null | tr -d ' ')" check_eq libsndfile1/fixture-stereo 32044 "$(wc -c < "$STEREO" 2>/dev/null | tr -d ' ')" m=$tmp/m.wav; s=$tmp/s.wav cp "$MONO" "$m" && cp "$STEREO" "$s" # ------------------------------------------------------------------- tools --- # All ten are one package (libsndfile1-bin, from the recipe's lib_package # split), so an absent one is a packaging fault on this image rather than a # legitimately absent tool -- `not ok`, not the `require` skip that guards # sndfile-info itself. Named one case each so a regression says which tool. for t in sndfile-info sndfile-convert sndfile-cmp sndfile-concat \ sndfile-interleave sndfile-deinterleave sndfile-metadata-get \ sndfile-metadata-set sndfile-salvage sndfile-play; do if command -v "$t" >/dev/null 2>&1; then bst_ok "libsndfile1/tool-$t" else bst_notok "libsndfile1/tool-$t" "$t is not on PATH, though libsndfile1-bin packages it"; fi done # sndfile-metadata-get with no arguments prints its usage, which ends in the # library version, and exits non-zero -- so the version is read from the output # rather than asserted through check_out, which would require exit 0. ver=$(sndfile-metadata-get 2>&1) case "$ver" in *libsndfile-1.2.2*) bst_ok libsndfile1/version ;; *) bst_notok libsndfile1/version "$(_bst_1line "$ver")" ;; esac # ------------------------------------------------------- sndfile-info reads --- # One exec, five facts: the parse is what every case below depends on, so it is # established before anything is converted. Format 0x00010002 is WAV|PCM_16. # # The summary block's keys are unindented and the per-chunk ones are not, so # anchoring at ^ picks the summary. Splitting on ': *' would NOT work: Duration # is 00:00:01.000 and an awk -F would go on splitting it into '00'. info=$(sndfile-info "$m" 2>&1) val() { printf '%s\n' "$info" | sed -n "s/^$1 *: *//p" | head -n 1; } field() { sndfile-info "$1" 2>&1 | sed -n "s/^$2 *: *//p" | head -n 1; } check_eq libsndfile1/info-rate 8000 "$(val 'Sample Rate')" check_eq libsndfile1/info-frames 8000 "$(val 'Frames')" check_eq libsndfile1/info-channels 1 "$(val 'Channels')" check_eq libsndfile1/info-format 0x00010002 "$(val 'Format')" check_eq libsndfile1/info-duration 00:00:01.000 "$(val 'Duration')" # ------------------------------------------- container rewrites, byte-exact --- # No arithmetic on this path at all -- the same PCM into a different wrapper -- # so equality with x86-64 is owed, not hoped for. for ext in aiff au w64 caf; do out=$tmp/m.$ext if sndfile-convert "$m" "$out" >/dev/null 2>&1; then check "libsndfile1/wav2$ext-exact" cmp "$BST_DATA/libsndfile1-mono8k.ref.$ext" "$out" else bst_notok "libsndfile1/wav2$ext-exact" "sndfile-convert wav -> $ext failed" fi done if sndfile-convert "$s" "$tmp/s.aiff" >/dev/null 2>&1; then check libsndfile1/stereo-wav2aiff-exact cmp "$BST_DATA/libsndfile1-stereo8k.ref.aiff" "$tmp/s.aiff" else bst_notok libsndfile1/stereo-wav2aiff-exact "sndfile-convert stereo wav -> aiff failed" fi # ------------------------------------ sample-format changes inside WAV, exact --- # ulaw and alaw are table lookups and pcm24 is a widening shift; all three are # exact integer transforms and were measured byte-identical across runs. for enc in ulaw alaw pcm24; do out=$tmp/m-$enc.wav if sndfile-convert "-$enc" "$m" "$out" >/dev/null 2>&1; then check "libsndfile1/$enc-exact" cmp "$BST_DATA/libsndfile1-mono8k.ref.$enc.wav" "$out" else bst_notok "libsndfile1/$enc-exact" "sndfile-convert -$enc failed" fi done # float32 is exact too, but libsndfile stamps the PEAK chunk with time(NULL). # Assert the chunk is where the canonicalisation assumes BEFORE zeroing, so a # layout change is reported rather than quietly blanking four bytes of audio. f32=$tmp/m-float32.wav if sndfile-convert -float32 "$m" "$f32" >/dev/null 2>&1; then magic=$(dd if="$f32" bs=1 skip=48 count=4 2>/dev/null) check_eq libsndfile1/float32-peak-layout PEAK "$magic" if [ "$magic" = PEAK ]; then dd if=/dev/zero of="$f32" bs=1 seek=60 count=4 conv=notrunc 2>/dev/null check libsndfile1/float32-exact cmp "$BST_DATA/libsndfile1-mono8k.ref.float32.wav" "$f32" else bst_notok libsndfile1/float32-exact "PEAK chunk is not at offset 48; refusing to zero four bytes blind" fi else bst_notok libsndfile1/float32-peak-layout "sndfile-convert -float32 failed" bst_notok libsndfile1/float32-exact "sndfile-convert -float32 failed" fi # --------------------------------------------- the library's own comparator --- # sndfile-cmp decodes both files and compares PCM, so it sees through the # container: the AIFF above must carry the same audio as the WAV it came from. check libsndfile1/cmp-aiff-pcm sndfile-cmp "$m" "$tmp/m.aiff" # ...and the negative control, without which the case above is vacuous: a # comparator that always reported "same" would pass it. ULAW is lossy, so this # pair MUST differ, and sndfile-cmp signals a difference with exit status 1. check_rc libsndfile1/cmp-detects-lossy 1 sndfile-cmp "$m" "$tmp/m-ulaw.wav" # ------------------------------------------------------------- round-trips --- # These need no reference at all, which is what makes them the strongest cases # here: the property is internal to the target. if sndfile-convert "$tmp/m.aiff" "$tmp/back.wav" >/dev/null 2>&1; then check libsndfile1/aiff-roundtrip cmp "$m" "$tmp/back.wav" else bst_notok libsndfile1/aiff-roundtrip "sndfile-convert aiff -> wav failed" fi if sndfile-convert -pcm16 "$tmp/m-pcm24.wav" "$tmp/narrow.wav" >/dev/null 2>&1; then check libsndfile1/pcm24-roundtrip cmp "$m" "$tmp/narrow.wav" else bst_notok libsndfile1/pcm24-roundtrip "sndfile-convert pcm24 -> pcm16 failed" fi # ------------------------------------------------------------------- FLAC --- fl=$tmp/m.flac if sndfile-convert "$m" "$fl" >/dev/null 2>&1 && sndfile-convert "$fl" "$tmp/fback.wav" >/dev/null 2>&1; then # THE gate for this path: FLAC is lossless, so what comes back must be what # went in, byte for byte, with no oracle involved. check libsndfile1/flac-lossless cmp "$m" "$tmp/fback.wav" # It must be a codec, not a container rewrite. fb=$(wc -c < "$fl" 2>/dev/null | tr -d ' ') if [ -n "$fb" ] && [ "$fb" -lt 16044 ]; then bst_ok libsndfile1/flac-compresses else bst_notok libsndfile1/flac-compresses "encoded $fb bytes from a 16044-byte fixture -- no compression"; fi check_eq libsndfile1/flac-format 0x00170002 "$(field "$fl" Format)" # The question case -- see the header. Not the port's gate. check libsndfile1/flac-exact cmp "$BST_DATA/libsndfile1-mono8k.ref.flac" "$fl" else for c in flac-lossless flac-compresses flac-format flac-exact; do bst_notok "libsndfile1/$c" "FLAC encode or decode failed" done fi # ---------------------------------------------------------------- Vorbis --- # Structural, not byte-exact, and deliberately so (header). Note the explicit # -pcm16 on the way back: a bare decode is REFUSED by design, since a WAV # container cannot hold Vorbis codec data -- asserting that refusal is itself # worth a case, because a tool that silently wrote a broken file instead would # pass everything else here. og=$tmp/m.ogg if sndfile-convert -vorbis "$m" "$og" >/dev/null 2>&1; then bst_ok libsndfile1/vorbis-encode check_eq libsndfile1/vorbis-format 0x00200060 "$(field "$og" Format)" check_eq libsndfile1/vorbis-frames 8000 "$(field "$og" Frames)" check_rc libsndfile1/vorbis-refuses-wav-codec 1 sndfile-convert "$og" "$tmp/bad.wav" if sndfile-convert -pcm16 "$og" "$tmp/vback.wav" >/dev/null 2>&1; then bst_ok libsndfile1/vorbis-decode check_eq libsndfile1/vorbis-decode-frames 8000 \ "$(field "$tmp/vback.wav" Frames)" else bst_notok libsndfile1/vorbis-decode "sndfile-convert -pcm16 ogg -> wav failed" bst_notok libsndfile1/vorbis-decode-frames "decode failed" fi else for c in vorbis-encode vorbis-format vorbis-frames vorbis-refuses-wav-codec \ vorbis-decode vorbis-decode-frames; do bst_notok "libsndfile1/$c" "Vorbis encode failed" done fi # -------------------------------------------- deinterleave / interleave pair --- # The fixture's two channels carry different pitches precisely so this pair # cannot pass by symmetry: identical channels would round-trip even if the tools # swapped them. cp "$s" "$tmp/sp.wav" if (cd "$tmp" && sndfile-deinterleave sp.wav >/dev/null 2>&1) && [ -f "$tmp/sp_00.wav" ] && [ -f "$tmp/sp_01.wav" ]; then bst_ok libsndfile1/deinterleave check_eq libsndfile1/deinterleave-mono 1 \ "$(field "$tmp/sp_00.wav" Channels)" if sndfile-interleave "$tmp/sp_00.wav" "$tmp/sp_01.wav" -o "$tmp/rejoined.wav" >/dev/null 2>&1; then bst_ok libsndfile1/interleave check libsndfile1/interleave-identical sndfile-cmp "$s" "$tmp/rejoined.wav" else bst_notok libsndfile1/interleave "sndfile-interleave failed" bst_notok libsndfile1/interleave-identical "sndfile-interleave failed" fi else for c in deinterleave deinterleave-mono interleave interleave-identical; do bst_notok "libsndfile1/$c" "sndfile-deinterleave produced no channel files" done fi # ---------------------------------------------------------------- concat --- if sndfile-concat "$m" "$m" "$tmp/cat2.wav" >/dev/null 2>&1; then check_eq libsndfile1/concat-frames 16000 \ "$(field "$tmp/cat2.wav" Frames)" else bst_notok libsndfile1/concat-frames "sndfile-concat failed" fi # -------------------------------------------------------------- metadata --- # A metadata WRITE rewrites the file in place -- a different path from anything # the converters exercise, and the one that touches the filesystem hardest. The # label sndfile-metadata-get prints for a title is `Name`, not `Title`. mt=$tmp/meta.wav cp "$m" "$mt" if sndfile-metadata-set --str-title brintOS --str-artist Emcraft "$mt" >/dev/null 2>&1; then bst_ok libsndfile1/metadata-set got=$(sndfile-metadata-get --str-title --str-artist "$mt" 2>&1) case "$got" in *brintOS*) bst_ok libsndfile1/metadata-title ;; *) bst_notok libsndfile1/metadata-title "$(_bst_1line "$got")" ;; esac case "$got" in *Emcraft*) bst_ok libsndfile1/metadata-artist ;; *) bst_notok libsndfile1/metadata-artist "$(_bst_1line "$got")" ;; esac # A tag write that corrupted a frame would pass both cases above. check libsndfile1/metadata-preserves-audio sndfile-cmp "$m" "$mt" else for c in metadata-set metadata-title metadata-artist metadata-preserves-audio; do bst_notok "libsndfile1/$c" "sndfile-metadata-set failed" done fi # Shape, not absence: this arm converts to shared libraries per recipe # (BRINTOS-1740), so a .so here is a conversion, not a policy breach. bst_lib_shape libsndfile1/static-only "/usr/lib/libsndfile.so" "/usr/lib/libsndfile.so.1" rm -rf "$tmp"