High-resolution real-time graphic audio spectrum analyzer JavaScript module with no dependencies.
This is the graphic spectrum analyzer I originally wrote for audioMotion, here in a standalone module for you to use in your own JavaScript projects.
- High-resolution (retina / HiDPI ready) real-time audio spectrum analyzer with fullscreen support
- Logarithmic frequency scale with customizable range
- 10 visualization modes: choose between discrete frequencies or octave bands based on the equal tempered scale
- Optional vintage LED effect and variable luminance bars for octave bands modes
- Customizable Web Audio API parameters: FFT size, sensitivity and time-smoothing constant
- Comes with 3 predefined color gradients - easily add your own!
- No dependencies, less than 20kB minified
Install with npm:
$ npm install audiomotion-analyzer
ES6 import:
import AudioMotionAnalyzer from 'audiomotion-analyzer';
Minimal constructor:
const audioMotion = new AudioMotionAnalyzer(
document.getElementById('container'),
{
source: document.getElementById('audio')
}
);
This will insert the analyzer canvas inside the #container element and start the visualization of audio coming from the #audio element.
new AudioMotionAnalyzer( [container], [{options}] )
Creates a new instance of audioMotion-analyzer. A canvas element will be created and inserted into the container
element. If container
is undefined, the canvas is appended to the document's body.
Available options with default values shown inside parentheses:
options = {
audioCtx: AudioContext object,
barSpace: number (2),
fftSize: number (8192),
fillAlpha: number (1),
gradient: string ('classic'),
height: number,
lineWidth: number (0),
loRes: boolean (false),
lumiBars: boolean (false),
maxDecibels: number (-25),
maxFreq: number (22000),
minDecibels: number (-85),
minFreq: number (20),
mode: number (0),
onCanvasDraw: function,
onCanvasResize: function,
showBgColor: boolean (true),
showFPS: boolean (false),
showLeds: boolean (false),
showPeaks: boolean (true),
showScale: boolean (true),
smoothing: number (0.5),
source: HTMLMediaElement,
start: boolean (true),
width: number
}
audioCtx
allows you to provide an external AudioContext object, but you usually don't need to specify this, as audioMotion-analyzer will create its own.
If source
is specified, the provided media element will be connected to the analyzer. You can later disconnect it by referring to the audioSource
object.
At least one audio source is required for the analyzer to work. You can also connect audio sources with the connectAudio()
method.
If start: false
is specified, the analyzer will be created stopped. You can then start it with the toggleAnalyzer()
method.
analyzer
AnalyserNode object
Connect any additional audio sources to this object, so their output is displayed in the graphic analyzer.
audioCtx
AudioContext object
AudioContext object created by audioMotion-analyzer or provided by the user in the constructor options.
Use this object to create additional audio sources to be connected to the analyzer, like oscillator nodes, gain nodes and media streams.
The code fragment below creates an oscillator and a gain node using audioMotion's audioContext, and then connects them to the analyzer:
const audioMotion = new AudioMotionAnalyzer( document.getElementById('container') ),
audioCtx = audioMotion.audioCtx,
oscillator = audioCtx.createOscillator(),
gainNode = audioCtx.createGain();
oscillator.frequency.setValueAtTime( 440, audioCtx.currentTime ); // play 440Hz tone
oscillator.connect( gainNode );
gainNode.gain.setValueAtTime( .5, audioCtx.currentTime );
gainNode.connect( audioMotion.analyzer );
oscillator.start();
audioSource
MediaElementAudioSourceNode object
Object representing the HTML media element connected using the source
property in the class constructor options. See also the connectAudio()
method.
Canvas element created by audioMotion.
2D rendering context for drawing in audioMotion's canvas.
Available since v2.0.0
Customize the spacing between bars in octave bands modes.
Use a value between 0 and 1 for spacing proportional to the bar width. Values >= 1 will be considered as a literal number of pixels.
For example, barSpace = 0.5
will use half of the bar width for spacing, while barSpace = 2
will set a fixed spacing of 2 pixels, independent of the width of bars.
Prefer proportional spacing to obtain consistent results among different resolutions and screen sizes.
barSpace = 0
will effectively show contiguous bars, except when the LED effect is on, in which case a minimum spacing is enforced.
Defaults to 0.1.
dataArray
UInt8Array array (Read only)
Data array returned by the analyzer's getByteFrequencyData()
.
Array size is half the current FFT size, with element values ranging from 0 to 255.
Each array element represents a specific value in the frequency domain, such that: frequency = i * audioCtx.sampleRate / fftSize
, where i is the array index.
The data is updated on every animation frame (ideally 60 times per second).
Number of samples used for the FFT performed by the analyzer node. It must be a power of 2 between 32 and 32768, so valid values are: 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, and 32768.
Higher values provide more detail in the frequency domain, but less detail in the time domain. Defaults to 8192.
Available since v2.0.0
Opacity for the Line / Area graph mode. Must be a float between 0 (completely transparent) and 1 (completely opaque).
Defaults to 1.
See also lineWidth
.
Current frame rate.
Canvas dimensions used during fullscreen mode. These take the current pixel ratio into account and will change accordingly when low-resolution mode is set.
Currently selected gradient. gradient must be the name of a built-in or registered gradient. Built-in gradients are 'classic', 'prism' and 'rainbow'. Defaults to 'classic'.
Nominal dimensions of the analyzer.
If one or both of these are undefined
, the analyzer will try to adjust to the container's width and/or height.
If the container's width and/or height are 0 (inline elements), a reference size of 640 x 270 pixels will be used to replace the missing dimension(s).
This should be considered the minimum dimensions for proper visualization of all available modes with the LED effect on.
You can set both values at once using the setCanvasSize()
method.
If you want the actual canvas dimensions, use audioMotion.canvas.width
and audioMotion.canvas.height
.
true when the analyzer is being displayed in fullscreen, or false otherwise.
true if the analyzer canvas animation is running, or false if it's stopped.
Available since v2.0.0
Line width for the Line / Area graph mode.
Defaults to 0. For the line to be distinguishable, set also fillAlpha
< 1.
true for low resolution mode. Defaults to false.
Low resolution mode halves the effective pixel ratio, resulting in four times less pixels to render. This may improve performance significantly, especially in 4K+ monitors.
If you plan on allowing users to interactively toggle low resolution mode, you may need to set a fixed size for the canvas via CSS, like so:
#container canvas {
width: 100%;
}
This will prevent the canvas size from changing, when switching the low resolution mode on and off.
Available since v1.1.0
true to always display full-height bars and vary their luminance instead. Only effective for visualization modes 1 to 8 (octave bands). Defaults to false.
Highest and lowest decibel values represented in the Y-axis of the analyzer. The loudest volume possible is 0.
maxDecibels defaults to -25 and minDecibels defaults to -85.
You can set both values at once using the setSensitivity()
method.
For more info, see AnalyserNode.minDecibels.
Highest and lowest frequencies represented in the X-axis of the analyzer. Values in Hertz. maxFreq defaults to 22000 and minFreq defaults to 20.
The minimum allowed value is 1. Trying to set a lower value will throw an error.
The maximum practical value is half the sampling rate (audioCtx.sampleRate
), although this is not enforced by audioMotion-analyzer.
It is preferable to use the setFreqRange()
method and set both values at once, to prevent minFreq
being higher than the current maxFreq
or vice-versa at a given moment.
Current visualization mode.
- Discrete frequencies mode provides the highest resolution, allowing you to visualize individual frequencies provided by the FFT;
- Octave bands modes display wider vertical bars, each one representing the nth part of an octave, based on a 24-tone equal tempered scale;
- Line / Area graph mode uses the discrete frequencies data to draw a filled shape and/or a continuous line (see
fillAlpha
andlineWidth
properties).
Valid values are:
Value | Mode | Available since |
---|---|---|
0 | Discrete frequencies | |
1 | 1/24th octave bands | |
2 | 1/12th octave bands | |
3 | 1/8th octave bands | |
4 | 1/6th octave bands | |
5 | 1/4th octave bands | |
6 | 1/3rd octave bands | |
7 | half octave bands | |
8 | full octave bands | |
9 | reserved (not valid) | |
10 | Line / Area graph | v1.1.0 |
Defaults to 0.
Current devicePixelRatio. This is usually 1 for standard displays and 2 for retina / Hi-DPI screens.
You can refer to this value to adjust any additional drawings done in the canvas (via callback function).
When low-resolution mode is active pixelRatio is halved, i.e. 0.5 for standard displays and 1 for retina / Hi-DPI.
true to use background color defined by current gradient; false for black background. Defaults to true.
true to display the current frame rate. Defaults to false.
true to activate LED display effect. Only effective for visualization modes 1 to 8 (octave bands). Defaults to false.
true to show amplitude peaks for each frequency. Defaults to true.
true to display frequency labels in the X axis. Defaults to true.
Sets the analyzer's smoothingTimeConstant. value must be a float between 0 and 1.
Lower values make the analyzer respond faster to changes. Defaults to 0.5.
Available since v2.0.0
Returns the current version of audioMotion-analyzer.
If defined, this function will be called after rendering each frame.
The audioMotion object will be passed as an argument to the callback function.
Example usage:
const audioMotion = new AudioMotionAnalyzer(
document.getElementById('container'),
{
source: document.getElementById('audio'),
onCanvasDraw: displayCanvasMsg
}
);
function displayCanvasMsg( instance ) {
let size = 20 * instance.pixelRatio;
if ( instance.isFullscreen )
size *= 2;
// find the data array index for 140Hz
const idx = Math.round( 140 * instance.analyzer.fftSize / instance.audioCtx.sampleRate );
// use the 140Hz amplitude to increase the font size and make the logo pulse to the beat
instance.canvasCtx.font = `${size + instance.dataArray[ idx ] / 16 * instance.pixelRatio}px Orbitron,sans-serif`;
instance.canvasCtx.fillStyle = '#fff8';
instance.canvasCtx.textAlign = 'center';
instance.canvasCtx.fillText( 'audioMotion', instance.canvas.width - size * 8, size * 2 );
}
If defined, this function will be called whenever the canvas is resized.
Two arguments are passed: a string with the reason why the function was called (see below) and the audioMotion object.
Reason | Description |
---|---|
'create' |
canvas created by the class constructor |
'fschange' |
analyzer entered or left fullscreen mode |
'lores' |
low resolution mode toggled on or off |
'resize' |
browser window resized (only when width and/or height are undefined) |
'user' |
canvas dimensions changed by user script, via height and width properties, setCanvasSize() or setOptions() methods |
Example usage:
const audioMotion = new AudioMotionAnalyzer(
document.getElementById('container'),
{
source: document.getElementById('audio'),
onCanvasResize: ( reason, instance ) => {
console.log( `[${reason}] set: ${instance.width} x ${instance.height} | actual: ${instance.canvas.width} x ${instance.canvas.height}` );
}
}
);
Connects an HTMLMediaElement (<audio>
or <video>
HTML element) to the analyzer.
Returns a MediaElementAudioSourceNode which can be used for later disconnection.
For connecting other audio sources, like oscillators and streams, use the audioCtx
and analyzer
objects.
Registers a custom color gradient.
name
must be a non-empty string that will be used when setting the gradient
property. options
must be an object as shown below:
const options = {
bgColor: '#111', // background color (required)
dir: 'h', // add this to create a horizontal gradient (optional)
colorStops: [ // list your gradient colors in this array (at least 2 entries are required)
'red', // colors may be defined in any CSS valid format
{ pos: .6, color: '#ff0' }, // use an object to adjust the position (0 to 1) of a color
'hsl( 120, 100%, 50% )' // colors may be defined in any CSS valid format
]
}
audioMotion.registerGradient( 'my-grad', options );
Additional information about gradient color-stops.
Sets the analyzer nominal dimensions in pixels. See height
and width
properties for details.
Sets the desired frequency range. Values are expressed in Hz (Hertz).
Shorthand method for setting several options at once.
options
is an object with the same structure used in the class constructor, except for the audioCtx
and source
options which are only available at construction time.
Adjust the analyzer's sensitivity. See maxDecibels
and minDecibels
properties.
Starts (true) or stops (false) the analyzer animation. If no argument provided, inverts the current status. Returns the resulting status.
The analyzer is started by default upon object construction, unless you specify start: false
in the options.
Toggles fullscreen mode. As per API specification, fullscreen requests must be triggered by user activation, so you must call this function from within an event handler or otherwise the request will be denied.
Available since v2.0.0
audioMotion-analyzer uses a custom error object to throw errors for some critical operations.
The code
property is a string label that can be checked to identify the specific error in a reliable way.
code |
Error description |
---|---|
ERR_AUDIO_CONTEXT_FAIL | Could not create audio context. The user agent may lack support for the Web Audio API. |
ERR_INVALID_AUDIO_CONTEXT | Audio context provided by user is not valid. |
ERR_INVALID_MODE | User tried to set the visualization mode to an invalid value. |
ERR_FREQUENCY_TOO_LOW | User tried to set the minFreq or maxFreq properties to a value lower than 1. |
ERR_GRADIENT_INVALID_NAME | The name parameter for registerGradient() must be a non-empty string. |
ERR_GRADIENT_NOT_AN_OBJECT | The options parameter for registerGradient() must be an object. |
ERR_GRADIENT_MISSING_COLOR | The options parameter for registerGradient() must define at least two color-stops. |
ERR_UNKNOWN_GRADIENT | User tried to select a gradient not previously registered. |
audioMotion-analyzer copyright (c) 2018-2020 Henrique Avila Vianna
Licensed under the GNU Affero General Public License, version 3 or later.