Skip to content

infojunkie/midi-player

 
 

Repository files navigation

midi-player

A MIDI player which sends MIDI messages to connected devices.

This module provides a player which sends MIDI messages to connected devices. It schedules the messages with a look ahead of about 500 milliseconds. It does not directly rely on the Web MIDI API but expects a MIDIOutput to be passed as constructor argument. But theoretically that could be anything which implements the same interface.

Features of this fork

This is a fork of the original midi-player module by Chris Guttandin. I decided to fork it instead of attempting to merge back the changes into the upstream because I am adding features outside the scope that Chris had envisioned for the module. Nothing prevents such a merge to happen in the future, given we find enough time to integrate the codebases. In the meantime, I do my best to keep this fork updated with the latest upstream changes, and to contribute to the core functionality that Chris maintains.

Here are the features added in this fork:

  • Add support for MIDIOutput.clear() for browsers that implement it MERGED 🎉
  • Add method IMidiPlayer.stop() MERGED 🎉
  • Send MIDI Control Change (CC) message "All Sound Off" on player pause/stop MERGED 🎉
  • Add methods IMidiPlayer.pause(), IMidiPlayer.resume() IMPLEMENTED 🎉
  • Add read-only attribute IMidiPlayer.state (stopped, playing, paused) IMPLEMENTED 🎉
  • Respect MIDI file duration before resolving the playback promise -- WIP at chrisguttandin#362
  • Fix bug with playback promise for IMidiPlayer.pause() and IMidiPlayer.resume() -- WIP at chrisguttandin#364
  • Support real-time cursor repositioning via attribute IMidiPlayer.position
  • Support real-time playback rate / velocity adjustment via attribute IMidiPlayer.velocity and arguments IMidiPlayer.play(velocity?), IMidiPlayer.resume(velocity?)
  • Support looping via arguments IMidiPlayer.play(repeat?), IMidiPlayer.resume(repeat?)

The version numbering used in this fork is <major>.<minor>.<patch>-<upstream-major>.<upstream-minor>.<upstream-patch>.

Usage

npm install git://github.com/infojunkie/midi-player.git#infojunkie

The only exported function is a factory method to create new player instances.

import { create } from 'midi-player';

// This is a JSON object which represents a MIDI file.
const json = {
    division: 480,
    format: 1,
    tracks: [
        { channel: 0, delta: 0, noteOn: { noteNumber: 36, velocity: 100 } },
        { channel: 0, delta: 240, noteOff: { noteNumber: 36, velocity: 64 } },
        { delta: 0, endOfTrack: true }
    ]
};

// This is a quick & dirty approach to grab the first known MIDI output.
const midiAccess = await navigator.requestMIDIAccess();
const midiOutput = Array.from(midiAccess.outputs)[0];

const midiPlayer = create({ json, midiOutput });

// All MIDI messages have been sent when the promise returned by play() resolves.
await midiPlayer.play();

By default only control change, note off, note on and program change events will be sent. But it's possible to provide a custom filter function. The following player will only send note off and note on events.

const midiPlayer = create({
    filterMidiMessage: (event) => 'noteOff' in event || 'noteOn' in event
    // ... other options as described above
});

If you want to play a binary MIDI file you can use the midi-json-parser package to transform it into a compatible JSON representation.

About

A simple MIDI player which sends MIDI messages to connected devices.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • JavaScript 69.9%
  • TypeScript 30.1%