{"_id":"@bjesuiter/audio-limiter","name":"@bjesuiter/audio-limiter","dist-tags":{"latest":"2.0.0"},"versions":{"2.0.0":{"name":"@bjesuiter/audio-limiter","version":"2.0.0","description":"Modern AudioWorklet limiter with explicit factory API","keywords":["audio","limiter","web-audio","worklet"],"license":"MIT","author":{"name":"bjesuiter@gmail.com"},"type":"module","main":"./dist/index.cjs","module":"./dist/index.mjs","types":"./dist/index.d.mts","exports":{".":{"import":{"types":"./dist/index.d.mts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}}},"publishConfig":{"access":"public","provenance":true},"scripts":{"clean":"rm -rf dist .tmp","type-check":"tsc --noEmit","build":"tsdown","lint":"oxlint src test tsdown.config.ts vitest.config.ts","format":"oxfmt src test tsdown.config.ts vitest.config.ts AGENTS.md README.md package.json","format:check":"oxfmt --check src test tsdown.config.ts vitest.config.ts AGENTS.md README.md package.json","test":"vitest run","test:browser":"vitest run --browser","prepack":"bun run clean && bun run format:check && bun run lint && bun run type-check && bun run test:browser && bun run build"},"devDependencies":{"@types/node":"^25.6.2","@vitest/browser":"^4.1.5","@vitest/browser-playwright":"^4.1.5","oxfmt":"^0.48.0","oxlint":"^1.63.0","playwright":"^1.59.1","tsdown":"^0.22.0","typescript":"^6.0.3","vitest":"^4.1.5"},"gitHead":"82aed0208447e85a4f91f88c018f2409e27ee411","_id":"@bjesuiter/audio-limiter@2.0.0","_nodeVersion":"25.9.0","_npmVersion":"11.12.1","dist":{"integrity":"sha512-40xbAEUBi9E2r7Xjross19koUFhb8HazpwVNh4+FPs488y8Kbey776uNaDLXTMneUVauFJ3yKyoYRzBEUb6znQ==","shasum":"19199dfa30b4d97a77b40dd889adb147c56ebc56","tarball":"https://registry.npmjs.org/@bjesuiter/audio-limiter/-/audio-limiter-2.0.0.tgz","fileCount":11,"unpackedSize":71183,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCdhianDl9OmtLKtvYPhArGuuwgPBrMl1sxpI3MnCgQSQIgZJKaz9bHZGiCqeVTOlRg5+v9KYwGdMakLD6hSgxs9sY="}]},"_npmUser":{"name":"bjesuiter","email":"bjesuiter@gmail.com"},"directories":{},"maintainers":[{"name":"bjesuiter","email":"bjesuiter@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/audio-limiter_2.0.0_1778482752649_0.03303899058401938"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-11T06:59:12.528Z","2.0.0":"2026-05-11T06:59:12.881Z","modified":"2026-05-11T06:59:13.133Z"},"maintainers":[{"name":"bjesuiter","email":"bjesuiter@gmail.com"}],"description":"Modern AudioWorklet limiter with explicit factory API","keywords":["audio","limiter","web-audio","worklet"],"author":{"name":"bjesuiter@gmail.com"},"license":"MIT","readme":"# audio-limiter\n\nModern AudioWorklet limiter for the Web Audio API.\n\nThis package exposes an explicit async factory. It does not patch `AudioContext.prototype`.\n\n## Installation\n\n```sh\nnpm install audio-limiter\n```\n\n## Usage\n\n```ts\nimport { createLimiter } from \"audio-limiter\";\n\nconst context = new AudioContext();\nconst limiter = await createLimiter(context, {\n  threshold: -6,\n  lookahead: 0.005,\n  attack: 0.003,\n  release: 0.05,\n});\n\nconst source = context.createBufferSource();\nsource.buffer = audioBuffer;\nsource.connect(limiter).connect(context.destination);\nsource.start();\n```\n\n`createLimiter()` works with both `AudioContext` and `OfflineAudioContext`:\n\n```ts\nconst context = new OfflineAudioContext({\n  numberOfChannels: 2,\n  length: 44_100,\n  sampleRate: 44_100,\n});\n\nconst limiter = await createLimiter(context, { threshold: -2 });\n```\n\n## API\n\n### `createLimiter(context, options?)`\n\nCreates and returns a ready `LimiterAudioWorkletNode`.\n\n```ts\nconst limiter = await createLimiter(context, options);\n```\n\nBy default, the AudioWorklet processor is loaded from an embedded Blob URL. If your app needs to manage the worklet asset itself, pass `workletUrl`:\n\n```ts\nconst limiter = await createLimiter(context, {\n  workletUrl: \"/assets/limiter-worklet.js\",\n});\n```\n\n### Advanced preload API\n\nFor most apps, use `createLimiter()`. If you want to preload the worklet during app setup and construct nodes synchronously later, use the advanced helpers:\n\n```ts\nimport { createLimiterNode, loadLimiterWorklet } from \"audio-limiter\";\n\nawait loadLimiterWorklet(context);\n\nconst limiter = createLimiterNode(context, {\n  threshold: -6,\n  lookahead: 0.005,\n});\n```\n\n`createLimiterNode()` assumes the processor was already registered with `loadLimiterWorklet()`. If it is called first, the browser will throw because the worklet processor name is not known yet.\n\n`loadLimiterWorklet()` accepts only loader options:\n\n```ts\nawait loadLimiterWorklet(context, {\n  workletUrl: \"/assets/limiter-worklet.js\",\n});\n```\n\nWorklet registration is cached per audio context. If `workletUrl` is provided for the first load, that URL is used; later loads for the same context reuse the existing registration.\n\n### Options\n\n| Option         | Type            |       Default | Description                                                                |\n| -------------- | --------------- | ------------: | -------------------------------------------------------------------------- |\n| `threshold`    | `number`        |          `-2` | Limiting threshold in dB.                                                  |\n| `attack`       | `number`        |           `0` | Envelope attack time in seconds.                                           |\n| `release`      | `number`        |         `0.1` | Envelope release time in seconds.                                          |\n| `preGain`      | `number`        |           `0` | Input gain in dB before limiting.                                          |\n| `postGain`     | `number`        |           `0` | Output gain in dB after limiting.                                          |\n| `bypass`       | `boolean`       |       `false` | Pass input through without limiting.                                       |\n| `lookahead`    | `number`        |       `0.005` | Delay in seconds used for limiter lookahead. Must be between `0` and `10`. |\n| `workletUrl`   | `string \\| URL` | embedded Blob | Optional caller-managed worklet module URL.                                |\n| `channelCount` | `number`        |           `2` | Number of channels.                                                        |\n\nThe limiter uses one input and one output, with `channelCountMode: 'explicit'`.\n\n### Parameters\n\nThe returned node is an `AudioWorkletNode`, so all limiter controls are native `AudioParam`s:\n\n```ts\nlimiter.parameters.get(\"threshold\")?.setValueAtTime(-8, context.currentTime);\n```\n\nFor convenience, the same params are also available as typed getters:\n\n```ts\nlimiter.threshold.setValueAtTime(-8, context.currentTime);\nlimiter.attack.setValueAtTime(0.005, context.currentTime);\nlimiter.release.setValueAtTime(0.1, context.currentTime);\nlimiter.preGain.setValueAtTime(3, context.currentTime);\nlimiter.postGain.setValueAtTime(0, context.currentTime);\nlimiter.bypass.setValueAtTime(1, context.currentTime);\n```\n\n## Development\n\n```sh\nbun install\nbun run format:check\nbun run lint\nbun run type-check\nbun run test:browser\nbun run build\n```\n\nThe browser tests use Vitest Browser with Playwright and render through `OfflineAudioContext`, so they exercise the real AudioWorklet path.\n\n## Acknowledgements\n\nThanks to Robert Kamiński and the original [`robert8888/audio-limiter`](https://github.com/robert8888/audio-limiter) package. This version was rebuilt with a modern TypeScript/tsdown setup and an explicit factory API, using the original package as inspiration for the limiter design and parameter model.\n\n## License\n\nMIT\n","readmeFilename":"README.md","_rev":"1-df20afc1f97a58a9564322da6b3731ef"}