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