How to integrate Superpowered

The Superpowered library is designed for application code to be used across multiple platforms. Language specific syntax aside, the API will look mostly the same across platforms and most importantly, Superpowered audio will be absolutely audibly identical across platforms. In other words, your filters and compressors will sound the same, no matter which OS/platform they’re running on.

SDKLanguage

Make sure you're being shown the correct language by toggling the language selector on the top right.

Licensing

The SDK may be evaluated for free, so you can get started with the library and start making some amazing products.

Please see our pricing options to choose the right licensing model and support package for your application and organization.

Javascript introduction

For the purposes of this guide, we'll be using vanilla ES6 Javascript to demonstrate how to get started with the Superpowered SDK. Using Superpowered in Javascript requires the use of WebAssembly to achieve the blazing speed that Superpowered is capable of. Setting up Javascript to handle realtime low latency audio with WebAssembly might be a little outside of what you're used to as it requires thinking about using multiple threads and WebAssembly Linear Memory. Don't worry, we've made it easy to understand.

Please note that setting Superpowered up correctly allows more of the code you write to be transferred between JS and C++ with as few syntax changes as possible.


What is WebAssembly?

WebAssembly is a rapidly evolving technology with great momentum. It allows for high-performance data processing in the browser. In short: what needed to be done in a native app, can now be possible in the browser. We've been able to take the Superpowered C++ SDK and port it to WebAssembly, bring all the great unique features you know and love to the web.

Within the last few years WebAssembly has become very widely supported, to a point where it is now a viable technology to use in production. If you'd like to see the wide range of browsers supported, see here.


What about the Web Audio API?

Superpowered uses the Web Audio API to set up audio I/O in the browser. But the Web Audio API has inconsistencies and slightly different DSP implementations across browsers/devices which mean you can't guarantee your great product will perform and sound identically across devices. One reason why you need Superpowered!

Superpowered runs within the Web Audio API's AudioWorklets, that are scheduled within a standard WebAudio AudioContext and can be used in standard WebAudio API nodes. This means you can leverage API such as getUserMedia and the MediaSourceNode to get live microphone signals into the Superpowered ecosystem. Once within the superpowered ecosystem you can perform all of your processing chain in one AudioWorkletProcessor, or chain multiple AudioWorklet's together in series or parallel.


Loading and serving the library

The Superpowered library is not yet available on NPM, only GitHub.

superpoweredSDK/web-audio-javascript-webassembly-SDK-interactive-audiohttps://github.com/superpoweredSDK/web-audio-javascript-webassembly-SDK-interactive-audio

The Superpowered Javascript SDK

Please download the superpowered library to your computer first.

git clone https://github.com/superpoweredSDK/web-audio-javascript-webassembly-SDK-interactive-audio superpowered

You'll need to both copy the Superpowered library into you Javascript application source code so it can be referenced and bundled by your main application, but you should also make the library available to be served statically and available to your frontend application at runtime. This is because the AudioWorklet processors that we will be writing later we need to be able to import the Superpowered WebAssembly and associated helper files, outside of the scope of your bundled JS application.

The library comprises of a mixture of files to ensure compatibility across browsers. Specifically, we need to offer two versions of classes because some browsers are not able to import ES6 modules at runtime. Within the library download you will find the following files:

FilenamePurpose
superpowered.wasmWebAssembly binary.
SuperpoweredGlue.js
(class SuperpoweredGlue)
The Javascript loader/glue around Superpowered WebAssembly, to be used with importScripts (such as Workers).
SuperpoweredGlueModule.jsSame as above, but for module import.
SuperpoweredWebAudio.js
(class SuperpoweredWebAudio)
Helper to set up Web Audio context.
SuperpoweredTrackLoader.js
(class SuperpoweredTrackLoader)
Helper to load and decode audio in the background, to be used with importScripts.
SuperpoweredTrackLoaderModule.jsSame as above, but for module import.
SuperpoweredTrackLoaderWorker.jsThe Worker used by SuperpoweredTrackLoader.

For the purpose of this guide, we will be making the full library available at http://localhost/static/superpowered/* but is also saved in src/lib/superpowered/* for our main JS application to bundle.


Loading the library

Although Superpowered can be loaded into an existing audio context, we recommend your application's main AudioContext is created by the method we provide in the SuperpoweredGlue helper class. This extended AudioContext offers useful tools to make sure you can get audio in and out of Superpowered efficiently and with ease across browsers. Behind the scenes, you'll still have a standard AudioContext which you can use elsewhere in your application if required.

To load Superpowered into your Javascript application, the following steps should place in order:

  1. Fetch and initialize the Superpowered WebAssembly, pass your license details and functionality requirements into the initialize method. Notice the async nature of the fetch as it's a standard GET request to the URL you supply.
  2. Create an application wide WebAudioManager with the SuperpoweredGlue wrapper, passing in both the required samplerate and the instantiated WebAssembly.

In ES6 Javascript, that looks like this:

import SuperpoweredGlue from './superpowered/SuperpoweredGlueModule';
import { SuperpoweredWebAudio } from './superpowered/SuperpoweredWebAudio';
const wasmPublicLocation = 'http://localhost/static/superpowered/superpowered.wasm'; // This should be publically served from your own location, not bundled.
const minimumSampleRate = 44100;
const superpowered = await SuperpoweredGlue.fetch(wasmPublicLocation);
superpowered.Initialize('ExampleLicenseKey-WillExpire-OnNextUpdate');
const webaudioManager = new SuperpoweredWebAudio(minimumSampleRate, superpowered);

After that, you'll have access to the helper methods under webaudioManager, and the standard AudioContext it sits on will be under webaudioManager.audioContext, with all of the standard WebAudio APIs available such as webaudioManager.audioContext.createGain() or audioEngine.webaudioManager.audioContext.currentTime for example.


Let's make some noise

We're going to keep things simple, so we'll be setting up a Superpowered Generator to create a sine tone, then pass that to the speakers. Make sure you turn down your speakers, unless you have a particular thing for a mathematically perfect A below middle C.

Setting up the required parts

AudioWorkletProcessor script

First, we need to create (and serve up) an AudioWorkletProcessor which will house a Superpowered Generator instance.

AudioWorkletProcessors operate on a separate, real-time audio thread, this is what makes them suitable to feed the audio stack with an uninterrupted and steady flow of data. But because of this, they are isolated and operate outside of the main Javascript thread. They should be fetched by the browser at runtime and cannot be bundled like traditional Javascript files.

// toneProcessor.js
// Import the SuperpoweredWebAudio helper to extend the SuperpoweredWebAudio.AudioWorkletProcessor class.
import { SuperpoweredWebAudio } from '../superpowered/SuperpoweredWebAudio.js';
class ToneProcessor extends SuperpoweredWebAudio.AudioWorkletProcessor {
// Runs after the constructor.
onReady() {
// Create an instance of a SP generator class.
this.generator = new this.Superpowered.Generator(
this.samplerate, // The initial sample rate in Hz. this.samplerate is inherited from the extended SuperpoweredWebAudio.AudioWorkletProcessor class.
this.Superpowered.Generator.Sine // The initial shape.
);
this.generator.frequency = 440; // Generate a simple test tone at A4.
this.genOutputBuffer = new this.Superpowered.Float32Buffer(2048); // An empty array to store the mono output of the generator.
// Pass an event object over to the main scope to tell it everything is ready.
// This is the callback defined as the final argument in webaudioManager.createAudioNodeAsync in the main thread.
// Here we use it to tell the main thread that audio I/O is ready and processing audio.
this.sendMessageToMainScope({ event: 'ready' });
}
// onDestruct is called when the parent destruct() method is called.
// You should clear up all Superpowered object instances here.
onDestruct() {
this.generator.destruct();
this.genOutputBuffer.free();
}
processAudio(inputBuffer, outputBuffer, buffersize, parameters) {
// Generates the next chunk of the sine wave.
this.generator.generate(
this.genOutputBuffer.pointer, // Output, pointer to floating point numbers. 32-bit MONO output.
buffersize // Number of frames.
);
// Next we need to convert the mono output of the generator into the interleaved stereo format that the AudioContext expects.
this.Superpowered.Interleave(
this.genOutputBuffer.pointer, // Left mono input.
this.genOutputBuffer.pointer, // Right mono input.
outputBuffer.pointer, // Stereo output - this is routed to the AudioWorkletProcessor output.
buffersize // Number of frames.
);
}
}
// The following code registers the processor script for the browser, note the label and reference.
if (typeof AudioWorkletProcessor !== 'undefined') registerProcessor('ToneProcessor', ToneProcessor);
export default ToneProcessor;

The AudioWorkletProcessor file(s) will need to be served up to the client side application at runtime, much like the Superpowered WebAssembly library above. For this example we'll have the toneProcessor.js file at http://localhost/static/processors/toneProcessor.js.

Note that the AudioWorkletProcessor is not bundled with your source code and it pulls its own copy of SuperpoweredWebAudio from the statically served Superpowered library files. It's important to understand where files are being served from here.

Main script

Earlier we set up Superpowered and got it initialized in our main Javascript scope. Next we need to load our AudioWorkletProcessor toneProcessor.js into the WebAudio AudioContext to be scheduled.

We've created a handy wrapper function called createAudioNodeAsync for this in the SuperpoweredWebAudio helper class. We pass the location of the processor file (served statically), the name of the processor it gets registered with, and a reference to a function that will handle all incoming messages from the audio thread.

// ... webaudioManager defined above in previous steps
// The location of the processor from the browser to fetch.
const noiseProcessorUrl = 'http://localhost/static/processors/toneProcessor.js'
// Define a handler that will be called whenever this.sendMessageToMainScope is called from the AudioWorkletProcessor scope.
// Remember we called it with a ready event so expect to see it here.
const onMessageProcessorAudioScope = (message) => {
if (message.event === 'ready') {
console.log(message);
}
}
// Now create the AudioWorkletNode, passing in the AudioWorkletProcessor url, its registered name (defined inside the processor) and the message callback.
const generatorProcessorNode = webaudioManager.createAudioNodeAsync(toneProcessorUrl, 'ToneProcessor', onMessageProcessorAudioScope);
// Connect the AudioWorkletNode to the WebAudio destination (main audio output by default, such as your speakers).
generatorProcessorNode.connect(webaudioManager.audioContext.destination);

See it all running

We created an ES6 sandbox with everything all hooked up for you. We'll be using this as the starting point for our guides later on. Fork the code sandbox and have fun!

Edit guide-boilerplate

Code examples

You can find example applications for common Javascript frameworks (React, Angular and Vue) having Superpowered loaded in and ready to roll here:

Now you've Superpowered up and running, so let's start doing some amazing things! Take a look at our guides for help with common tasks and setups you might require for your product:


Native apps introduction

Real-time audio I/O and the overall developer experience can be quite different between the operating systems supported by Superpowered. We provide open-source top level wrappers that iron out most of those differences and provide a near identical API to interact with system audio.

Integration guides

The following integration guides below will help you get off the ground with Superpowered on the various platforms.

Integrate iOSiOS
Integrate AndroidAndroid
Integrate macOSMac
Integrate WindowsWindows
Integrate LinuxLinux

v1.0.6