Library / SDK
chrisguttandin/standardized-audio-context avatar
chrisguttandin/standardized-audio-context

standardized-audio-context: a ponyfill for the Web Audio API

A cross-browser wrapper for the Web Audio API which aims to closely follow the standard.

779 stars37 forksJavaScriptMIT

At a glance

What is it?
standardized-audio-context is a wrapper that gives you the Web Audio API in a consistent form across browsers, and it deliberately does it without touching the global scope. It implements only the missing pieces rather than rewriting what the browser already provides, and it is published on npm with a documented list of what it cannot fake.
Who is it for?
standardized-audio-context suits a library author whose audio code must run identically in every browser, because it fills the gaps rather than replacing the platform and it does not patch globals, so it is safe to depend on from inside another package.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 52 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A ponyfill, not a polyfill

standardized-audio-context describes itself as a cross-browser wrapper for the Web Audio API which aims to closely follow the standard.

The distinguishing detail is in the second paragraph of the README, and it is a distinction that matters when you depend on it from a library. In contrast to other popular polyfills, the package does not patch or modify anything on the global scope. In other words, it causes no side effects, and it can therefore be used safely inside libraries. It is what is known as a ponyfill.

That word is the whole difference between this package and the more common approach. A polyfill reaches into the global object and replaces or augments the native AudioContext, which means every script on the page, including code you did not write, sees the change. A ponyfill exports its own implementation and leaves the browser's alone, so you import what you want and nothing else is affected.

For an application that owns its whole page, the difference is academic. For a package published to npm that other people will depend on, it is the difference between being usable and being a nuisance, because a library that patches globals changes the behaviour of code it knows nothing about.

The package is MIT licensed, published on npm, and the author is Christoph Guttandin.

The rule: implement only what is missing

One of the goals of the package is to only implement missing functionality and to avoid rewriting built-in features whenever possible, and the README sends you to the browser support section for the detail.

That is a different philosophy from most polyfills, and it has consequences worth understanding.

If a browser already has a native AudioContext with a complete implementation, the wrapper can simply delegate to it. You get the native behaviour, the native performance and the native bug fixes, and the wrapper only adds value where something is actually missing. If instead the wrapper reimplemented everything, then every browser would get the same behaviour, which sounds appealing until you realise that the reimplementation would be slower and would lose the browser specific optimisations.

The cost of the approach is that the wrapper is not perfectly uniform. Its behaviour depends on what the host browser provides, so the same code can behave slightly differently in two browsers that are missing different pieces. The README is upfront about the trade in the browser support section rather than claiming complete uniformity.

The other thing the README is upfront about is what cannot be done. There are some things which cannot be faked in a way that makes them as performant as they could be when implemented natively, and the most prominent is the AudioWorklet.

That is the important limitation in the package, and it is structural rather than a missing feature. The AudioWorklet runs your audio processing code on the audio thread, which is a mechanism the browser provides and a wrapper cannot emulate without giving up the timing guarantees that make the worklet worth having.

Using it

The package is on npm and is installed the usual way.

shell
npm install standardized-audio-context

You then import the two context classes from the package.

js
import { AudioContext, OfflineAudioContext } from 'standardized-audio-context';

And they are used exactly like their native counterparts. The README's example produces a sine wave.

js
import { AudioContext } from 'standardized-audio-context';

const audioContext = new AudioContext();
const oscillatorNode = audioContext.createOscillator();

oscillatorNode.connect(audioContext.destination);

oscillatorNode.start();

There is also a way to load the package from a service such as jspm, in which case the import statement points at a URL instead.

js
import { AudioContext, OfflineAudioContext } from 'https://jspm.dev/standardized-audio-context';

And there is an alternative to the factory methods: the AudioNode constructors can be used directly, which is a different calling convention from the native API and is offered as an option.

js
import { AudioContext, OscillatorNode } from 'standardized-audio-context';

const audioContext = new AudioContext();
const oscillatorNode = new OscillatorNode(audioContext);

That last form is worth a note, because it is a departure from the specification rather than an implementation of it. If your goal is to closely follow the standard, the factory method form is the one to use, and the constructor form is there for people who prefer it.

The API surface and what is missing

The README documents the two context classes as almost complete implementations of their specifications, and both miss the same single method: createScriptProcessor, which the README notes is deprecated anyway.

The AudioContext interface it implements extends EventTarget and carries the state, the current time, the sample rate, the base latency, the destination, the listener and the optional worklet, along with the factory methods for every node type: analysers, biquad filters, buffers and buffer sources, channel mergers and splitters, constant sources, convolvers, delays, dynamics compressors, gains, filters, media element and media stream sources, oscillators, panners, periodic waves, stereo panners and wave shapers, plus decoding of audio data and the resume, suspend and close methods.

The OfflineAudioContext interface has the same shape, with the length of the buffer to render added and the resume and suspend methods dropped, since an offline context renders as fast as the machine allows and has no notion of pausing.

What is missing from both is the one deprecated method. That is a deliberate choice, and it is worth noticing that the omission is safe for a different reason than the AudioWorklet one: a deprecated method can be removed because nothing should be calling it, whereas the worklet cannot be faked because the browser's own implementation is what provides the timing.

The README also links a list of all supported methods for the detail on each one, which is the reference to check against the specification for the method you care about.

The repository and the toolchain

The repository is small, with the source, the tests, a configuration directory and the usual GitHub and Husky directories.

The runtime dependencies are few and modest. There is the Babel runtime helper, a small library of custom event helpers, the TypeScript helpers library and the type definitions package. Nothing in that list touches audio.

The development dependencies are more revealing about how the project is tested. The test tooling includes the browser mode of the test runner with both Playwright and Webdriverio backends, the Puppeteer browser driver, Mocha, Chai for assertions, and the Prettier, ESLint, Husky and lint-staged toolchain. Two browser drivers and two test runners is a lot of machinery, and it is explained by the nature of the package: it exists because browsers differ, so it has to be run in browsers.

The build uses Rollup with the Babel plugin, and the package is written in TypeScript with the config shared across the project. The commit messages are checked by a commit lint tool with an Angular style configuration, and there is a commitizen configuration pointing at the conventional changelog tool, which is the setup that lets the release notes be generated from the commit history.

That combination, a typed source, a bundled output, browser based tests across two drivers and a generated changelog, is the shape of a library that takes its cross browser promise seriously.

Versions, maintenance and who should use it

The release tags are v25.3.77 from 2024-08-31, v25.3.76 from 2024-08-13 and v25.3.75 from 2024-07-12, and the last push was on 2026-09-01.

The version numbers encode the calendar year and the release counter, which is a common convention for packages maintained by a single maintainer with a steady release habit. There is a release roughly every two to three weeks in that period, which for a compatibility wrapper is a sensible cadence, since the thing it tracks is the browsers changing.

The gap between the last tag and the last commit is worth noting but not alarming. The work that is not tagged is likely maintenance against browser changes, and the repository is not dormant.

So the question of who should use it comes down to two things. If you are writing a library that other people install, the ponyfill property alone makes it the safe choice, because a global patch from a dependency is a genuine problem. If you are writing an application for one browser family, then the wrapper buys you consistency across versions of that family rather than across vendors, which is a smaller win.

And if your audio graph uses the AudioWorklet, the README's warning is the deciding factor: the worklet cannot be faked with the same performance, so a wrapper that promises consistency cannot promise it there, and your code has to handle the difference anyway.

Editorial conclusion

standardized-audio-context suits a library author whose audio code must run identically in every browser, because it fills the gaps rather than replacing the platform and it does not patch globals, so it is safe to depend on from inside another package. It is the wrong choice for an application that only targets browsers with a complete Web Audio implementation, since the wrapper then adds a layer for nothing, and it is the wrong choice if your audio graph depends on the AudioWorklet, which the README names as the thing that cannot be faked with the same performance as a native implementation. Verify first which parts of the API your browser target is missing, since that determines what the wrapper actually does at runtime, and check the documented list of supported methods before you rely on an edge of the specification.

Frequently asked questions

What is standardized-audio-context?

It is a cross-browser wrapper for the Web Audio API that provides a subset of it, almost complete, and works reliably and consistently in every supported browser.

How is it different from a polyfill?

It does not patch or modify anything on the global scope, so it causes no side effects and can be used safely inside libraries. That approach is known as a ponyfill.

What can it not replicate?

The README says some things cannot be faked as performantly as a native implementation, and names the AudioWorklet as the most prominent of them. It also notes that the deprecated createScriptProcessor method is the one API method left out of both context classes.

How do I install and import it?

Install it from npm with npm install standardized-audio-context and import the AudioContext and OfflineAudioContext classes from the package, or point the import at a URL if you load it through a service such as jspm.

Official sources

  1. chrisguttandin/standardized-audio-context on GitHub
  2. Issues
  3. License: MIT
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/chrisguttandin-standardized-audio-context.svg)](https://hysenlabs.com/projects/chrisguttandin-standardized-audio-context)

Was this useful?