npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

audio-limiter

v1.2.0

Published

limiter audio worklet node

Downloads

24

Readme

Audio Limiter Node


This library extending built in browser AudioContext and OfflineAudioContext by createLimiter() function.

DEMO PAGE

Installation

npm install audio-limiter

Usage

By calling createLimiter on AudioContext / OffLineAudioContext

import "audio-limiter" 
// call this import in any file on your project 
// recommendation - do it in main file
// this file will patch AudioContext prototype

crateAudio = async () => {
    const context = new AudioContext();
    const buffer = await fetch("./your-audio.mp3")
        .then(response => response.arrayBuffer())
        .then(arrayBuffer => context.decodeAudioData(arrayBuffer); 
    
    const source = context.createBufferSource();
    source.buffer = buffer;

    // and now most important 
    const limiter = await context.createLimiter();
    // connect
    source.connect(limiter)
    limiter.connect(context.destination);
    
    source.start(0);
} 

By creating new instance of LimiterNode

Whats allows connecting node in sync code

import LimiterNode from "audio-limiter"

const context = new AudioContext();
const limiter = new LimiterNode(context, {time: 0.005});
const oscillator = new OscillatorNode(context)
const gain = new GainNode(context);

gain.gain.value = 10; // should be strongly overdrive
oscillator.start(0);

oscillator.connect(gain)
gain.connect(limiter);
limiter.connect(context.destination);

limiter.isReady.then(() => {
    limiter.attack.setValueAtTime(0.1, 10)// set value 100ms in 10 second
    limiter.bypass.setValueAtTime(1, 20)// any not zero value will activate bypass
})

Creating LimiterNode always is asynchronous under the hood. If you need to be shure that everything inside LimiterNode is configured then you can wait for it by calling isReady. This will return Promise witch will be resolved when limiter worklet will be connected. before that LimiterNode is bypassed. But you don't have to wait to make you connections with other AudioNodes.

const context = new AudioContext();
const limiter = new LimiterNode(context)
await limiter.isReady;
// now signal is processed

Configuration

Time - [in seconds] - Latency time witch limiter will delay output. Any non zero attack/release time will lag envelope behind current processed audio. To attenuate right part of signal this limiter implements delay buffer. This value should be minium equal to attack time. If value of time will be less that attack then limiter will act on the past envelope change. By default value is 5ms. This means that audio is delayed by 5 ms and in this range is analyzed envelope.

const context = new OfflineAudioContext(OfflineAudioContextOptions)
//time - min: 0, max: 10s
const limiter = await context.createLimiter({time: 0.005})

Number of channels - default value is 2. you can change it by define it.

const context = new OfflineAudioContext(OfflineAudioContextOptions)
const limiter = await context.createLimiter({
        channelCount: 1, 
        time: 0.005 // 5ms
    })

Predefined configs that you can't change

const limiter = await context.createLimiter({
        channelCountMode: "explicit" 
        numberOfInputs: 1,
        numberOfOutputs: 1
    })

Parameters

import LimiterNode from "audio-limiter"
//static getter will return list of aviable parameters
LimiterNode.parametersList: {
    name: string, 
    minValue: number, 
    maxValue: number, 
    defaultValue: number
}[] 

Attack - [in seconds] defining how quickly the detection responds to rising amplitudes.

const limiter = await context.createLimiter();
//by access params map

const attack = limiter.parameters.get("attack");

attack.value = .001// 1ms - by default 0
attack.setValueAtTime(0.001, context.currentTime);

//or by shortcut getter 
limiter.attack.setValueAtTime(.001, context.currentTime)
limiter.attack.minValue // 0
limiter.attack.maxValue // 2s
limiter.attack.defaultValue // 0

Release - [in seconds] - defining how quickly the detection responds to falling amplitudes.

limiter.parameters.get("release").setValueAtTime(.001, context.currentTime)
//or
limiter.release.setValueAtTime(.001, context.currentTime)
limiter.release.minValue // 0
limiter.release.maxValue // 2
limiter.release.defaultValue // 0.1 - 100 ms

Threshold - [in dB] - level to witch will be limiting audio. Be default is -2dB this means that max amplitude value will be ~0.79... Set it to 0 if you expect sample value +- 1.

limiter.threshold.setValueAtTime(2, 0);
limiter.threshold.minValue // -100
limiter.threshold.maxValue // 0
limiter.threshold.defaultValue // -2dB

Pre Gain - [in dB] - just like apply gain before limiter node. can be useful in kind of normalization process.

limiter.preGain.setValueAtTime(2, 0);
limiter.preGain.minValue // -100
limiter.preGain.maxValue // 100
limiter.preGain.defaultValue // 0 dB

Post Gain - [in dB] - post limiting gain. Be careful if you expect not clipping data. If you set threshold -2dB then max post gain can be set to +2dB.

limiter.postGain.setValueAtTime(2, 0);
limiter.postGain.minValue // -100
limiter.postGain.maxValue // 100
limiter.postGain.defaultValue // 0 dB

Bypass - [boolean number] - Every value other than 0 is tracked as truth. If you pass truthy value to bypass param then signal will not be limited. But, delay buffer will still by the same.

limiter.bypass.setValueAtTime(1, 0);
limiter.bypass.minValue // 0
limiter.bypass.maxValue // 1
limiter.bypass.defaultValue // 0

What if I don't want modify AudioContext prototype ??

No problem. Don't import main library file. Just register limiter worklet processor and add module. You fill find it in library dist folder.

const context = new AudioContext();
const path = [
    "node_models",
    "limiter-audio-node",
    "dist",
    "limiter-audio-worklet-processor.js"
].join("/");

await context.audioWorklet.addMode(path);
const limiter = new LimiterAudioWorkletNode(context, 'limiter-processor', options);

Stack

Built with:

  • TypeScript
  • Webpack 5

Test:

  • Karma
  • Jasmine

MIT