Skip to content

Latest commit

 

History

History
593 lines (421 loc) · 17.1 KB

API.md

File metadata and controls

593 lines (421 loc) · 17.1 KB

waveform-data.js API documentation

WaveformData

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';

WaveformData.create(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.

Arguments

Name Type
data ArrayBuffer

Examples

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.

WaveformData.createFromAudio(options, callback)

Creates a WaveformData object from audio using the Web Audio API.

Arguments

Name Type
options Object (see below)
callback Function

Options

Name Type Description
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
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
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
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

Examples

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 ArrayBuffer containing 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_worker to true in 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`);
    });
  });

waveformData.sample_rate

Returns the sample rate of the original audio, in Hz.

Example

const waveform = WaveformData.create(buffer);

console.log(waveform.sample_rate); // -> 44100

waveformData.scale

Returns 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).

Example

const waveform = WaveformData.create(buffer);

console.log(waveform.scale); // -> 512

waveformData.seconds_per_pixel

Returns the amount of time (in seconds) represented by a single pixel.

Example

const waveform = WaveformData.create(buffer);

console.log(waveform.seconds_per_pixel); // -> 0.010666666666666666

waveformData.pixels_per_second

Returns the number of pixels per second.

Example

const waveform = WaveformData.create(buffer);

console.log(waveform.pixels_per_second); // -> 93.75

waveformData.length

Returns the length of the waveform data, in pixels.

Example

const waveform = WaveformData.create(buffer);

console.log(waveform.length); // -> 1000

waveformData.duration

Returns 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.

Example

const waveform = WaveformData.create(buffer);

console.log(waveform.duration); // -> 10.32

waveformData.bits

Returns the number of bits per sample, either 8 or 16.

Example

const waveform = WaveformData.create(buffer);

console.log(waveform.bits); // -> 8

waveformData.at_time(time)

Returns the pixel index for a given time.

Arguments

Name Type
time Number (seconds)

Example

const waveform = WaveformData.create(buffer);

console.log(waveform.at_time(0.116)); // -> 10

waveformData.time(index)

Returns the time in seconds for a given pixel index.

Arguments

Name Type
index Number (integer)

Example

const waveform = WaveformData.create(buffer);

console.log(waveform.time(10)); // 0.116

waveformData.channels

Returns 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.

Example

const waveform = WaveformData.create(buffer);
console.log(waveform.channels); // 1

waveformData.channel(index)

Returns a WaveformDataChannel object that provides access to the waveform data for the given channel index.

Arguments

Name Type
index Number (integer)

Example

const waveform = WaveformData.create(buffer);

for (let i = 0; i < waveform.channels; i++) {
  const channel = waveform.channel(i);
}

waveformData.resample(options)

Creates and returns a new WaveformData object with resampled data. Use this method to create waveform data at different zoom levels.

Arguments

Name Type
options Object (see below)

Options

Name Type
width Number (integer)
scale Number (integer)

Examples

To resample the waveform to fit to a specific width:

const waveform = WaveformData.create(buffer);
const resampledWaveform = waveform.resample({ width: 500 });

console.log(resampledWaveform.length); // -> 500

To 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); // -> 1024

Note 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 Error

waveformData.concat(...waveforms)

Concatenates the receiver with one or more other waveforms, returning a new WaveformData object.

The waveforms must be compatible, i.e., have the same sample rate, scale, and number of channels.

Arguments

Name Type
...waveforms One or more WaveformData instances

Example

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); // -> 900

waveformData.toJSON()

Returns an object containing the waveform data. This means you can use JSON.stringify() to produce a JSON string representation of the waveform data.

Example

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]}'

waveformData.toArrayBuffer()

Returns an object containing the waveform data in binary format.

Example

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
  // }
});

WaveformDataChannel

waveformDataChannel.min_sample(index)

Returns the waveform minimum at the given index position.

Arguments

Name Type
index Number (integer)

Example

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);
}

waveformDataChannel.max_sample(index)

Returns the waveform maximum at the given index position.

Arguments

Name Type
index Number (integer)

Example

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);
}

waveformDataChannel.min_array()

Returns all 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]);
}

waveformDataChannel.max_array()

Returns all 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]);
}