CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-webmidi

JavaScript library for MIDI communication that simplifies sending and receiving MIDI messages between browsers/Node.js and MIDI instruments

Pending
Overview
Eval results
Files

note-processing.mddocs/

Note Processing

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.

Capabilities

Note Construction

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);

Note Properties

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);    // 1500

Note Transformations

Transform 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)

Note Name Formats

Supported Input Formats

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 note

Octave Numbering

WebMidi.js uses scientific pitch notation:

  • C3 = Middle C (MIDI note 60)
  • A4 = 440 Hz (MIDI note 69)
  • Octaves range from -2 to 8
  • Each octave starts at C and ends at B
// 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)

Working with Note Arrays

Creating Note Arrays

// 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 })
);

Note Array Operations

// 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);

Integration with MIDI Messages

Playing Notes

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);

Note Event Handling

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}`);
});

Common Note Operations

Interval Calculations

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 semitones

Scale and Chord Generation

function 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");

Note Range Validation

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);
}

Types

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

docs

constants.md

index.md

message-forwarding.md

message-processing.md

midi-input.md

midi-output.md

note-processing.md

utilities.md

webmidi-interface.md

tile.json