This is the main object you use to interact with the waveform data. It provides access to the waveform data points and allows you to resample the data to display the waveform at zoom levels or fit to a given width.
It also allows you to create waveform data from audio content using the Web Audio API.
Use the following code to import it:
import WaveformData from 'waveform-data';Creates and returns a WaveformData instance from the given
data, which may be in binary (.dat) format in an
ArrayBuffer,
or a JavaScript object. Refer to the
data format documentation
for details.
| Name | Type |
|---|---|
data |
ArrayBuffer |
To create a WaveformData object from binary waveform data
(.dat format):
fetch('http://example.com/waveforms/track.dat')
.then(response => response.arrayBuffer())
.then(buffer => WaveformData.create(buffer))
.then(waveform => {
console.log(`Waveform has ${waveform.channels} channels`);
console.log(`Waveform has length ${waveform.length} points`);
});To create a WaveformData object from JSON format waveform
data:
fetch('http://example.com/waveforms/track.json')
.then(response => response.json())
.then(json => WaveformData.create(json))
.then(waveform => {
console.log(`Waveform has ${waveform.channels} channels`);
console.log(`Waveform has length ${waveform.length} points`);
});Note that previous (v1.x) versions of waveform-data.js would accept JSON strings as input, but this is not supported from v2.0 onwards.
Creates a WaveformData object from audio using the Web
Audio API.
| Name | Type |
|---|---|
options |
Object (see below) |
callback |
Function |
| Name | Type | Description |
|---|---|---|
array_buffer |
ArrayBuffer |
Contains encoded audio. If using this option, an audio_context is also required |
audio_buffer |
AudioBuffer |
Contains decoded audio. If using this option, an audio_context is not required |
audio_context |
AudioContext |
When using the array_buffer option to provide encoded audio, this should be a Web Audio AudioContext object, which will be used to decode the audio. Not required otherwise |
scale |
Number (integer, default: 512) |
Controls the resolution of the waveform data by specifying the number of input audio samples per output waveform data point |
bits |
Number (integer, default: 8) |
Sets the number of bits to use for output waveform data points. Valid values are either 8 or 16 |
amplitude_scale |
Number (default: 1.0) |
Applies amplitude scaling to the waveform data. For example, set to 2.0 to double the waveform amplitude |
split_channels |
Boolean (default: false) |
Set to true to produce separate waveform channels instead of combining all channels into a single waveform |
disable_worker |
Boolean (default: false) |
Set to true to disable use of a Web Worker |
To create a WaveformData object from audio content in an
ArrayBuffer:
const audioContext = new AudioContext();
fetch('https://example.com/audio/track.ogg')
.then(response => response.arrayBuffer())
.then(buffer => {
const options = {
audio_context: audioContext,
array_buffer: buffer,
scale: 512
};
WaveformData.createFromAudio(options, (err, waveform) => {
if (err) {
console.error(err);
return;
}
console.log(`Waveform has ${waveform.channels} channels`);
console.log(`Waveform has length ${waveform.length} points`);
});
});To create a WaveformData object from an
AudioBuffer:
const audioContext = new AudioContext();
const sampleRate = audioContext.sampleRate;
const audioBuffer = audioContext.createBuffer(2, sampleRate * 4, sampleRate);
// TODO: Fill audioBuffer with audio content (4 seconds)
const options = {
audio_buffer: audioBuffer
};
WaveformData.createFromAudio(options, (err, waveform) => {
if (err) {
console.error(err);
return;
}
console.log(`Waveform has ${waveform.channels} channels`);
console.log(`Waveform has length ${waveform.length} points`);
});To create a WaveformData object with multi-channel waveform
data:
const audioContext = new AudioContext();
fetch('https://example.com/audio/track.ogg')
.then(response => response.arrayBuffer())
.then(buffer => {
const options = {
audio_context: audioContext,
array_buffer: buffer,
scale: 512,
split_channels: true
};
WaveformData.createFromAudio(options, (err, waveform) => {
if (err) {
console.error(err);
return;
}
console.log(`Waveform has ${waveform.channels} channels`);
console.log(`Waveform has length ${waveform.length} points`);
});
});To create a WaveformData object without using a web worker,
set the disable_worker option to true. Waveform data is created in two steps:
-
If you pass an
ArrayBuffercontaining encoded audio, the audio is decoded using the Web Audio API's decodeAudioData method. This must done on the browser's UI thread, so will be a blocking operation. -
The decoded audio is processed to produce the waveform data. To avoid further blocking the browser's UI thread, by default this step is done using a Web Worker, if supported by the browser. You can disable the worker and run the processing in the main thread by setting
disable_workertotruein the options.
const audioContext = new AudioContext();
fetch('https://example.com/audio/track.ogg')
.then(response => response.arrayBuffer())
.then(buffer => {
const options = {
audio_context: audioContext,
array_buffer: buffer,
scale: 512,
disable_worker: true
};
WaveformData.createFromAudio(options, (err, waveform) => {
if (err) {
console.error(err);
return;
}
console.log(`Waveform has ${waveform.channels} channels`);
console.log(`Waveform has length ${waveform.length} points`);
});
});Returns the sample rate of the original audio, in Hz.
const waveform = WaveformData.create(buffer);
console.log(waveform.sample_rate); // -> 44100Returns the number of audio samples per pixel of the waveform data. This gives an indication of the zoom level (higher numbers mean lower resolution, i.e., more zoomed out).
const waveform = WaveformData.create(buffer);
console.log(waveform.scale); // -> 512Returns the amount of time (in seconds) represented by a single pixel.
const waveform = WaveformData.create(buffer);
console.log(waveform.seconds_per_pixel); // -> 0.010666666666666666Returns the number of pixels per second.
const waveform = WaveformData.create(buffer);
console.log(waveform.pixels_per_second); // -> 93.75Returns the length of the waveform data, in pixels.
const waveform = WaveformData.create(buffer);
console.log(waveform.length); // -> 1000Returns the approximate duration of the audio file, in seconds.
The duration is approximate because it is calculated based on the waveform length, number of samples per pixel, and audio sample rate.
const waveform = WaveformData.create(buffer);
console.log(waveform.duration); // -> 10.32Returns the number of bits per sample, either 8 or 16.
const waveform = WaveformData.create(buffer);
console.log(waveform.bits); // -> 8Returns the pixel index for a given time.
| Name | Type |
|---|---|
time |
Number (seconds) |
const waveform = WaveformData.create(buffer);
console.log(waveform.at_time(0.116)); // -> 10Returns the time in seconds for a given pixel index.
| Name | Type |
|---|---|
index |
Number (integer) |
const waveform = WaveformData.create(buffer);
console.log(waveform.time(10)); // 0.116Returns the number of waveform channels.
Note: by default, audiowaveform
combines all audio channels into a single channel waveform. Use the
--split-channels command-line option if you want multi-channel waveforms.
const waveform = WaveformData.create(buffer);
console.log(waveform.channels); // 1Returns a WaveformDataChannel object that provides
access to the waveform data for the given channel index.
| Name | Type |
|---|---|
index |
Number (integer) |
const waveform = WaveformData.create(buffer);
for (let i = 0; i < waveform.channels; i++) {
const channel = waveform.channel(i);
}Creates and returns a new WaveformData object with resampled
data. Use this method to create waveform data at different zoom levels.
| Name | Type |
|---|---|
| options | Object (see below) |
| Name | Type |
|---|---|
width |
Number (integer) |
scale |
Number (integer) |
To resample the waveform to fit to a specific width:
const waveform = WaveformData.create(buffer);
console.log(waveform.length); // -> 1000
const resampledWaveform = waveform.resample({ width: 500 });
console.log(resampledWaveform.length); // -> 500To resample the waveform to a specific zoom level, in samples per pixel:
const waveform = WaveformData.create(buffer);
const scale = waveform.scale; // -> 512
const resampledWaveform = waveform.resample({ scale: scale * 2 });
console.log(resampledWaveform.scale); // -> 1024Note that you cannot resample to a lower number of samples per pixel than the original waveform.
const waveform = WaveformData.create(buffer);
const scale = waveform.scale; // -> 512
const resampledWaveform = waveform.resample({ scale: scale / 2 }); // throws an ErrorConcatenates the receiver with one or more other waveforms, returning a new
WaveformData object.
The waveforms all have the same sample rate, scale, and number of channels.
| Name | Type |
|---|---|
| ...waveforms | One or more WaveformData instances |
To combine three waveforms into one long one:
const wave1 = WaveformData.create(buffer1);
const wave2 = WaveformData.create(buffer2);
const wave3 = WaveformData.create(buffer3);
const combinedResult = wave1.concat(wave2, wave3);
console.log(wave1.length); // -> 500
console.log(wave2.length); // -> 300
console.log(wave3.length); // -> 100
console.log(combinedResult.length); // -> 900Returns a subset of the waveform data between a given start and end point.
| Name | Type |
|---|---|
options |
An object containing either startIndex and endIndex values, which give the start and end indexes in the waveform data, or startTime and endTime, which give the start and end times (in seconds) |
To return the waveform between index 100 and index 200:
const waveform = WaveformData.create(buffer);
const slice = waveform.slice({ startIndex: 100, endIndex: 200 });
console.log(slice.length); // -> 100To return the waveform between 1.0 and 2.0 seconds:
const waveform = WaveformData.create(buffer);
const slice = waveform.slice({ startTime: 1.0, endTime: 2.0 });
console.log(slice.length); // -> 86Returns an object containing the waveform data. This means you can use JSON.stringify() to produce a JSON string representation of the waveform data.
const waveform = WaveformData.create(buffer);
console.log(waveform.toJSON());
// { version: 2, channels: 1, sample_rate: 44100, samples_per_pixel: 512,
// bits: 8, length: 4, data: [0, 0, -1, 1, -2, 2, -3, 3] }
console.log(JSON.stringify(waveform));
// '{"version":2,"channels":1,"sample_rate":44100,"samples_per_pixel":512,
// "bits":8,"length":4,"data":[0,0,-1,1,-2,2,-3,3]}'Returns an object containing the waveform data in binary format.
WaveformData.createFromAudio(buffer, function(err, waveformData) {
const waveformData = waveform.toArrayBuffer();
console.log(waveformData);
// ArrayBuffer {
// [Uint8Contents]: <02 00 00 00 01 00 00 00 44 68 AC 00 00 80 00 00 00 65 14 etc.>,
// byteLength: 20908
// }
});A WaveformDataChannel object allows you to access the waveform data point values.
Returns the waveform minimum at the given index position.
| Name | Type |
|---|---|
index |
Number (integer) |
const waveform = WaveformData.create(buffer);
const channel = waveform.channel(0);
for (let i = 0; i < waveform.length; i++) {
const time = waveform.time(i);
const min = channel.min_sample(i);
const max = channel.max_sample(i);
console.log(time, min, max);
}Returns the waveform maximum at the given index position.
| Name | Type |
|---|---|
index |
Number (integer) |
const waveform = WaveformData.create(buffer);
const channel = waveform.channel(0);
for (let i = 0; i < waveform.length; i++) {
const time = waveform.time(i);
const min = channel.min_sample(i);
const max = channel.max_sample(i);
console.log(time, min, max);
}Returns a copy of the waveform minimum values as an array.
const waveform = WaveformData.create(buffer);
const channel = waveform.channel(0);
console.log(waveform.length); // -> 3
const min = channel.min_array(); // -> [-7, -5, -10]
for (let i = 0; i < waveform.length; i++) {
console.log(min[i]);
}Returns a copy of the waveform maximum values as an array.
const waveform = WaveformData.create(buffer);
const channel = waveform.channel(0);
console.log(waveform.length); // -> 3
const max = channel.max_array(); // -> [7, 5, 10]
for (let i = 0; i < waveform.length; i++) {
console.log(max[i]);
}