UNPKG

xen-midi

Version:

Free-pitch polyphonic MIDI I/O based on webmidi.js using multi-channel pitch-bend

144 lines (143 loc) 5.16 kB
import { Output, Input } from 'webmidi'; /** * Pitch bend range measured in semitones (+-). */ export declare const BEND_RANGE_IN_SEMITONES = 2; /** * Abstraction for a pitch-bent midi channel. * Polyphonic in pure octaves and 12edo in general. */ export type Voice = { age: number; channel: number; centsOffset: number; }; /** * Free-pitch MIDI note to be played at a later time. */ export type Note = { /** Frequency in Hertz (Hz) */ frequency: number; /** Attack velocity from 0 to 127. */ rawAttack?: number; /** Release velocity from 0 to 127. */ rawRelease?: number; /** Note-on time in milliseconds (ms) as measured by `WebMidi.time`. * If time is a string prefixed with "+" and followed by a number, the message will be delayed by that many milliseconds. */ time: DOMHighResTimeStamp | string; /** Note duration in milliseconds (ms). */ duration: DOMHighResTimeStamp; }; declare function emptyNoteOff(rawRelease?: number, time?: DOMHighResTimeStamp): void; /** * Returned by MIDI note on. Turns the note off when called. */ export type NoteOff = typeof emptyNoteOff; /** * Wrapper for a webmidi.js output. * Uses multiple channels to achieve polyphonic microtuning. */ export declare class MidiOut { output: Output | null; channels: Set<number>; log: (msg: string) => void; private voices; private lastEventTime; /** * Constuct a new wrapper for a webmidi.js output. * @param output Output device or `null` if you need a dummy out. * @param channels Channels to use for sending pitch bent MIDI notes. Number of channels determines maximum microtonal polyphony. * @param log Logging function. */ constructor(output: Output | null, channels: Set<number>, log?: (msg: string) => void); private sendPitchBendRange; /** * Select a voice that's using a cents offset compatible channel or the oldest voice if nothing can be re-used. * @param centsOffset Cents offset (pitch-bend) from 12edo. * @returns A voice for the next note-on event. */ private selectVoice; /** * Send a note-on event and pitch-bend to the output device on one of the available channels. * @param frequency Frequency of the note in Hertz (Hz). * @param rawAttack Attack velocity of the note from 0 to 127. * @returns A callback for sending a corresponding note off on the correct channel. */ sendNoteOn(frequency: number, rawAttack?: number, time?: DOMHighResTimeStamp): NoteOff; /** * Schedule a series of notes to be played at a later time. * Please note that this reserves the channels until all notes have finished playing. * @param notes Notes to be played. */ playNotes(notes: Note[]): void; /** * Clear scheduled notes that have not yet been played. * Will start working once the Chrome bug is fixed: https://bugs.chromium.org/p/chromium/issues/detail?id=471798 */ clear(): void; } /** * Function to call when a MIDI note-on event is received (e.g. for turning on your synth). * Attack velocity is from 0 to 127. * Must return a note-off callback (e.g. for turning off your synth). */ export type NoteOnCallback = (index: number, rawAttack: number, channel: number) => NoteOff; /** * Wrapper for webmidi.js input. * Listens on multiple channels. */ export declare class MidiIn { callback: NoteOnCallback; channels: Set<number>; /** Note-off map from (noteNumber + (midiChannel - 1) * 128) to callbacks. */ private noteOffMap; private _noteOn; private _noteOff; log: (msg: string) => void; /** * Construct a new wrapper for a webmidi.js input device. * @param callback Function to call when a note-on event is received on any of the available channels. * @param channels Channels to listen on. * @param log Logging function. */ constructor(callback: NoteOnCallback, channels: Set<number>, log?: (msg: string) => void); /** * Make this wrapper (and your callback) respond to note-on/off events from this MIDI input. * @param input MIDI input to listen to. */ listen(input: Input): void; /** * Make this wrapper (and your callback) stop responding to note-on/off events from this MIDI input. * @param input MIDI input that was listened to. */ unlisten(input: Input): void; private noteOn; private noteOff; /** * Fire global note-off. */ deactivate(): void; } /** * Information about a MIDI key. */ export type MidiKeyInfo = { /** Contiguous index of the key with other white keys. */ whiteNumber: number; sharpOf?: undefined; flatOf?: undefined; } | { whiteNumber?: undefined; /** This black key is a sharp of that white key. */ sharpOf: number; /** This black key is a flat of that white key. */ flatOf: number; }; /** * Get information about a MIDI key. * @param chromaticNumber Contiguous chromatic index of the MIDI key * @returns Information about the MIDI key. */ export declare function midiKeyInfo(chromaticNumber: number): MidiKeyInfo; export {};