UNPKG

spessasynth_core

Version:

MIDI and SoundFont2/DLS library with no compromises

92 lines (86 loc) 3.11 kB
import { writeDword, writeWord } from "../../../utils/byte_functions/little_endian.js"; import { IndexedByteArray } from "../../../utils/indexed_array.js"; import { writeRIFFChunkRaw } from "../riff_chunk.js"; import { GEN_BYTE_SIZE, Generator } from "../generator.js"; import { generatorTypes } from "../generator_types.js"; /** * @this {BasicSoundBank} * @returns {ReturnedExtendedSf2Chunks} */ export function getPGEN() { // almost identical to igen, except the correct instrument instead of sample gen // goes through all preset zones and writes generators sequentially (add 4 for terminal) let pgenSize = GEN_BYTE_SIZE; for (const preset of this.presets) { pgenSize += preset.globalZone.generators.length * GEN_BYTE_SIZE; pgenSize += preset.presetZones.reduce((size, z) => { // clear instrument and range generators before determining the size z.generators = z.generators.filter(g => g.generatorType !== generatorTypes.instrument && g.generatorType !== generatorTypes.keyRange && g.generatorType !== generatorTypes.velRange ); // unshift vel then key and instrument is last if (z.hasVelRange) { z.prependGenerator(new Generator( generatorTypes.velRange, z.velRange.max << 8 | Math.max(z.velRange.min, 0), false )); } if (z.hasKeyRange) { z.prependGenerator(new Generator( generatorTypes.keyRange, z.keyRange.max << 8 | Math.max(z.keyRange.min, 0), false )); } // write the instrument id z.addGenerators(new Generator( generatorTypes.instrument, this.instruments.indexOf(z.instrument), false )); return z.generators.length * GEN_BYTE_SIZE + size; }, 0); } const pgenData = new IndexedByteArray(pgenSize); /** * @param z {BasicZone} */ const writeZone = z => { for (const gen of z.generators) { // name is deceptive, it works on negatives writeWord(pgenData, gen.generatorType); writeWord(pgenData, gen.generatorValue); } }; for (const preset of this.presets) { // global zone writeZone(preset.globalZone); for (const zone of preset.presetZones) { writeZone(zone); } } // terminal generator, is zero writeDword(pgenData, 0); // https://github.com/spessasus/soundfont-proposals/blob/main/extended_limits.md const xpgenData = new IndexedByteArray(GEN_BYTE_SIZE); writeDword(xpgenData, 0); const pgen = writeRIFFChunkRaw("pgen", pgenData); const xpgen = writeRIFFChunkRaw("pgen", xpgenData); return { pdta: pgen, xdta: xpgen, highestIndex: 0 // not applicable }; }