UNPKG

spessasynth_core

Version:

MIDI and SoundFont2/DLS library with no compromises

1,645 lines (1,610 loc) 133 kB
/** * Indexed_array.ts * purpose: extends Uint8Array with a currentIndex property. */ declare class IndexedByteArray extends Uint8Array { /** * The current index of the array. */ currentIndex: number; /** * Returns a section of an array. * @param start The beginning of the specified portion of the array. * @param end The end of the specified portion of the array. This is exclusive of the element at the index 'end'. */ slice(start?: number, end?: number): IndexedByteArray; } /** * Writes an audio into a valid WAV file. * @param audioData the audio data channels. * @param sampleRate the sample rate, in Hertz. * @param options Additional options for writing the file. * @returns the binary file. */ declare function audioToWav(audioData: Float32Array[], sampleRate: number, options?: Partial<WaveWriteOptions>): ArrayBuffer; /** * Reads number as Big endian. * @param dataArray the array to read from. * @param bytesAmount the number of bytes to read. * @param offset the offset to start reading from. * @returns the number. */ declare function readBigEndian(dataArray: number[] | ArrayLike<number>, bytesAmount: number, offset?: number): number; /** * Reads the number as little endian from an IndexedByteArray. * @param dataArray the array to read from. * @param bytesAmount the number of bytes to read. * @returns the number. */ declare function readLittleEndianIndexed(dataArray: IndexedByteArray, bytesAmount: number): number; /** * Reads bytes as an ASCII string from an IndexedByteArray. * @param dataArray the IndexedByteArray to read from. * @param bytes the amount of bytes to read. * @returns the string. */ declare function readBinaryStringIndexed(dataArray: IndexedByteArray, bytes: number): string; /** * Reads VLQ from a MIDI byte array. * @param MIDIbyteArray the array to read from. * @returns the number. */ declare function readVariableLengthQuantity(MIDIbyteArray: IndexedByteArray): number; /** * Enables or disables logging. * @param enableInfo enables info. * @param enableWarn enables warning. * @param enableGroup enables groups. */ declare function SpessaSynthLogging(enableInfo: boolean, enableWarn: boolean, enableGroup: boolean): void; declare function SpessaSynthInfo(...message: unknown[]): void; declare function SpessaSynthWarn(...message: unknown[]): void; declare function SpessaSynthGroup(...message: unknown[]): void; declare function SpessaSynthGroupCollapsed(...message: unknown[]): void; declare function SpessaSynthGroupEnd(): void; /** * All SoundFont2 Generator enumerations. */ declare const generatorTypes: { readonly INVALID: -1; readonly startAddrsOffset: 0; readonly endAddrOffset: 1; readonly startloopAddrsOffset: 2; readonly endloopAddrsOffset: 3; readonly startAddrsCoarseOffset: 4; readonly modLfoToPitch: 5; readonly vibLfoToPitch: 6; readonly modEnvToPitch: 7; readonly initialFilterFc: 8; readonly initialFilterQ: 9; readonly modLfoToFilterFc: 10; readonly modEnvToFilterFc: 11; readonly endAddrsCoarseOffset: 12; readonly modLfoToVolume: 13; readonly unused1: 14; readonly chorusEffectsSend: 15; readonly reverbEffectsSend: 16; readonly pan: 17; readonly unused2: 18; readonly unused3: 19; readonly unused4: 20; readonly delayModLFO: 21; readonly freqModLFO: 22; readonly delayVibLFO: 23; readonly freqVibLFO: 24; readonly delayModEnv: 25; readonly attackModEnv: 26; readonly holdModEnv: 27; readonly decayModEnv: 28; readonly sustainModEnv: 29; readonly releaseModEnv: 30; readonly keyNumToModEnvHold: 31; readonly keyNumToModEnvDecay: 32; readonly delayVolEnv: 33; readonly attackVolEnv: 34; readonly holdVolEnv: 35; readonly decayVolEnv: 36; readonly sustainVolEnv: 37; readonly releaseVolEnv: 38; readonly keyNumToVolEnvHold: 39; readonly keyNumToVolEnvDecay: 40; readonly instrument: 41; readonly reserved1: 42; readonly keyRange: 43; readonly velRange: 44; readonly startloopAddrsCoarseOffset: 45; readonly keyNum: 46; readonly velocity: 47; readonly initialAttenuation: 48; readonly reserved2: 49; readonly endloopAddrsCoarseOffset: 50; readonly coarseTune: 51; readonly fineTune: 52; readonly sampleID: 53; readonly sampleModes: 54; readonly reserved3: 55; readonly scaleTuning: 56; readonly exclusiveClass: 57; readonly overridingRootKey: 58; readonly unused5: 59; readonly endOper: 60; readonly vibLfoToVolume: 61; readonly vibLfoToFilterFc: 62; }; type GeneratorType = (typeof generatorTypes)[keyof typeof generatorTypes]; declare const GENERATORS_AMOUNT: number; declare const MAX_GENERATOR: number; /** * Min: minimum value, max: maximum value, def: default value, nrpn: nrpn scale... */ declare const generatorLimits: { min: number; max: number; def: number; nrpn: number; }[]; declare class Generator { /** * The generator's SF2 type. */ generatorType: GeneratorType; /** * The generator's 16-bit value. */ generatorValue: number; /** * Constructs a new generator * @param type generator type * @param value generator value * @param validate if the limits should be validated */ constructor(type: GeneratorType, value: number, validate?: boolean); write(genData: IndexedByteArray): void; toString(): string; } declare const sampleTypes: { readonly monoSample: 1; readonly rightSample: 2; readonly leftSample: 4; readonly linkedSample: 8; readonly romMonoSample: 32769; readonly romRightSample: 32770; readonly romLeftSample: 32772; readonly romLinkedSample: 32776; }; type SampleType = (typeof sampleTypes)[keyof typeof sampleTypes]; declare const modulatorSources: { readonly noController: 0; readonly noteOnVelocity: 2; readonly noteOnKeyNum: 3; readonly polyPressure: 10; readonly channelPressure: 13; readonly pitchWheel: 14; readonly pitchWheelRange: 16; readonly link: 127; }; type ModulatorSourceEnum = (typeof modulatorSources)[keyof typeof modulatorSources]; declare const modulatorCurveTypes: { readonly linear: 0; readonly concave: 1; readonly convex: 2; readonly switch: 3; }; type ModulatorCurveType = (typeof modulatorCurveTypes)[keyof typeof modulatorCurveTypes]; declare const modulatorTransformTypes: { readonly linear: 0; readonly absolute: 2; }; type ModulatorTransformType = (typeof modulatorTransformTypes)[keyof typeof modulatorTransformTypes]; type DLSTransform = ModulatorCurveType; declare const dlsSources: { readonly none: 0; readonly modLfo: 1; readonly velocity: 2; readonly keyNum: 3; readonly volEnv: 4; readonly modEnv: 5; readonly pitchWheel: 6; readonly polyPressure: 7; readonly channelPressure: 8; readonly vibratoLfo: 9; readonly modulationWheel: 129; readonly volume: 135; readonly pan: 138; readonly expression: 139; readonly chorus: 221; readonly reverb: 219; readonly pitchWheelRange: 256; readonly fineTune: 257; readonly coarseTune: 258; }; type DLSSource = (typeof dlsSources)[keyof typeof dlsSources]; declare const dlsDestinations: { readonly none: 0; readonly gain: 1; readonly reserved: 2; readonly pitch: 3; readonly pan: 4; readonly keyNum: 5; readonly chorusSend: 128; readonly reverbSend: 129; readonly modLfoFreq: 260; readonly modLfoDelay: 261; readonly vibLfoFreq: 276; readonly vibLfoDelay: 277; readonly volEnvAttack: 518; readonly volEnvDecay: 519; readonly reservedEG1: 520; readonly volEnvRelease: 521; readonly volEnvSustain: 522; readonly volEnvDelay: 523; readonly volEnvHold: 524; readonly modEnvAttack: 778; readonly modEnvDecay: 779; readonly reservedEG2: 780; readonly modEnvRelease: 781; readonly modEnvSustain: 782; readonly modEnvDelay: 783; readonly modEnvHold: 784; readonly filterCutoff: 1280; readonly filterQ: 1281; }; type DLSDestination = (typeof dlsDestinations)[keyof typeof dlsDestinations]; declare const DLSLoopTypes: { readonly forward: 0; readonly loopAndRelease: 1; }; type DLSLoopType = (typeof DLSLoopTypes)[keyof typeof DLSLoopTypes]; declare class BasicZone { /** * The zone's velocity range. * min -1 means that it is a default value */ velRange: GenericRange; /** * The zone's key range. * min -1 means that it is a default value. */ keyRange: GenericRange; /** * The zone's generators. */ generators: Generator[]; /** * The zone's modulators. */ modulators: Modulator[]; get hasKeyRange(): boolean; get hasVelRange(): boolean; /** * The current tuning in cents, taking in both coarse and fine generators. */ get fineTuning(): number; /** * The current tuning in cents, taking in both coarse and fine generators. */ set fineTuning(tuningCents: number); /** * Adds to a given generator, or its default value. */ addToGenerator(type: GeneratorType, value: number, validate?: boolean): void; /** * Sets a generator to a given value if preset, otherwise adds a new one. */ setGenerator(type: GeneratorType, value: number | null, validate?: boolean): void; /** * Adds generators to the zone. * @param generators */ addGenerators(...generators: Generator[]): void; addModulators(...modulators: Modulator[]): void; getGenerator<K>(generatorType: GeneratorType, notFoundValue: number | K): number | K; copyFrom(zone: BasicZone): void; /** * Filters the generators and prepends the range generators. */ getWriteGenerators(bank: BasicSoundBank): Generator[]; } declare class BasicGlobalZone extends BasicZone { } declare class BasicInstrumentZone extends BasicZone { /** * The instrument this zone belongs to. */ readonly parentInstrument: BasicInstrument; /** * For tracking on the individual zone level, since multiple presets can refer to the same instrument. */ useCount: number; /** * Creates a new instrument zone. * @param instrument The parent instrument. * @param sample The sample to use in this zone. */ constructor(instrument: BasicInstrument, sample: BasicSample); /** * Zone's sample. */ private _sample; /** * Zone's sample. */ get sample(): BasicSample; /** * Sets a sample for this zone. * @param sample the sample to set. */ set sample(sample: BasicSample); getWriteGenerators(bank: BasicSoundBank): Generator[]; } declare class BasicPresetZone extends BasicZone { /** * The preset this zone belongs to. */ readonly parentPreset: BasicPreset; /** * Creates a new preset zone. * @param preset the preset this zone belongs to. * @param instrument the instrument to use in this zone. */ constructor(preset: BasicPreset, instrument: BasicInstrument); /** * Zone's instrument. */ private _instrument; /** * Zone's instrument. */ get instrument(): BasicInstrument; /** * Zone's instrument. */ set instrument(instrument: BasicInstrument); getWriteGenerators(bank: BasicSoundBank): Generator[]; } interface MIDIPatch { /** * The MIDI program number. */ program: number; /** * The MIDI bank MSB number. */ bankMSB: number; /** * The MIDI bank LSB number. */ bankLSB: number; /** * If the preset is marked as GM/GS drum preset. Note that XG drums do not have this flag. */ isGMGSDrum: boolean; } interface MIDIPatchNamed extends MIDIPatch { /** * The name of the patch. */ name: string; } declare class MIDIPatchTools { /** * Converts a MIDI patch to a string. */ static toMIDIString(patch: MIDIPatch): string; /** * Gets a MIDI patch from a string. * @param string */ static fromMIDIString(string: string): MIDIPatch; /** * Converts a named MIDI patch to string. * @param patch */ static toNamedMIDIString(patch: MIDIPatchNamed): string; /** * Checks if two MIDI patches match. * @param patch1 * @param patch2 */ static matches(patch1: MIDIPatch, patch2: MIDIPatch): boolean; /** * Gets a named MIDI patch from a string. * @param string */ static fromNamedMIDIString(string: string): MIDIPatchNamed; static sorter(a: MIDIPatch, b: MIDIPatch): number; } /** * Returned structure containing extended SF2 chunks. */ interface ExtendedSF2Chunks { /** * The PDTA part of the chunk. */ pdta: IndexedByteArray; /** * The XDTA (https://github.com/spessasus/soundfont-proposals/blob/main/extended_limits.md) part of the chunk. */ xdta: IndexedByteArray; } /** * Write indexes for tracking writing a SoundFont file. */ interface SoundFontWriteIndexes { /** * Generator start index. */ gen: number; /** * Modulator start index. */ mod: number; /** * Zone start index. */ bag: number; /** * Preset/instrument start index. */ hdr: number; } declare class BasicPreset implements MIDIPatchNamed { /** * The parent soundbank instance * Currently used for determining default modulators and XG status */ readonly parentSoundBank: BasicSoundBank; /** * The preset's name */ name: string; program: number; bankMSB: number; bankLSB: number; isGMGSDrum: boolean; /** * The preset's zones */ zones: BasicPresetZone[]; /** * Preset's global zone */ readonly globalZone: BasicGlobalZone; /** * Unused metadata */ library: number; /** * Unused metadata */ genre: number; /** * Unused metadata */ morphology: number; /** * Creates a new preset representation. * @param parentSoundBank the sound bank this preset belongs to. * @param globalZone optional, a global zone to use. */ constructor(parentSoundBank: BasicSoundBank, globalZone?: BasicGlobalZone); get isXGDrums(): boolean; /** * Checks if this preset is a drum preset */ get isAnyDrums(): boolean; /** * Unlinks everything from this preset. */ delete(): void; /** * Deletes an instrument zone from this preset. * @param index the zone's index to delete. */ deleteZone(index: number): void; /** * Creates a new preset zone and returns it. * @param instrument the instrument to use in the zone. */ createZone(instrument: BasicInstrument): BasicPresetZone; /** * Preloads (loads and caches synthesis data) for a given key range. */ preload(keyMin: number, keyMax: number): void; /** * Checks if the bank and program numbers are the same for the given preset as this one. * @param preset The preset to check. */ matches(preset: MIDIPatch): boolean; /** * Returns the synthesis data from this preset * @param midiNote the MIDI note number * @param velocity the MIDI velocity * @returns the returned sound data */ getSynthesisData(midiNote: number, velocity: number): VoiceSynthesisData[]; /** * BankMSB:bankLSB:program:isGMGSDrum */ toMIDIString(): string; toString(): string; /** * Combines preset into an instrument, flattening the preset zones into instrument zones. * This is a really complex function that attempts to work around the DLS limitations of only having the instrument layer. * @returns The instrument containing the flattened zones. In theory, it should exactly the same as this preset. */ toFlattenedInstrument(): BasicInstrument; /** * Writes the SF2 header * @param phdrData * @param index */ write(phdrData: ExtendedSF2Chunks, index: number): void; } /** * Represents a single instrument */ declare class BasicInstrument { /** * The instrument's name */ name: string; /** * The instrument's zones */ zones: BasicInstrumentZone[]; /** * Instrument's global zone */ readonly globalZone: BasicGlobalZone; /** * Instrument's linked presets (the presets that use it) * note that duplicates are allowed since one preset can use the same instrument multiple times. */ readonly linkedTo: BasicPreset[]; /** * How many presets is this instrument used by */ get useCount(): number; /** * Creates a new instrument zone and returns it. * @param sample The sample to use in the zone. */ createZone(sample: BasicSample): BasicInstrumentZone; /** * Links the instrument ta a given preset * @param preset the preset to link to */ linkTo(preset: BasicPreset): void; /** * Unlinks the instrument from a given preset * @param preset the preset to unlink from */ unlinkFrom(preset: BasicPreset): void; deleteUnusedZones(): void; delete(): void; /** * Deletes a given instrument zone if it has no uses * @param index the index of the zone to delete * @param force ignores the use count and deletes forcibly * @returns if the zone has been deleted */ deleteZone(index: number, force?: boolean): boolean; /** * Globalizes the instrument *in-place.* * This means trying to move as many generators and modulators * to the global zone as possible to reduce clutter and the count of parameters. */ globalize(): void; write(instData: ExtendedSF2Chunks, index: number): void; } declare class BasicSample { /** * The sample's name. */ name: string; /** * Sample rate in Hz. */ sampleRate: number; /** * Original pitch of the sample as a MIDI note number. */ originalKey: number; /** * Pitch correction, in cents. Can be negative. */ pitchCorrection: number; /** * Linked sample, unused if mono. */ linkedSample?: BasicSample; /** * The type of the sample. */ sampleType: SampleType; /** * Relative to the start of the sample in sample points. */ loopStart: number; /** * Relative to the start of the sample in sample points. */ loopEnd: number; /** * Sample's linked instruments (the instruments that use it) * note that duplicates are allowed since one instrument can use the same sample multiple times. */ linkedTo: BasicInstrument[]; /** * Indicates if the data was overridden, so it cannot be copied back unchanged. */ protected dataOverridden: boolean; /** * The compressed sample data if the sample has been compressed. */ protected compressedData?: Uint8Array; /** * The sample's audio data. */ protected audioData?: Float32Array; /** * The basic representation of a sample * @param sampleName The sample's name * @param sampleRate The sample's rate in Hz * @param originalKey The sample's pitch as a MIDI note number * @param pitchCorrection The sample's pitch correction in cents * @param sampleType The sample's type, an enum that can indicate SF3 * @param loopStart The sample's loop start relative to the sample start in sample points * @param loopEnd The sample's loop end relative to the sample start in sample points */ constructor(sampleName: string, sampleRate: number, originalKey: number, pitchCorrection: number, sampleType: SampleType, loopStart: number, loopEnd: number); /** * Indicates if the sample is compressed using vorbis SF3. */ get isCompressed(): boolean; /** * If the sample is linked to another sample. */ get isLinked(): boolean; /** * The sample's use count */ get useCount(): number; /** * Get raw data for writing the file, either a compressed bit stream or signed 16-bit little endian PCM data. * @param allowVorbis if vorbis file data is allowed. * @return either s16le or vorbis data. */ getRawData(allowVorbis: boolean): Uint8Array; /** * Resamples the audio data to a given sample rate. */ resampleData(newSampleRate: number): void; /** * Compresses the audio data * @param encodeVorbis the compression function to use when compressing */ compressSample(encodeVorbis: SampleEncodingFunction): Promise<void>; /** * Sets the sample type and unlinks if needed. * @param type The type to set it to. */ setSampleType(type: SampleType): void; /** * Unlinks the sample from its stereo link if it has any. */ unlinkSample(): void; /** * Links a stereo sample. * @param sample the sample to link to. * @param type either left, right or linked. */ setLinkedSample(sample: BasicSample, type: SampleType): void; /** * Links the sample to a given instrument * @param instrument the instrument to link to */ linkTo(instrument: BasicInstrument): void; /** * Unlinks the sample from a given instrument * @param instrument the instrument to unlink from */ unlinkFrom(instrument: BasicInstrument): void; /** * Get the float32 audio data. * Note that this either decodes the compressed data or passes the ready sampleData. * If neither are set then it will throw an error! * @returns the audio data */ getAudioData(): Float32Array; /** * Replaces the audio data *in-place*. * @param audioData The new audio data as Float32. * @param sampleRate The new sample rate, in Hertz. */ setAudioData(audioData: Float32Array, sampleRate: number): void; /** * Replaces the audio with a compressed data sample and flags the sample as compressed * @param data the new compressed data */ setCompressedData(data: Uint8Array): void; /** * Encodes s16le sample * @return the encoded data */ protected encodeS16LE(): IndexedByteArray; /** * Decode binary vorbis into a float32 pcm */ protected decodeVorbis(): Float32Array; } declare class EmptySample extends BasicSample { /** * A simplified class for creating samples. */ constructor(); } declare const midiMessageTypes: { readonly noteOff: 128; readonly noteOn: 144; readonly polyPressure: 160; readonly controllerChange: 176; readonly programChange: 192; readonly channelPressure: 208; readonly pitchWheel: 224; readonly systemExclusive: 240; readonly timecode: 241; readonly songPosition: 242; readonly songSelect: 243; readonly tuneRequest: 246; readonly clock: 248; readonly start: 250; readonly continue: 251; readonly stop: 252; readonly activeSensing: 254; readonly reset: 255; readonly sequenceNumber: 0; readonly text: 1; readonly copyright: 2; readonly trackName: 3; readonly instrumentName: 4; readonly lyric: 5; readonly marker: 6; readonly cuePoint: 7; readonly programName: 8; readonly midiChannelPrefix: 32; readonly midiPort: 33; readonly endOfTrack: 47; readonly setTempo: 81; readonly smpteOffset: 84; readonly timeSignature: 88; readonly keySignature: 89; readonly sequenceSpecific: 127; }; type MIDIMessageType = (typeof midiMessageTypes)[keyof typeof midiMessageTypes]; declare const midiControllers: { readonly bankSelect: 0; readonly modulationWheel: 1; readonly breathController: 2; readonly undefinedCC3: 3; readonly footController: 4; readonly portamentoTime: 5; readonly dataEntryMSB: 6; readonly mainVolume: 7; readonly balance: 8; readonly undefinedCC9: 9; readonly pan: 10; readonly expressionController: 11; readonly effectControl1: 12; readonly effectControl2: 13; readonly undefinedCC14: 14; readonly undefinedCC15: 15; readonly generalPurposeController1: 16; readonly generalPurposeController2: 17; readonly generalPurposeController3: 18; readonly generalPurposeController4: 19; readonly undefinedCC20: 20; readonly undefinedCC21: 21; readonly undefinedCC22: 22; readonly undefinedCC23: 23; readonly undefinedCC24: 24; readonly undefinedCC25: 25; readonly undefinedCC26: 26; readonly undefinedCC27: 27; readonly undefinedCC28: 28; readonly undefinedCC29: 29; readonly undefinedCC30: 30; readonly undefinedCC31: 31; readonly bankSelectLSB: 32; readonly modulationWheelLSB: 33; readonly breathControllerLSB: 34; readonly undefinedCC3LSB: 35; readonly footControllerLSB: 36; readonly portamentoTimeLSB: 37; readonly dataEntryLSB: 38; readonly mainVolumeLSB: 39; readonly balanceLSB: 40; readonly undefinedCC9LSB: 41; readonly panLSB: 42; readonly expressionControllerLSB: 43; readonly effectControl1LSB: 44; readonly effectControl2LSB: 45; readonly undefinedCC14LSB: 46; readonly undefinedCC15LSB: 47; readonly undefinedCC16LSB: 48; readonly undefinedCC17LSB: 49; readonly undefinedCC18LSB: 50; readonly undefinedCC19LSB: 51; readonly undefinedCC20LSB: 52; readonly undefinedCC21LSB: 53; readonly undefinedCC22LSB: 54; readonly undefinedCC23LSB: 55; readonly undefinedCC24LSB: 56; readonly undefinedCC25LSB: 57; readonly undefinedCC26LSB: 58; readonly undefinedCC27LSB: 59; readonly undefinedCC28LSB: 60; readonly undefinedCC29LSB: 61; readonly undefinedCC30LSB: 62; readonly undefinedCC31LSB: 63; readonly sustainPedal: 64; readonly portamentoOnOff: 65; readonly sostenutoPedal: 66; readonly softPedal: 67; readonly legatoFootswitch: 68; readonly hold2Pedal: 69; readonly soundVariation: 70; readonly filterResonance: 71; readonly releaseTime: 72; readonly attackTime: 73; readonly brightness: 74; readonly decayTime: 75; readonly vibratoRate: 76; readonly vibratoDepth: 77; readonly vibratoDelay: 78; readonly soundController10: 79; readonly generalPurposeController5: 80; readonly generalPurposeController6: 81; readonly generalPurposeController7: 82; readonly generalPurposeController8: 83; readonly portamentoControl: 84; readonly undefinedCC85: 85; readonly undefinedCC86: 86; readonly undefinedCC87: 87; readonly undefinedCC88: 88; readonly undefinedCC89: 89; readonly undefinedCC90: 90; readonly reverbDepth: 91; readonly tremoloDepth: 92; readonly chorusDepth: 93; readonly detuneDepth: 94; readonly phaserDepth: 95; readonly dataIncrement: 96; readonly dataDecrement: 97; readonly nonRegisteredParameterLSB: 98; readonly nonRegisteredParameterMSB: 99; readonly registeredParameterLSB: 100; readonly registeredParameterMSB: 101; readonly undefinedCC102LSB: 102; readonly undefinedCC103LSB: 103; readonly undefinedCC104LSB: 104; readonly undefinedCC105LSB: 105; readonly undefinedCC106LSB: 106; readonly undefinedCC107LSB: 107; readonly undefinedCC108LSB: 108; readonly undefinedCC109LSB: 109; readonly undefinedCC110LSB: 110; readonly undefinedCC111LSB: 111; readonly undefinedCC112LSB: 112; readonly undefinedCC113LSB: 113; readonly undefinedCC114LSB: 114; readonly undefinedCC115LSB: 115; readonly undefinedCC116LSB: 116; readonly undefinedCC117LSB: 117; readonly undefinedCC118LSB: 118; readonly undefinedCC119LSB: 119; readonly allSoundOff: 120; readonly resetAllControllers: 121; readonly localControlOnOff: 122; readonly allNotesOff: 123; readonly omniModeOff: 124; readonly omniModeOn: 125; readonly monoModeOn: 126; readonly polyModeOn: 127; }; type MIDIController = (typeof midiControllers)[keyof typeof midiControllers]; type GenericRIFFFourCC = "RIFF" | "LIST" | "INFO"; type WAVFourCC = "wave" | "cue " | "fmt "; type FourCC = GenericRIFFFourCC | SoundBankInfoFourCC | SF2InfoFourCC | SF2ChunkFourCC | DLSInfoFourCC | DLSChunkFourCC | RMIDInfoFourCC | WAVFourCC; interface SoundBankManagerListEntry { /** * The unique string identifier of the sound bank. */ id: string; /** * The sound bank itself. */ soundBank: BasicSoundBank; /** * The bank MSB offset for this sound bank. */ bankOffset: number; } interface SF2VersionTag { /** * The major revision number of the sound bank. */ major: number; /** * The minor revision number of this sound bank. */ minor: number; } type GenericBankInfoFourCC = "INAM" | "ICRD" | "IENG" | "IPRD" | "ICOP" | "ICMT" | "ISFT"; type SF2InfoFourCC = GenericBankInfoFourCC | "ifil" | "isng" | "irom" | "iver" | "DMOD" | "LIST"; type SF2ChunkFourCC = "pdta" | "xdta" | "sdta" | "smpl" | "sm24" | "phdr" | "pbag" | "pmod" | "pgen" | "inst" | "ibag" | "imod" | "igen" | "shdr"; type DLSInfoFourCC = GenericBankInfoFourCC | "ISBJ"; type DLSChunkFourCC = WAVFourCC | "dls " | "dlid" | "cdl " | "ptbl" | "vers" | "colh" | "wvpl" | "wsmp" | "data" | "lart" | "lar2" | "art2" | "art1" | "lrgn" | "rgnh" | "wlnk" | "lins" | "ins " | "insh" | "rgn " | "rgn2" | "pgal"; interface SoundBankInfoData { /** * Name. */ name: string; /** * The sound bank's version. */ version: SF2VersionTag; /** * Creation date. */ creationDate: Date; /** * Sound engine. */ soundEngine: string; /** * Author. */ engineer?: string; /** * Product. */ product?: string; /** * Copyright. */ copyright?: string; /** * Comment. */ comment?: string; /** * Subject. */ subject?: string; /** * ROM information. */ romInfo?: string; /** * Software used to edit the file. */ software?: string; /** * A tag that only applies to SF2 and will usually be undefined. */ romVersion?: SF2VersionTag; } type SoundBankInfoFourCC = keyof SoundBankInfoData; interface VoiceSynthesisData { instrumentGenerators: Generator[]; presetGenerators: Generator[]; modulators: Modulator[]; sample: BasicSample; } type SampleEncodingFunction = (audioData: Float32Array, sampleRate: number) => Promise<Uint8Array>; type ModulatorSourceIndex = ModulatorSourceEnum | MIDIController; /** * A function to track progress during writing. */ type ProgressFunction = ( /** * The written sample name. */ sampleName: string, /** * The sample's index. */ sampleIndex: number, /** * The total sample count for progress displaying. */ sampleCount: number) => Promise<unknown>; /** * Options for writing a SoundFont2 file. */ interface SoundFont2WriteOptions { /** * If the soundfont should be compressed with a given function. */ compress: boolean; /** * The function for compressing samples. It can be undefined if not compressed. */ compressionFunction?: SampleEncodingFunction; /** * A function to show progress for writing large banks. It can be undefined. */ progressFunction?: ProgressFunction; /** * If the DMOD chunk should be written. Recommended. * Note that it will only be written if the modulators are unchanged. */ writeDefaultModulators: boolean; /** * If the XDTA chunk should be written to allow virtually infinite parameters. Recommended. * Note that it will only be written needed. */ writeExtendedLimits: boolean; /** * If an SF3 bank should be decompressed back to SF2. Not recommended. */ decompress: boolean; } /** * Options for writing a DLS file. */ interface DLSWriteOptions { /** * A function to show progress for writing large banks. It can be undefined. */ progressFunction?: ProgressFunction; } interface GenericRange { min: number; max: number; } interface DLSLoop { loopType: DLSLoopType; loopStart: number; loopLength: number; } declare const interpolationTypes: { readonly linear: 0; readonly nearestNeighbor: 1; readonly hermite: 2; }; type InterpolationType = (typeof interpolationTypes)[keyof typeof interpolationTypes]; declare const dataEntryStates: { readonly Idle: 0; readonly RPCoarse: 1; readonly RPFine: 2; readonly NRPCoarse: 3; readonly NRPFine: 4; readonly DataCoarse: 5; readonly DataFine: 6; }; type DataEntryState = (typeof dataEntryStates)[keyof typeof dataEntryStates]; declare const customControllers: { readonly channelTuning: 0; readonly channelTransposeFine: 1; readonly modulationMultiplier: 2; readonly masterTuning: 3; readonly channelTuningSemitones: 4; readonly channelKeyShift: 5; readonly sf2NPRNGeneratorLSB: 6; }; type CustomController = (typeof customControllers)[keyof typeof customControllers]; type SynthSystem = "gm" | "gm2" | "gs" | "xg"; interface NoteOnCallback { /** The MIDI note number. */ midiNote: number; /** The MIDI channel number. */ channel: number; /** The velocity of the note. */ velocity: number; } interface NoteOffCallback { /** The MIDI note number. */ midiNote: number; /** The MIDI channel number. */ channel: number; } interface DrumChangeCallback { /** The MIDI channel number. */ channel: number; /** Indicates if the channel is a drum channel. */ isDrumChannel: boolean; } interface ProgramChangeCallback extends MIDIPatch { /** The MIDI channel number. */ channel: number; } interface ControllerChangeCallback { /** The MIDI channel number. */ channel: number; /** The controller number. */ controllerNumber: number; /** The value of the controller. */ controllerValue: number; } interface MuteChannelCallback { /** The MIDI channel number. */ channel: number; /** Indicates if the channel is muted. */ isMuted: boolean; } interface PresetListEntry extends MIDIPatchNamed { /** * Indicates if this preset is any kind of drum preset. */ isAnyDrums: boolean; } /** * A list of preset changes, each with a name, bank, and program number. */ type PresetList = PresetListEntry[]; /** * The synthesizer display system exclusive data, EXCLUDING THE F0 BYTE! */ type SynthDisplayCallback = number[]; interface PitchWheelCallback { /** The MIDI channel number. */ channel: number; /** * The unsigned 14-bit value of the pitch: 0 - 16383. */ pitch: number; } interface ChannelPressureCallback { /** The MIDI channel number. */ channel: number; /** The pressure value. */ pressure: number; } interface PolyPressureCallback { /** The MIDI channel number. */ channel: number; /** The MIDI note number. */ midiNote: number; /** The pressure value. */ pressure: number; } /** * The error message for sound bank errors. */ type SoundBankErrorCallback = Error; interface StopAllCallback { /** * The MIDI channel number. */ channel: number; /** * If the channel was force stopped. (no release time) */ force: boolean; } type MasterParameterChangeCallback = { [P in keyof MasterParameterType]: { /** * The parameter that was changed. */ parameter: P; /** * The new value of this parameter. */ value: MasterParameterType[P]; }; }[keyof MasterParameterType]; interface ChannelPropertyChangeCallback { /** * The channel number of the new property. */ channel: number; /** * The updated property. */ property: ChannelProperty; } interface SynthProcessorEventData { /** * This event fires when a note is played. */ noteOn: NoteOnCallback; /** * This event fires when a note is released. */ noteOff: NoteOffCallback; /** * This event fires when a pitch wheel is changed. */ pitchWheel: PitchWheelCallback; /** * This event fires when a controller is changed. */ controllerChange: ControllerChangeCallback; /** * This event fires when a program is changed. */ programChange: ProgramChangeCallback; /** * This event fires when a channel pressure is changed. */ channelPressure: ChannelPressureCallback; /** * This event fires when a polyphonic pressure is changed. */ polyPressure: PolyPressureCallback; /** * This event fires when a drum channel is changed. */ drumChange: DrumChangeCallback; /** * This event fires when all notes on a channel are stopped. */ stopAll: StopAllCallback; /** * This event fires when a new channel is created. There is no data for this event. */ newChannel: void; /** * This event fires when a channel is muted or unmuted. */ muteChannel: MuteChannelCallback; /** * This event fires when the preset list is changed. */ presetListChange: PresetList; /** * This event fires when all controllers on all channels are reset. There is no data for this event. */ allControllerReset: void; /** * This event fires when a sound bank parsing error occurs. */ soundBankError: SoundBankErrorCallback; /** * This event fires when the synthesizer receives a display message. */ synthDisplay: SynthDisplayCallback; /** * This event fires when a master parameter changes. */ masterParameterChange: MasterParameterChangeCallback; /** * This event fires when a channel property changes. */ channelPropertyChange: ChannelPropertyChangeCallback; } type SynthProcessorEvent = { [K in keyof SynthProcessorEventData]: { type: K; data: SynthProcessorEventData[K]; }; }[keyof SynthProcessorEventData]; interface SynthMethodOptions { /** * The audio context time when the event should execute, in seconds. */ time: number; } /** * KeyNum: tuning. */ type MTSProgramTuning = MTSNoteTuning[]; interface MTSNoteTuning { /** * The base MIDI note to use, -1 means no change. */ midiNote: number; /** * Additional tuning. */ centTuning: number | null; } /** * Looping mode of the sample. * 0 - no loop. * 1 - loop. * 2 - UNOFFICIAL: polyphone 2.4 added start on release. * 3 - loop then play when released. */ type SampleLoopingMode = 0 | 1 | 2 | 3; /** * A list of voices for a given key:velocity. */ type VoiceList = Voice[]; interface ChannelProperty { /** * The channel's current voice amount. */ voicesAmount: number; /** * The channel's current pitch wheel 0 - 16384. */ pitchWheel: number; /** * The pitch wheel's range, in semitones. */ pitchWheelRange: number; /** * Indicates whether the channel is muted. */ isMuted: boolean; /** * Indicates whether the channel is a drum channel. */ isDrum: boolean; /** * The channel's transposition, in semitones. */ transposition: number; } interface SynthProcessorOptions { /** * Indicates if the event system is enabled. This can be changed later. */ enableEventSystem: boolean; /** * The initial time of the synth, in seconds. */ initialTime: number; /** * Indicates if the effects are enabled. This can be changed later. */ enableEffects: boolean; } /** * The master parameters of the synthesizer. */ interface MasterParameterType { /** * The master gain, from 0 to any number. 1 is 100% volume. */ masterGain: number; /** * The master pan, from -1 (left) to 1 (right). 0 is center. */ masterPan: number; /** * The maximum number of voices that can be played at once. */ voiceCap: number; /** * The interpolation type used for sample playback. */ interpolationType: InterpolationType; /** * The MIDI system used by the synthesizer for bank selects and system exclusives. (GM, GM2, GS, XG) */ midiSystem: SynthSystem; /** * Indicates whether the synthesizer is in monophonic retrigger mode. * This emulates the behavior of Microsoft GS Wavetable Synth, * Where a new note will kill the previous one if it is still playing. */ monophonicRetriggerMode: boolean; /** * The reverb gain, from 0 to any number. 1 is 100% reverb. */ reverbGain: number; /** * The chorus gain, from 0 to any number. 1 is 100% chorus. */ chorusGain: number; /** * Forces note killing instead of releasing. Improves performance in black MIDIs. */ blackMIDIMode: boolean; /** * The global transposition in semitones. It can be decimal to provide microtonal tuning. */ transposition: number; /** * Synthesizer's device ID for system exclusive messages. Set to -1 to accept all. */ deviceID: number; } /** * Sets a master parameter of the synthesizer. * @param parameter The type of the master parameter to set. * @param value The value to set for the master parameter. */ declare function setMasterParameterInternal<P extends keyof MasterParameterType>(this: SpessaSynthProcessor, parameter: P, value: MasterParameterType[P]): void; /** * Gets a master parameter of the synthesizer. * @param type The type of the master parameter to get. * @returns The value of the master parameter. */ declare function getMasterParameterInternal<P extends keyof MasterParameterType>(this: SpessaSynthProcessor, type: P): MasterParameterType[P]; /** * Gets all master parameters of the synthesizer. * @returns All the master parameters. */ declare function getAllMasterParametersInternal(this: SpessaSynthProcessor): MasterParameterType; declare class SoundBankManager { /** * All the sound banks, ordered from the most important to the least. */ soundBankList: SoundBankManagerListEntry[]; private readonly presetListChangeCallback; private selectablePresetList; /** * @param presetListChangeCallback Supplied by the parent synthesizer class, * this is called whenever the preset list changes. */ constructor(presetListChangeCallback: () => unknown); private _presetList; /** * The list of all presets in the sound bank stack. */ get presetList(): PresetListEntry[]; /** * The current sound bank priority order. * @returns The IDs of the sound banks in the current order. */ get priorityOrder(): string[]; /** * The current sound bank priority order. * @param newList The new order of sound bank IDs. */ set priorityOrder(newList: string[]); /** * Deletes a given sound bank by its ID. * @param id the ID of the sound bank to delete. */ deleteSoundBank(id: string): void; /** * Adds a new sound bank with a given ID, or replaces an existing one. * @param font the sound bank to add. * @param id the ID of the sound bank. * @param bankOffset the bank offset of the sound bank. */ addSoundBank(font: BasicSoundBank, id: string, bankOffset?: number): void; /** * Gets a given preset from the sound bank stack. * @param patch The MIDI patch to search for. * @param system The MIDI system to select the preset for. * @returns An object containing the preset and its bank offset. */ getPreset(patch: MIDIPatch, system: SynthSystem): BasicPreset; destroy(): void; private generatePresetList; } /** * Kills the specified number of voices based on their priority. * This function will remove the least important voices from all channels. * @param amount The number of voices to remove. */ declare function killVoicesIntenral(this: SpessaSynthProcessor, amount: number): void; type TypedArray = Uint8Array | Int8Array | Uint16Array | Int16Array | Uint32Array | Int32Array | Uint8ClampedArray | Float32Array | Float64Array; /** * Executes a system exclusive message for the synthesizer. * @param syx The system exclusive message as an array of bytes. * @param channelOffset The channel offset to apply (default is 0). * @remarks * This is a rather extensive method that handles various system exclusive messages, * including Roland GS, MIDI Tuning Standard, and other non-realtime messages. */ declare function systemExclusiveInternal(this: SpessaSynthProcessor, syx: number[] | IndexedByteArray | TypedArray, channelOffset?: number): void; /** * Executes a data entry fine (LSB) change for the current channel. * @param dataValue The value to set for the data entry fine controller (0-127). */ declare function dataEntryFine(this: MIDIChannel, dataValue: number): void; /** * Handles MIDI controller changes for a channel. * @param controllerNumber The MIDI controller number (0-127). * @param controllerValue The value of the controller (0-127). * @param sendEvent If an event should be emitted. * @remarks * This function processes MIDI controller changes, updating the channel's * midiControllers table and handling special cases like bank select, * data entry, and sustain pedal. It also computes modulators for all voices * in the channel based on the controller change. * If the controller number is greater than 127, it is treated as a channel * configuration controller, and the `force` parameter must be set to true * to allow changes. */ declare function controllerChange(this: MIDIChannel, controllerNumber: MIDIController, controllerValue: number, sendEvent?: boolean): void; /** * Executes a data entry coarse (MSB) change for the current channel. * @param dataValue The value to set for the data entry coarse controller (0-127). */ declare function dataEntryCoarse(this: MIDIChannel, dataValue: number): void; /** * Sends a "MIDI Note on" message and starts a note. * @param midiNote The MIDI note number (0-127). * @param velocity The velocity of the note (0-127). If less than 1, it will send a note off instead. */ declare function noteOn(this: MIDIChannel, midiNote: number, velocity: number): void; /** * Releases a note by its MIDI note number. * If the note is in high performance mode and the channel is not a drum channel, * it kills the note instead of releasing it. * @param midiNote The MIDI note number to release (0-127). */ declare function noteOff(this: MIDIChannel, midiNote: number): void; /** * Changes the program (preset) of the channel. * @param program The program number (0-127) to change to. */ declare function programChange(this: MIDIChannel, program: number): void; /** * A class for dynamic modulators * that are assigned for more complex system exclusive messages */ declare class DynamicModulatorSystem { /** * The current dynamic modulator list. */ modulatorList: { mod: Modulator; id: string; }[]; resetModulators(): void; /** * @param source Like in midiControllers: values below NON_CC_INDEX_OFFSET are CCs, * above are regular modulator sources. * @param destination The generator type to modulate. * @param amount The amount of modulation to apply. * @param isBipolar If true, the modulation is bipolar (ranges from -1 to 1 instead of from 0 to 1). * @param isNegative If true, the modulation is negative (goes from 1 to 0 instead of from 0 to 1). */ setModulator(source: ModulatorSourceEnum, destination: GeneratorType, amount: number, isBipolar?: boolean, isNegative?: boolean): void; private getModulatorID; private deleteModulator; } declare class ProtectedSynthValues { /** * This.tunings[program][key] = tuning */ readonly tunings: MTSProgramTuning[]; masterParameters: MasterParameterType; /** * The volume gain, set by MIDI sysEx */ midiVolume: number; /** * Set via system exclusive. */ reverbSend: number; /** * Set via system exclusive. */ chorusSend: number; /** * The pan of the left channel */ panLeft: number; /** * The pan of the right channel */ panRight: number; /** * Synth's default (reset) preset */ defaultPreset: BasicPreset | undefined; /** * Synth's default (reset) drum preset */ drumPreset: BasicPreset | undefined; readonly volumeEnvelopeSmoothingFactor: number; readonly panSmoothingFactor: number; readonly filterSmoothingFactor: number; /** * Calls when an event occurs. * @param eventType The event type. * @param eventData The event data. */ eventCallbackHandler: <K extends keyof SynthProcessorEventData>(eventType: K, eventData: SynthProcessorEventData[K]) => unknown; getVoices: (channel: number, midiNote: number, velocity: number, realKey: number) => VoiceList; voiceKilling: (amount: number) => unknown; /** * Cached voices for all presets for this synthesizer. * Nesting goes like this: * this.cachedVoices[bankMSB][bankLSB][programNumber][midiNote][velocity] = a list of voices for that. */ cachedVoices: VoiceList[][][][][]; constructor(eventCallbackHandler: <K extends keyof SynthProcessorEventData>(eventType: K, eventData: SynthProcessorEventData[K]) => unknown, getVoices: (channel: number, midiNote: number, velocity: number, realKey: number) => VoiceL