Features
Layouts, search and filters, hundreds of sounds, keyboard, the address, downloads, analytics, server rendering, mobile — Features.
WaveformSounds is a searchable, filterable list of sounds for showcasing the previews inside a sample pack, preset bank or sound library. Each row is a sound with a mini waveform, its type, BPM, key and length; above the rows sit a search box, type chips, a key menu, a BPM range menu, a sort menu and a Loop toggle. Press a row and it plays; press ↓ while it plays and the next one plays — the way a sample browser auditions.
It is built for hundreds of sounds, not a handful: one WaveformPlayer (self mode) is the audio engine for the whole list, and the rows are light — a button, some text and a small canvas drawn from low-resolution peaks only when it scrolls into view. 300 sounds is 300 rows, not 300 players.
Here’s a real one, loaded from a manifest. Press a row, use the chips and the search, or focus a row and use the arrow keys:
That’s one element — <div data-waveform-sounds data-manifest="/audio/sounds.json"> — and a JSON file written by waveform-gen --manifest. This demo’s sounds carry no BPM or key, so the BPM menu, the key menu and those sort orders simply don’t appear: every control shows up only when the data gives it something to do.
Both build on the player; they’re for different jobs.
| WaveformPlaylist | WaveformSounds | |
|---|---|---|
| Made for | Albums, podcasts, chaptered episodes | Sample packs, preset banks, sound libraries |
| Typical size | A handful of tracks | Tens to hundreds of short previews |
| Finding things | Scroll the list | Search, filter by type / key / BPM, sort |
| Waveform | One full player for the selected track | A mini waveform on every row (or one docked player, the strip layout) |
| Per-item data | Artist, artwork, album, chapters | Type, BPM, key, length, tags, an optional download |
| Data source | [data-track] markup |
A JSON manifest, a sounds array, or server-rendered rows |
If listeners sit back and listen, use the playlist. If they hunt for the right kick, use this.
Install it alongside the core player:
npm install @arraypress/waveform-player @arraypress/waveform-soundspnpm add @arraypress/waveform-player @arraypress/waveform-soundsyarn add @arraypress/waveform-player @arraypress/waveform-soundsbun add @arraypress/waveform-player @arraypress/waveform-soundsimport '@arraypress/waveform-player'; // registers window.WaveformPlayer, the engineimport '@arraypress/waveform-sounds'; // registers window.WaveformSounds and auto-initsimport '@arraypress/waveform-player/styles.css';import '@arraypress/waveform-sounds/styles.css';Or from a CDN — player first, then the list:
<link rel="stylesheet" href="https://unpkg.com/@arraypress/waveform-player@latest/dist/waveform-player.css"><link rel="stylesheet" href="https://unpkg.com/@arraypress/waveform-sounds@latest/dist/waveform-sounds.css">
<script src="https://unpkg.com/@arraypress/waveform-player@latest/dist/waveform-player.min.js"></script><script src="https://unpkg.com/@arraypress/waveform-sounds@latest/dist/waveform-sounds.min.js"></script>The package ships an IIFE (waveform-sounds.js, minified waveform-sounds.min.js, the unpkg default) exposing window.WaveformSounds, ESM and CJS builds, two more entry points — /render (a DOM-free server renderer) and /no-autoinit — and the stylesheet (waveform-sounds.css, also waveform-sounds.min.css, and exported as @arraypress/waveform-sounds/styles.css). Typings are bundled. Framework wrappers for Astro, React, Svelte and Vue are separate packages.
Write a manifest from your folder of previews. BPM and key are read from file names like Bass_Loop_04_128_Fmin.wav; the type is the sub-folder. --base-url is the public URL the folder is served at:
npx @arraypress/waveform-gen ./public/previews/ --recursive \ --manifest ./public/previews/sounds.json --base-url /previews/--manifest needs @arraypress/waveform-gen 2.1.0 or later. See Sounds manifest for every flag and the file-name rules.
Point a container at it. Every [data-waveform-sounds] element is initialised when the DOM is ready — no JavaScript to write:
<div data-waveform-sounds data-manifest="/previews/sounds.json"></div>Configure it with data-* if the defaults don’t suit — every option has an attribute:
<div data-waveform-sounds data-manifest="/previews/sounds.json" data-page-size="100" data-columns="type,bpm,key" data-url-state="true"></div>Or construct it yourself with a sounds array — no manifest, no fetch:
import WaveformSounds from '@arraypress/waveform-sounds';
const list = new WaveformSounds('#pack', { sounds: [ { url: '/previews/kick-01.mp3', title: 'Kick 01', type: 'Drums', duration: 2.4 }, { url: '/previews/bass-04.mp3', title: 'Bass Loop 04', type: 'Bass', bpm: 128, key: 'F minor' }, ], onPlay: (sound) => console.log('playing', sound.title),});The list takes its sounds from the first of these it finds:
[data-ws-list] element, as written by the /render entry or a framework wrapper). The runtime adopts that markup instead of rebuilding it.sounds option — an array. An empty array counts: it renders an empty list and the manifest is not fetched.manifest option (data-manifest) — a URL fetched with fetch() when there are no sounds. A failed request is reported through onError / waveformsounds:error.{ "version": 1, "sounds": [ { "url": "/previews/Bass/NW_Bass_Loop_04_128_Fmin.wav", "title": "NW Bass Loop 04", "type": "Bass", "bpm": 128, "key": "Fm", "duration": 8.02, "peaks": "1f3a…" } ]}A bare array of sounds works too. version is informational. peakScale is the maximum of integer peaks arrays (e.g. 100 for values 0..100) — hex peaks, which is what waveform-gen writes, ignore it.
| Field | Type | Description |
|---|---|---|
url |
string |
Required. The audio URL. A sound without one is dropped. |
title |
string |
Display name. Defaults to the file name, with its extension dropped and _ turned into spaces. |
type |
string |
The kind of sound (“Drum loops”, “Bass”, “One-shots”) — the type chips and the Type column. |
bpm |
number | string |
Tempo. Enables the BPM range menu and sort, and lets a number in the search match it. Kept to two decimals; 0 or anything non-numeric is no BPM. |
key |
string |
Musical key in any common spelling — "F minor", "Fmin", "f m" → Fm; "C# Major", "C♯" → C#. Shown and filtered in that short form; an unparseable key is kept as written. |
duration |
number | string |
Length: seconds (8.02) or "m:ss" / "h:mm:ss". Shown as m:ss, or in tenths under a second (0.4s, 0.1.3+). |
tags |
string[] | string |
Extra words the search matches. A string is split on commas. |
peaks |
string | number[] |
Low-resolution peaks for the row waveform: an 8-bit hex string (two characters per bar, 00–ff) or numbers 0..1. Without them the row shows a flat line until it’s played. |
waveform |
string | number[] |
Full-resolution peaks for the strip layout’s docked player — a waveform-gen .json URL or an array. |
download |
string |
An optional download link for this sound. Rows with one get a download button; rows without carry nothing. |
loop |
boolean |
true for a loop; anything else is a one-shot (the default). Loops get a loop icon, a list with both gets a Loops / One-shots filter, and the Loop toggle repeats only loops. 0.2.0+. See Loops and one-shots. |
id |
string |
A stable id for play('id'). Defaults to sound-<n>, 1-based in list order. A repeated id gets -2, -3, … appended. |
Features
Layouts, search and filters, hundreds of sounds, keyboard, the address, downloads, analytics, server rendering, mobile — Features.
Options
Every option with its type, default and data-* attribute — Options.
API & events
Methods, properties, static methods, events, /render and utils — API.
Theming
The --ws-* custom properties and CSS classes — Theming.