Skip to content

uttori/uttori-audio-midi

Repository files navigation

view on npm npm module downloads Tree-Shaking Support Dependency Count Minified + GZip Minified

Uttori Audio MIDI

A utility to manipulate and parse MIDI data.

Install

npm install --save @uttori/audio-midi

Example

import fs from 'fs';
import AudioMIDI from '@uttori/audio-midi';
const data = fs.readFileSync('./song.mid');
const midi = new AudioPadInfo(data);
console.log('MIDI:', midi);

API Reference

Classes

AudioMIDIDataBuffer

AudioMIDI - MIDI Utility MIDI File Format Parser & Generator

Typedefs

WritableNote : object
WritableTrack : object
NoteData : object
SysExData : object
EventData : string | number | Uint8Array | NoteData | SysExData
MidiTrackEvent : object
Header : object
Track : object
UsedNote : object

AudioMIDI ⇐ DataBuffer

AudioMIDI - MIDI Utility MIDI File Format Parser & Generator

Kind: global class
Extends: DataBuffer

new AudioMIDI([input], [options])

Creates a new AudioMIDI.

Param Type Description
[input] Array.<number> | ArrayBuffer | Buffer | DataBuffer | Int8Array | Int16Array | Int32Array | number | string | Uint8Array | Uint16Array | Uint32Array | undefined The data to process.
[options] object Options for this AudioMIDI instance.
[options.format] number The MIDI format: 0, 1, or 2, default is 0.
[options.timeDivision] number The indication of how MIDI ticks should be translated into time, default is 128.

Example (AudioMIDI)

const data = fs.readFileSync('./song.mid');
const file = new AudioMIDI(data);
file.parse();
console.log('Chunks:', file.chunks);

audioMIDI.format : number

The MIDI format: 0, 1, or 2

Kind: instance property of AudioMIDI

audioMIDI.trackCount : number

The internal track count.

Kind: instance property of AudioMIDI

audioMIDI.timeDivision : number

The indication of how MIDI ticks should be translated into time.

Kind: instance property of AudioMIDI

audioMIDI.chunks : Array.<Track>

Kind: instance property of AudioMIDI

audioMIDI.readVariableLengthValues ⇒ number

Several different values in events are expressed as variable length quantities (e.g. delta time values). A variable length value uses a minimum number of bytes to hold the value, and in most circumstances this leads to some degree of data compresssion.

A variable length value uses the low order 7 bits of a byte to represent the value or part of the value. The high order bit is an "escape" or "continuation" bit. All but the last byte of a variable length value have the high order bit set. The last byte has the high order bit cleared. The bytes always appear most significant byte first.

Kind: instance property of AudioMIDI
Returns: number - The length of the next chunk.

audioMIDI.parse()

Parse a MIDI file from a Uint8Array.

Kind: instance method of AudioMIDI
See

audioMIDI.addTrack() ⇒ Track

Adds a new track to the MIDI file.

Kind: instance method of AudioMIDI
Returns: Track - The new track.

audioMIDI.addEvent(track, event)

Adds an event to a track.

Kind: instance method of AudioMIDI

Param Type Description
track Track The track to add the event to.
event Event | Array.<Event> The event to add.

audioMIDI.saveToDataBuffer() ⇒ DataBuffer

Writes the MIDI data to a binary file.

Kind: instance method of AudioMIDI
Returns: DataBuffer - The binary data buffer.

audioMIDI.writeChunk(dataBuffer, chunk)

Write a track chunk to the data buffer.

Kind: instance method of AudioMIDI

Param Type Description
dataBuffer DataBuffer The data buffer to write to.
chunk Track The track chunk to write.

audioMIDI.writeEvent(dataBuffer, event)

Helper function to write an event to the data buffer.

Kind: instance method of AudioMIDI

Param Type Description
dataBuffer DataBuffer The data buffer to write to.
event MidiTrackEvent The event to write.

audioMIDI.getUsedNotes() ⇒ Array.<UsedNote>

Returns a sorted list of all unique note numbers used in "Note On" events, along with their note names (e.g. "C3", "D#4").

Kind: instance method of AudioMIDI
Returns: Array.<UsedNote> - Array of note data

audioMIDI.validate() ⇒ Array.<string>

Validate a MIDI instance for common issues. Matching Note Ons / Offs: A velocity > 0 "Note On" increments activeNotes[note]. A "Note Off" or "Note On" with velocity == 0 decrements. If the count is already 0, that is invalid. At the end of the track, if any notes still have a positive count, that is also invalid. Meta Events: We do a small switch on event.metaType to check if the declared metaEventLength is correct for well-known meta events (End of Track, Set Tempo, Time Signature, etc.). Chunk Length: Since the parser already stored each chunk's chunkLength, we do minimal checks: if chunkLength > 0 but there are zero events, or vice versa, that is unusual.

Kind: instance method of AudioMIDI
Returns: Array.<string> - Array of warning / error messages discovered, an empty array if no issues are found.

AudioMIDI.decodeHeader(chunk) ⇒ Header

Decodes and validates MIDI Header. Checks for MThd header, reads the chunk length, format, track count, and PPQN (pulses per quarter note) / PPQ (pulses per quarter) / PQN (per quarter note) / TPQN (ticks per quarter note) / TPB (ticks per beat).

Signature (Decimal): [77, 84, 104, 100, ...] Signature (Hexadecimal): [4D, 54, 68, 64, ...] Signature (ASCII): [M, T, h, d, ...]

Kind: static method of AudioMIDI
Returns: Header - The decoded values.
Throws:

  • Error Invalid WAV header
Param Type Description
chunk Buffer | string | Uint8Array Data Blob

AudioMIDI.getControllerLabel(controller) ⇒ string

Return the human readable controller name from the ID.

Kind: static method of AudioMIDI
Returns: string - The human-readable controller name.
See

Param Type Description
controller number The controller ID.

AudioMIDI.getManufacturerLabel(manufacturerId) ⇒ string

Return the human readable manufacturer name from the ID.

Kind: static method of AudioMIDI
Returns: string - The human-readable manufacturer name.
See: MidiKit Help MIDI Manufacturers List

Param Type Description
manufacturerId number The manufacturer ID.

AudioMIDI.writeVariableLengthValue(dataBuffer, value)

Write a variable-length value.

Kind: static method of AudioMIDI

Param Type Description
dataBuffer DataBuffer The data buffer to write to.
value number The value to write as a variable-length quantity.

AudioMIDI.writeEventData(dataBuffer, data)

Write event data.

Kind: static method of AudioMIDI

Param Type Description
dataBuffer DataBuffer The data buffer to write to.
data Uint8Array | Array.<number> The event data to write.

AudioMIDI.generateTempoEvent(bpm) ⇒ MidiTrackEvent

Generate a Set Tempo event with a provided BPM.

Kind: static method of AudioMIDI
Returns: MidiTrackEvent - The tempo event with the correct byte values.

Param Type Description
bpm number The desired tempo in Beats Per Minute.

AudioMIDI.generateMetaStringEvent(metaType, data) ⇒ MidiTrackEvent

Generate a Meta String event:

  • 0x01: 'Text Event'
  • 0x02: 'Copyright Notice'
  • 0x03: 'Sequence / Track Name'
  • 0x04: 'Instrument Name'
  • 0x05: 'Lyrics'
  • 0x06: 'Marker'
  • 0x07: 'Cue Point'
  • 0x08: 'Program Name'
  • 0x09: 'Device (Port) Name'

Kind: static method of AudioMIDI
Returns: MidiTrackEvent - The meta string event with the encoded string data.

Param Type Description
metaType number The meta event type. (e.g., 0x03 for Track Name).
data string The string value for the event (e.g., the name of the track).

AudioMIDI.generateEndOfTrackEvent() ⇒ MidiTrackEvent

Generate an end of track event.

Kind: static method of AudioMIDI
Returns: MidiTrackEvent - The end of track event.

AudioMIDI.convertToMidi(options) ⇒ AudioMIDI

Convert a collection of tracks and notes into a new AudioMIDI instance.

Kind: static method of AudioMIDI
Returns: AudioMIDI - The newly constured MIDI

Param Type Description
options object The options
[options.ppq] number The pulses per quarter note, default is 480.
[options.bpm] number The BPM of the track, when blank no tempo event will be added.
[options.tracks] Array.<WritableTrack> The MIDI tracks to write.
[options.skipNotes] Array.<number> The MIDI notes to ship, if any.

Example

const midi = AudioMIDI.convertToMidi({
  bpm,
  ppq,
  tracks: [
    {
      notes: myCustomNotes.map((note) => {
        return {
          note: note.midiNote,
          velocity: note.velocity,
          length: note.length,
        }
      }),
      metaStringEvents: {
        0x03: `Custom MIDI`,
      },
    }
  ],
  skipNotes: [128],
});
return midi;

AudioMIDI.noteToMidi(noteString, [octaveOffset], [noteMap]) ⇒ number

Convert a note string like C1 or D#2 to the MIDI value.

Kind: static method of AudioMIDI
Returns: number - The MIDI value for the provided note.

Param Type Default Description
noteString string The notation string.
[octaveOffset] number 2 The default octave offset for C1, where a value of 2 means C1 = 36; default is 2.
[noteMap] Record.<string, number> The note map to use for the conversion.

Example

AudioMIDI.noteToMidi('C4') === 72
AudioMIDI.noteToMidi('C3') === 60
AudioMIDI.noteToMidi('C2') === 48
AudioMIDI.noteToMidi('C1') === 36
AudioMIDI.noteToMidi('C-1') === 12
AudioMIDI.noteToMidi('C-2') === 0

AudioMIDI.midiToNote(midiValue, [octaveOffset], [noteNames]) ⇒ string

Convert a MIDI value back to a note string like C1 or D#2.

Kind: static method of AudioMIDI
Returns: string - The note label corresponding to the MIDI value.

Param Type Default Description
midiValue number The MIDI value (0-127).
[octaveOffset] number 2 The default octave offset for C1, where a value of 2 means C1 = 36; default is 2.
[noteNames] Array.<string> The note names to use for the conversion.

Example

AudioMIDI.midiToNote(72) === 'C4'
AudioMIDI.midiToNote(60) === 'C3'
AudioMIDI.midiToNote(48) === 'C2'
AudioMIDI.midiToNote(36) === 'C1'
AudioMIDI.midiToNote(12) === 'C-1'
AudioMIDI.midiToNote(0) === 'C-2'

WritableNote : object

Kind: global typedef
Properties

Name Type Description
ticks number The delay in ticks until the next track.
midiNote number The MIDI note value.
velocity number The velocity of the note (0-127).
length number The length of the note in ticks.

WritableTrack : object

Kind: global typedef
Properties

Name Type Description
[bpm] number The BPM of the track, when blank no tempo event will be added.
[metaStringEvents] Record.<number, string> A key value collection of meta events to add where they key is the event type and the value is the data to add.
[notes] Array.<WritableNote> A collection of notes to write on the track.

NoteData : object

Kind: global typedef
Properties

Name Type Description
note string A note value.
velocity number The velocity of the note (0-127).
length number The length of the note in ticks.

SysExData : object

Kind: global typedef
Properties

Name Type Description
manufacturerId number The manufacturer's ID code.
manufacturerLabel string The manufacturer's label based on the ID.
data Array.<number> The SysEx data bytes.

EventData : string | number | Uint8Array | NoteData | SysExData

Kind: global typedef

MidiTrackEvent : object

Kind: global typedef
Properties

Name Type Description
deltaTime number The delta time of the MIDI event.
type number The type of the event (e.g., meta event, regular event).
label string A human-readable label describing the event.
data EventData The data associated with the event.
[metaType] number The subtype of the meta event.
[metaEventLength] number The length of the meta event data.
[channel] number The MIDI channel the event is for.
[tag] number The tag for the M-Live Tag event.

Header : object

Kind: global typedef
Properties

Name Type Description
type string The type of the chunk (e.g., MThd, MTrk).
format number The format of the MIDI file (header only).
trackCount number The number of tracks in the MIDI file (header only).
timeDivision number The time division of the MIDI file (header only).
chunkLength number The length of the chunk data.

Track : object

Kind: global typedef
Properties

Name Type Description
type string The type of the chunk (e.g., MThd, MTrk).
chunkLength number The length of the chunk data.
events Array.<MidiTrackEvent> The collection of events in the track.

UsedNote : object

Kind: global typedef
Properties

Name Type Description
noteNumber number The numeric value of the note.
noteString string The human-readable note string.

Tests

To run the test suite, first install the dependencies, then run npm test:

npm install
npm test
DEBUG=Uttori* npm test

Contributors

References

I found these links really helpful for understanding the MIDI format.

License

Releases

No releases published

Packages

No packages published