/**
* Module containing functionality to apply {@link WebAudioAPI} note modifications.
* @module Modification
*/
import { ModificationType } from './Constants.mjs';
import { Accent } from '../modifications/Accent.mjs';
import { Crescendo } from '../modifications/Crescendo.mjs';
import { Fermata } from '../modifications/Fermata.mjs';
import { Glissando } from '../modifications/Glissando.mjs';
import { GlobalDynamic } from '../modifications/GlobalDynamic.mjs';
import { Grace } from '../modifications/Grace.mjs';
import { Marcato } from '../modifications/Marcato.mjs';
import { Mordent } from '../modifications/Mordent.mjs';
import { Natural } from '../modifications/Natural.mjs';
import { OctaveShift } from '../modifications/OctaveShift.mjs';
import { Portamento } from '../modifications/Portamento.mjs';
import { Sforzando } from '../modifications/Sforzando.mjs';
import { Slur } from '../modifications/Slur.mjs';
import { Staccato } from '../modifications/Staccato.mjs';
import { Tenuto } from '../modifications/Tenuto.mjs';
import { Tie } from '../modifications/Tie.mjs';
import { Trill } from '../modifications/Trill.mjs';
import { Tuplet } from '../modifications/Tuplet.mjs';
import { TupletNote } from '../modifications/TupletNote.mjs';
import { Turn } from '../modifications/Turn.mjs';
import { Velocity } from '../modifications/Velocity.mjs';
import { NoteDetails } from '../modifications/ModificationBase.mjs';
export { GlobalDynamic, NoteDetails };
const ModificationClasses = {
[ModificationType.Accent]: [Accent, Accent],
[ModificationType.Marcato]: [Marcato, Marcato],
[ModificationType.Staccato]: [Staccato, Staccato.bind(null, false)],
[ModificationType.Staccatissimo]: [Staccato, Staccato.bind(null, true)],
[ModificationType.Tenuto]: [Tenuto, Tenuto],
[ModificationType.Sforzando]: [Sforzando, Sforzando],
[ModificationType.Slur]: [Slur, Slur],
[ModificationType.Portamento]: [Portamento, Portamento],
[ModificationType.Crescendo]: [Crescendo, Crescendo.bind(null, false)],
[ModificationType.Decrescendo]: [Crescendo, Crescendo.bind(null, true)],
[ModificationType.Diminuendo]: [Crescendo, Crescendo.bind(null, true)],
[ModificationType.TrillUpper]: [Trill, Trill.bind(null, true)],
[ModificationType.TrillLower]: [Trill, Trill.bind(null, false)],
[ModificationType.MordentUpper]: [Mordent, Mordent.bind(null, true)],
[ModificationType.MordentLower]: [Mordent, Mordent.bind(null, false)],
[ModificationType.TurnUpper]: [Turn, Turn.bind(null, true)],
[ModificationType.TurnLower]: [Turn, Turn.bind(null, false)],
[ModificationType.Glissando]: [Glissando, Glissando],
[ModificationType.GraceAcciaccatura]: [Grace, Grace.bind(null, false)],
[ModificationType.GraceAppoggiatura]: [Grace, Grace.bind(null, true)],
[ModificationType.Tie]: [Tie, Tie],
[ModificationType.Velocity]: [Velocity, Velocity],
[ModificationType.Natural]: [Natural, Natural],
[ModificationType.Piano]: [GlobalDynamic, GlobalDynamic.bind(null, -1)],
[ModificationType.MezzoPiano]: [GlobalDynamic, GlobalDynamic.bind(null, -0.5)],
[ModificationType.OctaveShiftUp]: [OctaveShift, OctaveShift.bind(null, true)],
[ModificationType.OctaveShiftDown]: [OctaveShift, OctaveShift.bind(null, false)],
[ModificationType.Pianissimo]: [GlobalDynamic, GlobalDynamic.bind(null, -2)],
[ModificationType.Pianississimo]: [GlobalDynamic, GlobalDynamic.bind(null, -3)],
[ModificationType.Forte]: [GlobalDynamic, GlobalDynamic.bind(null, 1)],
[ModificationType.MezzoForte]: [GlobalDynamic, GlobalDynamic.bind(null, 0.5)],
[ModificationType.Fortissimo]: [GlobalDynamic, GlobalDynamic.bind(null, 2)],
[ModificationType.Fortississimo]: [GlobalDynamic, GlobalDynamic.bind(null, 3)],
[ModificationType.Tuplet]: [Tuplet, Tuplet],
[ModificationType.Triplet]: [TupletNote, TupletNote.bind(null, 3)],
[ModificationType.Quintuplet]: [TupletNote, TupletNote.bind(null, 5)],
[ModificationType.Sextuplet]: [TupletNote, TupletNote.bind(null, 6)],
[ModificationType.Septuplet]: [TupletNote, TupletNote.bind(null, 7)],
[ModificationType.Fermata]: [Fermata, Fermata]
};
/**
* Returns whether the corresponding {@link module:Constants.ModificationType ModificationType}
* can be used to modify a sequence of notes.
*
* @param {number} modificationType - The {@link module:Constants.ModificationType ModificationType} about which to query
* @returns {boolean} Whether the corresponding modification type can be used to modify a sequence of notes
* @see {@link module:Constants.ModificationType ModificationType}
*/
export function canModifySequence(modificationType) {
return ModificationClasses[modificationType][0].canModifySequence();
}
/**
* Returns a list of modification-specific parameters for use with the corresponding
* {@link module:Constants.ModificationType ModificationType}.
*
* Note that the `modificationType` parameter must be the **numeric value** associated
* with a certain {@link module:Constants.ModificationType ModificationType}, not a
* string-based key.
*
* The object returned from this function will contain 2 keys: 'required' and 'optional'.
* These keys can be used to access sub-objects with 2 keys: 'singleNote' and 'sequence'.
* These keys hold arrays containing the string-based names of parameters that are available
* for manipulation within the given modification.
*
* Parameter values within the "sequence" array indicate parameters that have meaning when
* used with the {@link WebAudioAPI#playSequence playSequence()} function. Parameter values
* within the "singleNote" array indicate parameters that have meaning when used with the
* {@link WebAudioAPI#playNote playNote()} function.
*
* @param {number} modificationType - The {@link module:Constants.ModificationType ModificationType} for which to return a parameter list
* @returns {Object<string,Object<string,string[]>>} List of modification-specific parameter keys and when they are required
* @see {@link module:Constants.ModificationType ModificationType}
*/
export function getModificationParameters(modificationType) {
return ModificationClasses[modificationType][0].getParameters();
}
/**
* Attempts to infer the required modification parameter values from a given sequence of notes.
*
* @param {number} modificationType - Numeric value corresponding to the desired {@link module:Constants.ModificationType ModificationType}
* @param {Array<Array|Array<Array>>} sequence - Array of `[note, duration]` and/or chords corresponding to the sequence to be played
* @param {number} index - Index of the current note in the sequence
* @param {Object|null} params - Object containing the currently known parameter values
* @returns {Object} Object containing the inferred and known parameter values
* @see {@link module:Constants.ModificationType ModificationType}
*/
export function inferModificationParametersFromSequence(modificationType, sequence, index, params) {
return ModificationClasses[modificationType][0].inferParametersFromSequence(sequence, index, params);
}
/**
* Loads a concrete {@link ModificationBase} instance capable of modifying an individual note
* and duration.
*
* @param {number} modificationType - Numeric value corresponding to the desired {@link module:Constants.ModificationType ModificationType}
* @param {Tempo} tempo - Reference to the current global {@link Tempo} object
* @param {Key} key - Reference to the current global {@link Key} object
* @param {NoteDetails} details - Unmodified details about the note to be played
* @returns {ModificationBase} Newly created note {@link ModificationBase} object
* @see {@link module:Constants.ModificationType ModificationType}
* @see {@link ModificationBase}
* @see {@link NoteDetails}
* @see {@link Tempo}
*/
export function loadModification(modificationType, tempo, key, details) {
// Load the requested concrete modification type
return new ModificationClasses[modificationType][1](tempo, key, details);
}