# MP3 encoder notices and publication checklist Panda Music Pad uses **lamejs 1.2.1**, by Alex Zhukov, a JavaScript rewrite of jump3r/libmp3lame, under **LGPL-3.0** (upstream package declaration). LAME: https://lame.sourceforge.net/ ; lamejs: https://github.com/zhuker/lamejs . The encoder is unmodified. Panda's adapter is separate application code. ## Provenance Primary publisher artifact: https://registry.npmjs.org/lamejs/-/lamejs-1.2.1.tgz Primary version metadata: https://registry.npmjs.org/lamejs/1.2.1 The local archive is the full original npm distribution, not a bundle-only or reconstructed archive. Its SHA-1 and SHA-512 integrity match freshly fetched primary registry metadata, and its bytes match a fresh primary artifact download. The bundled `lame.min.js`, original LICENSE and README match archive members byte for byte. Archive includes 37 JavaScript source entries, the unminified distribution, Java source and build scripts `makeall.sh`/`minify.sh`. Upstream scripts require browserify, Java and Closure Compiler (compiler.jar); these tools are not included. We do not claim a bit-reproducible build with unspecified historical tool versions. Verification script/evidence: `releases/mp3-proof/verify-provenance.py` and `provenance.json`. npm signing-key verification is not claimed. - Archive SHA256: `d8d099ef788808c15bc9b4a407dd23ae935feb1152e6bb0efdcd24e3e91c2a2d` - Encoder SHA256: `15d285e2587b3bdbfd18a68de6ce07cc074f7480a82c3815da2dc1c348ec6df4` ## Files to publish together at /vendor/ Do not deploy only index.html with the new embedded encoder. Publish: - `lame.min.js` — standalone, unmodified encoder, also available for replacement. - `lamejs-1.2.1-source.tgz` — full corresponding upstream source distribution. - `lamejs-COPYING.txt` — full GNU GPL version 3 text. - `lamejs-COPYING.LESSER.txt` — full GNU LGPL version 3 text. - `lamejs-LICENSE.txt` — original upstream usage/license notice (NOT a substitute for full license texts). - `lamejs-UPSTREAM-README.txt` — original upstream documentation. - `lamejs-package-metadata.json` — publisher/version/license/integrity record. - `MP3-NOTICES.txt` — this acknowledgement and replacement instructions. Add a prominent user-accessible MP3 attribution in the application linking to `/vendor/MP3-NOTICES.txt`, both full license texts and `/vendor/lamejs-1.2.1-source.tgz`. Keep these available wherever the combined app is distributed, including offline packages; a source comment alone is not a prominent user notice. Do not impose terms prohibiting modification of the library or reverse engineering to debug such modifications. This checklist implements the accompanying-source/notices/recombination approach of LGPLv3 section 4; it is not a blanket legal certification of the final distribution. ## Recombining an embedded copy The distributed HTML is editable application source. Retain a separately identifiable encoder script block and the nonminified adapter/application scripts. Users can save the HTML and vendor files locally, replace ONLY the encoder block with an interface-compatible modified `lame.min.js`, or replace that block with ``. Keep the encoder before the PandaMp3 adapter and application. No signing, integrity lock or other restriction may prevent running that changed local copy. If the final build obscures those boundaries, parent must instead publish the application source/build inputs necessary to recombine it, or use the separate replaceable script mechanism. ## Adapter contract Browser: load the upstream bundle before `mp3-export.js`; then `await PandaMp3.encode(audioBuffer, {onProgress})` returns an `audio/mpeg` Blob. CommonJS: evaluate the official browser bundle in a Node VM, then `require('./mp3-export.js').create(context.lamejs).encode(...)`. The npm CommonJS encoder sources are deliberately not required. Always stereo 192kbps. Mono input is duplicated to stereo. Accepted source rates: 32000, 44100, 48000 Hz; other rates are explicitly rejected to avoid silent resampling/bitrate reduction. Input length must be a positive safe integer; channel count one or two; channel arrays Float32 and exact length; nonfinite samples reject. Finite out-of-range samples clip without modifying input. Only two 1152-sample PCM16 conversion buffers are allocated; compressed chunks are retained until Blob construction. Initial timer yield and one yield per 16 blocks, progress 0 through 1 (final 1 only after flush/Blob). Caller must not mutate source PCM while the asynchronous encode is running. Progress callback exceptions propagate as rejection. Proof is numeric Node VM/ffmpeg verification, not native-browser responsiveness, listening quality or mobile QA. No user audio is uploaded.