@openclaw/whatsapp 2026.9.6 → 2026.9.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/icon.png +0 -0
- package/dist/.setup/{accounts-D_NGDjCx.mjs → accounts-CtRPAQCL.mjs} +3 -9
- package/dist/.setup/{action-runtime-DZZFamfl.mjs → action-runtime-DeVk5V7r.mjs} +2 -2
- package/dist/.setup/{approval-handler.runtime-C0hzmMSj.mjs → approval-handler.runtime-CjqMlPOX.mjs} +6 -26
- package/dist/.setup/{approval-reactions-BnXw-UZI.mjs → approval-reactions-DiOFvb1s.mjs} +8 -14
- package/dist/.setup/{auth-store-Dh8a3cba.mjs → auth-store-BBonwKks.mjs} +9 -33
- package/dist/.setup/{channel-Bg_fS2iF.mjs → channel-CJFE0kD_.mjs} +82 -154
- package/dist/.setup/{channel-react-action-1iBiEnq7.mjs → channel-react-action-2r_hjLZV.mjs} +4 -8
- package/dist/.setup/{channel.runtime-rurG-kbr.mjs → channel.runtime-C94goLw9.mjs} +4 -4
- package/dist/.setup/{channel.setup-C8P5q8uD.mjs → channel.setup-CfN1UfdY.mjs} +1 -1
- package/dist/.setup/{connection-controller-C60mU7j7.mjs → connection-controller-CHo1oRJA.mjs} +13 -63
- package/dist/.setup/{creds-files-Drg3usj1.mjs → creds-files-CDATZWWM.mjs} +5 -11
- package/dist/.setup/{directory-config-BHPoBklt.mjs → directory-config-DUiJ5d8I.mjs} +13 -14
- package/dist/.setup/doctor-iMwg0Vhr.mjs +222 -0
- package/dist/.setup/group-config-path-DZr3ucUO.mjs +40 -0
- package/dist/.setup/{group-session-key-D22hYMdE.mjs → group-session-key-2-mja4OF.mjs} +3 -9
- package/dist/.setup/{login-2dmd1TfE.mjs → login-BFlvSh9h.mjs} +9 -11
- package/dist/.setup/{login-qr-CgKtO_ef.mjs → login-qr-Ayb8i25J.mjs} +29 -77
- package/dist/.setup/{monitor-By82ehLA.mjs → monitor-CGpV2VNN.mjs} +376 -504
- package/dist/.setup/{question-reactions-D3Zq9Gbn.mjs → question-reactions-CPyyi5AY.mjs} +2 -2
- package/dist/.setup/rolldown-runtime-BBjsoOtd.mjs +27 -0
- package/dist/.setup/{send-C6jDmcL9.mjs → send-BGdvf5cC.mjs} +31 -80
- package/dist/.setup/{send-api-B4DOt2RJ.mjs → send-api-H4AkQJjT.mjs} +45 -109
- package/dist/.setup/{session-errors-JuazczrA.mjs → session-errors-B8UcAnZN.mjs} +1 -4
- package/dist/.setup/{session.runtime-DcJuO42v.mjs → session.runtime-st1konFI.mjs} +1 -1
- package/dist/.setup/{setup-finalize-pGqWOiFX.mjs → setup-finalize-DmPX4EaW.mjs} +32 -70
- package/dist/.setup/setup-plugin-api-vJlxKzca.mjs +3 -0
- package/dist/.setup/{setup-surface-B9CYwDPZ.mjs → setup-surface-43fj197P.mjs} +3 -3
- package/dist/.setup/{shared-DVgQ8kRG.mjs → shared-DgOG5Iqr.mjs} +26 -37
- package/dist/.setup/{socket-close-CCVSFufF.mjs → socket-close-CT__V2fz.mjs} +80 -92
- package/dist/.setup/{targets-runtime-RBjx3pg_.mjs → targets-runtime-DmiqXIXO.mjs} +2 -7
- package/dist/action-runtime-api.js +1 -1
- package/dist/action-runtime.runtime.js +1 -1
- package/dist/agent-tools-api.js +5 -12
- package/dist/api.js +10 -10
- package/dist/auth-presence.js +1 -1
- package/dist/channel-plugin-api.js +1 -1
- package/dist/contract-api.js +2 -2
- package/dist/directory-contract-api.js +1 -1
- package/dist/doctor-contract-api.js +9 -10
- package/dist/light-runtime-api.js +2 -2
- package/dist/login-qr-runtime.js +1 -1
- package/dist/runtime-api.js +9 -9
- package/dist/setup-entry.js +1 -1
- package/dist/setup-plugin-api.js +1 -1
- package/node_modules/audio-decode/LICENSE +9 -10
- package/node_modules/audio-decode/README.md +16 -0
- package/node_modules/audio-decode/audio-decode.d.ts +2 -14
- package/node_modules/audio-decode/audio-decode.js +4 -92
- package/node_modules/audio-decode/meta.js +1 -0
- package/node_modules/audio-decode/node_modules/{audio-buffer → @audio/decode}/LICENSE +1 -1
- package/node_modules/audio-decode/node_modules/@audio/decode/audio-decode.d.ts +52 -0
- package/node_modules/audio-decode/node_modules/@audio/decode/audio-decode.js +242 -0
- package/node_modules/audio-decode/node_modules/@audio/decode/meta.js +14 -0
- package/node_modules/audio-decode/node_modules/@audio/decode/package.json +114 -0
- package/node_modules/audio-decode/node_modules/@audio/decode/readme.md +191 -0
- package/node_modules/audio-decode/node_modules/@audio/decode/stream.d.ts +12 -0
- package/node_modules/audio-decode/node_modules/@audio/decode/stream.js +1 -0
- package/node_modules/audio-decode/node_modules/@audio/decode/test.html +52 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-aac/LICENSE +9 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-aac/README.md +80 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-aac/alac.js +326 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-aac/audio.d.ts +15 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-aac/audio.js +10 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-aac/decode-aac.d.ts +24 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-aac/decode-aac.js +452 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-aac/meta.js +81 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-aac/package.json +63 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-aac/src/aac.wasm.js +0 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-ac3/LICENSE +12 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-ac3/LICENSE.liba52 +340 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-ac3/README.md +41 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-ac3/audio.d.ts +15 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-ac3/audio.js +9 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-ac3/decode-ac3.d.ts +20 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-ac3/decode-ac3.js +131 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-ac3/package.json +64 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-ac3/src/ac3.wasm.js +0 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-aiff/LICENSE +21 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-aiff/README.md +46 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-aiff/audio.d.ts +15 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-aiff/audio.js +10 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-aiff/decode-aiff.d.ts +16 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-aiff/decode-aiff.js +583 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-aiff/package.json +52 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-amr/LICENSE +191 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-amr/README.md +65 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-amr/audio.d.ts +15 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-amr/audio.js +10 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-amr/decode-amr.d.ts +16 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-amr/decode-amr.js +150 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-amr/package.json +58 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-amr/src/amr.wasm.js +0 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-avi/LICENSE +21 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-avi/README.md +53 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-avi/audio.d.ts +15 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-avi/audio.js +9 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-avi/decode-avi.d.ts +21 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-avi/decode-avi.js +241 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-avi/package.json +66 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-caf/LICENSE +21 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-caf/README.md +48 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-caf/audio.d.ts +15 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-caf/audio.js +10 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-caf/decode-caf.d.ts +16 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-caf/decode-caf.js +238 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-caf/package.json +53 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-dsd/LICENSE +21 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-dsd/README.md +73 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-dsd/audio.d.ts +21 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-dsd/audio.js +15 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-dsd/decode-dsd.d.ts +29 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-dsd/decode-dsd.js +423 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-dsd/meta.js +40 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-dsd/package.json +64 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-dts/LICENSE +12 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-dts/LICENSE.libdca +339 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-dts/README.md +41 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-dts/audio.d.ts +15 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-dts/audio.js +9 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-dts/decode-dts.d.ts +20 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-dts/decode-dts.js +139 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-dts/package.json +64 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-dts/src/dts.wasm.js +0 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-eac3/LICENSE +12 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-eac3/LICENSE.ffmpeg +502 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-eac3/README.md +45 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-eac3/audio.d.ts +15 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-eac3/audio.js +9 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-eac3/decode-eac3.d.ts +20 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-eac3/decode-eac3.js +124 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-eac3/package.json +68 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-eac3/src/eac3.wasm.js +0 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-flac/LICENSE +25 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-flac/README.md +23 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-flac/audio.d.ts +15 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-flac/audio.js +10 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-flac/decode-flac.d.ts +18 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-flac/decode-flac.js +3172 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-flac/meta.js +115 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-flac/package.json +60 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-mod/LICENSE +23 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-mod/LICENSE.libopenmpt +25 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-mod/README.md +86 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-mod/audio.d.ts +20 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-mod/audio.js +12 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-mod/decode-mod.d.ts +58 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-mod/decode-mod.js +148 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-mod/package.json +68 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-mod/src/mod.wasm.js +0 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-mp3/LICENSE +25 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-mp3/README.md +20 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-mp3/audio.d.ts +15 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-mp3/audio.js +10 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-mp3/decode-mp3.d.ts +16 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-mp3/decode-mp3.js +793 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-mp3/meta.js +143 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-mp3/package.json +60 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-mp4/LICENSE +21 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-mp4/README.md +58 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-mp4/audio.d.ts +15 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-mp4/audio.js +9 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-mp4/decode-mp4.d.ts +21 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-mp4/decode-mp4.js +455 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-mp4/package.json +74 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-mpc/LICENSE +31 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-mpc/LICENSE.libmpcdec +31 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-mpc/README.md +60 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-mpc/audio.d.ts +15 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-mpc/audio.js +9 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-mpc/decode-mpc.d.ts +20 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-mpc/decode-mpc.js +158 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-mpc/package.json +64 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-mpc/src/mpc.wasm.js +0 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-opus/LICENSE +25 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-opus/LICENSE.libopus +44 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-opus/README.md +32 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-opus/audio.d.ts +15 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-opus/audio.js +10 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-opus/core.d.ts +33 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-opus/core.js +147 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-opus/decode-opus.d.ts +18 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-opus/decode-opus.js +1 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-opus/meta.js +103 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-opus/package.json +68 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-opus/src/decode-opus.js +2 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-opus/src/opus.wasm.js +0 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-qoa/LICENSE +25 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-qoa/README.md +19 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-qoa/audio.d.ts +15 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-qoa/audio.js +10 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-qoa/decode-qoa.d.ts +16 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-qoa/decode-qoa.js +275 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-qoa/package.json +56 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-tta/LICENSE +21 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-tta/LICENSE.ttadec +39 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-tta/README.md +58 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-tta/audio.d.ts +15 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-tta/audio.js +9 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-tta/decode-tta.d.ts +17 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-tta/decode-tta.js +302 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-tta/package.json +58 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-vorbis/LICENSE +25 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-vorbis/README.md +33 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-vorbis/audio.d.ts +15 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-vorbis/audio.js +10 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-vorbis/decode-vorbis.d.ts +18 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-vorbis/decode-vorbis.js +2984 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-vorbis/meta.js +102 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-vorbis/package.json +60 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-wav/LICENSE +21 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-wav/README.md +23 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-wav/audio.d.ts +15 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-wav/audio.js +10 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-wav/decode-wav.d.ts +8 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-wav/decode-wav.js +256 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-wav/meta.js +114 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-wav/package.json +52 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-wavpack/LICENSE +29 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-wavpack/LICENSE.wavpack +25 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-wavpack/README.md +41 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-wavpack/audio.d.ts +15 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-wavpack/audio.js +9 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-wavpack/decode-wavpack.d.ts +18 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-wavpack/decode-wavpack.js +140 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-wavpack/package.json +62 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-wavpack/src/wavpack.wasm.js +0 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-webm/LICENSE +21 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-webm/LICENSE.libopus +44 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-webm/README.md +59 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-webm/audio.d.ts +15 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-webm/audio.js +10 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-webm/decode-webm.d.ts +18 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-webm/decode-webm.js +141 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-webm/package.json +76 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-webm/src/opus.wasm.js +0 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-wma/LICENSE +12 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-wma/README.md +74 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-wma/audio.d.ts +15 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-wma/audio.js +10 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-wma/decode-wma.d.ts +33 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-wma/decode-wma.js +516 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-wma/package.json +57 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-wma/src/wma.wasm.js +0 -0
- package/node_modules/audio-decode/package.json +37 -39
- package/node_modules/audio-decode/stream.d.ts +2 -0
- package/node_modules/audio-decode/stream.js +2 -0
- package/node_modules/baileys/lib/Utils/messages-media.js +1 -1
- package/node_modules/baileys/node_modules/file-type/package.json +1 -1
- package/node_modules/baileys/node_modules/file-type/readme.md +2 -0
- package/node_modules/baileys/node_modules/file-type/source/detectors/zip.js +9 -4
- package/node_modules/baileys/package.json +1 -1
- package/node_modules/typebox/build/compile/code.mjs +1 -2
- package/node_modules/typebox/build/compile/validator.mjs +5 -1
- package/node_modules/typebox/build/format/iri.mjs +16 -9
- package/node_modules/typebox/build/guard/emit.mjs +2 -2
- package/node_modules/typebox/build/guard/guard.d.mts +7 -5
- package/node_modules/typebox/build/guard/guard.mjs +14 -9
- package/node_modules/typebox/build/guard/index.mjs +6 -0
- package/node_modules/typebox/build/guard/unicode/unicode.d.mts +6 -0
- package/node_modules/typebox/build/guard/unicode/unicode.mjs +35 -0
- package/node_modules/typebox/build/guard/{string.mjs → unicode/unicode_segment.mjs} +16 -19
- package/node_modules/typebox/build/schema/build.mjs +2 -3
- package/node_modules/typebox/build/schema/engine/_pathing.d.mts +1 -0
- package/node_modules/typebox/build/schema/engine/_pathing.mjs +11 -0
- package/node_modules/typebox/build/schema/engine/_refine.mjs +13 -5
- package/node_modules/typebox/build/schema/engine/additionalProperties.mjs +2 -1
- package/node_modules/typebox/build/schema/engine/dependencies.mjs +2 -1
- package/node_modules/typebox/build/schema/engine/dependentSchemas.mjs +2 -1
- package/node_modules/typebox/build/schema/engine/dynamicRef.d.mts +1 -1
- package/node_modules/typebox/build/schema/engine/dynamicRef.mjs +2 -2
- package/node_modules/typebox/build/schema/engine/format.mjs +9 -2
- package/node_modules/typebox/build/schema/engine/patternProperties.mjs +3 -2
- package/node_modules/typebox/build/schema/engine/properties.mjs +3 -2
- package/node_modules/typebox/build/schema/engine/propertyNames.mjs +2 -1
- package/node_modules/typebox/build/schema/engine/recursiveRef.d.mts +1 -1
- package/node_modules/typebox/build/schema/engine/recursiveRef.mjs +2 -2
- package/node_modules/typebox/build/schema/engine/ref.d.mts +1 -1
- package/node_modules/typebox/build/schema/engine/ref.mjs +2 -2
- package/node_modules/typebox/build/schema/engine/schema.mjs +24 -24
- package/node_modules/typebox/build/schema/parse.mjs +3 -0
- package/node_modules/typebox/build/schema/pointer/pointer.d.mts +1 -6
- package/node_modules/typebox/build/schema/pointer/pointer.mjs +47 -64
- package/node_modules/typebox/build/system/settings/internal.d.mts +2 -0
- package/node_modules/typebox/build/system/settings/internal.mjs +20 -0
- package/node_modules/typebox/build/system/settings/settings.d.mts +11 -0
- package/node_modules/typebox/build/system/settings/settings.mjs +14 -0
- package/node_modules/typebox/build/type/extends/inference.d.mts +1 -1
- package/node_modules/typebox/build/type/extends/inference.mjs +15 -2
- package/node_modules/typebox/build/type/extends/tuple.d.mts +2 -1
- package/node_modules/typebox/build/type/extends/tuple.mjs +21 -1
- package/node_modules/typebox/build/value/parse/parse.mjs +10 -4
- package/node_modules/typebox/package.json +1 -1
- package/node_modules/typebox/readme.md +3 -1
- package/package.json +6 -6
- package/dist/.setup/doctor-BPb-SjdE.mjs +0 -65
- package/dist/.setup/group-config-path-BGyzT9Lg.mjs +0 -54
- package/dist/.setup/normalize-DdsROMMa.mjs +0 -2
- package/dist/.setup/rolldown-runtime-D7D4PA-g.mjs +0 -13
- package/dist/.setup/runtime-group-policy-DeSRFXEV.mjs +0 -11
- package/dist/.setup/setup-plugin-api-2wUapweU.mjs +0 -3
- package/dist/.setup/text-runtime-CHl0iPYe.mjs +0 -4
- package/node_modules/audio-decode/.eslintrc.json +0 -43
- package/node_modules/audio-decode/.github/workflows/test.js.yml +0 -31
- package/node_modules/audio-decode/.travis.yml +0 -13
- package/node_modules/audio-decode/node_modules/@wasm-audio-decoders/opus-ml/README.md +0 -293
- package/node_modules/audio-decode/node_modules/@wasm-audio-decoders/opus-ml/dist/opus-ml-decoder.min.js +0 -11646
- package/node_modules/audio-decode/node_modules/@wasm-audio-decoders/opus-ml/dist/opus-ml-decoder.min.js.map +0 -1
- package/node_modules/audio-decode/node_modules/@wasm-audio-decoders/opus-ml/index.js +0 -8
- package/node_modules/audio-decode/node_modules/@wasm-audio-decoders/opus-ml/package.json +0 -58
- package/node_modules/audio-decode/node_modules/@wasm-audio-decoders/opus-ml/src/EmscriptenWasm.js +0 -0
- package/node_modules/audio-decode/node_modules/@wasm-audio-decoders/opus-ml/src/OpusMLDecoder.js +0 -253
- package/node_modules/audio-decode/node_modules/@wasm-audio-decoders/opus-ml/src/OpusMLDecoderWebWorker.js +0 -17
- package/node_modules/audio-decode/node_modules/@wasm-audio-decoders/opus-ml/types.d.ts +0 -77
- package/node_modules/audio-decode/node_modules/audio-buffer/.eslintrc.json +0 -44
- package/node_modules/audio-decode/node_modules/audio-buffer/.github/workflows/node.js.yml +0 -31
- package/node_modules/audio-decode/node_modules/audio-buffer/.travis.yml +0 -7
- package/node_modules/audio-decode/node_modules/audio-buffer/index.js +0 -76
- package/node_modules/audio-decode/node_modules/audio-buffer/package.json +0 -37
- package/node_modules/audio-decode/node_modules/audio-buffer/readme.md +0 -56
- package/node_modules/audio-decode/node_modules/node-wav/README.md +0 -35
- package/node_modules/audio-decode/node_modules/node-wav/file.wav +0 -0
- package/node_modules/audio-decode/node_modules/node-wav/index.js +0 -291
- package/node_modules/audio-decode/node_modules/node-wav/package.json +0 -29
- package/node_modules/audio-decode/node_modules/node-wav/tests/file1.wav +0 -0
- package/node_modules/audio-decode/node_modules/node-wav/tests/test.js +0 -66
- package/node_modules/audio-decode/node_modules/node-wav/x.js +0 -12
- package/node_modules/audio-decode/node_modules/node-wav/x.json +0 -86702
- package/node_modules/audio-decode/node_modules/node-wav/x.js~ +0 -13
- package/node_modules/audio-decode/node_modules/ogg-opus-decoder/README.md +0 -320
- package/node_modules/audio-decode/node_modules/ogg-opus-decoder/dist/ogg-opus-decoder.min.js +0 -232
- package/node_modules/audio-decode/node_modules/ogg-opus-decoder/dist/ogg-opus-decoder.min.js.map +0 -1
- package/node_modules/audio-decode/node_modules/ogg-opus-decoder/dist/ogg-opus-decoder.opus-ml.min.js +0 -0
- package/node_modules/audio-decode/node_modules/ogg-opus-decoder/dist/ogg-opus-decoder.opus-ml.min.js.map +0 -1
- package/node_modules/audio-decode/node_modules/ogg-opus-decoder/index.js +0 -8
- package/node_modules/audio-decode/node_modules/ogg-opus-decoder/package.json +0 -74
- package/node_modules/audio-decode/node_modules/ogg-opus-decoder/src/OggOpusDecoder.js +0 -226
- package/node_modules/audio-decode/node_modules/ogg-opus-decoder/src/OggOpusDecoderWebWorker.js +0 -17
- package/node_modules/audio-decode/node_modules/ogg-opus-decoder/types.d.ts +0 -37
- package/node_modules/audio-decode/node_modules/opus-decoder/README.md +0 -265
- package/node_modules/audio-decode/node_modules/opus-decoder/dist/opus-decoder.min.js +0 -232
- package/node_modules/audio-decode/node_modules/opus-decoder/dist/opus-decoder.min.js.map +0 -1
- package/node_modules/audio-decode/node_modules/opus-decoder/index.js +0 -8
- package/node_modules/audio-decode/node_modules/opus-decoder/package.json +0 -56
- package/node_modules/audio-decode/node_modules/opus-decoder/src/EmscriptenWasm.js +0 -0
- package/node_modules/audio-decode/node_modules/opus-decoder/src/OpusDecoder.js +0 -239
- package/node_modules/audio-decode/node_modules/opus-decoder/src/OpusDecoderWebWorker.js +0 -17
- package/node_modules/audio-decode/node_modules/opus-decoder/types.d.ts +0 -74
- package/node_modules/audio-decode/readme.md +0 -49
- package/node_modules/audio-decode/tea.yaml +0 -6
- package/node_modules/audio-decode/test-case.js +0 -11
- package/node_modules/audio-decode/test.html +0 -15
- package/node_modules/audio-decode/test.js +0 -107
- /package/node_modules/typebox/build/guard/{string.d.mts → unicode/unicode_segment.d.mts} +0 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@audio/decode-caf",
|
|
3
|
+
"version": "1.4.0",
|
|
4
|
+
"description": "Decode CAF (Core Audio Format) audio to PCM samples",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "decode-caf.js",
|
|
7
|
+
"types": "decode-caf.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": "./decode-caf.js",
|
|
10
|
+
"./audio": {
|
|
11
|
+
"types": "./audio.d.ts",
|
|
12
|
+
"default": "./audio.js"
|
|
13
|
+
},
|
|
14
|
+
"./package.json": "./package.json"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"decode-caf.js",
|
|
18
|
+
"decode-caf.d.ts",
|
|
19
|
+
"LICENSE",
|
|
20
|
+
"audio.js",
|
|
21
|
+
"audio.d.ts"
|
|
22
|
+
],
|
|
23
|
+
"scripts": {
|
|
24
|
+
"test": "node test.js"
|
|
25
|
+
},
|
|
26
|
+
"keywords": [
|
|
27
|
+
"caf",
|
|
28
|
+
"core-audio",
|
|
29
|
+
"apple",
|
|
30
|
+
"audio",
|
|
31
|
+
"decode",
|
|
32
|
+
"decoder",
|
|
33
|
+
"pcm"
|
|
34
|
+
],
|
|
35
|
+
"publishConfig": {
|
|
36
|
+
"access": "public"
|
|
37
|
+
},
|
|
38
|
+
"license": "MIT",
|
|
39
|
+
"author": "audiojs",
|
|
40
|
+
"homepage": "https://github.com/audiojs/decode/tree/master/packages/decode-caf#readme",
|
|
41
|
+
"repository": {
|
|
42
|
+
"type": "git",
|
|
43
|
+
"url": "git+https://github.com/audiojs/decode.git",
|
|
44
|
+
"directory": "packages/decode-caf"
|
|
45
|
+
},
|
|
46
|
+
"engines": {
|
|
47
|
+
"node": ">=18"
|
|
48
|
+
},
|
|
49
|
+
"bugs": "https://github.com/audiojs/decode/issues",
|
|
50
|
+
"audio": "./audio.js",
|
|
51
|
+
"sideEffects": false,
|
|
52
|
+
"funding": "https://github.com/sponsors/audiojs"
|
|
53
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 audiojs
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# @audio/decode-dsd [](https://www.npmjs.com/package/@audio/decode-dsd) [](https://github.com/krishnized/license)
|
|
2
|
+
|
|
3
|
+
Decode DSD (DSF, DFF) audio to PCM float samples.
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
npm install @audio/decode-dsd
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
```js
|
|
10
|
+
import decode, { decoder } from '@audio/decode-dsd'
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
DSD is a 1-bit-per-sample sigma-delta stream running at 2.8224 MHz and up ("DSD64", "DSD128", …). Getting to PCM is a low-pass + decimate: a Kaiser-windowed-sinc FIR removes the noise-shaped quantization noise pushed above the audio band, then every Nth sample is kept. The first decimation stage (raw bits → 8× that rate) runs directly on the 1-bit stream using per-byte lookup tables — the classic trick from Sebastian Gesemann's [dsd2pcm](https://github.com/sdaau/dsd2pcm) (BSD), also used by ffmpeg's `dsd_lsbf_planar`/`dsd_msbf` decoders; this is an independent implementation of the same idea, not a port. A second, ordinary decimating FIR (on the now multi-bit float stream, much cheaper) reaches 44.1/88.2/176.4 kHz.
|
|
14
|
+
|
|
15
|
+
```js
|
|
16
|
+
let { channelData, sampleRate } = decode(dsfOrDffBytes)
|
|
17
|
+
|
|
18
|
+
let dec = decoder({ sampleRate: 88200 })
|
|
19
|
+
let head = dec.decode(chunk1) // synchronous; partial blocks carry over
|
|
20
|
+
let tail = dec.flush()
|
|
21
|
+
dec.free()
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Both `decode()` and `decoder()` are synchronous — no WASM, no async setup.
|
|
25
|
+
|
|
26
|
+
## Formats
|
|
27
|
+
|
|
28
|
+
**DSF** (Sony DSD Stream File): `DSD `/`fmt `/`data` chunks, up to 5.1 channels, DSD64/128/256/512 sample rates, 1-bit LSB-first or MSB-first packing (per the `fmt` chunk's `bitsPerSample` field, exactly as the [spec](https://dsd-guide.com/sonys-dsf-file-format-spec) defines it), data interleaved in fixed 4096-byte-per-channel blocks. Trailing ID3v2 tag (pointed to by the `DSD ` chunk header) via `@audio/decode-dsd/meta`.
|
|
29
|
+
|
|
30
|
+
**DFF** (Philips DSDIFF): `FRM8`/`FVER`/`PROP` (`FS`, `CHNL`, `CMPR`)/`DSD ` chunks, data interleaved byte-per-channel, always MSB-first. DST-compressed files (`CMPR` = `'DST '`) throw `Unsupported: DST` — DST is a separate lossless codec, not raw DSD. Edited-master chunks (`DIIN`/`DITI`/…) are ignored. A non-standard `ID3 ` chunk, if present, is also readable via `@audio/decode-dsd/meta`.
|
|
31
|
+
|
|
32
|
+
## API
|
|
33
|
+
|
|
34
|
+
### `decode(src, opts?): AudioData`
|
|
35
|
+
|
|
36
|
+
Decode a complete `Uint8Array` or `ArrayBuffer`.
|
|
37
|
+
|
|
38
|
+
### `decoder(opts?): DSDDecoder`
|
|
39
|
+
|
|
40
|
+
- `dec.decode(data)`: decode a chunk. DSF needs a full `4096 × channels`-byte block group per channel before it can decode anything (that's the container's own interleave unit); DFF only needs one `channels`-byte frame.
|
|
41
|
+
- `dec.flush()`: zero-pads a short final block to the container's own frame size (matching the DSF spec's own convention for a partial last block) and decodes it — it does not separately drain the FIR's group-delay tail.
|
|
42
|
+
- `dec.free()`: release state. Idempotent.
|
|
43
|
+
|
|
44
|
+
| Option | Default | |
|
|
45
|
+
|---|---|---|
|
|
46
|
+
| `sampleRate` | `dsdRate / 32` | Output rate. Must equal `dsdRate / 8`, `/16`, `/32`, or `/64` (DSD64 → 352.8k / 176.4k / 88.2k / 44.1k) — the byte-lookup-table stage only decimates in whole-byte (8-bit) steps. |
|
|
47
|
+
| `cutoff` | `0.45` | Passband edge, as a fraction of the output rate, for whichever stage sets the final rate. |
|
|
48
|
+
| `length` | computed | FIR taps for that stage. Longer = closer to the `stopband` target, slower. |
|
|
49
|
+
| `stopband` | `100` | Target stopband attenuation (dB), used to derive the Kaiser β. |
|
|
50
|
+
|
|
51
|
+
`AudioData` is `{ channelData: Float32Array[], sampleRate: number }`.
|
|
52
|
+
|
|
53
|
+
DSD's 1-bit ±1 maps directly to PCM full scale — no gain change is applied. SACD material mastered at DSD's nominal "0 dB" can legitimately hit +6 dB relative to PCM full scale; this decoder does not clamp or renormalize, so such material will clip in the Float32 sense (values outside ±1) exactly as it would on any other bit-transparent DSD decoder.
|
|
54
|
+
|
|
55
|
+
## Numbers
|
|
56
|
+
|
|
57
|
+
- Bit-domain stage 1 (fixed): 192 taps (96-tap half + symmetry, 12-byte lookup tables), cutoff 0.45×(dsdRate/8), 100 dB target stopband.
|
|
58
|
+
- Stage 2 (built per request): length computed from the Kaiser formula for a truly alias-free transition band (passband edge to the decimation's own mirror point) at the requested `stopband`.
|
|
59
|
+
- Measured (2nd-order test tone through a properly-synthesized 5th-order 1-bit modulator, `test.js`): in-band SNR 114–117 dB at 44.1k/88.2k/176.4k (≥ 80 dB required, conservative under the modulator's own ~100+ dB theoretical ceiling — see `test.js` for the exact citation).
|
|
60
|
+
- Cross-checked against `ffmpeg -i x.dsf -f f32le -ar 88200 -`: 1 kHz tone amplitude within 0.000 dB, phase within 1.6° after delay alignment, duration exact.
|
|
61
|
+
- Speed: 60 s stereo DSD64 → 88.2 kHz decodes in ≈ 2.1 s (pure JS, single core).
|
|
62
|
+
|
|
63
|
+
## License
|
|
64
|
+
|
|
65
|
+
[ॐ](https://github.com/krishnized/license/) · [MIT](./LICENSE)
|
|
66
|
+
|
|
67
|
+
**Use when:** you have raw DSD/SACD-rip material (`.dsf`/`.dff`) and need PCM — playback, format conversion, or feeding a conventional DSP chain. Not a DST decoder (DST-compressed DFF throws) and not a DSD *encoder*.
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
Part of [@audio/decode](https://github.com/audiojs/decode) — the decode family umbrella.
|
|
72
|
+
|
|
73
|
+
MIT © [audiojs](https://github.com/audiojs)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// Generated from the audio.js manifest (params metadata is the source of truth).
|
|
2
|
+
// Regenerate: node tools/dts.js in @audio/compile. Do not edit by hand.
|
|
3
|
+
|
|
4
|
+
/** Automatable number — scalar, `t => value` fn, or breakpoint curve {t, v} */
|
|
5
|
+
type Auto = number | ((t: number) => number) | { t: number[], v: number[] }
|
|
6
|
+
/** Per-block param values as delivered by hosts (numbers arrive as 1-length Float32Array) */
|
|
7
|
+
type Live = Record<string, Float32Array | string | boolean>
|
|
8
|
+
type Ctx = { sampleRate: number, maxBlockSize: number, maxChannels: number, currentTime: number, duration?: number, events?: readonly any[], emit?: (name: string, ...args: any[]) => void, [k: string]: unknown }
|
|
9
|
+
type Process = (inputs: Float32Array[][], outputs: Float32Array[][], params: Live) => void
|
|
10
|
+
|
|
11
|
+
/** Codec plugin 'dsf' — extends audio()'s openable formats / save() targets */
|
|
12
|
+
export declare const dsf: {
|
|
13
|
+
codec: 'dsf'
|
|
14
|
+
decode(bytes: Uint8Array): { channelData: Float32Array[], sampleRate: number } | Promise<{ channelData: Float32Array[], sampleRate: number }>
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** Codec plugin 'dff' — extends audio()'s openable formats / save() targets */
|
|
18
|
+
export declare const dff: {
|
|
19
|
+
codec: 'dff'
|
|
20
|
+
decode(bytes: Uint8Array): { channelData: Float32Array[], sampleRate: number } | Promise<{ channelData: Float32Array[], sampleRate: number }>
|
|
21
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// audio.js manifest — codec atoms, decode half: whole-buffer bytes → { channelData,
|
|
2
|
+
// sampleRate }. One decoder serves both DSD containers. Format detection is magic-byte
|
|
3
|
+
// (audio-type) — no test() needed here.
|
|
4
|
+
|
|
5
|
+
import decodeFn from './decode-dsd.js'
|
|
6
|
+
|
|
7
|
+
export const dsf = {
|
|
8
|
+
codec: 'dsf',
|
|
9
|
+
decode: (bytes) => decodeFn(bytes),
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const dff = {
|
|
13
|
+
codec: 'dff',
|
|
14
|
+
decode: (bytes) => decodeFn(bytes),
|
|
15
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export interface AudioData {
|
|
2
|
+
channelData: Float32Array[];
|
|
3
|
+
sampleRate: number;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export interface DSDDecoderOptions {
|
|
7
|
+
/** Output sample rate in Hz. Must equal dsdRate/8, /16, /32 or /64. Default: dsdRate/32. */
|
|
8
|
+
sampleRate?: number;
|
|
9
|
+
/** Passband edge as a fraction of the output rate. Default 0.45. */
|
|
10
|
+
cutoff?: number;
|
|
11
|
+
/** Total FIR taps of the rate-determining filter (stage 2, or stage 1 when ratio===8). */
|
|
12
|
+
length?: number;
|
|
13
|
+
/** Target stopband attenuation in dB, used to derive the Kaiser β. Default 100. */
|
|
14
|
+
stopband?: number;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
interface DSDDecoder {
|
|
18
|
+
/** Decode a chunk of raw DSF or DFF bytes synchronously. Partial blocks carry over. */
|
|
19
|
+
decode(data: Uint8Array | ArrayBuffer): AudioData;
|
|
20
|
+
/** Zero-pad and decode the final partial block; drops nothing already emitted. */
|
|
21
|
+
flush(): AudioData;
|
|
22
|
+
free(): void;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Decode a complete DSF or DFF file synchronously. */
|
|
26
|
+
export default function decode(src: ArrayBuffer | Uint8Array, opts?: DSDDecoderOptions): AudioData;
|
|
27
|
+
|
|
28
|
+
/** Create a synchronous streaming decoder. */
|
|
29
|
+
export function decoder(opts?: DSDDecoderOptions): DSDDecoder;
|
|
@@ -0,0 +1,423 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DSD → PCM decoder — pure JS
|
|
3
|
+
* Decodes DSF (Sony DSD Stream File) and DFF (Philips DSDIFF) to Float32 PCM.
|
|
4
|
+
*
|
|
5
|
+
* DSD is a 1-bit-per-sample sigma-delta stream at 2.8224 MHz×2^n ("DSD64" and up). Converting it
|
|
6
|
+
* to PCM is a low-pass + decimate: a windowed-sinc (Kaiser) FIR removes the shaped quantization
|
|
7
|
+
* noise pushed above the audio band, then every Nth sample is kept.
|
|
8
|
+
*
|
|
9
|
+
* Stage 1 always decimates the raw bitstream ×8 (e.g. DSD64 → 352.8 kHz) using the classic
|
|
10
|
+
* per-byte lookup-table trick: each DSD bit is ±1, so an 8-bit tap group against 8 filter taps has
|
|
11
|
+
* only 256 possible partial sums — precompute them once (Sebastian Gesemann's dsd2pcm, BSD
|
|
12
|
+
* license, https://github.com/sdaau/dsd2pcm; the same technique is in ffmpeg's libavcodec/dsd.c).
|
|
13
|
+
* This implementation is written from scratch, not a port.
|
|
14
|
+
* Stage 2 (when the requested ratio is > 8) is an ordinary decimating FIR on the float output of
|
|
15
|
+
* stage 1 — cheap, since it now runs at 1/8th the raw bit rate.
|
|
16
|
+
*
|
|
17
|
+
* let { channelData, sampleRate } = decode(dsfOrDffBytes)
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
const EMPTY = Object.freeze({ channelData: [], sampleRate: 0 })
|
|
21
|
+
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
// Bit-reversal (byte-level): DSF with bitsPerSample===1 stores each channel byte LSB-first
|
|
24
|
+
// (bit 0 = oldest sample); DFF and DSF with bitsPerSample===8 are MSB-first. The stage-1 engine
|
|
25
|
+
// below assumes MSB-first, so LSB-first bytes are run through this table on the way in.
|
|
26
|
+
const REV8 = new Uint8Array(256)
|
|
27
|
+
for (let i = 0; i < 256; i++) {
|
|
28
|
+
let v = i, r = 0
|
|
29
|
+
for (let b = 0; b < 8; b++) { r = (r << 1) | (v & 1); v >>= 1 }
|
|
30
|
+
REV8[i] = r
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// ---------------------------------------------------------------------------
|
|
34
|
+
// Kaiser-windowed-sinc FIR design — Kaiser (1966); formulas per Oppenheim & Schafer,
|
|
35
|
+
// "Discrete-Time Signal Processing" 3rd ed., §7.5.3 (Table 7.3 / eq. 7.75-7.76).
|
|
36
|
+
|
|
37
|
+
// Modified Bessel function I0(x), power series (converges fast for the |x| this uses, β ≤ ~20).
|
|
38
|
+
function besselI0(x) {
|
|
39
|
+
let sum = 1, term = 1, k = 1
|
|
40
|
+
const y = (x * x) / 4
|
|
41
|
+
while (k < 64 && term > sum * 1e-16) { term *= y / (k * k); sum += term; k++ }
|
|
42
|
+
return sum
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// β from target stopband attenuation A (dB). Kaiser's empirical formula.
|
|
46
|
+
function kaiserBeta(A) {
|
|
47
|
+
if (A > 50) return 0.1102 * (A - 8.71)
|
|
48
|
+
if (A >= 21) return 0.5842 * Math.pow(A - 21, 0.4) + 0.07886 * (A - 21)
|
|
49
|
+
return 0
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Filter length for transition width dw (rad/sample) at attenuation A (dB).
|
|
53
|
+
function kaiserLength(A, dw) {
|
|
54
|
+
return Math.max(4, Math.ceil((A - 8) / (2.285 * dw)))
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Windowed-sinc lowpass, cutoff fc (Hz) at sample rate fs (Hz), N taps, Kaiser β. Unity DC gain.
|
|
58
|
+
// N may be even (no exact center sample — used for stage 1, matches the classic dsd2pcm layout)
|
|
59
|
+
// or odd (Type-I linear phase, single center tap — used for stage 2).
|
|
60
|
+
function designLowpass(fc, fs, N, beta) {
|
|
61
|
+
const h = new Float64Array(N), M = (N - 1) / 2, wc = (2 * Math.PI * fc) / fs, i0b = besselI0(beta)
|
|
62
|
+
let sum = 0
|
|
63
|
+
for (let n = 0; n < N; n++) {
|
|
64
|
+
const m = n - M
|
|
65
|
+
const sinc = m === 0 ? wc / Math.PI : Math.sin(wc * m) / (Math.PI * m)
|
|
66
|
+
const w = besselI0(beta * Math.sqrt(Math.max(0, 1 - (m / M) ** 2))) / i0b
|
|
67
|
+
h[n] = sinc * w
|
|
68
|
+
sum += h[n]
|
|
69
|
+
}
|
|
70
|
+
for (let n = 0; n < N; n++) h[n] /= sum
|
|
71
|
+
return h
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// ---------------------------------------------------------------------------
|
|
75
|
+
// Stage 1: bit-domain LUT decimator, fixed ×8 (raw DSD bits → dsdRate/8 float PCM).
|
|
76
|
+
//
|
|
77
|
+
// Fixed default length/cutoff: N1=192 taps (HTAPS=96, CTABLES=12), cutoff 0.45×(dsdRate/8),
|
|
78
|
+
// target stopband 100 dB. At DSD64 (dsdRate=2 822 400 Hz) this gives an achieved transition width
|
|
79
|
+
// of about 95 kHz (β=kaiserBeta(100)≈10.06, computed from N1 via the length formula above),
|
|
80
|
+
// i.e. clean below ~159 kHz and re-suppressed by ~247 kHz — both far above the audio band, and
|
|
81
|
+
// (for ratio>8) further cleaned by stage 2's own passband, which sits far below stage 1's
|
|
82
|
+
// transition region. Override via opts.length/opts.cutoff/opts.stopband (applies when ratio===8,
|
|
83
|
+
// since stage 1 is then the only stage).
|
|
84
|
+
const STAGE1_TAPS = 192
|
|
85
|
+
const STOPBAND_DB = 100
|
|
86
|
+
|
|
87
|
+
function buildStage1(dsdRate, opts) {
|
|
88
|
+
const outRate = dsdRate / 8
|
|
89
|
+
const cutoff = (opts.cutoff ?? 0.45) * outRate
|
|
90
|
+
const stopband = opts.stopband ?? STOPBAND_DB
|
|
91
|
+
const N = (opts.length && opts.ratio === 8 ? opts.length : STAGE1_TAPS) | 0
|
|
92
|
+
const evenN = N + (N & 1) // force even: no unpaired center tap (dsd2pcm-style symmetric halves)
|
|
93
|
+
const beta = kaiserBeta(stopband)
|
|
94
|
+
const h = designLowpass(cutoff, dsdRate, evenN, beta)
|
|
95
|
+
const HTAPS = evenN / 2
|
|
96
|
+
const half = h.subarray(HTAPS) // 2nd half of the symmetric filter, length HTAPS
|
|
97
|
+
const CTABLES = Math.ceil(HTAPS / 8)
|
|
98
|
+
const tables = Array.from({ length: CTABLES }, () => new Float32Array(256))
|
|
99
|
+
const acc = new Float64Array(CTABLES)
|
|
100
|
+
for (let byteVal = 0; byteVal < 256; byteVal++) {
|
|
101
|
+
acc.fill(0)
|
|
102
|
+
for (let bit = 0; bit < 8; bit++) {
|
|
103
|
+
// MSB-first: bit 0 of the group = bit 7 of the byte = earliest sample in time.
|
|
104
|
+
const sign = ((byteVal >> (7 - bit)) & 1) * 2 - 1
|
|
105
|
+
for (let t = 0; t < CTABLES; t++) {
|
|
106
|
+
const tapIdx = t * 8 + bit
|
|
107
|
+
acc[t] += sign * (tapIdx < HTAPS ? half[tapIdx] : 0)
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
for (let t = 0; t < CTABLES; t++) tables[CTABLES - 1 - t][byteVal] = acc[t]
|
|
111
|
+
}
|
|
112
|
+
return { CTABLES, tables, outRate, taps: evenN, cutoff, stopband }
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Per-channel bit-domain FIFO + convolution state. push(byte) → one Float64 PCM sample.
|
|
116
|
+
function makeStage1Channel(stage1) {
|
|
117
|
+
const { CTABLES, tables } = stage1
|
|
118
|
+
let size = 4
|
|
119
|
+
while (size < CTABLES * 2) size <<= 1
|
|
120
|
+
const MASK = size - 1
|
|
121
|
+
const buf = new Uint8Array(size)
|
|
122
|
+
let pos = 0
|
|
123
|
+
return {
|
|
124
|
+
push(byte) {
|
|
125
|
+
buf[pos] = byte
|
|
126
|
+
const p = (pos - CTABLES) & MASK
|
|
127
|
+
buf[p] = REV8[buf[p]]
|
|
128
|
+
let sum = 0
|
|
129
|
+
for (let i = 0; i < CTABLES; i++) {
|
|
130
|
+
const a = buf[(pos - i) & MASK]
|
|
131
|
+
const b = buf[(pos - (CTABLES * 2 - 1) + i) & MASK]
|
|
132
|
+
sum += tables[i][a] + tables[i][b]
|
|
133
|
+
}
|
|
134
|
+
pos = (pos + 1) & MASK
|
|
135
|
+
return sum
|
|
136
|
+
},
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// ---------------------------------------------------------------------------
|
|
141
|
+
// Stage 2: ordinary decimating FIR on stage 1's float output, only built when ratio > 8.
|
|
142
|
+
// Anti-alias-correct by construction: transition band runs from the passband edge to the
|
|
143
|
+
// mirror point of the decimation (outRate − cutoff), so no energy folds back into the passband
|
|
144
|
+
// regardless of what's above it — this stage is the last one, so it must hold on its own.
|
|
145
|
+
function buildStage2(rateIn, ratio, opts) {
|
|
146
|
+
const outRate = rateIn / ratio
|
|
147
|
+
const cutoff = (opts.cutoff ?? 0.45) * outRate
|
|
148
|
+
const stopband = opts.stopband ?? STOPBAND_DB
|
|
149
|
+
const df = outRate - 2 * cutoff // transition width to the alias-safe mirror point
|
|
150
|
+
if (df <= 0) throw Error('cutoff too high for alias-free decimation (must be < 0.5× output rate)')
|
|
151
|
+
const beta = kaiserBeta(stopband)
|
|
152
|
+
let N = opts.length || kaiserLength(stopband, (2 * Math.PI * df) / rateIn)
|
|
153
|
+
N += N & 1 // force even (symmetric halves, no unpaired center tap)
|
|
154
|
+
const h = designLowpass(cutoff, rateIn, N, beta)
|
|
155
|
+
return { h, N, outRate, cutoff, stopband }
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Per-channel streaming decimator: carries FIR history and global sample-phase across calls.
|
|
159
|
+
function makeStage2Channel(stage2, ratio) {
|
|
160
|
+
const { h, N } = stage2
|
|
161
|
+
const half = N / 2
|
|
162
|
+
let hist = new Float64Array(N - 1) // zero-initialized: implicit silence pre-roll
|
|
163
|
+
let pos = 0 // total stage-1 samples absorbed so far (persistent across calls)
|
|
164
|
+
return {
|
|
165
|
+
// input: Float64Array of new stage-1-rate samples. Returns Float32Array decimated output.
|
|
166
|
+
push(input) {
|
|
167
|
+
const total = hist.length + input.length
|
|
168
|
+
const buf = new Float64Array(total)
|
|
169
|
+
buf.set(hist)
|
|
170
|
+
buf.set(input, hist.length)
|
|
171
|
+
const globalStart = pos - hist.length
|
|
172
|
+
// emit for every global index g ≡ (N-1) mod ratio, g >= N-1
|
|
173
|
+
let j = (((N - 1 - globalStart) % ratio) + ratio) % ratio
|
|
174
|
+
if (j < N - 1) j += ratio * Math.ceil((N - 1 - j) / ratio)
|
|
175
|
+
const out = []
|
|
176
|
+
for (; j < total; j += ratio) {
|
|
177
|
+
let sum = 0
|
|
178
|
+
const base = j - (N - 1)
|
|
179
|
+
for (let n = 0; n < half; n++) sum += h[n] * (buf[base + n] + buf[j - n])
|
|
180
|
+
out.push(sum)
|
|
181
|
+
}
|
|
182
|
+
hist = buf.subarray(total - (N - 1)).slice() // total is always >= N-1 since hist.length===N-1
|
|
183
|
+
pos += input.length
|
|
184
|
+
return Float32Array.from(out)
|
|
185
|
+
},
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// ---------------------------------------------------------------------------
|
|
190
|
+
// Container parsing
|
|
191
|
+
|
|
192
|
+
function str4(b, o) { return String.fromCharCode(b[o], b[o + 1], b[o + 2], b[o + 3]) }
|
|
193
|
+
function u32le(b, o) { return (b[o] | (b[o + 1] << 8) | (b[o + 2] << 16) | (b[o + 3] << 24)) >>> 0 }
|
|
194
|
+
function u64le(b, o) { return u32le(b, o) + u32le(b, o + 4) * 0x100000000 }
|
|
195
|
+
function u32be(b, o) { return ((b[o] << 24) | (b[o + 1] << 16) | (b[o + 2] << 8) | b[o + 3]) >>> 0 }
|
|
196
|
+
function u64be(b, o) { return u32be(b, o) * 0x100000000 + u32be(b, o + 4) }
|
|
197
|
+
function u16be(b, o) { return (b[o] << 8) | b[o + 1] }
|
|
198
|
+
|
|
199
|
+
// Returns null if buf doesn't yet hold the whole fixed-size DSF header (92 bytes), else the
|
|
200
|
+
// parsed header + dataStart offset. Throws on structurally invalid input.
|
|
201
|
+
function scanDsfHeader(buf) {
|
|
202
|
+
if (buf.length < 12) return null
|
|
203
|
+
if (str4(buf, 0) !== 'DSD ') throw Error('Not a DSF file')
|
|
204
|
+
if (buf.length < 28) return null
|
|
205
|
+
if (u64le(buf, 4) !== 28) throw Error('Not a DSF file')
|
|
206
|
+
const fileSize = u64le(buf, 12)
|
|
207
|
+
const metaPointer = u64le(buf, 20)
|
|
208
|
+
if (buf.length < 92) return null
|
|
209
|
+
if (str4(buf, 28) !== 'fmt ') throw Error('Malformed DSF: missing fmt chunk')
|
|
210
|
+
const fmtSize = u64le(buf, 32)
|
|
211
|
+
if (fmtSize < 52) throw Error('Malformed DSF: fmt chunk too small')
|
|
212
|
+
if (u32le(buf, 40) !== 1) throw Error('Unsupported DSF format version')
|
|
213
|
+
if (u32le(buf, 44) !== 0) throw Error('Unsupported DSF format id (not raw DSD)')
|
|
214
|
+
const channels = u32le(buf, 52) // channelNum is authoritative for buffer sizing; channelType (offset 48) is informational
|
|
215
|
+
if (!channels) throw Error('Malformed DSF: zero channels')
|
|
216
|
+
const dsdRate = u32le(buf, 56)
|
|
217
|
+
const bitsPerSample = u32le(buf, 60)
|
|
218
|
+
if (bitsPerSample !== 1 && bitsPerSample !== 8) throw Error('Unsupported DSF bits-per-sample: ' + bitsPerSample)
|
|
219
|
+
const sampleCount = u64le(buf, 64)
|
|
220
|
+
const blockSize = u32le(buf, 72)
|
|
221
|
+
if (blockSize <= 0) throw Error('Malformed DSF: invalid block size')
|
|
222
|
+
const dataHdr = 28 + fmtSize
|
|
223
|
+
if (buf.length < dataHdr + 12) return null
|
|
224
|
+
if (str4(buf, dataHdr) !== 'data') throw Error('Malformed DSF: missing data chunk')
|
|
225
|
+
const dataChunkSize = u64le(buf, dataHdr + 4)
|
|
226
|
+
const dataStart = dataHdr + 12
|
|
227
|
+
const dataSize = Math.max(0, dataChunkSize - 12)
|
|
228
|
+
return { container: 'dsf', dsdRate, channels, bitsPerSample, sampleCount, blockSize, dataStart, dataSize, fileSize, metaPointer }
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// IFF-style local chunk header reader: {id, size, bodyStart} or null if not enough bytes.
|
|
232
|
+
function readChunkHdr(buf, off) {
|
|
233
|
+
if (off + 12 > buf.length) return null
|
|
234
|
+
return { id: str4(buf, off), size: u64be(buf, off + 4), bodyStart: off + 12 }
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// Returns null if the DFF header (FRM8/FVER/PROP + enough to find the DSD chunk) isn't fully
|
|
238
|
+
// buffered yet, else the parsed header + dataStart offset. Throws on DST compression or bad magic.
|
|
239
|
+
function scanDffHeader(buf) {
|
|
240
|
+
if (buf.length < 16) return null
|
|
241
|
+
if (str4(buf, 0) !== 'FRM8') throw Error('Not a DFF file')
|
|
242
|
+
if (str4(buf, 12) !== 'DSD ') throw Error('Not a DFF file')
|
|
243
|
+
let off = 16, dsdRate = 0, channels = 0, chanIds = [], sawFver = false, sawProp = false
|
|
244
|
+
while (true) {
|
|
245
|
+
const ck = readChunkHdr(buf, off)
|
|
246
|
+
if (!ck) return null
|
|
247
|
+
const bodyEnd = ck.bodyStart + ck.size
|
|
248
|
+
const next = bodyEnd + (ck.size & 1) // pad to even
|
|
249
|
+
if (ck.id === 'FVER') {
|
|
250
|
+
if (bodyEnd > buf.length) return null
|
|
251
|
+
sawFver = true
|
|
252
|
+
} else if (ck.id === 'PROP') {
|
|
253
|
+
if (ck.bodyStart + 4 > buf.length) return null
|
|
254
|
+
if (str4(buf, ck.bodyStart) !== 'SND ') throw Error('Unsupported DFF property type')
|
|
255
|
+
let p = ck.bodyStart + 4
|
|
256
|
+
while (p < bodyEnd) {
|
|
257
|
+
const sub = readChunkHdr(buf, p)
|
|
258
|
+
if (!sub) return null
|
|
259
|
+
const subEnd = sub.bodyStart + sub.size
|
|
260
|
+
if (subEnd > buf.length) return null
|
|
261
|
+
if (sub.id === 'FS ') dsdRate = u32be(buf, sub.bodyStart)
|
|
262
|
+
else if (sub.id === 'CHNL') {
|
|
263
|
+
channels = u16be(buf, sub.bodyStart)
|
|
264
|
+
chanIds = []
|
|
265
|
+
for (let c = 0; c < channels; c++) chanIds.push(str4(buf, sub.bodyStart + 2 + c * 4))
|
|
266
|
+
} else if (sub.id === 'CMPR') {
|
|
267
|
+
const compType = str4(buf, sub.bodyStart)
|
|
268
|
+
if (compType === 'DST ') throw Error('Unsupported: DST')
|
|
269
|
+
if (compType !== 'DSD ') throw Error('Unsupported DFF compression: ' + compType)
|
|
270
|
+
}
|
|
271
|
+
p = subEnd + (sub.size & 1)
|
|
272
|
+
}
|
|
273
|
+
sawProp = true
|
|
274
|
+
} else if (ck.id === 'DSD ') {
|
|
275
|
+
if (!sawFver || !sawProp) throw Error('Malformed DFF: DSD chunk before FVER/PROP')
|
|
276
|
+
if (!dsdRate || !channels) throw Error('Malformed DFF: missing FS or CHNL')
|
|
277
|
+
return { container: 'dff', dsdRate, channels, chanIds, dataStart: ck.bodyStart, dataSize: ck.size }
|
|
278
|
+
} else if (ck.id === 'DST ') {
|
|
279
|
+
throw Error('Unsupported: DST')
|
|
280
|
+
}
|
|
281
|
+
// COMT, DIIN/DITI/DIAR/EMID/MARK, MANF, ABSS, LSCO (inside PROP, handled above) — skip.
|
|
282
|
+
if (bodyEnd > buf.length) return null
|
|
283
|
+
off = next
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// ---------------------------------------------------------------------------
|
|
288
|
+
// Streaming decoder
|
|
289
|
+
|
|
290
|
+
const VALID_RATIOS = [8, 16, 32, 64]
|
|
291
|
+
|
|
292
|
+
function catBytes(a, b) {
|
|
293
|
+
const r = new Uint8Array(a.length + b.length)
|
|
294
|
+
r.set(a); r.set(b, a.length)
|
|
295
|
+
return r
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/** Create a synchronous DSD (DSF/DFF) → PCM decoder. */
|
|
299
|
+
export function decoder(opts = {}) {
|
|
300
|
+
let header = null, carry = null, freed = false
|
|
301
|
+
let stage1 = null, stage1Ch = [], stage2 = null, stage2Ch = null, ratio = 8
|
|
302
|
+
let dataConsumed = 0 // bytes of the *data region* consumed so far (post-header), all channels combined
|
|
303
|
+
let finalEmitted = 0 // samples emitted per channel so far at the final rate (for DSF trimming)
|
|
304
|
+
let finalLimit = Infinity // true sample count per channel at the final rate (DSF only)
|
|
305
|
+
|
|
306
|
+
function setupFilters(h) {
|
|
307
|
+
if (opts.sampleRate) {
|
|
308
|
+
const r = Math.round(h.dsdRate / opts.sampleRate)
|
|
309
|
+
if (!VALID_RATIOS.includes(r) || Math.abs(h.dsdRate / r - opts.sampleRate) > 1e-6)
|
|
310
|
+
throw Error('Unsupported sampleRate: ' + opts.sampleRate + ' (dsdRate/8, /16, /32 or /64 only)')
|
|
311
|
+
ratio = r
|
|
312
|
+
} else ratio = opts.ratio && VALID_RATIOS.includes(opts.ratio) ? opts.ratio : 32
|
|
313
|
+
stage1 = buildStage1(h.dsdRate, { ...opts, ratio })
|
|
314
|
+
stage1Ch = Array.from({ length: h.channels }, () => makeStage1Channel(stage1))
|
|
315
|
+
if (ratio > 8) {
|
|
316
|
+
stage2 = buildStage2(stage1.outRate, ratio / 8, opts)
|
|
317
|
+
stage2Ch = Array.from({ length: h.channels }, () => makeStage2Channel(stage2, ratio / 8))
|
|
318
|
+
}
|
|
319
|
+
if (h.container === 'dsf' && h.sampleCount) finalLimit = Math.floor(h.sampleCount / ratio)
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// Run `bytes` (raw data-region bytes, already sliced to a whole multiple of the frame unit)
|
|
323
|
+
// through stage 1 (+ stage 2) per channel, per the container's interleave layout.
|
|
324
|
+
function decodeFrames(bytes) {
|
|
325
|
+
const nCh = header.channels
|
|
326
|
+
const outCh = []
|
|
327
|
+
if (header.container === 'dsf') {
|
|
328
|
+
const blockSize = header.blockSize, group = blockSize * nCh
|
|
329
|
+
const groups = bytes.length / group
|
|
330
|
+
for (let c = 0; c < nCh; c++) {
|
|
331
|
+
const s1 = new Float64Array(groups * blockSize)
|
|
332
|
+
let o = 0
|
|
333
|
+
for (let g = 0; g < groups; g++) {
|
|
334
|
+
const base = g * group + c * blockSize
|
|
335
|
+
for (let i = 0; i < blockSize; i++) {
|
|
336
|
+
const byte = header.bitsPerSample === 1 ? REV8[bytes[base + i]] : bytes[base + i]
|
|
337
|
+
s1[o++] = stage1Ch[c].push(byte)
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
outCh.push(stage2 ? stage2Ch[c].push(s1) : Float32Array.from(s1))
|
|
341
|
+
}
|
|
342
|
+
} else {
|
|
343
|
+
const nFrames = bytes.length / nCh
|
|
344
|
+
const s1 = Array.from({ length: nCh }, () => new Float64Array(nFrames))
|
|
345
|
+
for (let f = 0, o = 0; f < nFrames; f++, o += nCh)
|
|
346
|
+
for (let c = 0; c < nCh; c++) s1[c][f] = stage1Ch[c].push(bytes[o + c])
|
|
347
|
+
for (let c = 0; c < nCh; c++) outCh.push(stage2 ? stage2Ch[c].push(s1[c]) : Float32Array.from(s1[c]))
|
|
348
|
+
}
|
|
349
|
+
return outCh
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
function trim(channelData) {
|
|
353
|
+
if (finalEmitted >= finalLimit) return channelData.map(() => new Float32Array(0))
|
|
354
|
+
const room = finalLimit - finalEmitted
|
|
355
|
+
const len = channelData[0]?.length ?? 0
|
|
356
|
+
if (len <= room) { finalEmitted += len; return channelData }
|
|
357
|
+
finalEmitted = finalLimit
|
|
358
|
+
return channelData.map((c) => c.subarray(0, room))
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
return {
|
|
362
|
+
decode(data) {
|
|
363
|
+
if (freed) throw Error('Decoder already freed')
|
|
364
|
+
if (!data || !data.byteLength) return EMPTY
|
|
365
|
+
let buf = data instanceof Uint8Array ? data : new Uint8Array(data)
|
|
366
|
+
if (carry) { buf = catBytes(carry, buf); carry = null }
|
|
367
|
+
if (!header) {
|
|
368
|
+
if (buf.length < 4) { carry = buf; return EMPTY }
|
|
369
|
+
const h = str4(buf, 0) === 'FRM8' ? scanDffHeader(buf) : scanDsfHeader(buf)
|
|
370
|
+
if (!h) { carry = buf; return EMPTY }
|
|
371
|
+
header = h
|
|
372
|
+
setupFilters(h)
|
|
373
|
+
buf = buf.subarray(h.dataStart)
|
|
374
|
+
dataConsumed = 0
|
|
375
|
+
}
|
|
376
|
+
const remaining = header.dataSize - dataConsumed
|
|
377
|
+
if (remaining <= 0) return EMPTY
|
|
378
|
+
if (buf.length > remaining) buf = buf.subarray(0, remaining)
|
|
379
|
+
const frame = header.container === 'dsf' ? header.blockSize * header.channels : header.channels
|
|
380
|
+
const complete = Math.floor(buf.length / frame) * frame
|
|
381
|
+
if (!complete) { carry = buf.length ? buf.slice() : null; return EMPTY }
|
|
382
|
+
if (buf.length > complete) carry = buf.subarray(complete).slice()
|
|
383
|
+
dataConsumed += complete
|
|
384
|
+
const channelData = trim(decodeFrames(buf.subarray(0, complete)))
|
|
385
|
+
return { channelData, sampleRate: ratio > 8 ? stage2.outRate : stage1.outRate }
|
|
386
|
+
},
|
|
387
|
+
flush() {
|
|
388
|
+
if (!header || !carry || !carry.length) { carry = null; return EMPTY }
|
|
389
|
+
const frame = header.container === 'dsf' ? header.blockSize * header.channels : header.channels
|
|
390
|
+
const padded = new Uint8Array(Math.ceil(carry.length / frame) * frame) // zero-pad, matches the
|
|
391
|
+
padded.set(carry) // DSF spec's own convention for a short final block
|
|
392
|
+
carry = null
|
|
393
|
+
dataConsumed += padded.length
|
|
394
|
+
const channelData = trim(decodeFrames(padded))
|
|
395
|
+
return { channelData, sampleRate: ratio > 8 ? stage2.outRate : stage1.outRate }
|
|
396
|
+
},
|
|
397
|
+
free() {
|
|
398
|
+
freed = true
|
|
399
|
+
header = null; carry = null; stage1 = null; stage1Ch = []; stage2 = null; stage2Ch = null
|
|
400
|
+
},
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/** Decode a complete DSF or DFF buffer synchronously. */
|
|
405
|
+
export default function decode(src, opts) {
|
|
406
|
+
const dec = decoder(opts)
|
|
407
|
+
try {
|
|
408
|
+
const head = dec.decode(src instanceof Uint8Array ? src : new Uint8Array(src))
|
|
409
|
+
const tail = dec.flush()
|
|
410
|
+
if (!head.channelData.length) return tail
|
|
411
|
+
if (!tail.channelData.length) return head
|
|
412
|
+
return {
|
|
413
|
+
channelData: head.channelData.map((c, i) => {
|
|
414
|
+
const r = new Float32Array(c.length + tail.channelData[i].length)
|
|
415
|
+
r.set(c); r.set(tail.channelData[i], c.length)
|
|
416
|
+
return r
|
|
417
|
+
}),
|
|
418
|
+
sampleRate: head.sampleRate,
|
|
419
|
+
}
|
|
420
|
+
} finally {
|
|
421
|
+
dec.free()
|
|
422
|
+
}
|
|
423
|
+
}
|