{"id":21951029,"url":"https://github.com/fr0stbyter/api","last_synced_at":"2026-04-20T05:34:47.756Z","repository":{"id":70752265,"uuid":"408201154","full_name":"Fr0stbyteR/api","owner":"Fr0stbyteR","description":"WebAudioModules API","archived":false,"fork":false,"pushed_at":"2021-10-25T17:13:08.000Z","size":153,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-06-01T19:18:06.645Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Fr0stbyteR.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-09-19T18:07:41.000Z","updated_at":"2021-10-25T17:13:11.000Z","dependencies_parsed_at":"2023-03-11T09:08:40.659Z","dependency_job_id":null,"html_url":"https://github.com/Fr0stbyteR/api","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Fr0stbyteR/api","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Fr0stbyteR%2Fapi","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Fr0stbyteR%2Fapi/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Fr0stbyteR%2Fapi/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Fr0stbyteR%2Fapi/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Fr0stbyteR","download_url":"https://codeload.github.com/Fr0stbyteR/api/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Fr0stbyteR%2Fapi/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32034764,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-20T00:18:06.643Z","status":"online","status_checked_at":"2026-04-20T02:00:06.527Z","response_time":94,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-29T06:11:28.671Z","updated_at":"2026-04-20T05:34:47.687Z","avatar_url":"https://github.com/Fr0stbyteR.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# WebAudioModules API\r\n\r\nThe repository includes API definition files for WebAudioModules (WAM) written in TypeScript, abstract classes that conforms the API written in JavaScript, and different implementations and utilities that can be used in WAM projects.\r\n\r\nThe legacy WAM API is available in branch [v10](https://github.com/webaudiomodules/api/tree/v10).\r\n\r\n## Installing the API\r\n\r\n```Bash\r\nnpm i -D @webaudiomodules/api\r\n```\r\n\r\n## API definitions\r\n\r\nThe WAM API is considered as the plugin specification that should be implemented in each WAM. All the interfaces and types in the specification are described in TypeScript language in `src/types.d.ts`.\r\n\r\nThe API is designed for making Web-based audio plugins (WAMs) and using them in the hosts. As the VST, AudioUnit or AAX standards on the desktop DAWs, audio plugins usually includes an insertable DSP and an UI on the given platform along with some extra features such as parameter automations, MIDI message processing, state saving and loading, etc. These features' interface are standardized in the API for audio plugin and host developers.\r\n\r\n\u003e VSCode IntelliSense will take the types into account by using JSDoc or TypeScript import. For example:\r\n```JavaScript\r\n// JavaScript\r\n/** @typedef {import('@webaudiomodules/api').WamEvent} IWamEvent */\r\n```\r\n```TypeScript\r\n// TypeScript\r\nimport { WamEvent } from '@webaudiomodules/api';\r\n```\r\n\r\n### Features\r\n\r\nThe API supports these primary features:\r\n\r\n- Getting the WAM's information by fetching a JSON file.\r\n\r\n- Loading the WAM plugin constructor by fetching an ECMAScript Module file.\r\n\r\n- Getting a WebAudio AudioNode-compatible processor that can be inserted into an existing audio graph.\r\n\r\n- Saving and Restoring the plugin's state.\r\n\r\n- Getting parameter information from both main thread and audio thread (`AudioWorklet`).\r\n\r\n- Scheduling automation events of audio parameters from both threads.\r\n\r\n- Scheduling transport, MIDI and OSC events with the host from both threads.\r\n\r\n- Emitting events for downstream WAM plugins from both threads.\r\n\r\n- The clean up when the plugin instance is destroyed.\r\n\r\n### API Overview\r\n\r\nThe interfaces defined are: \r\n\r\n- A `WebAudioModule` interface, which is the main entry point of a WAM plugin instance.\r\n\r\n- A `WamDescriptor` interface, which the descriptor JSON file should provide as the plugin's general information.\r\n\r\n- A `WamNode` interface, which extends WebAudio `AudioNode` that will be connected to the host's audio graph.\r\n\r\n- A `WamProcessor` interface, which extends `AudioWorkletProcessor` that process signals in the audio thread.\r\n\r\n- A `WamParameter` interface, which provides parameter information on both threads.\r\n\r\n- A `WamEvent` interface, which can be used to schedule or emit WAM related events like automations or MIDI messages.\r\n\r\n- A `WamEnv` interface, which is available on the audio thread to maintain the graph information there.\r\n\r\n### WebAudioModule interface\r\n\r\nAs a WAM distribution should include at least a descriptor in JSON and a JavaScript file that exports by default a WebAudioModule constructor. The constructor should provide statically:\r\n\r\n1. `isWebAudioModuleConstructor` getter that returns `true`.\r\n\r\n2. `createInstance` method that asynchronously instantiates the WebAudioModule.\r\n\r\n    \u003e This method is a short hand for calling the constructor then the `initialize` method, and should return a Promise that resolves the WebAudioModule constructed and initialized.\r\n    \r\n3. the `new` constructor.\r\n\r\n    \u003e The WAM instance constructed by the `new` operator is only usable after calling `initialize` method.\r\n\r\nFrom the host side, once imported the default export from the ESM module, the host can firstly do a type check using the `isWebAudioModuleConstructor` getter, then construct the WAM instance using the `createInstance` method. For example,\r\n\r\n```JavaScript\r\n/** @typedef {typeof import('@webaudiomodules/api').WebAudioModule} WebAudioModuleConstructor */\r\n(async () =\u003e {\r\n    const audioCtx = new AudioContext();\r\n    const initialState = {};\r\n    const imported = await import('./path_to_wam/index.js');\r\n    /** @type {WebAudioModuleConstructor} */\r\n    const WAM = imported.default;\r\n    const isWAM = typeof WAM === 'function' \u0026\u0026 WAM.isWebAudioModuleConstructor;\r\n    if (!isWAM) return;\r\n    const wam = await WAM.createInstance(audioCtx, initialState);\r\n    return wam;\r\n})();\r\n```\r\n\r\nHere, \r\n```JavaScript\r\nconst wam = await WAM.createInstance(audioCtx, initialState);\r\n```\r\nis equivalent to \r\n\r\n```JavaScript\r\nconst wam = new WAM(audioCtx);\r\nawait wam.initialize(initialState);\r\n```\r\n\r\nThe following properties and methods should also be implemented.\r\n\r\n1. `isWebAudioModule` getter that returns `true`.\r\n\r\n2. `audioContext` getter that returns the current `BaseAudioContext` the WAM belongs to.\r\n\r\n3. `audioNode` getter that returns the `AudioNode` to be attached to an audio graph.\r\n\r\n4. `initialized` getter that returns `false` before initialized, and `true` after.\r\n\r\n5. `moduleId` getter that returns an identifier of the current WAM, usually composed by its vender + its name.\r\n\r\n6. `instanceId` getter that returns the unique identifier of the current WAM instance.\r\n\r\n7. `descriptor` getter that returns a `WamDescriptor`, same as the WAM's information in the JSON file.\r\n\r\n8. `name` getter that returns the WAM's name.\r\n\r\n9. `vendor` getter that returns the WAM vendor's name.\r\n\r\n10. `initialize` method to asynchronously initialize the newly constructed WAM and its `AudioNode`, accepting one optional argument to set its initial state, returning a Promise that resolves a `WamNode`. After initialized, the WAM will be available to connect its `AudioNode` to the host's audio graph.\r\n\r\n11. `createGui` method to asynchronously create an `Element` that can be attached to the HTML Document as the WAM's GUI, returning a Promise that resolves an `Element`.\r\n\r\n    \u003e There could be multiple GUI controlling the same WAM. Make sure all the GUI can control the WAM and are responding to any state change.\r\n\r\n12. `destroyGui` method, used to clean up a created GUI, accepting an argument of type `Element` which is an existing but no longer useful GUI, returning `void`.\r\n\r\nFor example, a host can get and append to the document the WAM's GUI by doing following:\r\n\r\n```JavaScript\r\n(async () =\u003e {\r\n    const container = document.getElementById('wam-container');\r\n    const wamGui = await wam.createGui();\r\n    container.appendChild(wamGui);\r\n})();\r\n```\r\n\r\nand remove it by:\r\n\r\n```JavaScript\r\nwamGui.remove();\r\nwam.destroyGui(wamGui);\r\n```\r\n\r\nTo connect an initialized WAM to an audio graph:\r\n\r\n```JavaScript\r\n(async () =\u003e {\r\n    const defaultConstraints = {\r\n        audio: {\r\n            echoCancellation: false,\r\n            mozNoiseSuppression: false,\r\n            mozAutoGainControl: false,\r\n        },\r\n    };\r\n    const stream = await navigator.mediaDevices.getUserMedia(defaultConstraints);\r\n    const inputNode = audioCtx.createMediaStreamSource(stream);\r\n\r\n    const { audioNode } = wam;\r\n    inputNode.connect(audioNode);\r\n    audioNode.connect(audioCtx.destination);\r\n})();\r\n```\r\n\r\n### WamDescriptor interface\r\n\r\nThe WAM descriptor contains information that can be used for the host to properly categorize, display, and load WAM by its features. The `WamDescriptor` interface is an object used in the WAM's descriptor JSON file and in its instance's `descriptor` property. It has the following properties.\r\n\r\n1. `name`: the WAM's name.\r\n2. `vendor`: the WAM vendor's name.\r\n3. `version`: current version (string).\r\n4. `sdkVersion`: the WAM SDK (API) version used.\r\n5. `thumbnail`: a URL containing an image for the WAM's thumbnail.\r\n6. `keywords`: an array of keyword strings.\r\n7. `isInstrument`: boolean, `true` if the WAM is a MIDI instrument.\r\n8. `website`: a URL of the WAM's development website.\r\n\r\na set of boolean properties indicating the IO support of the WAM. They are optional in the descriptor JSON, but mandatory to the `descriptor` getter under the `WebAudioModule` interface. These properties will affect the WAM's behavior in the host when it receives audio or events from the upstream WAMs.\r\n\r\n9. `hasAudioInput`\r\n10. `hasAudioOutput`\r\n11. `hasMidiInput`\r\n12. `hasMidiOutput`\r\n13. `hasAutomationInput`\r\n14. `hasAutomationOutput`\r\n15. `hasMpeInput`\r\n16. `hasMpeOutput`\r\n17. `hasOscInput`\r\n18. `hasOscOutput`\r\n19. `hasSysexInput`\r\n20. `hasSysexOutput`\r\n\r\n### WamNode interface\r\n`WamNode` is an extended WebAudio `AudioNode`, available with the `audioNode` getter under the `WebAudioModule` interface. \r\n\r\nA WAM host will use its native (or overridden) [`connect`](https://www.w3.org/TR/webaudio/#dom-audionode-connect) and [`disconnect`](https://www.w3.org/TR/webaudio/#dom-audionode-disconnect) methods to run its underlying DSP in an audio graph. The `WamNode` can also be the destination node of any `AudioNode` connection.\r\n\r\nIn this `WamNode` interface, the related `WebAudioModule` can be found using the `module` getter.\r\n\r\nIt has following methods:\r\n\r\nLifecycle related:\r\n\r\n1. `destroy`: This method should be called by the host before removing the `WamNode`. The WAM developer could perform a clean up by overriding this method. For example, remove event listeners or close AudioWorklet port.\r\n\r\nState related:\r\n\r\n2. `getState`\r\n3. `setState`\r\n\r\n```JavaScript\r\n(async () =\u003e {\r\n    const currentState = await wamNode.getState();\r\n    await wamNode.setState(currentState);\r\n})();\r\n```\r\n\r\nA state could be any serializable type used to save or restore a state of a WAM.\r\n\r\nParameters related:\r\n\r\n4. `getParameterInfo`\r\n5. `getParameterValues`\r\n6. `setParameterValues`\r\n\r\nNote that a WAM parameter is different from WebAudio `AudioParam` to support audio thread side manipulations. To schedule automations to the WAM parameters, the host can use `scheduleEvents`.\r\n\r\nEvent related:\r\n\r\n7. `scheduleEvents`: schedule an WAM event with a timestamp.\r\n8. `clearEvents`: remove all the future events.\r\n\r\nAn WAM events can contain parameter changes, MIDI events, etc. To all a WAM to send events to other WAMs the host can call following methods.\r\n\r\n9. `connectEvents`\r\n10. `disconnectEvents`\r\n\r\nThe connection should be done on the audio thread by calling `webAudioModules.connectEvents` or `webAudioModules.disconnectEvents`.\r\n\r\nThese events will be dispatched when sended or processed at the scheduled time. The host can capture them by `addEventListener`.\r\n\r\n11. `getCompensationDelay`: The host can get a compensation delay hint value in samples. The value is not measured by the host but provided by the WAM developer.\r\n\r\n### WamProcessor interface\r\n\r\nEach WAM plugin should provide an `WamProcessor` interface on the `AudioWorklet` thread. The interface is extended by an `AudioWorkletProcessor`, created by an `WamNode`. On the audio thread, the processor can access a `WamEnv` interface under `globalThis.webAudioModules`. When the processor is created, it should call `webAudioModules.create(this);` to register itself to the `WamEnv`.\r\n\r\n`WamProcessor` has the following getters and methods:\r\n\r\n1. `moduleId` getter: returns an identifier of the current WAM, same as in the `WebAudioModule` interface.\r\n\r\n2. `instanceId` getter: returns the unique identifier of the current WAM instance, same as in the `WebAudioModule` interface.\r\n\r\n3. `getCompensationDelay`\r\n4. `scheduleEvents`\r\n5. `clearEvents`\r\n6. `destroy`: the method should disconnect from its event graph by calling `webAudioModules.destroy(this);`\r\n\r\nThey are the same as in the `WamNode` interface.\r\n\r\n7. `emitEvents` can be used by the WAM to pass any event to downstream WAMs in the event graph.\r\n\r\n\r\n\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffr0stbyter%2Fapi","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffr0stbyter%2Fapi","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffr0stbyter%2Fapi/lists"}