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 🙏

© 2024 – Pkg Stats / Ryan Hefner

@flat/midijs

v0.15.1

Published

Read and write Standard MIDI files and enable communication with MIDI devices!

Downloads

10

Readme

@flat/midijs

Read and write Standard MIDI files and enable communication with MIDI devices!

This module provides a high-level API for working with Standard MIDI and General MIDI events that are sent through MIDI inputs and outputs, or read from a file.

npm version build status

Install

npm install --save @flat/midijs

Run tests

cd midijs/
npm install
npm test

Check code coverage

cd midijs/
npm install
npm run coverage

Make documentation

cd midijs/
npm install
npm run docs

Usage

File

Read or write data from or to a Standard MIDI file.
Creating an empty file:

var MIDI = require('@flat/midijs');
var file = new MIDI.File();

// file.header contains default header data
// file.tracks is empty

Loading data from an existing file, using the Buffer API:

var MIDI = require('@flat/midijs');
var fs = require('fs');

fs.readFile(path, function (err, data) {
    if (err) {
        throw err;
    }

    var file = new MIDI.File(data, function (err) {
        if (err) {
            throw err;
        }

        // file.header contains header data
        // file.tracks contains file tracks
    });
});

Or using the Stream API:

var MIDI = require('@flat/midijs');
var fs = require('fs');

var file = new MIDI.File();

file.on('parsed', function () {
    // file.header contains header data
    // file.tracks contains file tracks
});

file.on('error', function (err) {
    throw err;
});

fs.createReadStream(path).pipe(file);

Changing elements in a file:

var MIDI = require('@flat/midijs');
var File = MIDI.File;

/** edit header **/

file.getHeader().setTicksPerBeat(60); // speed up twice
file.getHeader().setFileType(File.Header.FILE_TYPE.SINGLE_TRACK); // change file type

/** edit tracks **/

file.getTracks(); // get all tracks
file.getTrack(0); // get a track
file.removeTrack(0); // remove given track

// add a track with events
file.addTrack(2, // position (optional)
    new File.ChannelEvent(File.ChannelEvent.TYPE.NOTE_ON, {
        note: 45
    }),
    new File.MetaEvent(File.MetaEvent.TYPE.END_OF_TRACK)
);

/** edit events in a track **/

track.getEvents(); // get all events
track.getEvent(0); // get an event
track.removeEvent(0); // remove given event
track.addEvent(1, // position (optional)
    new File.ChannelEvent(File.ChannelEvent.TYPE.PROGRAM_CHANGE, {
        program: MIDI.gm.getProgram('Church Organ')
    }, 0, 200)
);

Saving data to a SMF file, using the Buffer API:

var MIDI = require('@flat/midijs');
var fs = require('fs');

var file = new MIDI.File();

// add/remove tracks or events...

file.getData(function (err, data) {
    if (err) {
        throw err;
    }

    fs.writeFile(path, data, function (err) {
        if (err) {
            throw err;
        }

        // file at 'path' now contains binary MIDI data
        // ready to be played by any other MIDI program
        // (or re-read by this module later)
    });
});

Or using the Stream API:

var MIDI = require('@flat/midijs');
var fs = require('fs');

var file = new MIDI.File();

// add/remove tracks or events...

file.on('end', function () {
    // file at 'path' now contains binary MIDI data
    // ready to be played by any other MIDI program
    // (or re-read by this module later)
});

file.on('error', function (err) {
    throw err;
});

file.pipe(fs.createWriteStream(path));

gm

List of programs numbers associated to instruments and families defined by the General MIDI standard.

Knowing an instrument's name (as a string) as defined by the specification, you can retrieve its program number, using the getProgram() method.

IMPORTANT NOTE: the program number is calculated starting from 0, but the specification's indices start from 1. Be careful.

MIDI.gm.getProgram('MUSIC BOX'); // 10
MIDI.gm.getProgram('music Box'); // 10
MIDI.gm.getProgram('Music Box', 'Chromatic Percussion'); // 10
MIDI.gm.getProgram('Music Box', 'Strings'); // false

Knowing an instrument's program number as defined by the specification, you can retrieve its name, using the getInstrument() method, or its family name with the getFamily() method.

MIDI.gm.getInstrument(10); // 'music box'
MIDI.gm.getFamily(10); // 'chromatic percussion'
MIDI.gm.getFamily('music box'); // 'chromatic percussion'
MIDI.gm.getInstrument(10, 'Chromatic Percussion'); // 'music box'
MIDI.gm.getInstrument(10, 'Strings'); // false

Result of the getProgram() or getInstrument() method can be limited to check if the given instrument is within the given family, using the second argument.

connect()

Access a MIDI driver that enables communication with the plugged MIDI devices (outputs and inputs). This API is currently only available in the browser. It relies on the WebMIDI API and thus requires an authorization from the user.

If the user declines access to his MIDI devices, then the Promise fails. Otherwise, it is fullfilled with a driver instance.
Attempting to connect:

var MIDI = require('@flat/midijs');

MIDI.connect()
    .then(function (driver) {
        // work with the outputs/inputs
    })
    .catch(function (error) {
        // something happened
    });

The driver is a bridge to output and input devices. It contains a list of devices that are currently plugged in, and emits connect or disconnect events whether one of them is connected or disconnected.

var MIDI = require('@flat/midijs');

// driver.inputs is a list of current inputs
// driver.outputs is a list of current outputs

driver.on('connect', function (port) {
    if (port instanceof MIDI.connect.Input) {
        // an input just got plugged in
    } else {
        // it was an output
    }
});

You can send events to an output:

var MIDI = require('@flat/midijs');
var ChannelEvent = MIDI.File.ChannelEvent;

output.send(new ChannelEvent(ChannelEvent.TYPE.NOTE_ON, {
    note: 56,
    velocity: 127
}, 0));

And wait for events from an input:

var MIDI = require('@flat/midijs');
var ChannelEvent = MIDI.File.ChannelEvent;

input.on('event', function (event) {
    if (event.type === ChannelEvent.TYPE.NOTE_ON) {
        // do something
    }
});

You can select a default input and a default output on the driver. Events from the default input will bubble to the driver and events sent to the driver will be sent to the default output.

var MIDI = require('@flat/midijs');

driver.setInput(driver.inputs[2]); // by position
driver.setInput('Input id'); // by unique input ID

driver.setOutput(driver.outputs[2]); // by position
driver.setOutput('Output id'); // by unique output ID

// send a "note on" event to the default output
driver.send(new ChannelEvent(ChannelEvent.TYPE.NOTE_ON, {
    note: 56,
    velocity: 127
}, 0));

driver.on('event', function (event) {
    if (event.type === ChannelEvent.TYPE.NOTE_ON) {
        // "note on" event received from default input
    }
});

errors

Constructors of errors that can be emitted by this module.

Contributing

All contributions are welcome! In order to have a consistent repo, we however ask you to comply to the following conventions whenever possible.

1. Commit tags

All commits should be tagged with emojis to make the commit list more readable.

| Emoji | Commit content | |:----------:|:--------------------- | | :book: | Documentation updates | | :bug: | Bug fixes | | :ledger: | Rename/move files | | :bulb: | Features | | :lipstick: | Fix coding style |

2. Branches

Please use a branch name that differs from master whenever possible, when making pull requests, so that the network history is more readable.

For example, if you wanted to fix the issue "improve documentation", you could have chosen the following branch name: improve-docs.

3. Coding style

Javascript can be authored by following a lot of different style guides but we decided to be a bit soft on that.

Just follow the conventions that are encoded into the .eslintrc configuration file. By the way, be sure to check out ESLint, which is a great toolable style checker.

  • Use the radix parameter in parseInt() calls.
  • Declare all your variables at the top of the functions.
  • Use the one true brace style.
  • Put one space after commas, and no space before.
  • Put your comma at the end of the lines.
  • Use simple quotes.
  • Use camelcase.
  • Use 4 spaces for indentation.

License

See LICENSE.