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

@ng-web-apis/audio

v4.11.1

Published

This is a library for declarative use of Web Audio API with Angular

Downloads

411

Readme

ng-web-apis logo Web Audio API for Angular

npm version npm bundle size codecov

This is a library for declarative use of Web Audio API with Angular 7+. It is a complete conversion to declarative Angular directives, if you find any inconsistencies or errors, please file an issue. Watch out for 💡 emoji in this README for additional features and special use cases.

How to use

After you installed the package, you must add @ng-web-apis/audio/polyfill to your polyfills.ts. It is required to normalize things like webkitAudioContext, otherwise your code would fail.

You can build audio graph with directives. For example, here's a typical echo feedback loop:

<audio
  src="/demo.wav"
  waMediaElementAudioSourceNode
>
  <ng-container
    #node="AudioNode"
    waDelayNode
    [delayTime]="delayTime"
  >
    <ng-container
      waGainNode
      [gain]="gain"
    >
      <ng-container [waOutput]="node"></ng-container>
      <ng-container waAudioDestinationNode></ng-container>
    </ng-container>
  </ng-container>
  <ng-container waAudioDestinationNode></ng-container>
</audio>

💡 AudioBufferService

This library has AudioBufferService with fetch method, returning Promise which allows you to easily turn your hosted audio file into AudioBuffer through GET requests. Result is stored in service's cache so same file is not requested again while application is running.

This service is also used within directives that have AudioBuffer inputs (such as AudioBufferSourceNode or ConvolverNode) so you can just pass string URL, as well as an actual AudioBuffer. For example:

<button
  #source="AudioNode"
  buffer="/demo.wav"
  waAudioBufferSourceNode
  (click)="source.start()"
>
  Play
  <ng-container waAudioDestinationNode></ng-container>
</button>

Supported nodes

You can use following audio nodes through directives of the same name (prefixed with wa standing for Web API):

Terminal nodes

Sources

Processors

AudioWorkletNode

You can use AudioWorkletNode in supporting browsers. To register your AudioWorkletProcessors in a global default AudioContext you can use tokens:

@NgModule({
  bootstrap: [AppComponent],
  declarations: [AppComponent],
  providers: [
    {
      provide: AUDIO_WORKLET_PROCESSORS,
      useValue: 'assets/my-processor.js',
      multi: true,
    },
  ],
})
export class AppModule {}
@Component({
  selector: 'app',
  templateUrl: './app.component.html',
})
export class App {
  constructor(@Inject(AUDIO_WORKLET_PROCESSORS_READY) readonly processorsReady: Promise<boolean>) {}

  // ...
}

You can then instantiate your AudioWorkletNode:

<ng-container
  *ngIf="processorsReady | async"
  waAudioWorkletNode
  name="my-processor"
>
  <ng-container waAudioDestinationNode></ng-container>
</ng-container>

If you need to create your own node with custom AudioParam and control it declaratively you can extend WebAudioWorklet class and add audioParam decorator to new component's inputs:

@Directive({
  selector: '[my-worklet-node]',
  exportAs: 'AudioNode',
  providers: [asAudioNode(MyWorklet)],
})
export class MyWorklet extends WebAudioWorklet {
  @Input()
  @audioParam()
  customParam?: AudioParamInput;

  constructor(
    @Inject(AUDIO_CONTEXT) context: BaseAudioContext,
    @SkipSelf() @Inject(AUDIO_NODE) node: AudioNode | null,
  ) {
    super(context, node, 'my-processor');
  }
}

💡 AudioParam

Since work with AudioParam is imperative in its nature, there are difference to native API when working with declarative inputs and directives.

NOTE: You can always access directives through template reference variables / @ViewChild and since they extend native nodes work with AudioParam in traditional Web Audio fashion

AudioParam inputs for directives accept following arguments:

  • number to set in instantly, equivalent to setting AudioParam.value

  • AudioParamCurve to set array of values over given duration, equivalent to AudioParam.setValueCurveAtTime called with AudioContext.currentTime

    export type AudioParamCurve = {
        readonly value: number[];
        readonly duration: number;
    }
  • AudioParamAutomation to linearly or exponentially ramp to given value starting from AudioContext.currentTime

    export type AudioParamAutomation = {
        readonly value: number;
        readonly duration: number;
        readonly mode: 'instant' | 'linear' | 'exponential';
    };
  • AudioParamAutomation[] to schedule multiple changes in value, stacking one after another

You can use waAudioParam pipe to turn your number values into AudioParamAutomation (default mode is exponential, so last argument can be omitted) or number arrays to AudioParamCurve (second argument duration is in seconds):

<ng-container
  waGainNode
  gain="0"
  [gain]="gain | waAudioParam : 0.1 : 'linear'"
></ng-container>

This way values would change smoothly rather than abruptly, causing audio artifacts.

NOTE: You can set initial value for AudioParam through argument binding combined with dynamic property binding as seen above.

To schedule an audio envelope looking something like this:

Envelope

You would need to pass the following array of AudioParamAutomation items:

const envelope = [
  {
    value: 0,
    duration: 0,
    mode: 'instant',
  },
  {
    value: 1,
    duration: ATTACK_TIME,
    mode: 'linear',
  },
  {
    value: SUS,
    duration: DECAY_TIME,
    mode: 'linear',
  },
  {
    value: SUS,
    duration: SUSTAIN_TIME,
    mode: 'instant',
  },
  {
    value: 0,
    duration: RELEASE_TIME,
    mode: 'exponential',
  },
];

💡 Special cases

<!-- Inverting left and right channel -->
<audio
  src="/demo.wav"
  waMediaElementAudioSourceNode
>
  <ng-container waChannelSplitterNode>
    <ng-container [waOutput]="right"></ng-container>
    <ng-container [waOutput]="left"></ng-container>
  </ng-container>
  <ng-container waChannelMergerNode>
    <ng-container
      #left="AudioNode"
      waChannel
    ></ng-container>
    <ng-container
      #right="AudioNode"
      waChannel
    ></ng-container>
    <ng-container waAudioDestinationNode></ng-container>
  </ng-container>
</audio>

💡 Tokens

Browser support

| | | | | | :-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | | 12+ | 31+ | 34+ | 9+ |

Note that some features (AudioWorklet etc.) were added later and are supported only by more recent versions

IMPORTANT: You must add @ng-web-apis/audio/polyfill to your polyfills.ts, otherwise you will get ReferenceError: X is not defined in browsers for entities they do not support

💡 StereoPannerNode is emulated with PannerNode in browsers that do not support it yet

💡 positionX (orientationX) and other similar properties of AudioListener and PannerNode fall back to setPosition (setOrientation) method if browser does not support it

Angular Universal

If you want to use this package with SSR, you need to mock native Web Audio API classes on the server:

import '@ng-web-apis/audio/mocks';

It is recommended to keep the import statement at the top of your server.ts or main.server.ts file.

Demo

You can try online demo here

See also

Other Web APIs for Angular by @ng-web-apis