npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

d-piano

v1.1.0

Published

Web Audio instrument using Salamander Grand Piano samples

Readme

d-piano

A web audio piano instrument

About

This is a fork of @tonejs/piano by Yotam Mann with performance optimizations and more active maintaince. Built on high-quality samples from Salamander Grand Piano.

Features

  • High-quality samples - Up to 16 velocity levels across 88 keys (Yamaha C5)
  • Complete instrument - Includes pedal sounds and string harmonics
  • Progressive loading - Loads 1 velocity level immediately for fast startup, then upgrades to full quality in the background during browser idle time
  • Cache-aware - Probes the Cache Storage API at startup; if target-quality samples are already cached, starts at full quality immediately rather than the single-velocity warm-up pass
  • Buffer caching - Audio buffers are shared across multiple piano instances and across progressive upgrade steps — no re-fetching

Install

Install the npm package:

npm install --save d-piano

d-piano requires Tone.js as a peer dependency:

npm install --save tone

Usage

Import

import { Piano } from 'd-piano'

Create and load samples

// Create the piano — progressive loading is automatic
const piano = new Piano({
	velocities: 8  // target quality; default is 8
})

// Connect to speaker output
piano.toDestination()

// Resolves as soon as the first pass (1 velocity) is ready to play.
// Upgrading to full quality happens automatically in the background.
piano.load().then(() => {
	console.log('Piano ready — playing at 1 velocity, upgrading in background')
})

How progressive loading works

load() resolves after a fast first pass (1 velocity layer) so you can start playing immediately. The upgrade to the target velocity count happens in the background via requestIdleCallback, expanding the velocity layers in-place without interrupting notes that are already playing.

If the target samples are already in the Cache Storage API, the piano starts at full quality immediately instead of going through the single-velocity warm-up pass first. This pairs well with preloadSamples and any service worker caching strategy in your own app.

Cold load (nothing cached):
  load() resolves → playing at 1 velocity
  [idle] → upgrades to 8 velocities in-place, no interruption

Warm load (samples cached):
  load() resolves → playing at 8 velocities immediately

Preloading samples

Use preloadSamples to fetch samples ahead of time without importing the full Tone.js piano. Combined with a service worker caching strategy in your app, this means Piano will detect the cached samples on the next load and start at full quality immediately.

import { preloadSamples } from 'd-piano'

await preloadSamples(8, {
	baseUrl: '/assets/samples/piano/',
	minNote: 21,
	maxNote: 108,
})

API Reference

Piano Options

interface PianoOptions {
	velocities: number;    // Target velocity levels (default: 8, max: 16). Progressive
	                       // loading starts at 1 and upgrades to this in the background.
	minNote: number;       // Lowest MIDI note to load (default: 21)
	maxNote: number;       // Highest MIDI note to load (default: 108)
	release: boolean;      // Include release sounds (default: false)
	pedal: boolean;        // Include pedal sounds (default: true)
	url: string;           // Sample directory URL
	maxPolyphony: number;  // Max simultaneous notes (default: 32)
	volume: {              // Component volume levels in dB (default: 0)
		pedal: number;
		strings: number;
		keybed: number;
		harmonics: number;
	}
}

Methods

.keyDown({ note: string, time?: Time, velocity?: number })

Press a note down on the piano.

// Play a 'C4' immediately
piano.keyDown({ note: 'C4' })

// Play a 'C4' 1 second from now with velocity 0.8
piano.keyDown({ note: 'C4', time: '+1', velocity: 0.8 })

.keyUp({ note: string, time?: Time })

Release a note at the given time.

// Release the pressed 'C4' immediately
piano.keyUp({ note: 'C4' })

.pedalDown({ time?: Time })

Press and hold the sustain pedal. Notes played while the pedal is down will be sustained until the pedal is released.

.pedalUp({ time?: Time })

Release the sustain pedal and dampen any sustained notes.

.load(): Promise<void>

Start loading samples. Resolves as soon as the first velocity pass is ready to play. The upgrade to full velocity resolution continues in the background and requires no further interaction.

.loaded: boolean

true once the first velocity pass has finished loading and the piano is ready to play.

.dispose()

Clean up the piano instance and free resources.

Development

Building

npm run build

Testing

npm test

Linting

npm run lint

Credits

This project builds upon the great work of:

License

MIT License - see LICENSE file for details.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.