JavaScript library for MIDI communication that simplifies sending and receiving MIDI messages between browsers/Node.js and MIDI instruments
—
Note processing provides comprehensive functionality for representing musical notes and converting between different note formats. The Note class handles note creation, properties, and transformations for MIDI applications.
Create Note objects from various input formats.
class Note {
/**
* Create a Note object from various input formats
* @param value - Note input (string, number, or Note object)
* @param options - Note creation options
* @param options.duration - Note duration in milliseconds
* @param options.attack - Attack velocity (0-1, default: 0.5)
* @param options.release - Release velocity (0-1, default: 0.5)
* @param options.octaveOffset - Octave offset to apply
*/
constructor(value: string | number | Note, options?: {
duration?: number;
attack?: number;
release?: number;
octaveOffset?: number;
});
}Usage Examples:
import { Note } from "webmidi";
// Create from note name
const c4 = new Note("C4");
const fSharp3 = new Note("F#3");
const bFlat5 = new Note("Bb5");
// Create from MIDI number
const middleC = new Note(60); // C4
const highA = new Note(81); // A5
// Create with options
const note = new Note("G4", {
duration: 2000, // 2 seconds
attack: 0.8, // Strong attack
release: 0.3, // Soft release
octaveOffset: -1 // One octave lower
});
// Create from existing Note
const noteCopy = new Note(c4);Access note properties and characteristics.
/**
* Full note identifier (e.g., "C4", "F#3", "Bb5")
*/
readonly identifier: string;
/**
* Note name without octave (e.g., "C", "F#", "Bb")
*/
readonly name: string;
/**
* Accidental symbol (sharp/flat) or undefined for natural notes
*/
readonly accidental?: string;
/**
* Octave number (-2 to 8)
*/
readonly octave: number;
/**
* MIDI note number (0-127)
*/
readonly number: number;
/**
* Note duration in milliseconds (if specified)
*/
readonly duration?: number;
/**
* Attack velocity as float (0-1)
*/
readonly attack: number;
/**
* Release velocity as float (0-1)
*/
readonly release: number;
/**
* Raw attack velocity (0-127)
*/
readonly rawAttack: number;
/**
* Raw release velocity (0-127)
*/
readonly rawRelease: number;Usage Examples:
const note = new Note("F#4", { attack: 0.8, release: 0.6, duration: 1500 });
console.log(note.identifier); // "F#4"
console.log(note.name); // "F#"
console.log(note.accidental); // "#"
console.log(note.octave); // 4
console.log(note.number); // 66
console.log(note.attack); // 0.8
console.log(note.rawAttack); // 101 (0.8 * 127)
console.log(note.duration); // 1500Transform notes with offsets and modifications.
/**
* Get MIDI note number with applied offsets
* @param octaveOffset - Octave offset to apply (default: 0)
* @param semitoneOffset - Semitone offset to apply (default: 0)
* @returns Modified MIDI note number (0-127)
*/
getOffsetNumber(octaveOffset?: number, semitoneOffset?: number): number;Usage Examples:
const c4 = new Note("C4"); // MIDI number 60
// Apply offsets
console.log(c4.getOffsetNumber()); // 60 (no offset)
console.log(c4.getOffsetNumber(1)); // 72 (C5)
console.log(c4.getOffsetNumber(-1)); // 48 (C3)
console.log(c4.getOffsetNumber(0, 7)); // 67 (G4)
console.log(c4.getOffsetNumber(1, -5)); // 67 (G5)WebMidi.js supports various note name formats:
// Basic note names
new Note("C4"); // C in 4th octave
new Note("A0"); // Lowest A
new Note("G8"); // Highest G
// Sharp notes
new Note("C#4"); // C-sharp
new Note("F#3"); // F-sharp
// Flat notes
new Note("Bb4"); // B-flat
new Note("Db2"); // D-flat
// Alternative flat notation
new Note("B♭4"); // B-flat (Unicode)
new Note("D♭2"); // D-flat (Unicode)
// Alternative sharp notation
new Note("C♯4"); // C-sharp (Unicode)
new Note("F♯3"); // F-sharp (Unicode)
// MIDI numbers
new Note(60); // Middle C (C4)
new Note(69); // A4 (440 Hz)
new Note(127); // Highest MIDI noteWebMidi.js uses scientific pitch notation:
// Octave examples
new Note("C-2"); // MIDI 0 (lowest)
new Note("C-1"); // MIDI 12
new Note("C0"); // MIDI 24
new Note("C1"); // MIDI 36
new Note("C2"); // MIDI 48
new Note("C3"); // MIDI 60
new Note("C4"); // MIDI 72
new Note("C5"); // MIDI 84
new Note("C6"); // MIDI 96
new Note("C7"); // MIDI 108
new Note("C8"); // MIDI 120
new Note("G8"); // MIDI 127 (highest)// From string array
const notes = ["C4", "E4", "G4"].map(n => new Note(n));
// From mixed inputs
const chord = [
new Note("C4"),
new Note(64), // E4
new Note("G4", { attack: 0.7 })
];
// With consistent options
const melody = ["C4", "D4", "E4", "F4"].map(note =>
new Note(note, { duration: 500, attack: 0.6 })
);// Find notes by property
const sharps = notes.filter(note => note.accidental === "#");
const highNotes = notes.filter(note => note.octave >= 5);
// Transform notes
const transposed = notes.map(note =>
new Note(note.getOffsetNumber(1)) // Up one octave
);
// Sort notes by pitch
notes.sort((a, b) => a.number - b.number);import { WebMidi, Note } from "webmidi";
await WebMidi.enable();
const output = WebMidi.outputs[0];
// Play individual notes
const c4 = new Note("C4", { attack: 0.8, duration: 1000 });
output.channels[0].playNote(c4);
// Play chord with consistent timing
const chord = ["C4", "E4", "G4"].map(n =>
new Note(n, { attack: 0.7, duration: 2000 })
);
output.channels[0].playNote(chord);const input = WebMidi.inputs[0];
input.addListener("noteon", (e) => {
const playedNote = e.note;
console.log(`Played: ${playedNote.identifier}`);
console.log(`MIDI: ${playedNote.number}`);
console.log(`Octave: ${playedNote.octave}`);
console.log(`Velocity: ${playedNote.attack}`);
});function getInterval(note1, note2) {
return Math.abs(note1.number - note2.number);
}
const c4 = new Note("C4");
const g4 = new Note("G4");
const perfectFifth = getInterval(c4, g4); // 7 semitonesfunction generateMajorScale(root) {
const intervals = [0, 2, 4, 5, 7, 9, 11]; // Major scale intervals
const rootNote = new Note(root);
return intervals.map(interval =>
new Note(rootNote.getOffsetNumber(0, interval))
);
}
function generateMajorTriad(root) {
const rootNote = new Note(root);
return [
rootNote, // Root
new Note(rootNote.getOffsetNumber(0, 4)), // Major third
new Note(rootNote.getOffsetNumber(0, 7)) // Perfect fifth
];
}
// Usage
const cMajorScale = generateMajorScale("C4");
const fMajorChord = generateMajorTriad("F4");function isValidMidiNote(note) {
const noteObj = new Note(note);
return noteObj.number >= 0 && noteObj.number <= 127;
}
function transposeWithinRange(note, semitones) {
const originalNote = new Note(note);
const transposed = originalNote.getOffsetNumber(0, semitones);
if (transposed < 0 || transposed > 127) {
throw new Error("Transposition out of MIDI range");
}
return new Note(transposed);
}interface NoteOptions {
duration?: number;
attack?: number;
release?: number;
octaveOffset?: number;
}
type NoteInput = string | number | Note;
type NoteArray = Array<string | number | Note>;Install with Tessl CLI
npx tessl i tessl/npm-webmidi