### Install waveform-data.js with npm Source: https://github.com/bbc/waveform-data.js/blob/master/README.md Use npm to install the waveform-data.js library. This command works for both Node.js and browser-based applications. ```bash npm install --save waveform-data ``` -------------------------------- ### JavaScript Example: Create Waveform from Audio Source: https://github.com/bbc/waveform-data.js/blob/master/_autodocs/types.md Example demonstrating how to create waveform data from encoded audio using WaveformData.createFromAudio. Ensure an AudioContext and ArrayBuffer are provided. ```javascript const options = { audio_context: new AudioContext(), array_buffer: encodedAudioBuffer, scale: 512, split_channels: true }; WaveformData.createFromAudio(options, callback); ``` -------------------------------- ### Create WaveformData from AudioBuffer Source: https://github.com/bbc/waveform-data.js/blob/master/_autodocs/types.md Example of creating waveform data using WaveformData.createFromAudio with an AudioBuffer. Ensure the AudioBuffer is decoded before passing it. ```javascript const audioContext = new AudioContext(); const audioBuffer = await audioContext.decodeAudioData(encodedData); const options = { audio_buffer: audioBuffer, scale: 256 }; WaveformData.createFromAudio(options, callback); ``` -------------------------------- ### Handle WaveformData Creation Callback Source: https://github.com/bbc/waveform-data.js/blob/master/_autodocs/types.md Example of a callback function for WaveformData.createFromAudio. It checks for errors and logs waveform details upon successful creation. ```javascript WaveformData.createFromAudio(options, (error, waveform, audioBuffer) => { if (error) { console.error('Waveform creation failed:', error); return; } console.log('Waveform created successfully'); console.log(`Duration: ${waveform.duration}s`); console.log(`Channels: ${waveform.channels}`); }); ``` -------------------------------- ### D3.js Waveform Visualization Setup Source: https://github.com/bbc/waveform-data.js/blob/master/README.md This snippet sets up a D3.js visualization for waveform data within a specified HTML container. It configures scales and an area generator for the waveform path. ```html
``` ```javascript const waveform = WaveformData.create(raw_data); const channel = waveform.channel(0); const container = d3.select('#waveform-container'); const x = d3.scaleLinear(); const y = d3.scaleLinear(); const offsetX = 100; const min = channel.min_array(); const max = channel.max_array(); x.domain([0, waveform.length]).rangeRound([0, 1000]); y.domain([d3.min(min), d3.max(max)]).rangeRound([offsetX, -offsetX]); const area = d3.svg.area() .x((d, i) => x(i)) .y0((d, i) => y(min[i])) .y1((d, i) => y(d)); const graph = container.append('svg') .style('width', '1000px') .style('height', '200px') .datum(max) .append('path') .attr('transform', () => `translate(0, ${offsetX})`) .attr('d', area) .attr('stroke', 'black'); ``` -------------------------------- ### Resample Waveform Data from API Source: https://github.com/bbc/waveform-data.js/blob/master/README.md This Node.js CLI example fetches waveform data from a web API, resamples it to a specified width, and outputs min/max arrays. Requires superagent and yargs. ```javascript #!/usr/bin/env node // Save as: app/bin/cli-resampler.js const WaveformData = require('waveform-data'); const request = require('superagent'); const args = require('yargs').argv; request.get(`https://api.example.com/waveforms/${args.waveformid}.json`) .then(response => { const waveform = WaveformData.create(response.body); const resampledWaveform = waveform.resample({ width: 2000 }); const channel = resampledWaveform.channel(0); process.stdout.write(JSON.stringify({ min: channel.min_array(), max: channel.max_array() })); }); ``` -------------------------------- ### Get All Minimum Sample Values Source: https://github.com/bbc/waveform-data.js/blob/master/doc/API.md Obtain all minimum sample values for a channel as an array. This provides a quick way to access the entire set of minimums. ```javascript 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]); } ``` -------------------------------- ### Get Bits Per Sample Source: https://github.com/bbc/waveform-data.js/blob/master/doc/API.md Returns the number of bits per sample for the audio data. This will typically be 8 or 16. ```javascript const waveform = WaveformData.create(buffer); console.log(waveform.bits); // -> 8 ``` -------------------------------- ### Drawing Waveforms with Canvas API Source: https://github.com/bbc/waveform-data.js/blob/master/_autodocs/api-reference/WaveformDataChannel.md An example demonstrating how to draw waveform data onto an HTML Canvas element using min and max sample values. Includes a helper function for scaling amplitude to canvas height. ```javascript const waveform = WaveformData.create(buffer); const channel = waveform.channel(0); const canvas = document.getElementById('waveform'); const ctx = canvas.getContext('2d'); const scaleY = (amplitude, height) => { const range = 256; const offset = 128; return height - ((amplitude + offset) * height) / range; }; ctx.beginPath(); // Draw upper half (min values) for (let x = 0; x < waveform.length; x++) { const val = channel.min_sample(x); ctx.lineTo(x + 0.5, scaleY(val, canvas.height) + 0.5); } // Draw lower half (max values) for (let x = waveform.length - 1; x >= 0; x--) { const val = channel.max_sample(x); ctx.lineTo(x + 0.5, scaleY(val, canvas.height) + 0.5); } ctx.closePath(); ctx.stroke(); ctx.fill(); ``` -------------------------------- ### Get All Maximum Sample Values Source: https://github.com/bbc/waveform-data.js/blob/master/doc/API.md Retrieve all maximum sample values for a channel as an array. This method is useful for accessing the complete set of maximums efficiently. ```javascript 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]); } ``` -------------------------------- ### slice(options) Source: https://github.com/bbc/waveform-data.js/blob/master/_autodocs/api-reference/WaveformData.md Returns a subset of waveform data between specified start and end points, which can be defined by pixel indices or time values. ```APIDOC ## slice(options) ### Description Returns a subset of waveform data between start and end points, specified either as pixel indices or time values. ### Method Signature ```javascript slice(options: { startIndex: number; endIndex: number } | { startTime: number; endTime: number }) => WaveformData ``` ### Parameters #### options - **startIndex** (`number`) - Required - Start pixel index (0-based). - **endIndex** (`number`) - Required - End pixel index (exclusive). - **startTime** (`number`) - Required - Start time in seconds. - **endTime** (`number`) - Required - End time in seconds. ### Returns - `WaveformData` — New waveform containing the slice. ### Throws - `RangeError` — If startIndex or endIndex is negative. ### Behavior - Indices/times outside bounds are clamped to valid range [0, length]. - If startIndex > endIndex, startIndex is set to endIndex. ### Usage Examples Slice by index: ```javascript const waveform = WaveformData.create(buffer); const slice = waveform.slice({ startIndex: 100, endIndex: 200 }); console.log(slice.length); // -> 100 ``` Slice by time: ```javascript const waveform = WaveformData.create(buffer); const slice = waveform.slice({ startTime: 1.0, endTime: 2.0 }); console.log(slice.duration); // -> ~1.0 second ``` ``` -------------------------------- ### Get All Minimum Samples Source: https://github.com/bbc/waveform-data.js/blob/master/_autodocs/api-reference/WaveformDataChannel.md Retrieves an array containing all minimum sample values for the channel, one per pixel. Useful for bulk processing or when all data is needed. ```javascript const waveform = WaveformData.create(buffer); const channel = waveform.channel(0); console.log(waveform.length); // -> 3 const minValues = channel.min_array(); // -> [-7, -5, -10] for (let i = 0; i < waveform.length; i++) { console.log(`Pixel ${i}: min = ${minValues[i]}`); } ``` -------------------------------- ### Get Specific Min/Max Sample Values Source: https://github.com/bbc/waveform-data.js/blob/master/doc/migration-guide.md Access individual min/max sample values using channel.min_sample(index) and channel.max_sample(index). ```javascript const minValue = waveformData.min[index]; const maxValue = waveformData.max[index]; ``` ```javascript const channel = waveformData.channel(0); const minValue = channel.min_sample(index); const maxValue = channel.max_sample(index); ``` -------------------------------- ### Get All Maximum Samples Source: https://github.com/bbc/waveform-data.js/blob/master/_autodocs/api-reference/WaveformDataChannel.md Retrieves an array containing all maximum sample values for the channel, one per pixel. Useful for bulk processing or when all data is needed. ```javascript const waveform = WaveformData.create(buffer); const channel = waveform.channel(0); console.log(waveform.length); // -> 3 const maxValues = channel.max_array(); // -> [7, 5, 10] for (let i = 0; i < waveform.length; i++) { console.log(`Pixel ${i}: max = ${maxValues[i]}`); } ``` -------------------------------- ### Create WaveformData from JSON Source: https://github.com/bbc/waveform-data.js/blob/master/_autodocs/types.md Example of creating a WaveformData object from a JSON structure. The JSON object must conform to the JsonWaveformData interface. This is useful for initializing waveforms from stored data. ```javascript const json = { version: 2, channels: 1, sample_rate: 44100, samples_per_pixel: 512, bits: 8, length: 4, data: [0, 0, -1, 1, -2, 2, -3, 3] }; const waveform = WaveformData.create(json); console.log(waveform.duration); // 0.046 seconds ``` -------------------------------- ### Drawing a Waveform on Canvas Source: https://github.com/bbc/waveform-data.js/blob/master/_autodocs/README.md Example of drawing a waveform onto an HTML canvas using the Canvas API. It iterates through min and max sample data to render the waveform shape. ```javascript const waveform = WaveformData.create(data); const channel = waveform.channel(0); const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d'); const scaleY = (val, height) => { const range = 256; const offset = 128; return height - ((val + offset) * height) / range; }; ctx.beginPath(); // Draw upper half (minima) for (let i = 0; i < waveform.length; i++) { ctx.lineTo(i, scaleY(channel.min_sample(i), canvas.height)); } // Draw lower half (maxima) for (let i = waveform.length - 1; i >= 0; i--) { ctx.lineTo(i, scaleY(channel.max_sample(i), canvas.height)); } ctx.closePath(); ctx.stroke(); ``` -------------------------------- ### Get Min/Max Values Arrays Source: https://github.com/bbc/waveform-data.js/blob/master/doc/migration-guide.md Use waveformData.channel(0).min_array() and .max_array() to get arrays of min/max values. ```javascript const minValues = waveformData.min; const maxValues = waveformData.max; ``` ```javascript const channel = waveformData.channel(0); const minValues = channel.min_array(); const maxValues = channel.max_array(); ``` -------------------------------- ### Access WaveformData Length Source: https://github.com/bbc/waveform-data.js/blob/master/doc/API.md Get the total length of the waveform data in pixels from the `length` property. ```javascript const waveform = WaveformData.create(buffer); console.log(waveform.length); // -> 1000 ``` -------------------------------- ### Accessing Waveform Length Source: https://github.com/bbc/waveform-data.js/blob/master/_autodocs/api-reference/WaveformData.md Get the total length of the waveform data in pixels. This is a read-only property. ```javascript const waveform = WaveformData.create(buffer); console.log(waveform.length); // -> 1000 ``` -------------------------------- ### WaveformDataFromAudioCallback Source: https://github.com/bbc/waveform-data.js/blob/master/_autodocs/types.md Callback function signature for `WaveformData.createFromAudio()`. ```APIDOC ## WaveformDataFromAudioCallback Callback function signature for `WaveformData.createFromAudio()`. ### Parameters | Parameter | Type | Description | |---|---|---| | error | `DOMException | null` | Error object if creation failed, null if successful | | waveformData | `WaveformData` | Created WaveformData instance (undefined if error occurred) | | audioBuffer | `AudioBuffer` | Original or decoded AudioBuffer used to create the waveform | ### Example ```javascript WaveformData.createFromAudio(options, (error, waveform, audioBuffer) => { if (error) { console.error('Waveform creation failed:', error); return; } console.log('Waveform created successfully'); console.log(`Duration: ${waveform.duration}s`); console.log(`Channels: ${waveform.channels}`); }); ``` ``` -------------------------------- ### Load Binary Waveform Data with Fetch Source: https://github.com/bbc/waveform-data.js/blob/master/demo/index.html Fetches and loads binary waveform data from a file. Handles potential network errors and logs waveform details. Requires the waveform-data.js library to be included. ```javascript document.querySelector('button[data-action="load-dat"]').addEventListener('click', function() { fetch('07023003-2channel.dat') .then(response => { if (response.ok) { return response.arrayBuffer(); } else { throw new Error(`${response.status} ${response.statusText}`); } }) .then(buffer => WaveformData.create(buffer)) .then(waveform => { console.log(`Waveform has ${waveform.channels} channels`); console.log(`Waveform has length ${waveform.length} points`); updateOffsetSlider(waveform); drawWaveform(canvas, waveform, 0); waveformData = waveform; }) .catch(err => { console.error(err.message); }); }); ``` -------------------------------- ### Get Number of Channels Source: https://github.com/bbc/waveform-data.js/blob/master/doc/API.md Returns the number of channels present in the waveform data. By default, audiowaveform combines channels, so this is often 1. ```javascript const waveform = WaveformData.create(buffer); console.log(waveform.channels); // 1 ``` -------------------------------- ### Create Waveform from Binary Data Source: https://github.com/bbc/waveform-data.js/blob/master/_autodocs/README.md Load waveform data from a binary (.dat) file using fetch and create a WaveformData object. Requires the data to be in ArrayBuffer format. ```javascript import WaveformData from 'waveform-data'; // Binary format (.dat file) fetch('/waveforms/audio.dat') .then(res => res.arrayBuffer()) .then(buffer => WaveformData.create(buffer)) .then(waveform => { console.log(`Loaded waveform: ${waveform.channels} channels, ${waveform.length} pixels`); }); ``` -------------------------------- ### Accessing Seconds Per Pixel Source: https://github.com/bbc/waveform-data.js/blob/master/_autodocs/api-reference/WaveformData.md Get the time in seconds represented by a single pixel. This read-only property is calculated as scale / sample_rate. ```javascript const waveform = WaveformData.create(buffer); console.log(waveform.seconds_per_pixel); // -> 0.0116 (at 44100 Hz with scale 512) ``` -------------------------------- ### Low-Resolution (Overview) Waveform Configuration Source: https://github.com/bbc/waveform-data.js/blob/master/_autodocs/configuration.md Use this configuration for a very low-detail overview of the waveform, ideal for mini-maps or timelines. It produces a minimal file size. ```javascript const options = { audio_context: audioContext, array_buffer: buffer, scale: 2048, // Few pixels = overview only bits: 8 }; ``` -------------------------------- ### Load Binary Waveform Data Source: https://github.com/bbc/waveform-data.js/blob/master/demo/d3.html Fetches a binary waveform data file (.dat) and loads it using WaveformData.create. Handles fetch errors and logs waveform properties. ```javascript document.querySelector('button[data-action="load-dat"]').addEventListener('click', function() { fetch('07023003-2channel.dat') .then(response => { if (response.ok) { return response.arrayBuffer(); } else { throw new Error(`${response.status} ${response.statusText}`); } }) .then(buffer => WaveformData.create(buffer)) .then(waveform => { console.log(`Waveform has ${waveform.channels} channels`); console.log(`Waveform has length ${waveform.length} points`); drawWaveform(waveform, '#929982'); }) .catch(err => { console.error(err.message); }); }); ``` -------------------------------- ### Options Source: https://github.com/bbc/waveform-data.js/blob/master/_autodocs/types.md Base options object used across multiple creation methods. It allows configuration of waveform resolution, bit depth, amplitude scaling, channel splitting, and worker usage. ```APIDOC ## Options ### Description Base options object used across multiple creation methods. It allows configuration of waveform resolution, bit depth, amplitude scaling, channel splitting, and worker usage. ### Fields - **scale** (number) - Optional - Number of audio samples per pixel. Higher values = lower resolution (more zoomed out). Default: 512. - **bits** (number) - Optional - Bits per sample. Valid values: 8 or 16. Default: 8. - **amplitude_scale** (number) - Optional - Amplitude scaling factor applied to waveform data. Use 2.0 to double amplitude. Default: 1.0. - **split_channels** (boolean) - Optional - If true, create separate waveform per channel. If false, combine all channels into one. Default: false. - **disable_worker** (boolean) - Optional - If true, run waveform generation on main thread (blocking). If false, use Web Worker (non-blocking). Default: false. ### Used By - `WaveformData.createFromAudio()` — Base options for all audio input methods ``` -------------------------------- ### Get Maximum Sample by Index Source: https://github.com/bbc/waveform-data.js/blob/master/_autodocs/api-reference/WaveformDataChannel.md Retrieves the maximum waveform amplitude at a specific pixel index. Useful for detailed analysis of individual points. ```javascript const waveform = WaveformData.create(buffer); const channel = waveform.channel(0); const maxAt0 = channel.max_sample(0); const maxAt100 = channel.max_sample(100); console.log(maxAt0); // -> 50 console.log(maxAt100); // -> 127 ``` -------------------------------- ### Initialize WaveformData with ArrayBuffer Source: https://github.com/bbc/waveform-data.js/blob/master/doc/migration-guide.md Replace XHR object input with ArrayBuffer or parsed JSON for WaveformData.create(). ```javascript const xhr = new XMLHttpRequest(); // .dat file generated by audiowaveform program xhr.responseType = 'arraybuffer'; xhr.open("GET", 'https://example.com/waveforms/track.dat'); xhr.addEventListener('load', (event) => { const waveform = WaveformData.create(event.target); console.log(waveform.duration); }); xhr.send(); ``` ```javascript xhr.addEventListener('load', (event) => { const waveform = WaveformData.create(event.target.response); console.log(waveform.duration); }); ``` -------------------------------- ### Get Minimum Sample by Index Source: https://github.com/bbc/waveform-data.js/blob/master/_autodocs/api-reference/WaveformDataChannel.md Retrieves the minimum waveform amplitude at a specific pixel index. Useful for detailed analysis of individual points. ```javascript const waveform = WaveformData.create(buffer); const channel = waveform.channel(0); const minAt0 = channel.min_sample(0); const minAt100 = channel.min_sample(100); console.log(minAt0); // -> -45 console.log(minAt100); // -> -120 ``` -------------------------------- ### Create WaveformData from Encoded Audio Source: https://github.com/bbc/waveform-data.js/blob/master/_autodocs/configuration.md Use this snippet when you have encoded audio data (e.g., MP3, WAV) and an AudioContext. It fetches the audio, decodes it, and prepares it for waveform generation. ```javascript const audioContext = new AudioContext(); const response = await fetch('https://example.com/audio.mp3'); const arrayBuffer = await response.arrayBuffer(); const options = { array_buffer: arrayBuffer, audio_context: audioContext, scale: 512 }; ``` -------------------------------- ### WaveformData.createFromAudio(options, callback) Source: https://github.com/bbc/waveform-data.js/blob/master/_autodocs/api-reference/WaveformData.md Generates WaveformData from audio using the Web Audio API, optionally with Web Workers for non-blocking processing. ```APIDOC ## WaveformData.createFromAudio(options, callback) ### Description Creates a `WaveformData` object from audio using the Web Audio API. The audio can be provided as encoded data (e.g., MP3, OGG) or as a decoded `AudioBuffer`. Waveform generation optionally uses a Web Worker for non-blocking processing. ### Method Signature ```javascript static createFromAudio( options: WaveformDataAudioContextOptions | WaveformDataAudioBufferOptions, callback: WaveformDataFromAudioCallback ) => void ``` ### Parameters #### Path Parameters - **options** (Object) - Required - Configuration object (see below) - **callback** (function(error, waveform, audioBuffer)) - Required - Callback function invoked with the created waveform or error ### Options #### Path Parameters - **audio_context** (AudioContext) - Required when `array_buffer` is provided. The Web Audio context used to decode audio - **array_buffer** (ArrayBuffer) - Encoded audio data (e.g., MP3, OGG, WAV). Requires `audio_context` for decoding - **audio_buffer** (AudioBuffer) - Already-decoded audio buffer from Web Audio API - **scale** (number) - Optional - Audio samples per pixel. Controls waveform resolution. Default: 512 - **bits** (number) - Optional - Bits per sample. Valid values: 8 or 16. Default: 8 - **amplitude_scale** (number) - Optional - Amplitude scaling factor (e.g., 2.0 to double amplitude). Default: 1.0 - **split_channels** (boolean) - Optional - Generate separate waveform per channel instead of combining all channels. Default: false - **disable_worker** (boolean) - Optional - Disable Web Worker and process on main thread (blocking operation). Default: false ### Callback Signature ```javascript callback(error: DOMException | null, waveform: WaveformData, audioBuffer: AudioBuffer) => void ``` ### Usage Examples #### From encoded audio with Web Worker (non-blocking): ```javascript 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('Failed to generate waveform:', err); return; } console.log(`Waveform: ${waveform.channels} channels, ${waveform.length} pixels`); }); }); ``` #### From AudioBuffer: ```javascript const audioContext = new AudioContext(); const audioBuffer = audioContext.createBuffer(2, 44100 * 4, 44100); // 4 seconds const options = { audio_buffer: audioBuffer, scale: 256 }; WaveformData.createFromAudio(options, (err, waveform) => { if (err) return console.error(err); console.log('Waveform created with scale:', waveform.scale); }); ``` #### With multi-channel separation: ```javascript const options = { audio_context: audioContext, array_buffer: buffer, scale: 512, split_channels: true }; WaveformData.createFromAudio(options, (err, waveform) => { if (err) return; console.log(`Generated ${waveform.channels} separate channels`); }); ``` ``` -------------------------------- ### WaveformData.createFromAudio with AudioBuffer Source: https://github.com/bbc/waveform-data.js/blob/master/doc/API.md Creates a WaveformData object from an existing AudioBuffer. ```APIDOC ## WaveformData.createFromAudio with AudioBuffer ### Description Creates a WaveformData object from an existing AudioBuffer. ### Method ```javascript WaveformData.createFromAudio(options, callback) ``` ### Parameters #### Options - **audio_buffer** (AudioBuffer) - Required - The AudioBuffer containing the audio data. #### Callback - **err** (Error) - An error object if creation fails. - **waveform** (WaveformData) - The created WaveformData object. ``` -------------------------------- ### Get Time from Pixel Index Source: https://github.com/bbc/waveform-data.js/blob/master/_autodocs/api-reference/WaveformData.md Converts a pixel index to its corresponding time in seconds. This is useful for displaying the current playback time or calculating durations. ```javascript const waveform = WaveformData.create(buffer); const seconds = waveform.time(100); console.log(seconds); // -> 1.157 seconds ``` -------------------------------- ### Web: Responsive Timeline Visualization Configuration Source: https://github.com/bbc/waveform-data.js/blob/master/_autodocs/configuration.md Configuration for a responsive timeline visualization in a web application. Employs `disable_worker: false` to ensure a smooth user experience. ```javascript const audioContext = new AudioContext(); const response = await fetch('audio.mp3'); const buffer = await response.arrayBuffer(); const options = { audio_context: audioContext, array_buffer: buffer, scale: 512, // Standard view bits: 8, // Smaller files split_channels: false, // Mono for simplicity disable_worker: false }; WaveformData.createFromAudio(options, (err, waveform) => { if (err) return; renderWaveform(waveform); }); ``` -------------------------------- ### Access WaveformData Scale Source: https://github.com/bbc/waveform-data.js/blob/master/doc/API.md Get the scale factor, representing audio samples per pixel, from the `scale` property. Higher values indicate a more zoomed-out view. ```javascript const waveform = WaveformData.create(buffer); console.log(waveform.scale); // -> 512 ``` -------------------------------- ### Configure Multi-Channel Output Source: https://github.com/bbc/waveform-data.js/blob/master/_autodocs/configuration.md Generates one waveform channel per audio channel. This is useful for multi-track visualization and detailed channel analysis. ```javascript const options = { split_channels: true }; ``` -------------------------------- ### Accessing Audio Duration Source: https://github.com/bbc/waveform-data.js/blob/master/_autodocs/api-reference/WaveformData.md Get the approximate duration of the audio file in seconds. This read-only property is calculated from the waveform's length, scale, and sample rate. ```javascript const waveform = WaveformData.create(buffer); console.log(waveform.duration); // -> 10.32 (seconds) ``` -------------------------------- ### TypeScript Interface: Options Source: https://github.com/bbc/waveform-data.js/blob/master/_autodocs/types.md Base options object used across multiple creation methods. Configure sample resolution, bit depth, amplitude scaling, channel splitting, and worker usage. ```typescript interface Options { scale?: number; bits?: number; amplitude_scale?: number; split_channels?: boolean; disable_worker?: boolean; } ``` -------------------------------- ### Bulk Data Access for Performance Source: https://github.com/bbc/waveform-data.js/blob/master/_autodocs/api-reference/WaveformDataChannel.md Retrieves all minimum and maximum sample arrays at once for performance-critical operations. Allows efficient processing of all pixel data. ```javascript const waveform = WaveformData.create(buffer); const channel = waveform.channel(0); const minArray = channel.min_array(); const maxArray = channel.max_array(); // Process all pixels efficiently for (let i = 0; i < waveform.length; i++) { const min = minArray[i]; const max = maxArray[i]; // ... use min and max values } ``` -------------------------------- ### Get Pixel Index from Time Source: https://github.com/bbc/waveform-data.js/blob/master/_autodocs/api-reference/WaveformData.md Converts a given time in seconds to its corresponding pixel index within the waveform. Useful for locating specific points in audio playback. ```javascript const waveform = WaveformData.create(buffer); const pixelIndex = waveform.at_time(0.5); // Index at 0.5 seconds console.log(pixelIndex); // -> 43 (for 44100 Hz, scale 512) ``` -------------------------------- ### Standard Waveform Configuration Source: https://github.com/bbc/waveform-data.js/blob/master/_autodocs/configuration.md This preset generates a standard detail, single mono waveform, offering a balance between file size and detail. It is suitable for most visualization needs. ```javascript const options = { audio_context: audioContext, array_buffer: buffer, scale: 512, // Default zoom level bits: 8, // Standard bit depth split_channels: false }; ``` -------------------------------- ### WaveformDataAudioContextOptions Source: https://github.com/bbc/waveform-data.js/blob/master/_autodocs/types.md Options for creating waveform data from encoded audio (e.g., MP3, OGG) using a Web Audio context. This type extends the base Options and requires an AudioContext and an ArrayBuffer of the audio data. ```APIDOC ## WaveformDataAudioContextOptions ### Description Options for creating waveform data from encoded audio (e.g., MP3, OGG) using a Web Audio context. This type extends the base Options and requires an AudioContext and an ArrayBuffer of the audio data. ### Fields - **audio_context** (AudioContext) - Required - The Web Audio AudioContext instance. Used to decode the encoded audio data. - **array_buffer** (ArrayBuffer) - Required - Encoded audio data (MP3, OGG, WAV, etc.). - **scale** (number) - Optional - Inherited from `Options`. Number of audio samples per pixel. Default: 512. - **bits** (number) - Optional - Inherited from `Options`. Bits per sample. Valid values: 8 or 16. Default: 8. - **amplitude_scale** (number) - Optional - Inherited from `Options`. Amplitude scaling factor applied to waveform data. Default: 1.0. - **split_channels** (boolean) - Optional - Inherited from `Options`. If true, create separate waveform per channel. Default: false. - **disable_worker** (boolean) - Optional - Inherited from `Options`. If true, run waveform generation on main thread. Default: false. ### Used By - `WaveformData.createFromAudio()` — When creating from encoded audio ### Request Example ```javascript const options = { audio_context: new AudioContext(), array_buffer: encodedAudioBuffer, scale: 512, split_channels: true }; WaveformData.createFromAudio(options, callback); ``` ``` -------------------------------- ### Get Audio Duration Source: https://github.com/bbc/waveform-data.js/blob/master/doc/API.md Retrieves the approximate duration of the audio file in seconds. This value is calculated based on waveform length, samples per pixel, and audio sample rate. ```javascript const waveform = WaveformData.create(buffer); console.log(waveform.duration); // -> 10.32 ``` -------------------------------- ### WaveformData.createFromAudio with split_channels Source: https://github.com/bbc/waveform-data.js/blob/master/doc/API.md Creates a WaveformData object with multi-channel waveform data by setting the `split_channels` option to true. ```APIDOC ## WaveformData.createFromAudio with split_channels ### Description Creates a WaveformData object with multi-channel waveform data by setting the `split_channels` option to true. ### Method ```javascript WaveformData.createFromAudio(options, callback) ``` ### Parameters #### Options - **audio_context** (AudioContext) - Required - The AudioContext to use for decoding. - **array_buffer** (ArrayBuffer) - Required - The audio data as an ArrayBuffer. - **scale** (number) - Optional - The number of audio samples per pixel. - **split_channels** (boolean) - Required - Set to `true` to create separate waveforms for each audio channel. #### Callback - **err** (Error) - An error object if creation fails. - **waveform** (WaveformData) - The created WaveformData object. ``` -------------------------------- ### Handle WaveformData.resample() Missing Options Source: https://github.com/bbc/waveform-data.js/blob/master/_autodocs/errors.md Catch errors when calling resample() without the required 'scale' or 'width' options. Ensure one of these is always provided. ```javascript waveform.resample({}); // Error waveform.resample({ bits: 16 }); // Error (unrelated option) ``` ```javascript try { const resampled = waveform.resample(options); } catch (error) { if (error instanceof Error && error.message.includes('Missing')) { console.error('Resample requires scale or width:', error.message); } } ``` -------------------------------- ### Import WaveformData using RequireJS Source: https://github.com/bbc/waveform-data.js/blob/master/README.md Use the UMD bundle with RequireJS to asynchronously load the WaveformData module. This is suitable for projects that use RequireJS for dependency management. ```javascript define(['WaveformData'], function(WaveformData) { // ... }); ``` -------------------------------- ### Serve Waveform Data with Express Source: https://github.com/bbc/waveform-data.js/blob/master/README.md Use this snippet to serve JSON waveform data from a file using Express. Ensure the file path is correct. ```javascript const WaveformData = require('waveform-data'); const express = require('express'); const fs = require('fs'); const app = express(); app.get('/waveforms/:id.json', (req, res) => { res.set('Content-Type', 'application/json'); fs.createReadStream(`path/to/${req.params.id}.json`) .pipe(res); }); ``` -------------------------------- ### Slice Waveform by Index Source: https://github.com/bbc/waveform-data.js/blob/master/doc/API.md Use `slice` with `startIndex` and `endIndex` to get a portion of the waveform data based on sample indices. The returned slice's length corresponds to the number of samples within the specified range. ```javascript const waveform = WaveformData.create(buffer); const slice = waveform.slice({ startIndex: 100, endIndex: 200 }); console.log(slice.length); // -> 100 ``` -------------------------------- ### Waveform-data.js Module Structure Source: https://github.com/bbc/waveform-data.js/blob/master/_autodocs/README.md Illustrates the directory and file organization of the waveform-data.js project, detailing the purpose of key files and directories. ```tree waveform-data.js/ ├── src/ │ ├── waveform-data.js # Main class (WaveformData) │ ├── waveform-data-channel.js # Channel class │ ├── waveform-generator.js # Waveform generation algorithm │ ├── waveform-data-worker.js # Web Worker entry point │ ├── waveform-utils.js # Format utilities │ └── utils.js # Internal utilities ├── dist/ │ ├── waveform-data.cjs.js # CommonJS build │ ├── waveform-data.esm.js # ES modules build │ └── waveform-data.min.js # Minified UMD └── waveform-data.d.ts # TypeScript definitions ``` -------------------------------- ### Generate Waveform via Web Worker Source: https://github.com/bbc/waveform-data.js/blob/master/_autodocs/api-reference/WaveformGenerator.md Recommended for large files to avoid UI blocking. Audio data buffers are transferred for efficiency. ```javascript const worker = new Worker('waveform-data-worker.js'); const channelData = [ audioBuffer.getChannelData(0).buffer, // Transferable audioBuffer.getChannelData(1).buffer ]; worker.postMessage({ scale: 512, bits: 8, amplitude_scale: 1.0, split_channels: true, length: audioBuffer.length, sample_rate: audioBuffer.sampleRate, channels: channelData }, channelData); // Transfer objects for efficiency worker.onmessage = (evt) => { const waveformBuffer = evt.data; // ArrayBuffer result const waveform = new WaveformData(waveformBuffer); }; ``` -------------------------------- ### Generate Waveform from Audio File Source: https://github.com/bbc/waveform-data.js/blob/master/demo/d3.html Fetches an audio file, uses the Web Audio API to decode it, and then generates waveform data using WaveformData.createFromAudio. Closes the AudioContext after generation. ```javascript document.querySelector('button[data-action="generate"]').addEventListener('click', function() { fetch('07023003.mp3') .then(response => { if (response.ok) { return response.arrayBuffer(); } else { throw new Error(`${response.status} ${response.statusText}`); } }) .then(buffer => { const audioContext = new AudioContext(); const options = { audio_context: audioContext, array_buffer: buffer, scale: 128 }; return new Promise((resolve, reject) => { WaveformData.createFromAudio(options, (err, waveform) => { if (err) { reject(err); } else { resolve(waveform); } audioContext.close(); }); }); }) .then(waveform => { console.log(`Waveform has ${waveform.channels} channels`); console.log(`Waveform has length ${waveform.length} points`); drawWaveform(waveform, '#b7999c'); }) .catch(err => { console.error(err.message); }); }); ``` -------------------------------- ### Load Binary Waveform Data using Fetch API Source: https://github.com/bbc/waveform-data.js/blob/master/README.md Fetch binary waveform data from a URL, convert the response to an ArrayBuffer, and then create a WaveformData object. This method is efficient for large datasets. ```javascript fetch('https://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`); }); ``` -------------------------------- ### Generate Waveform Directly (Main Thread) Source: https://github.com/bbc/waveform-data.js/blob/master/_autodocs/api-reference/WaveformGenerator.md Use this method for smaller files or when Web Workers are not feasible. It generates the waveform data directly on the main thread. ```javascript const waveformBuffer = generateWaveformData({ scale: 512, bits: 8, amplitude_scale: 1.0, split_channels: false, length: audioBuffer.length, sample_rate: audioBuffer.sampleRate, channels: [ new Float32Array(audioBuffer.getChannelData(0)), new Float32Array(audioBuffer.getChannelData(1)) ] }); const waveform = new WaveformData(waveformBuffer); ``` -------------------------------- ### Generate Binary Waveform Data Source: https://github.com/bbc/waveform-data.js/blob/master/README.md Use the audiowaveform CLI tool to generate binary waveform data from an audio file. Specify output file, bit depth (-b), and zoom factor (-z). ```shell audiowaveform -i track.mp3 -o track.dat -b 8 -z 256 ``` -------------------------------- ### High-Quality (Detailed) Waveform Configuration Source: https://github.com/bbc/waveform-data.js/blob/master/_autodocs/configuration.md Use this preset for detailed waveform generation, suitable for editing applications. It results in a larger file size due to higher detail and multi-channel output. ```javascript const options = { audio_context: audioContext, array_buffer: buffer, scale: 128, // More pixels = higher detail bits: 16, // More bits = more precision split_channels: true }; ``` -------------------------------- ### TypeScript Interface: WaveformDataAudioContextOptions Source: https://github.com/bbc/waveform-data.js/blob/master/_autodocs/types.md Options for creating waveform data from encoded audio using a Web Audio context. Extends base options with required AudioContext and ArrayBuffer. ```typescript interface WaveformDataAudioContextOptions extends Options { audio_context: AudioContext; array_buffer: ArrayBuffer; } ``` -------------------------------- ### Generate Waveform from Audio in Browser Source: https://github.com/bbc/waveform-data.js/blob/master/_autodocs/README.md Generate waveform data from an audio file (e.g., MP3) directly in the browser using the Web Audio API. Options include the audio context, array buffer of the audio, and a scale factor. ```javascript const audioContext = new AudioContext(); fetch('/audio/track.mp3') .then(res => res.arrayBuffer()) .then(buffer => { const options = { audio_context: audioContext, array_buffer: buffer, scale: 512 }; return new Promise((resolve, reject) => { WaveformData.createFromAudio(options, (err, waveform) => { if (err) reject(err); else resolve(waveform); }); }); }) .then(waveform => { console.log(`Generated waveform: ${waveform.duration}s`); }); ``` -------------------------------- ### Create Waveform from Decoded AudioBuffer Source: https://github.com/bbc/waveform-data.js/blob/master/README.md This snippet demonstrates how to create waveform data when you already have a decoded AudioBuffer. It bypasses the initial audio decoding step and directly processes the AudioBuffer. ```javascript const audioContext = new AudioContext(); audioContext.decodeAudioData(arrayBuffer) .then((audioBuffer) => { const options = { audio_context: audioContext, audio_buffer: audioBuffer, scale: 128 }; return new Promise((resolve, reject) => { WaveformData.createFromAudio(options, (err, waveform) => { if (err) { reject(err); } else { resolve(waveform); } }); }); }) .then(waveform => { console.log(`Waveform has ${waveform.channels} channels`); console.log(`Waveform has length ${waveform.length} points`); }); ``` -------------------------------- ### Load JSON Waveform Data with Fetch Source: https://github.com/bbc/waveform-data.js/blob/master/demo/index.html Fetches and loads waveform data from a JSON file. Handles potential network errors and logs waveform details. Requires the waveform-data.js library to be included. ```javascript document.querySelector('button[data-action="load-json"]').addEventListener('click', function() { fetch('07023003-2channel.json') .then(response => { if (response.ok) { return response.json(); } else { throw new Error(`${response.status} ${response.statusText}`); } }) .then(json => WaveformData.create(json)) .then(waveform => { console.log(`Waveform has ${waveform.channels} channels`); console.log(`Waveform has length ${waveform.length} points`); updateOffsetSlider(waveform); drawWaveform(canvas, waveform, 0); waveformData = waveform; }) .catch(err => { console.error(err.message); }); }); ``` -------------------------------- ### Exporting Waveform Data Source: https://github.com/bbc/waveform-data.js/blob/master/_autodocs/README.md Shows how to export waveform data into JSON and binary formats. The JSON format is human-readable, while the binary format is efficient for storage and transmission. ```javascript const waveform = WaveformData.create(data); // As JSON const json = waveform.toJSON(); const jsonString = JSON.stringify(json); // Send or save jsonString // As binary const binary = waveform.toArrayBuffer(); // Send or save binary data ``` -------------------------------- ### Handle Audio Decoding Failed with DOMException Source: https://github.com/bbc/waveform-data.js/blob/master/_autodocs/errors.md Catch DOMExceptions that occur during audio decoding when using WaveformData.createFromAudio. This typically happens with unsupported formats, corrupted data, or network issues. Check the 'name' property of the DOMException for specific error types. ```javascript const options = { audio_context: audioContext, array_buffer: corruptedData, // Invalid audio scale: 512 }; WaveformData.createFromAudio(options, (err, waveform) => { if (err instanceof DOMException) { console.error('Audio decoding failed:', err.name, err.message); } }); ``` ```javascript WaveformData.createFromAudio(options, (err, waveform) => { if (err) { if (err instanceof DOMException) { console.error('DOMException:', err.name); // err.name could be: "NotSupportedError", "EncodingError", etc. } else { console.error('Other error:', err); } return; } // Success console.log('Waveform created'); }); ``` -------------------------------- ### WaveformDataAudioBufferOptions Interface Source: https://github.com/bbc/waveform-data.js/blob/master/_autodocs/types.md Defines the options object for creating waveform data from an existing AudioBuffer. The audio_buffer field is required. ```typescript interface WaveformDataAudioBufferOptions extends Options { audio_buffer: AudioBuffer; } ``` -------------------------------- ### Access Waveform Data Array (Removed) Source: https://github.com/bbc/waveform-data.js/blob/master/doc/migration-guide.md The WaveformData.at() method has been removed. Use channel.min_sample() and channel.max_sample() for specific index access. ```javascript const index = 20; const minValue = waveformData.at(index); const maxValue = waveformData.at(index + 1); ``` ```javascript const channel = waveformData.channel(0); const index = 10; const minValue = channel.min_sample(index); const maxValue = channel.max_sample(index); ``` -------------------------------- ### WaveformData Class Source: https://github.com/bbc/waveform-data.js/blob/master/_autodocs/INDEX.md Documentation for the main WaveformData class, including static methods for creation, properties, and instance methods for data access and manipulation. ```APIDOC ## WaveformData Class ### Description Provides the core functionality for creating, accessing, and manipulating waveform data. ### Static Methods - `create()`: Creates a new WaveformData instance. - `createFromAudio()`: Creates a WaveformData instance from an audio source. ### Properties - `sample_rate` (number): The sample rate of the waveform. - `scale` (number): The scaling factor for the waveform data. - `length` (number): The total number of samples in the waveform. - `duration` (number): The duration of the waveform in seconds. - `bits` (number): The bit depth of the waveform data. - `channels` (number): The number of audio channels. ### Methods - `at_time(time)`: Returns the sample value at a specific time. - `time(sample_index)`: Returns the time corresponding to a sample index. - `channel(channel_index)`: Accesses a specific channel of the waveform. - `resample(new_sample_rate)`: Resamples the waveform to a new sample rate. - `concat(other_waveform)`: Concatenates another waveform to the current one. - `slice(start_time, end_time)`: Extracts a portion of the waveform. - `toJSON()`: Converts the waveform data to a JSON representation. - `toArrayBuffer()`: Converts the waveform data to an ArrayBuffer. ``` -------------------------------- ### WaveformData.createFromAudio with ArrayBuffer Source: https://github.com/bbc/waveform-data.js/blob/master/doc/API.md Creates a WaveformData object from an ArrayBuffer containing audio data. The audio context and scale can be provided as options. ```APIDOC ## WaveformData.createFromAudio with ArrayBuffer ### Description Creates a WaveformData object from an ArrayBuffer containing audio data. The audio context and scale can be provided as options. ### Method ```javascript WaveformData.createFromAudio(options, callback) ``` ### Parameters #### Options - **audio_context** (AudioContext) - Required - The AudioContext to use for decoding. - **array_buffer** (ArrayBuffer) - Required - The audio data as an ArrayBuffer. - **scale** (number) - Optional - The number of audio samples per pixel. - **split_channels** (boolean) - Optional - If true, creates separate waveforms for each audio channel. - **disable_worker** (boolean) - Optional - If true, disables the use of Web Workers for processing. #### Callback - **err** (Error) - An error object if creation fails. - **waveform** (WaveformData) - The created WaveformData object. ``` -------------------------------- ### WaveformData.create(data) Source: https://github.com/bbc/waveform-data.js/blob/master/_autodocs/api-reference/WaveformData.md Creates a new WaveformData instance from binary (ArrayBuffer) or JSON waveform data. ```APIDOC ## WaveformData.create(data) ### Description Creates and returns a new `WaveformData` instance from binary or JSON format waveform data. ### Method Signature ```javascript static create(data: ArrayBuffer | JsonWaveformData) => WaveformData ``` ### Parameters #### Path Parameters - **data** (ArrayBuffer | JsonWaveformData) - Required - Binary waveform data in ArrayBuffer format (`.dat` file) or a JavaScript object with JSON waveform data ### Returns - `WaveformData` instance ### Throws - `TypeError` — If the data format is not recognized as binary or JSON ### Usage Examples #### From binary data: ```javascript fetch('https://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`); }); ``` #### From JSON data: ```javascript fetch('https://example.com/waveforms/track.json') .then(response => response.json()) .then(json => WaveformData.create(json)) .then(waveform => { console.log(`Sample rate: ${waveform.sample_rate} Hz`); }); ``` ``` -------------------------------- ### WaveformDataAudioBufferOptions Source: https://github.com/bbc/waveform-data.js/blob/master/_autodocs/types.md Options for creating waveform data from an already-decoded AudioBuffer. ```APIDOC ## WaveformDataAudioBufferOptions Options for creating waveform data from an already-decoded AudioBuffer. ### Fields | Field | Type | Required | Description | |---|---|---|---| | audio_buffer | `AudioBuffer` | Yes | Decoded audio buffer from Web Audio API | | scale | `number` | No | Inherited from `Options` | | bits | `number` | No | Inherited from `Options` | | amplitude_scale | `number` | No | Inherited from `Options` | | split_channels | `boolean` | No | Inherited from `Options` | | disable_worker | `boolean` | No | Inherited from `Options` | ### Example ```javascript const audioContext = new AudioContext(); const audioBuffer = await audioContext.decodeAudioData(encodedData); const options = { audio_buffer: audioBuffer, scale: 256 }; WaveformData.createFromAudio(options, callback); ``` ```