UNPKG

wam-community

Version:

A collection of prebuilt Web Audio Modules ready for use

168 lines (145 loc) 4.33 kB
import { WebAudioModule} from '../../utils/sdk/dist/index.js'; import PedalBoardNode from './Audio/PedalBoardNode.js'; import { createElement } from './Gui/index.js'; /** * @param {URL} relativeURL * @returns {string} */ const getBasetUrl = (relativeURL) => { const baseURL = relativeURL.href.substring( 0, relativeURL.href.lastIndexOf('/') ); return baseURL; }; export default class PedalBoardPlugin extends WebAudioModule { _baseURL = getBasetUrl(new URL('.', import.meta.url)); _descriptorUrl = `${this._baseURL}/descriptor.json`; id = 0; removeRelativeUrl = (relativeURL) => { if (relativeURL[0] == '.') { return `${this._baseURL}${relativeURL.substring(1)}`; } else { return relativeURL; } }; async _loadDescriptor() { const url = this._descriptorUrl; if (!url) throw new TypeError('Descriptor not found'); const response = await fetch(url); const descriptor = await response.json(); Object.assign(this.descriptor, descriptor); } async initialize(state) { await this._loadDescriptor(); await this.fetchServers(); return super.initialize(state); } /** * Initialize the WamNode of the PedalBoard with an initialState if provided. * @param {*} initialState * @returns The PedalBoardNode. * @author Quentin Beauchet */ async createAudioNode(initialState) { await PedalBoardNode.addModules(this.audioContext, this.moduleId); this.pedalboardNode = new PedalBoardNode(this, {}); await this.pedalboardNode._initialize(); if (initialState) { this.pedalboardNode.initialState = initialState; } else { let file = await fetch(`${this._baseURL}/initialState.json`); this.pedalboardNode.initialState = await file.json(); } return this.pedalboardNode; } /** * Fetch the wam from each of the servers in the repositories.json file and then import their WebAudioModule. * For each of them store the needed information in this.WAMS. * @author Quentin Beauchet */ async fetchServers() { const filterFetch = (el) => el.status == 'fulfilled' && el.value.status == 200; let repos = await fetch(`${this._baseURL}/repositories.json`); let json2 = await repos.json(); let files = await Promise.allSettled( json2.map((el) => fetch(this.removeRelativeUrl(el))) ); let urls = await Promise.all( files.filter(filterFetch).map((el) => el.value.json()) ); urls = urls.reduce((arr, next) => arr.concat(next), []); let responses = await Promise.allSettled( urls.map((el) => fetch(`${el}descriptor.json`)) ); let descriptors = await Promise.all( responses.map((el) => filterFetch(el) ? el.value.json() : undefined ) ); let modules = await Promise.allSettled( urls.map((el) => import(`${el}index.js`)) ); this.WAMS = {}; descriptors.forEach((el, index) => { if ( el && modules[index].status == 'fulfilled' && !this.WAMS[el.name] ) { this.WAMS[el.name] = { url: urls[index], descriptor: el, module: modules[index].value, }; } }); } async loadPreset(nodes) { this.gui.loadingPreset = true; this.gui.setPreviewFullness(true); let board = this.gui.board; this.pedalboardNode.disconnectNodes(board.childNodes, true); board.innerHTML = ''; let size = 0; for (let i = 0; i < nodes.length; i++) { let node = nodes[i]; if ((await this.addWAM(node.name, node.state)) == false) { break; } size++; } this.gui.setPreviewFullness(size >= this.pedalboardNode.MAX_NODES); this.gui.loadingPreset = false; } /** * Add a wam to the board, instanciate the WamNode with an initial state if provided and append the Gui to the board. * @param {string} WamName * @param {Object} state * @author Quentin Beauchet */ async addWAM(WamName, state) { const { default: WAM } = this.WAMS[WamName].module; let instance; try { instance = await WAM.createInstance( this.pedalboardNode.subGroupId, this.pedalboardNode.context ); } catch (e) { return false; } this.pedalboardNode.addPlugin(instance.audioNode, WamName, this.id); await this.gui.addPlugin(instance, this.WAMS[WamName].img, this.id); if (state) { await instance.audioNode.setState(state); } if (this.id == 100) this.gui.disableFaustPlugins(); this.id++; return true; } createGui() { return createElement(this); } }