UNPKG

@polygonjs/polygonjs

Version:

node-based WebGL 3D engine https://polygonjs.com

114 lines (113 loc) 3.13 kB
"use strict"; import { TypedAudioNode } from "./_Base"; import { NodeParamsConfig, ParamConfig } from "../utils/params/ParamsConfig"; import { AudioBuilder } from "../../../core/audio/AudioBuilder"; import { Sampler } from "tone/build/esm/instrument/Sampler"; import { StringParamLanguage } from "../../params/utils/OptionsController"; import { sanitizeUrl } from "../../../core/UrlHelper"; import { CoreLoaderAudio } from "../../../core/loader/Audio"; import { Poly } from "../../Poly"; import { AudioType } from "../../poly/registers/nodes/types/Audio"; export const SAMPLER_DEFAULTS = { attack: 0.01, release: 1 }; const DEFAULT_NOTE_MAP = { A0: "A0", C1: "C1", "D#1": "Ds1", "F#1": "Fs1", A1: "A1", C2: "C2", "D#2": "Ds2", "F#2": "Fs2", A2: "A2", C3: "C3", "D#3": "Ds3", "F#3": "Fs3", A3: "A3", C4: "C4", "D#4": "Ds4", "F#4": "Fs4", A4: "A4", C5: "C5", "D#5": "Ds5", "F#5": "Fs5", A5: "A5", C6: "C6", "D#6": "Ds6", "F#6": "Fs6", A6: "A6", C7: "C7", "D#7": "Ds7", "F#7": "Fs7", A7: "A7", C8: "C8" }; class SamplerAudioParamsConfig extends NodeParamsConfig { constructor() { super(...arguments); /** @param map of notes to load */ this.urlsMap = ParamConfig.STRING(JSON.stringify(DEFAULT_NOTE_MAP, null, 2), { language: StringParamLanguage.JSON }); /** @param base url */ this.baseUrl = ParamConfig.STRING("./"); /** @param extension */ this.extension = ParamConfig.STRING("mp3"); } } const ParamsConfig = new SamplerAudioParamsConfig(); export class SamplerAudioNode extends TypedAudioNode { constructor() { super(...arguments); this.paramsConfig = ParamsConfig; } static type() { return AudioType.SAMPLER; } initializeNode() { this.io.inputs.setCount(1); } dispose() { super.dispose(); Poly.blobs.clearBlobsForNode(this); } async cook(inputContents) { const envelopeBuilder = inputContents[0]; const envelopeParams = envelopeBuilder.envelopeParams() || SAMPLER_DEFAULTS; let urlsJSON = {}; let urls = []; try { const extension = this.pv.extension; urlsJSON = JSON.parse(this.pv.urlsMap); const noteNames = Object.keys(urlsJSON); for (const noteName of noteNames) { const urlFileName = urlsJSON[noteName]; const url = `${this.pv.baseUrl}/${urlFileName}.${extension}`; urlsJSON[noteName] = sanitizeUrl(url); urls.push(url); } } catch (err) { this.states.error.set("urlsMap is invalid JSON"); } const loaders = urls.map( (url) => new CoreLoaderAudio(url, this, { multiAssetsForNode: true }) ); await Promise.all(loaders.map((loader) => loader.load())); const sampler = new Sampler({ urls: urlsJSON, attack: envelopeParams.attack, release: envelopeParams.release, baseUrl: "", onerror: (err) => { this.states.error.set(err.message); }, onload: () => { const audioBuilder = new AudioBuilder(); audioBuilder.setInstrument(sampler); this.setAudioBuilder(audioBuilder); } }); } }