Source: music21/instrument.js

/**
 * music21j -- Javascript reimplementation of Core music21p features.
 * music21/instrument -- instrument objects
 *
 * Copyright (c) 2013-16, Michael Scott Cuthbert and cuthbertLab
 * Based on music21 (=music21p), Copyright (c) 2006–16, Michael Scott Cuthbert and cuthbertLab
 *
 * Instrument module, see {@link music21.instrument}
 * Looking for the {@link music21.instrument.Instrument} object? :-)
 *
 * @exports music21/instrument
 *
 * @namespace music21.instrument
 * @memberof music21
 * @requires music21/base
 */
import * as base from './base';

/**
 *
 * @type {number[]}
 */
export const global_usedChannels = []; // differs from m21p -- stored midiProgram numbers
/**
 *
 * @type {number}
 */
export const maxMidi = 16;

/**
 *
 * @type {Array<{fn: string, name: string, midiNumber: number}>}
 */
export const info = [
    { fn: 'acoustic_grand_piano', name: 'Acoustic Grand Piano', midiNumber: 0 },
    {
        fn: 'bright_acoustic_piano',
        name: 'Bright Acoustic Piano',
        midiNumber: 1,
    },
    { fn: 'electric_grand_piano', name: 'Electric Grand Piano', midiNumber: 2 },
    { fn: 'honkytonk_piano', name: 'Honky-tonk Piano', midiNumber: 3 },
    { fn: 'electric_piano_1', name: 'Electric Piano 1', midiNumber: 4 },
    { fn: 'electric_piano_2', name: 'Electric Piano 2', midiNumber: 5 },
    { fn: 'harpsichord', name: 'Harpsichord', midiNumber: 6 },
    { fn: 'clavinet', name: 'Clavinet', midiNumber: 7 },
    { fn: 'celesta', name: 'Celesta', midiNumber: 8 },
    { fn: 'glockenspiel', name: 'Glockenspiel', midiNumber: 9 },
    { fn: 'music_box', name: 'Music Box', midiNumber: 10 },
    { fn: 'vibraphone', name: 'Vibraphone', midiNumber: 11 },
    { fn: 'marimba', name: 'Marimba', midiNumber: 12 },
    { fn: 'xylophone', name: 'Xylophone', midiNumber: 13 },
    { fn: 'tubular_bells', name: 'Tubular Bells', midiNumber: 14 },
    { fn: 'dulcimer', name: 'Dulcimer', midiNumber: 15 },
    { fn: 'drawbar_organ', name: 'Drawbar Organ', midiNumber: 16 },
    { fn: 'percussive_organ', name: 'Percussive Organ', midiNumber: 17 },
    { fn: 'rock_organ', name: 'Rock Organ', midiNumber: 18 },
    { fn: 'church_organ', name: 'Church Organ', midiNumber: 19 },
    { fn: 'reed_organ', name: 'Reed Organ', midiNumber: 20 },
    { fn: 'accordion', name: 'Accordion', midiNumber: 21 },
    { fn: 'harmonica', name: 'Harmonica', midiNumber: 22 },
    { fn: 'tango_accordion', name: 'Tango Accordion', midiNumber: 23 },
    {
        fn: 'acoustic_guitar_nylon',
        name: 'Acoustic Guitar (nylon)',
        midiNumber: 24,
    },
    {
        fn: 'acoustic_guitar_steel',
        name: 'Acoustic Guitar (steel)',
        midiNumber: 25,
    },
    {
        fn: 'electric_guitar_jazz',
        name: 'Electric Guitar (jazz)',
        midiNumber: 26,
    },
    {
        fn: 'electric_guitar_clean',
        name: 'Electric Guitar (clean)',
        midiNumber: 27,
    },
    {
        fn: 'electric_guitar_muted',
        name: 'Electric Guitar (muted)',
        midiNumber: 28,
    },
    { fn: 'overdriven_guitar', name: 'Overdriven Guitar', midiNumber: 29 },
    { fn: 'distortion_guitar', name: 'Distortion Guitar', midiNumber: 30 },
    { fn: 'guitar_harmonics', name: 'Guitar Harmonics', midiNumber: 31 },
    { fn: 'acoustic_bass', name: 'Acoustic Bass', midiNumber: 32 },
    {
        fn: 'electric_bass_finger',
        name: 'Electric Bass (finger)',
        midiNumber: 33,
    },
    { fn: 'electric_bass_pick', name: 'Electric Bass (pick)', midiNumber: 34 },
    { fn: 'fretless_bass', name: 'Fretless Bass', midiNumber: 35 },
    { fn: 'slap_bass_1', name: 'Slap Bass 1', midiNumber: 36 },
    { fn: 'slap_bass_2', name: 'Slap Bass 2', midiNumber: 37 },
    { fn: 'synth_bass_1', name: 'Synth Bass 1', midiNumber: 38 },
    { fn: 'synth_bass_2', name: 'Synth Bass 2', midiNumber: 39 },
    { fn: 'violin', name: 'Violin', midiNumber: 40 },
    { fn: 'viola', name: 'Viola', midiNumber: 41 },
    { fn: 'cello', name: 'Cello', midiNumber: 42 },
    { fn: 'contrabass', name: 'Contrabass', midiNumber: 43 },
    { fn: 'tremolo_strings', name: 'Tremolo Strings', midiNumber: 44 },
    { fn: 'pizzicato_strings', name: 'Pizzicato Strings', midiNumber: 45 },
    { fn: 'orchestral_harp', name: 'Orchestral Harp', midiNumber: 46 },
    { fn: 'timpani', name: 'Timpani', midiNumber: 47 },
    { fn: 'string_ensemble_1', name: 'String Ensemble 1', midiNumber: 48 },
    { fn: 'string_ensemble_2', name: 'String Ensemble 2', midiNumber: 49 },
    { fn: 'synth_strings_1', name: 'Synth Strings 1', midiNumber: 50 },
    { fn: 'synth_strings_2', name: 'Synth Strings 2', midiNumber: 51 },
    { fn: 'choir_aahs', name: 'Choir Aahs', midiNumber: 52 },
    { fn: 'voice_oohs', name: 'Voice Oohs', midiNumber: 53 },
    { fn: 'synth_choir', name: 'Synth Choir', midiNumber: 54 },
    { fn: 'orchestra_hit', name: 'Orchestra Hit', midiNumber: 55 },
    { fn: 'trumpet', name: 'Trumpet', midiNumber: 56 },
    { fn: 'trombone', name: 'Trombone', midiNumber: 57 },
    { fn: 'tuba', name: 'Tuba', midiNumber: 58 },
    { fn: 'muted_trumpet', name: 'Muted Trumpet', midiNumber: 59 },
    { fn: 'french_horn', name: 'French Horn', midiNumber: 60 },
    { fn: 'brass_section', name: 'Brass Section', midiNumber: 61 },
    { fn: 'synth_brass_1', name: 'Synth Brass 1', midiNumber: 62 },
    { fn: 'synth_brass_2', name: 'Synth Brass 2', midiNumber: 63 },
    { fn: 'soprano_sax', name: 'Soprano Sax', midiNumber: 64 },
    { fn: 'alto_sax', name: 'Alto Sax', midiNumber: 65 },
    { fn: 'tenor_sax', name: 'Tenor Sax', midiNumber: 66 },
    { fn: 'baritone_sax', name: 'Baritone Sax', midiNumber: 67 },
    { fn: 'oboe', name: 'Oboe', midiNumber: 68 },
    { fn: 'english_horn', name: 'English Horn', midiNumber: 69 },
    { fn: 'bassoon', name: 'Bassoon', midiNumber: 70 },
    { fn: 'clarinet', name: 'Clarinet', midiNumber: 71 },
    { fn: 'piccolo', name: 'Piccolo', midiNumber: 72 },
    { fn: 'flute', name: 'Flute', midiNumber: 73 },
    { fn: 'recorder', name: 'Recorder', midiNumber: 74 },
    { fn: 'pan_flute', name: 'Pan Flute', midiNumber: 75 },
    { fn: 'blown_bottle', name: 'Blown bottle', midiNumber: 76 },
    { fn: 'shakuhachi', name: 'Shakuhachi', midiNumber: 77 },
    { fn: 'whistle', name: 'Whistle', midiNumber: 78 },
    { fn: 'ocarina', name: 'Ocarina', midiNumber: 79 },
    { fn: 'lead_1_square', name: 'Lead 1 (square)', midiNumber: 80 },
    { fn: 'lead_2_sawtooth', name: 'Lead 2 (sawtooth)', midiNumber: 81 },
    { fn: 'lead_3_calliope', name: 'Lead 3 (calliope)', midiNumber: 82 },
    { fn: 'lead_4_chiff', name: 'Lead 4 chiff', midiNumber: 83 },
    { fn: 'lead_5_charang', name: 'Lead 5 (charang)', midiNumber: 84 },
    { fn: 'lead_6_voice', name: 'Lead 6 (voice)', midiNumber: 85 },
    { fn: 'lead_7_fifths', name: 'Lead 7 (fifths)', midiNumber: 86 },
    { fn: 'lead_8_bass__lead', name: 'Lead 8 (bass + lead)', midiNumber: 87 },
    { fn: 'pad_1_new_age', name: 'Pad 1 (new age)', midiNumber: 88 },
    { fn: 'pad_2_warm', name: 'Pad 2 (warm)', midiNumber: 89 },
    { fn: 'pad_3_polysynth', name: 'Pad 3 (polysynth)', midiNumber: 90 },
    { fn: 'pad_4_choir', name: 'Pad 4 (choir)', midiNumber: 91 },
    { fn: 'pad_5_bowed', name: 'Pad 5 (bowed)', midiNumber: 92 },
    { fn: 'pad_6_metallic', name: 'Pad 6 (metallic)', midiNumber: 93 },
    { fn: 'pad_7_halo', name: 'Pad 7 (halo)', midiNumber: 94 },
    { fn: 'pad_8_sweep', name: 'Pad 8 (sweep)', midiNumber: 95 },
    { fn: 'fx_1_rain', name: 'FX 1 (rain)', midiNumber: 96 },
    { fn: 'fx_2_soundtrack', name: 'FX 2 (soundtrack)', midiNumber: 97 },
    { fn: 'fx_3_crystal', name: 'FX 3 (crystal)', midiNumber: 98 },
    { fn: 'fx_4_atmosphere', name: 'FX 4 (atmosphere)', midiNumber: 99 },
    { fn: 'fx_5_brightness', name: 'FX 5 (brightness)', midiNumber: 100 },
    { fn: 'fx_6_goblins', name: 'FX 6 (goblins)', midiNumber: 101 },
    { fn: 'fx_7_echoes', name: 'FX 7 (echoes)', midiNumber: 102 },
    { fn: 'fx_8_scifi', name: 'FX 8 (sci-fi)', midiNumber: 103 },
    { fn: 'sitar', name: 'Sitar', midiNumber: 104 },
    { fn: 'banjo', name: 'Banjo', midiNumber: 105 },
    { fn: 'shamisen', name: 'Shamisen', midiNumber: 106 },
    { fn: 'koto', name: 'Koto', midiNumber: 107 },
    { fn: 'kalimba', name: 'Kalimba', midiNumber: 108 },
    { fn: 'bagpipe', name: 'Bagpipe', midiNumber: 109 },
    { fn: 'fiddle', name: 'Fiddle', midiNumber: 110 },
    { fn: 'shanai', name: 'Shanai', midiNumber: 111 },
    { fn: 'tinkle_bell', name: 'Tinkle Bell', midiNumber: 112 },
    { fn: 'agogo', name: 'Agogo', midiNumber: 113 },
    { fn: 'steel_drums', name: 'Steel Drums', midiNumber: 114 },
    { fn: 'woodblock', name: 'Woodblock', midiNumber: 115 },
    { fn: 'taiko_drum', name: 'Taiko Drum', midiNumber: 116 },
    { fn: 'melodic_tom', name: 'Melodic Tom', midiNumber: 117 },
    { fn: 'synth_drum', name: 'Synth Drum', midiNumber: 118 },
    { fn: 'reverse_cymbal', name: 'Reverse Cymbal', midiNumber: 119 },
    { fn: 'guitar_fret_noise', name: 'Guitar Fret Noise', midiNumber: 120 },
    { fn: 'breath_noise', name: 'Breath Noise', midiNumber: 121 },
    { fn: 'seashore', name: 'Seashore', midiNumber: 122 },
    { fn: 'bird_tweet', name: 'Bird Tweet', midiNumber: 123 },
    { fn: 'telephone_ring', name: 'Telephone Ring', midiNumber: 124 },
    { fn: 'helicopter', name: 'Helicopter', midiNumber: 125 },
    { fn: 'applause', name: 'Applause', midiNumber: 126 },
    { fn: 'gunshot', name: 'Gunshot', midiNumber: 127 },
];


/**
 * Represents an instrument.  instrumentNames are found in the ext/soundfonts directory
 *
 * See {@link music21.miditools} and esp. `loadSoundfont` for a way of loading soundfonts into
 * instruments.
 *
 * @class Instrument
 * @memberof music21.instrument
 * @extends music21.base.Music21Object
 * @param {string} instrumentName
 * @property {string|undefined} partId
 * @property {string|undefined} partName
 * @property {string|undefined} partAbbreviation
 * @property {string|undefined} instrumentId
 * @property {string|undefined} instrumentName
 * @property {string|undefined} instrumentAbbreviation
 * @property {int|undefined} midiProgram
 * @property {int|undefined} midiChannel
 * @property {int|undefined} lowestNote
 * @property {int|undefined} highestNote
 * @property {music21.interval.Interval|undefined} transposition
 * @property {Boolean} inGMPercMap=false
 * @property {string|undefined} soundfontFn
 * @property {string|undefined} oggSoundfont - url of oggSoundfont for this instrument
 * @property {string|undefined} mp3Soundfont - url of mp3Soundfont for this instrument
 */
export class Instrument extends base.Music21Object {
    constructor(instrumentName) {
        super();
        this.classSortOrder = -25;

        this.partId = undefined;
        this.partName = undefined;
        this.partAbbreviation = undefined;

        this.instrumentId = undefined;
        this.instrumentName = instrumentName;
        this.instrumentAbbreviation = undefined;
        this.midiProgram = undefined;
        this._midiChannel = undefined;

        this.lowestNote = undefined;
        this.highestNote = undefined;

        this.transpostion = undefined;

        this.inGMPercMap = false;
        this.soundfontFn = undefined;

        if (instrumentName !== undefined) {
            find(instrumentName, this);
        }
    }

    /**
     * Assign an instrument to an unused midi channel.
     *
     * Will use the global list of used channels (`music21.instrument.Instrument.usedChannels`)
     * if not given.  Assigns up to `music21.instrument.maxMidi` channels (16)
     * Skips 10 unless this.inGMPercMap is true
     *
     * @param {int[]} [usedChannels]
     * @returns {number|undefined}
     */
    autoAssignMidiChannel(usedChannels) {
        if (usedChannels === undefined) {
            usedChannels = global_usedChannels;
        }
        let startChannel = 0;
        if (this.inGMPercMap) {
            startChannel = 10;
        }
        for (let ch = startChannel; ch < maxMidi; ch++) {
            if (ch % 16 === 10 && this.inGMPercMap !== true) {
                continue; // skip 10 / percussion.
            }
            if (
                usedChannels[ch] === undefined
                || usedChannels[ch] === this.midiProgram
            ) {
                usedChannels[ch] = this.midiProgram;
                this.midiChannel = ch;
                return ch;
            }
        }
        // TODO: no channels! throw exception!
        return undefined;
    }

    get oggSoundfont() {
        return this.soundfontFn + '-ogg.js';
    }

    get mp3Soundfont() {
        return this.soundfontFn + '-mp3.js';
    }

    get midiChannel() {
        if (this._midiChannel === undefined) {
            this.autoAssignMidiChannel();
        }
        return this._midiChannel;
    }

    set midiChannel(ch) {
        this._midiChannel = ch;
    }
}

/**
 * Find information for a given instrument (by filename or name)
 * and load it into an instrument object.
 *
 * @function music21.instrument.find
 * @memberof music21.instrument
 * @param {string} fn - name or filename of instrument
 * @param {music21.instrument.Instrument} [inst] - instrument object to load into
 * @returns {music21.instrument.Instrument|undefined}
 */
export function find(fn, inst) {
    if (inst === undefined) {
        inst = new Instrument();
    }
    for (const innerInfo of info) {
        if (innerInfo.fn === fn || innerInfo.name === fn) {
            inst.soundfontFn = innerInfo.fn;
            inst.instrumentName = innerInfo.name;
            inst.midiProgram = innerInfo.midiNumber;
            return inst;
        }
    }
    return undefined;
}
Music21j, Copyright © 2013-2021 Michael Scott Asato Cuthbert.
Documentation generated by JSDoc 3.6.3 on Wed Jul 31st 2019 using the DocStrap template.