• Stars
    star
    662
  • Rank 67,875 (Top 2 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created almost 9 years ago
  • Updated 3 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

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

logo

standardized-audio-context

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

version

This package provides a subset (although it's almost complete) of the Web Audio API which works in a reliable and consistent way in every supported browser. In contrast to other popular polyfills standardized-audio-context does not patch or modify anything on the global scope. In other words, it does not cause any side effects. It can therefore be used safely inside of libraries. It's what's known as a ponyfill.

One of the goals of standardized-audio-context is to only implement missing functionality and to avoid rewriting built-in features whenever possible. Please take a look at the paragraph about the browser support below for more information.

There are some things which cannot be faked in a way that makes them as performant as they could be when implemented natively. The most prominent amongst those things is the AudioWorklet. Please have a look at the list of all supported methods below for more detailed information.

Usage

The standardized-audio-context is available on npm and can be installed as usual.

npm install standardized-audio-context

You can then import the AudioContext and OfflineAudioContext like this:

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

It is also possible to load standardized-audio-context with a service like jspm. The import statement from above would then need to be changed to point to a URL.

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

Once the AudioContext and/or OfflineAudioContext are imported they can be used in the same way as their native counterparts. The following snippet will for example produce a nice and clean (as well as annoying) sine wave.

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

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

oscillatorNode.connect(audioContext.destination);

oscillatorNode.start();

An alternative approach would be to use the AudioNode constructors (the OscillatorNode constructor in this case) instead of the factory methods.

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

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

oscillatorNode.connect(audioContext.destination);

oscillatorNode.start();

API

AudioContext

This is an almost complete implementation of the AudioContext interface. It only misses the createScriptProcessor() method which is deprecated anyway.

⚠️ Setting the sampleRate is not supported in Safari so far.

⚠️ Safari allows only 4 running AudioContexts at the same time. Creating the fifth AudioContext will throw an UnknownError.

The AudioContext implements the following TypeScript interface.

interface IAudioContext extends EventTarget {
    readonly audioWorklet?: IAudioWorklet;
    readonly baseLatency: number;
    readonly currentTime: number;
    readonly destination: IAudioDestinationNode<IAudioContext>;
    readonly listener: IAudioListener;
    onstatechange: null | TEventHandler<IAudioContext>;
    readonly sampleRate: number;
    readonly state: TAudioContextState;
    close(): Promise<void>;
    createAnalyser(): IAnalyserNode<IAudioContext>;
    createBiquadFilter(): IBiquadFilterNode<IAudioContext>;
    createBuffer(numberOfChannels: number, length: number, sampleRate: number): IAudioBuffer;
    createBufferSource(): IAudioBufferSourceNode<IAudioContext>;
    createChannelMerger(numberOfInputs?: number): IAudioNode<IAudioContext>;
    createChannelSplitter(numberOfOutputs?: number): IAudioNode<IAudioContext>;
    createConstantSource(): IConstantSourceNode<IAudioContext>;
    createConvolver(): IConvolverNode<IAudioContext>;
    createDelay(maxDelayTime?: number): IDelayNode<IAudioContext>;
    createDynamicsCompressor(): IDynamicsCompressorNode<IAudioContext>;
    createGain(): IGainNode<IAudioContext>;
    createIIRFilter(feedforward: number[], feedback: number[]): IIIRFilterNode<IAudioContext>;
    createMediaElementSource(mediaElement: HTMLMediaElement): IMediaElementAudioSourceNode<IAudioContext>;
    createMediaStreamDestination(): IMediaElementAudioDestinationNode<IAudioContext>;
    createMediaStreamSource(mediaStream: MediaStream): IMediaStreamAudioSourceNode<IAudioContext>;
    createMediaStreamTrackSource(mediaStreamTrack: MediaStreamTrack): IMediaStreamTrackAudioSourceNode<IAudioContext>;
    createOscillator(): IOscillatorNode<IAudioContext>;
    createPanner(): IPannerNode<IAudioContext>;
    createPeriodicWave(real: number[], imag: number[], constraints?: Partial<IPeriodicWaveConstraints>): IPeriodicWave;
    createStereoPanner(): IStereoPannerNode<IAudioContext>;
    createWaveShaper(): IWaveShaperNode<IAudioContext>;
    decodeAudioData(
        audioData: ArrayBuffer,
        successCallback?: TDecodeSuccessCallback,
        errorCallback?: TDecodeErrorCallback
    ): Promise<IAudioBuffer>;
    resume(): Promise<void>;
    suspend(): Promise<void>;
}

The properties and methods are described in greater detail below.

OfflineAudioContext

This is an almost complete implementation of the OfflineAudioContext interface. It only misses the createScriptProcessor() method which is deprecated anyway.

⚠️ Safari does not support creating an OfflineAudioContext with more than 10 channels or with a sampleRate below 44100 Hz.

It implements the following TypeScript interface.

interface IOfflineAudioContext extends EventTarget {
    readonly audioWorklet?: IAudioWorklet;
    readonly baseLatency: number;
    readonly currentTime: number;
    readonly destination: IAudioDestinationNode<IOfflineAudioContext>;
    readonly length: number;
    readonly listener: IAudioListener;
    onstatechange: null | TEventHandler<IOfflineAudioContext>;
    readonly sampleRate: number;
    readonly state: TAudioContextState;
    createAnalyser(): IAnalyserNode<IOfflineAudioContext>;
    createBiquadFilter(): IBiquadFilterNode<IOfflineAudioContext>;
    createBuffer(numberOfChannels: number, length: number, sampleRate: number): IAudioBuffer;
    createBufferSource(): IAudioBufferSourceNode<IOfflineAudioContext>;
    createChannelMerger(numberOfInputs?: number): IAudioNode<IOfflineAudioContext>;
    createChannelSplitter(numberOfOutputs?: number): IAudioNode<IOfflineAudioContext>;
    createConstantSource(): IConstantSourceNode<IOfflineAudioContext>;
    createConvolver(): IConvolverNode<IOfflineAudioContext>;
    createDelay(maxDelayTime?: number): IDelayNode<IOfflineAudioContext>;
    createDynamicsCompressor(): IDynamicsCompressorNode<IOfflineAudioContext>;
    createGain(): IGainNode<IOfflineAudioContext>;
    createIIRFilter(feedforward: number[], feedback: number[]): IIIRFilterNode<IOfflineAudioContext>;
    createOscillator(): IOscillatorNode<IOfflineAudioContext>;
    createPanner(): IPannerNode<IOfflineAudioContext>;
    createPeriodicWave(real: number[], imag: number[], constraints?: Partial<IPeriodicWaveConstraints>): IPeriodicWave;
    createStereoPanner(): IStereoPannerNode<IOfflineAudioContext>;
    createWaveShaper(): IWaveShaperNode<IOfflineAudioContext>;
    decodeAudioData(
        audioData: ArrayBuffer,
        successCallback?: TDecodeSuccessCallback,
        errorCallback?: TDecodeErrorCallback
    ): Promise<IAudioBuffer>;
    startRendering(): Promise<IAudioBuffer>;
}

The properties and methods are described in greater detail below.

audioWorklet

⚠️ The AudioWorklet is accessible as a property of an AudioContext or OfflineAudioContext. It uses the ScriptProcessorNode internally to create an AudioWorkletProcessor in Safari. This means it will only provide the performance improvements that you would normally expect from using an AudioWorklet in Chrome, Edge and Firefox.

⚠️ The fact that the internal implementation relies on a ScriptProcessorNode also implies that the channelCountMode can only be 'explicit' for now. It also means that the total number of channels of all inputs plus the number of all parameters can't be larger than six.

⚠️ Another thing to keep in mind is that the fallback will evaluate the AudioWorkletProcessor on the global scope. It gets isolated in a basic way to mimic the AudioWorkletGlobalScope but that can't be done in a way which makes it impossible for an attacker to break out of that sandbox. This should not be a problem unless you load an AudioWorklet from an untrusted source.

listener

⚠️ Firefox and Safari up to version 14.0.1 do not support modifying the listener via AudioParams. Therefore calling any of the scheduling functions on the AudioParams of a listener of an OfflineAudioContext throws a NotSupportedError.

createAnalyser() / AnalyserNode

This is an implementation of the createAnalyser() factory method. The AnalyserNode constructor may be used as an alternative.

createBiquadFilter() / BiquadFilterNode

This is an implementation of the createBiquadFilter() factory method. The BiquadFilterNode constructor may be used as an alternative.

createBuffer() / AudioBuffer

This is an implementation of the createBuffer() factory method. The AudioBuffer constructor may be used as an alternative.

⚠️ Safari does not support AudioBuffers with a sampleRate below 22050 Hz.

createBufferSource() / AudioBufferSourceNode

This is an implementation of the createBufferSource() factory method. The AudioBufferSourceNode constructor may be used as an alternative.

⚠️ The detune AudioParam is not implemented so far.

⚠️ Safari up to version 14.0.1 did not support to connect a signal to the playbackRate AudioParam. Therefore an attempt to connect any other AudioNode to it will throw a NotSupportedError in those version of Safari.

createChannelMerger() / ChannelMergerNode

This is an implementation of the createChannelMerger() factory method. The ChannelMergerNode constructor may be used as an alternative.

createChannelSplitter() / ChannelSplitterNode

This is an implementation of the createChannelSplitter() factory method. The ChannelSplitterNode constructor may be used as an alternative.

createConstantSource() / ConstantSourceNode

This is an implementation of the createConstantSource() factory method. The ConstantSourceNode constructor may be used as an alternative.

createConvolver() / ConvolverNode

This is an implementation of the createConvolver() factory method. The ConvolverNode constructor may be used as an alternative.

createDelay() / DelayNode

This is an implementation of the createDelay() factory method. The DelayNode constructor may be used as an alternative.

⚠️ The delayTime AudioParam can't be set to very small values in any browser except Firefox.

createDynamicsCompressor() / DynamicsCompressorNode

This is an implementation of the createDynamicsCompressor() factory method. The DynamicsCompressorNode constructor may be used as an alternative.

createGain() / GainNode

This is an implementation of the createGain() factory method. The GainNode constructor may be used as an alternative.

createIIRFilter() / IIRFilterNode

This is an implementation of the createIIRFilter() factory method. The IIRFilterNode constructor may be used as an alternative.

⚠️ It has to be faked internally with a ScriptProcessorNode in Safari which means it is not as performant as in other browsers which support it natively.

createMediaElementSource() / MediaElementAudioSourceNode

This is an implementation of the createMediaElementSource() factory method. The MediaElementAudioSourceNode constructor may be used as an alternative.

It does only work with an AudioContext but not with an OfflineAudioContext.

createMediaStreamDestination() / MediaStreamAudioDestinationNode

This is an implementation of the createMediaStreamDestination() factory method. The MediaStreamAudioDestinationNode constructor may be used as an alternative.

It does only work with an AudioContext but not with an OfflineAudioContext.

createMediaStreamSource() / MediaStreamAudioSourceNode

This is an implementation of the createMediaStreamSource() factory method. The MediaStreamAudioSourceNode constructor may be used as an alternative.

It does only work with an AudioContext but not with an OfflineAudioContext.

⚠️ Safari outputs silence if the MediaStreamAudioSourceNode is disconnected for about two seconds.

createMediaStreamTrackSource() / MediaStreamTrackAudioSourceNode

This is an implementation of the createMediaStreamTrackSource() factory method. The MediaStreamTrackAudioSourceNode constructor may be used as an alternative.

It does only work with an AudioContext but not with an OfflineAudioContext.

createOscillator() / OscillatorNode

This is an implementation of the createOscillator() factory method. The OscillatorNode constructor may be used as an alternative.

createPanner() / PannerNode

This is an implementation of the createPanner() factory method. The PannerNode constructor may be used as an alternative.

createPeriodicWave() / PeriodicWave

This is an implementation of the createPeriodicWave() factory method. The PeriodicWave constructor may be used as an alternative.

createStereoPanner() / StereoPannerNode

This is an implementation of the createStereoPanner() factory method. The StereoPannerNode constructor may be used as an alternative.

The channelCountMode can only be 'explicit' unless Safari comes up with a native implementation.

createWaveShaper() / WaveShaperNode

This is an implementation of the createWaveShaper() factory method. The WaveShaperNode constructor may be used as an alternative.

decodeAudioData()

This is an implementation of the decodeAudioData() method. There is also a standalone method with a similar interface described below.

decodeAudioData()

This is a standalone wrapper which can be used in a similar way as the instance method with the same name. The most notable difference is that it expects an (Offline)AudioContext created with this library as the first parameter. But it can also handle a native (webkit)(Offline)AudioContext. Another difference is that it only returns a promise. It will not call any callbacks.

import { decodeAudioData } from 'standardized-audio-context';

// Let's imagine you run this in Safari.
const nativeAudioContext = new webkitAudioContextContext();

const response = await fetch('/a-super-cool-audio-file');
const arrayBuffer = await response.arrayBuffer();

const audioBuffer = await decodeAudioData(nativeAudioContext, arrayBuffer);

isAnyAudioContext()

This is a utility function which determines if the given value is an AudioContext or not. It does not differentiate between an AudioContext created by standardized-audio-context or a native one. But it will return false for an OfflineAudioContext.

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

// This will create an AudioContext from standardized-audio-context.
const audioContext = new AudioContext();

isAnyAudioContext(audioContext); // true

// This will create a native AudioContext.
const nativeAudioContext = new window.AudioContext();

isAnyAudioContext(nativeAudioContext); // true

isAnyAudioNode()

This is a helper function which allows to identify an AudioNode without any custom instanceof or property checks. It returns true if the given value is an AudioNode or false if not. It doesn't matter if the given value is an AudioNode which has been created with standardized-audio-context or not.

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

// This will create a native AudioContext.
const nativeAudioContext = new AudioContext();

isAnyAudioNode(nativeAudioContext.createGain()); // true

// This will create an OfflineAudioContext from standardized-audio-context.
const offlineAudioContext = new OfflineAudioContext({ length: 10, sampleRate: 44100 });

isAnyAudioNode(offlineAudioContext.createGain()); // true

isAnyAudioParam()

This is a helper function similiar to isAnyAudioNode() but for AudioParams. It returns true if the given value is an AudioParam or false in case it isn't. It doesn't matter if the given value is an AudioParam which has been created with standardized-audio-context or not.

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

// This will create a native AudioContext.
const nativeAudioContext = new AudioContext();

isAnyAudioParam(nativeAudioContext.createGain().gain); // true

// This will create an OfflineAudioContext from standardized-audio-context.
const offlineAudioContext = new OfflineAudioContext({ length: 10, sampleRate: 44100 });

isAnyAudioParam(offlineAudioContext.createGain().gain); // true

isAnyOfflineAudioContext()

This is a utility function which determines if the given value is an OfflineAudioContext or not. It does not differentiate between an OfflineAudioContext created by standardized-audio-context or a native one.

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

// This will create an OfflineAudioContext from standardized-audio-context.
const offlineAudioContext = new OfflineAudioContext({ length: 10, sampleRate: 44100 });

isAnyOfflineAudioContext(offlineAudioContext); // true

// This will create a native OfflineAudioContext.
const nativeOfflineAudioContext = new window.OfflineAudioContext(1, 10, 44100);

isAnyOfflineAudioContext(nativeOfflineAudioContext); // true

isSupported()

standardized-audio-context is also exporting a promise which can be accessed by calling isSupported(). This promise resolves to a boolean which indicates if the functionality is supported within the currently used browser. This is not part of the specification.

import { isSupported } from 'standardized-audio-context';

isSupported().then((isSupported) => {
    if (isSupported) {
        // yeah everything should work
    } else {
        // oh no this browser seems to be outdated
    }
});

Browser Support

The goal of this package is to provide a consistent API. But at the same time this package should not grow indefinitely until everything works in IE 6. Whenever a feature is implemented in every supported browser which required a polyfill before to work correctly that polyfill gets removed from this package. And hopefully at some point in the future this package boils down to a file which only re-exports built-in objects.

But until then great care is taken to avoid any unnecessary bloat. This means whenever a workaround for a certain browser is added to this library it will be accompanied by a test which checks that this particular workaround is still needed. I call those tests expectation tests because they test if a browser behaves as expected. An expectation test is designed to fail when the browser eventually ships a fix. Once that happens the workaround and the backing expectation test get removed. The expectation test however gets recycled and will now be used as part of the browser check performed when calling isSupported().

The list of currently supported browsers includes Chrome v81+, Edge v81+, Firefox v70+ and Safari v12.1+. Please note that the tests only run in the current and upcoming version of each browser.

Supporting a browser only means that it is supported on the feature level. It is absolutely possible that a transpiler like Babel is necessary to use this package in every supported browser without encountering any syntax errors.

This package doesn't work with Node.js.

TypeScript

This package is written in TypeScript which means it can be used seamlessly in any TypeScript project. But that is entirely optional.

In contrast to the Web Audio API types that TypeScript provides out of the box the types exported by standardized-audio-context do actually match the concrete implementation. TypeScript generates its types from the Web IDL definition of the Web Audio API which does not always match the actually available implementations.

Tests

All implemented methods are covered by a large number of tests which run in all the browsers mentioned above. Many thanks to BrowserStack and Sauce Labs for allowing this module to be tested with their services.

More Repositories

1

worker-timers

A replacement for setInterval() and setTimeout() which works in unfocused windows.
JavaScript
566
star
2

web-audio-beat-detector

A beat detection utility which is using the Web Audio API.
JavaScript
559
star
3

extendable-media-recorder

An extendable drop-in replacement for the native MediaRecorder.
JavaScript
253
star
4

angular-prerender

A command line tool to prerender Angular Apps.
JavaScript
125
star
5

midi-json-parser

This module is parsing midi files into a human-readable JSON object.
JavaScript
111
star
6

subscribable-things

A collection of reactive wrappers for various browser APIs.
JavaScript
42
star
7

json-midi-encoder

This module encodes a JSON representation of MIDI data into a binary MIDI file.
JavaScript
40
star
8

timing-object

An implementation of the timing object specification.
JavaScript
37
star
9

extendable-media-recorder-wav-encoder

A Wave file encoder for the extendable-media-recorder package.
JavaScript
36
star
10

timingsrc

A library to synchronize a MediaElement with a TimingObject.
JavaScript
31
star
11

timing-provider

An implementation of the timing provider specification.
JavaScript
30
star
12

midi-player

A MIDI player which sends MIDI messages to connected devices.
JavaScript
27
star
13

rxjs-broker

An RxJS message broker for WebRTC DataChannels and WebSockets.
JavaScript
24
star
14

dynamo-converters

A collection of converter functions to get good old JavaScript key/value objects into a DynamoDB friendly schema and back again.
JavaScript
24
star
15

recorder-audio-worklet

This module provides a loader for the RecorderAudioWorkletProcessor and the corresponding RecorderAudioWorkletNode.
JavaScript
24
star
16

angular-audio-context

An Angular wrapper for the Web Audio API's AudioContext.
JavaScript
21
star
17

standardized-audio-context-mock

A mocked version of the standardized-audio-context module.
JavaScript
20
star
18

limiter-audio-worklet

This module provides a loader for the LimiterAudioWorkletProcessor and the corresponding LimiterAudioWorkletNode.
JavaScript
17
star
19

audio-context-timers

A replacement for setInterval() and setTimeout() which works in unfocused windows.
JavaScript
15
star
20

timing-provider-server

A command line tool to spin up a server which can be used with the timing-provider.
JavaScript
15
star
21

video-synchronization-demo

A website to demo usage of the media-sync package with a TimingObject and a TimingProvider.
JavaScript
13
star
22

dynamo-db-local

A wrapper around Amazon's DynamoDB Local to start and stop it from Node.js.
JavaScript
13
star
23

automation-events

A module which provides an implementation of an automation event list.
JavaScript
12
star
24

audio-fingerprinting-file-reader

A reader for files created by audfprint.
JavaScript
11
star
25

web-audio-beat-detector-worker

The worker which is used by the web-audio-beat-detector package.
JavaScript
8
star
26

midi-file-slicer

This module is slicing a midi representation into parts.
JavaScript
7
star
27

web-codecs

A (not yet) extendable and (not yet) complete drop-in replacement for the native WebCodecs API.
JavaScript
7
star
28

limiter-audio-worklet-processor

The AudioWorkletProcessor which is used by the limiter-audio-worklet package.
JavaScript
7
star
29

recorder-audio-worklet-processor

The AudioWorkletProcessor which is used by the recorder-audio-worklet package.
JavaScript
6
star
30

metadata-detector

A tool to locate and strip metadata from files.
JavaScript
6
star
31

midi-json-parser-worker

The worker which is used by the midi-json-parser package.
TypeScript
6
star
32

karma-virtualbox-ie11-launcher

!!! DEPRECATED !!! A Karma launcher for Internet Explorer 11 on VirtualBox.
JavaScript
6
star
33

web-audio-beat-detector-broker

The broker which is used by the web-audio-beat-detector package.
JavaScript
5
star
34

worker-timers-broker

The broker which is used by the worker-timers package.
JavaScript
4
star
35

metadata-detector-streams

A tool to locate and strip metadata from files.
TypeScript
4
star
36

karma-virtualbox-edge-launcher

!!! DEPRECATED !!! A Karma launcher for Edge on VirtualBox.
JavaScript
4
star
37

standardized-audio-context-demo

A demo page to show how to use standardized-audio-context.
JavaScript
4
star
38

timed-audio-buffer-source-node-audio-worklet

This module provides a loader for the TimedAudioBufferSourceNodeAudioWorkletProcessor and the corresponding TimedAudioBufferSourceNodeAudioWorkletNode.
JavaScript
3
star
39

multi-buffer-data-view

A wrapper around the native DataView which can handle multiple ArrayBuffers.
JavaScript
3
star
40

demuxed-2022

My talk at Demuxed 2022.
HTML
3
star
41

worker-timers-worker

The worker which is used by the worker-timers package.
JavaScript
3
star
42

analog4all-client

This is the client for analog4all.
TypeScript
2
star
43

extendable-media-recorder-wav-encoder-worker

The worker which is used by the extendable-media-recorder-wav-encoder package.
JavaScript
2
star
44

web-timing-demo

A website to demo the Web Timing Object.
JavaScript
2
star
45

web-audio-conference-2017

My talk at the Web Audio Conference 2017.
TypeScript
2
star
46

media-encoder-host

This is a module to load and manage media encoders.
JavaScript
2
star
47

fast-unique-numbers

A module to create a set of unique numbers as fast as possible.
JavaScript
2
star
48

json-midi-message-encoder

This module encodes a JSON representation of a MIDI event into a binary MIDI event.
TypeScript
2
star
49

tonejs-synchronization-demo

A website to demo how to connect Tone.js to a Timing Object.
JavaScript
2
star
50

audio-developer-conference-2022

My talk at the Audio Developer Conference in 2022.
TypeScript
2
star
51

broker-factory

A little factory function to create a broker for a JSON-RPC based Web Worker.
JavaScript
2
star
52

analog4all-provider

This is the provider for analog4all.
TypeScript
2
star
53

web-audio-metronome-demo

A website to demo a Web Audio metronome connected to a Web Timing Object.
JavaScript
2
star
54

user-media-audio-visualizer

A super basic visualizer of user media's audio input.
JavaScript
2
star
55

here-maps-type-guards

A guarded version of the TypeScript type definitions for HERE Maps.
TypeScript
2
star
56

create-s3-object-write-stream

Creates a writable stream which uses Amazon's Multipart Upload API under the hood.
JavaScript
2
star
57

rxjs-connector

A module to accept WebRTC DataChannel connections by using WebSockets.
TypeScript
2
star
58

tpac-2022

My talk at the TPAC 2022.
TypeScript
1
star
59

karma-yakbak-preprocessor

!!! DEPRECATED !!! A Karma preprocessor for yakbak.
JavaScript
1
star
60

dynamo-db-provisioner

A lightweight and promise-based wrapper of the AWS SDK to create and delete tables.
JavaScript
1
star
61

worker-factory

A little factory function to create a JSON-RPC based Web Worker implementation.
JavaScript
1
star
62

synchsafe

A module to decode and encode synchsafe integers.
JavaScript
1
star
63

web-audio-meetup-march-2017

My talk at the Web Audio meetup in March 2017.
TypeScript
1
star
64

timed-audio-buffer-source-node-audio-worklet-processor

The AudioWorkletProcessor which is used by the timed-audio-buffer-source-node-audio-worklet package.
JavaScript
1
star
65

tsconfig-holy-grail

This is my personal collection of tsconfig files.
JavaScript
1
star
66

mse-tests

A collection of MSE tests.
JavaScript
1
star
67

web-audio-meetup-may-2019

My talk at the Web Audio meetup in May 2019.
TypeScript
1
star
68

metadata-detector-broker

The broker which is used by the metadata-detector package.
JavaScript
1
star
69

angular-consistent-contenteditable

AngularJS directive to overcome browser inconsisteny when using line breaks in contenteditable.
JavaScript
1
star
70

extendable-media-recorder-wav-encoder-broker

The broker which is used by the extendable-media-recorder-wav-encoder package.
JavaScript
1
star