UNPKG

@doc.e.dub/csound-browser

Version:

[![npm (scoped with tag)](https://shields.shivering-isles.com/npm/v/@csound/browser/latest)](https://www.npmjs.com/package/@csound/browser) [![GitHub Workflow Status](https://shields.shivering-isles.com/github/workflow/status/csound/csound/csound_wasm)](h

1,747 lines (1,513 loc) 64.2 kB
// this file is intended for @csound/nodejs function _isPlaceholder(a) { return a != null && typeof a === 'object' && a['@@functional/placeholder'] === true; } /** * Optimized internal one-arity curry function. * * @private * @category Function * @param {Function} fn The function to curry. * @return {Function} The curried function. */ function _curry1(fn) { return function f1(a) { if (arguments.length === 0 || _isPlaceholder(a)) { return f1; } else { return fn.apply(this, arguments); } }; } /** * Optimized internal two-arity curry function. * * @private * @category Function * @param {Function} fn The function to curry. * @return {Function} The curried function. */ function _curry2(fn) { return function f2(a, b) { switch (arguments.length) { case 0: return f2; case 1: return _isPlaceholder(a) ? f2 : _curry1(function (_b) { return fn(a, _b); }); default: return _isPlaceholder(a) && _isPlaceholder(b) ? f2 : _isPlaceholder(a) ? _curry1(function (_a) { return fn(_a, b); }) : _isPlaceholder(b) ? _curry1(function (_b) { return fn(a, _b); }) : fn(a, b); } }; } function _arity(n, fn) { /* eslint-disable no-unused-vars */ switch (n) { case 0: return function () { return fn.apply(this, arguments); }; case 1: return function (a0) { return fn.apply(this, arguments); }; case 2: return function (a0, a1) { return fn.apply(this, arguments); }; case 3: return function (a0, a1, a2) { return fn.apply(this, arguments); }; case 4: return function (a0, a1, a2, a3) { return fn.apply(this, arguments); }; case 5: return function (a0, a1, a2, a3, a4) { return fn.apply(this, arguments); }; case 6: return function (a0, a1, a2, a3, a4, a5) { return fn.apply(this, arguments); }; case 7: return function (a0, a1, a2, a3, a4, a5, a6) { return fn.apply(this, arguments); }; case 8: return function (a0, a1, a2, a3, a4, a5, a6, a7) { return fn.apply(this, arguments); }; case 9: return function (a0, a1, a2, a3, a4, a5, a6, a7, a8) { return fn.apply(this, arguments); }; case 10: return function (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) { return fn.apply(this, arguments); }; default: throw new Error('First argument to _arity must be a non-negative integer no greater than ten'); } } /** * Internal curryN function. * * @private * @category Function * @param {Number} length The arity of the curried function. * @param {Array} received An array of arguments received thus far. * @param {Function} fn The function to curry. * @return {Function} The curried function. */ function _curryN(length, received, fn) { return function () { var combined = []; var argsIdx = 0; var left = length; var combinedIdx = 0; while (combinedIdx < received.length || argsIdx < arguments.length) { var result; if (combinedIdx < received.length && (!_isPlaceholder(received[combinedIdx]) || argsIdx >= arguments.length)) { result = received[combinedIdx]; } else { result = arguments[argsIdx]; argsIdx += 1; } combined[combinedIdx] = result; if (!_isPlaceholder(result)) { left -= 1; } combinedIdx += 1; } return left <= 0 ? fn.apply(this, combined) : _arity(left, _curryN(length, combined, fn)); }; } /** * Returns a curried equivalent of the provided function, with the specified * arity. The curried function has two unusual capabilities. First, its * arguments needn't be provided one at a time. If `g` is `R.curryN(3, f)`, the * following are equivalent: * * - `g(1)(2)(3)` * - `g(1)(2, 3)` * - `g(1, 2)(3)` * - `g(1, 2, 3)` * * Secondly, the special placeholder value [`R.__`](#__) may be used to specify * "gaps", allowing partial application of any combination of arguments, * regardless of their positions. If `g` is as above and `_` is [`R.__`](#__), * the following are equivalent: * * - `g(1, 2, 3)` * - `g(_, 2, 3)(1)` * - `g(_, _, 3)(1)(2)` * - `g(_, _, 3)(1, 2)` * - `g(_, 2)(1)(3)` * - `g(_, 2)(1, 3)` * - `g(_, 2)(_, 3)(1)` * * @func * @memberOf R * @since v0.5.0 * @category Function * @sig Number -> (* -> a) -> (* -> a) * @param {Number} length The arity for the returned function. * @param {Function} fn The function to curry. * @return {Function} A new, curried function. * @see R.curry * @example * * const sumArgs = (...args) => R.sum(args); * * const curriedAddFourNumbers = R.curryN(4, sumArgs); * const f = curriedAddFourNumbers(1, 2); * const g = f(3); * g(4); //=> 10 */ var curryN = /*#__PURE__*/ _curry2(function curryN(length, fn) { if (length === 1) { return _curry1(fn); } return _arity(length, _curryN(length, [], fn)); }); /** * Optimized internal three-arity curry function. * * @private * @category Function * @param {Function} fn The function to curry. * @return {Function} The curried function. */ function _curry3(fn) { return function f3(a, b, c) { switch (arguments.length) { case 0: return f3; case 1: return _isPlaceholder(a) ? f3 : _curry2(function (_b, _c) { return fn(a, _b, _c); }); case 2: return _isPlaceholder(a) && _isPlaceholder(b) ? f3 : _isPlaceholder(a) ? _curry2(function (_a, _c) { return fn(_a, b, _c); }) : _isPlaceholder(b) ? _curry2(function (_b, _c) { return fn(a, _b, _c); }) : _curry1(function (_c) { return fn(a, b, _c); }); default: return _isPlaceholder(a) && _isPlaceholder(b) && _isPlaceholder(c) ? f3 : _isPlaceholder(a) && _isPlaceholder(b) ? _curry2(function (_a, _b) { return fn(_a, _b, c); }) : _isPlaceholder(a) && _isPlaceholder(c) ? _curry2(function (_a, _c) { return fn(_a, b, _c); }) : _isPlaceholder(b) && _isPlaceholder(c) ? _curry2(function (_b, _c) { return fn(a, _b, _c); }) : _isPlaceholder(a) ? _curry1(function (_a) { return fn(_a, b, c); }) : _isPlaceholder(b) ? _curry1(function (_b) { return fn(a, _b, c); }) : _isPlaceholder(c) ? _curry1(function (_c) { return fn(a, b, _c); }) : fn(a, b, c); } }; } /** * Tests whether or not an object is an array. * * @private * @param {*} val The object to test. * @return {Boolean} `true` if `val` is an array, `false` otherwise. * @example * * _isArray([]); //=> true * _isArray(null); //=> false * _isArray({}); //=> false */ var _isArray = Array.isArray || function _isArray(val) { return val != null && val.length >= 0 && Object.prototype.toString.call(val) === '[object Array]'; }; function _isString(x) { return Object.prototype.toString.call(x) === '[object String]'; } /** * Tests whether or not an object is similar to an array. * * @private * @category Type * @category List * @sig * -> Boolean * @param {*} x The object to test. * @return {Boolean} `true` if `x` has a numeric length property and extreme indices defined; `false` otherwise. * @example * * _isArrayLike([]); //=> true * _isArrayLike(true); //=> false * _isArrayLike({}); //=> false * _isArrayLike({length: 10}); //=> false * _isArrayLike({0: 'zero', 9: 'nine', length: 10}); //=> true */ var _isArrayLike = /*#__PURE__*/ _curry1(function isArrayLike(x) { if (_isArray(x)) { return true; } if (!x) { return false; } if (typeof x !== 'object') { return false; } if (_isString(x)) { return false; } if (x.nodeType === 1) { return !!x.length; } if (x.length === 0) { return true; } if (x.length > 0) { return x.hasOwnProperty(0) && x.hasOwnProperty(x.length - 1); } return false; }); var XWrap = /*#__PURE__*/ function () { function XWrap(fn) { this.f = fn; } XWrap.prototype['@@transducer/init'] = function () { throw new Error('init not implemented on XWrap'); }; XWrap.prototype['@@transducer/result'] = function (acc) { return acc; }; XWrap.prototype['@@transducer/step'] = function (acc, x) { return this.f(acc, x); }; return XWrap; }(); function _xwrap(fn) { return new XWrap(fn); } /** * Creates a function that is bound to a context. * Note: `R.bind` does not provide the additional argument-binding capabilities of * [Function.prototype.bind](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind). * * @func * @memberOf R * @since v0.6.0 * @category Function * @category Object * @sig (* -> *) -> {*} -> (* -> *) * @param {Function} fn The function to bind to context * @param {Object} thisObj The context to bind `fn` to * @return {Function} A function that will execute in the context of `thisObj`. * @see R.partial * @example * * const log = R.bind(console.log, console); * R.pipe(R.assoc('a', 2), R.tap(log), R.assoc('a', 3))({a: 1}); //=> {a: 3} * // logs {a: 2} * @symb R.bind(f, o)(a, b) = f.call(o, a, b) */ var bind = /*#__PURE__*/ _curry2(function bind(fn, thisObj) { return _arity(fn.length, function () { return fn.apply(thisObj, arguments); }); }); function _arrayReduce(xf, acc, list) { var idx = 0; var len = list.length; while (idx < len) { acc = xf['@@transducer/step'](acc, list[idx]); if (acc && acc['@@transducer/reduced']) { acc = acc['@@transducer/value']; break; } idx += 1; } return xf['@@transducer/result'](acc); } function _iterableReduce(xf, acc, iter) { var step = iter.next(); while (!step.done) { acc = xf['@@transducer/step'](acc, step.value); if (acc && acc['@@transducer/reduced']) { acc = acc['@@transducer/value']; break; } step = iter.next(); } return xf['@@transducer/result'](acc); } function _methodReduce(xf, acc, obj, methodName) { return xf['@@transducer/result'](obj[methodName](bind(xf['@@transducer/step'], xf), acc)); } var symIterator = typeof Symbol !== 'undefined' ? Symbol.iterator : '@@iterator'; function _reduce(fn, acc, list) { if (typeof fn === 'function') { fn = _xwrap(fn); } if (_isArrayLike(list)) { return _arrayReduce(fn, acc, list); } if (typeof list['fantasy-land/reduce'] === 'function') { return _methodReduce(fn, acc, list, 'fantasy-land/reduce'); } if (list[symIterator] != null) { return _iterableReduce(fn, acc, list[symIterator]()); } if (typeof list.next === 'function') { return _iterableReduce(fn, acc, list); } if (typeof list.reduce === 'function') { return _methodReduce(fn, acc, list, 'reduce'); } throw new TypeError('reduce: list must be array or iterable'); } function _has(prop, obj) { return Object.prototype.hasOwnProperty.call(obj, prop); } var toString = Object.prototype.toString; var _isArguments = /*#__PURE__*/ function () { return toString.call(arguments) === '[object Arguments]' ? function _isArguments(x) { return toString.call(x) === '[object Arguments]'; } : function _isArguments(x) { return _has('callee', x); }; }(); var hasEnumBug = ! /*#__PURE__*/ { toString: null }.propertyIsEnumerable('toString'); var nonEnumerableProps = ['constructor', 'valueOf', 'isPrototypeOf', 'toString', 'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString']; // Safari bug var hasArgsEnumBug = /*#__PURE__*/ function () { return arguments.propertyIsEnumerable('length'); }(); var contains = function contains(list, item) { var idx = 0; while (idx < list.length) { if (list[idx] === item) { return true; } idx += 1; } return false; }; /** * Returns a list containing the names of all the enumerable own properties of * the supplied object. * Note that the order of the output array is not guaranteed to be consistent * across different JS platforms. * * @func * @memberOf R * @since v0.1.0 * @category Object * @sig {k: v} -> [k] * @param {Object} obj The object to extract properties from * @return {Array} An array of the object's own properties. * @see R.keysIn, R.values * @example * * R.keys({a: 1, b: 2, c: 3}); //=> ['a', 'b', 'c'] */ var keys = typeof Object.keys === 'function' && !hasArgsEnumBug ? /*#__PURE__*/ _curry1(function keys(obj) { return Object(obj) !== obj ? [] : Object.keys(obj); }) : /*#__PURE__*/ _curry1(function keys(obj) { if (Object(obj) !== obj) { return []; } var prop, nIdx; var ks = []; var checkArgsLength = hasArgsEnumBug && _isArguments(obj); for (prop in obj) { if (_has(prop, obj) && (!checkArgsLength || prop !== 'length')) { ks[ks.length] = prop; } } if (hasEnumBug) { nIdx = nonEnumerableProps.length - 1; while (nIdx >= 0) { prop = nonEnumerableProps[nIdx]; if (_has(prop, obj) && !contains(ks, prop)) { ks[ks.length] = prop; } nIdx -= 1; } } return ks; }); /** * Returns a single item by iterating through the list, successively calling * the iterator function and passing it an accumulator value and the current * value from the array, and then passing the result to the next call. * * The iterator function receives two values: *(acc, value)*. It may use * [`R.reduced`](#reduced) to shortcut the iteration. * * The arguments' order of [`reduceRight`](#reduceRight)'s iterator function * is *(value, acc)*. * * Note: `R.reduce` does not skip deleted or unassigned indices (sparse * arrays), unlike the native `Array.prototype.reduce` method. For more details * on this behavior, see: * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce#Description * * Dispatches to the `reduce` method of the third argument, if present. When * doing so, it is up to the user to handle the [`R.reduced`](#reduced) * shortcuting, as this is not implemented by `reduce`. * * @func * @memberOf R * @since v0.1.0 * @category List * @sig ((a, b) -> a) -> a -> [b] -> a * @param {Function} fn The iterator function. Receives two values, the accumulator and the * current element from the array. * @param {*} acc The accumulator value. * @param {Array} list The list to iterate over. * @return {*} The final, accumulated value. * @see R.reduced, R.addIndex, R.reduceRight * @example * * R.reduce(R.subtract, 0, [1, 2, 3, 4]) // => ((((0 - 1) - 2) - 3) - 4) = -10 * // - -10 * // / \ / \ * // - 4 -6 4 * // / \ / \ * // - 3 ==> -3 3 * // / \ / \ * // - 2 -1 2 * // / \ / \ * // 0 1 0 1 * * @symb R.reduce(f, a, [b, c, d]) = f(f(f(a, b), c), d) */ var reduce = /*#__PURE__*/ _curry3(_reduce); /** * Makes a shallow clone of an object, setting or overriding the specified * property with the given value. Note that this copies and flattens prototype * properties onto the new object as well. All non-primitive properties are * copied by reference. * * @func * @memberOf R * @since v0.8.0 * @category Object * @sig String -> a -> {k: v} -> {k: v} * @param {String} prop The property name to set * @param {*} val The new value * @param {Object} obj The object to clone * @return {Object} A new object equivalent to the original except for the changed property. * @see R.dissoc, R.pick * @example * * R.assoc('c', 3, {a: 1, b: 2}); //=> {a: 1, b: 2, c: 3} */ var assoc = /*#__PURE__*/ _curry3(function assoc(prop, val, obj) { var result = {}; for (var p in obj) { result[p] = obj[p]; } result[prop] = val; return result; }); /** * Returns a curried equivalent of the provided function. The curried function * has two unusual capabilities. First, its arguments needn't be provided one * at a time. If `f` is a ternary function and `g` is `R.curry(f)`, the * following are equivalent: * * - `g(1)(2)(3)` * - `g(1)(2, 3)` * - `g(1, 2)(3)` * - `g(1, 2, 3)` * * Secondly, the special placeholder value [`R.__`](#__) may be used to specify * "gaps", allowing partial application of any combination of arguments, * regardless of their positions. If `g` is as above and `_` is [`R.__`](#__), * the following are equivalent: * * - `g(1, 2, 3)` * - `g(_, 2, 3)(1)` * - `g(_, _, 3)(1)(2)` * - `g(_, _, 3)(1, 2)` * - `g(_, 2)(1)(3)` * - `g(_, 2)(1, 3)` * - `g(_, 2)(_, 3)(1)` * * @func * @memberOf R * @since v0.1.0 * @category Function * @sig (* -> a) -> (* -> a) * @param {Function} fn The function to curry. * @return {Function} A new, curried function. * @see R.curryN, R.partial * @example * * const addFourNumbers = (a, b, c, d) => a + b + c + d; * * const curriedAddFourNumbers = R.curry(addFourNumbers); * const f = curriedAddFourNumbers(1, 2); * const g = f(3); * g(4); //=> 10 */ var curry = /*#__PURE__*/ _curry1(function curry(fn) { return curryN(fn.length, fn); }); function _isNumber(x) { return Object.prototype.toString.call(x) === '[object Number]'; } /** * Returns a list of numbers from `from` (inclusive) to `to` (exclusive). * * @func * @memberOf R * @since v0.1.0 * @category List * @sig Number -> Number -> [Number] * @param {Number} from The first number in the list. * @param {Number} to One more than the last number in the list. * @return {Array} The list of numbers in the set `[a, b)`. * @example * * R.range(1, 5); //=> [1, 2, 3, 4] * R.range(50, 53); //=> [50, 51, 52] */ var range = /*#__PURE__*/ _curry2(function range(from, to) { if (!(_isNumber(from) && _isNumber(to))) { throw new TypeError('Both arguments to range must be numbers'); } var result = []; var n = from; while (n < to) { result.push(n); n += 1; } return result; }); /* csound instantiation module from <csound.h> https://csound.com/docs/api/modules.html */ /** * creates Csound instance * (inferred in @csound/wasm/browser) * @private */ const csoundCreate = (wasm) => () => wasm.exports.csoundCreateWasi(); csoundCreate.toString = () => "create = async () => undefined;"; /** * Destroys an instance of Csound and frees memory * @async * @function * @name destroy * @memberof CsoundObj * @return {Promise.<undefined>} */ const csoundDestroy = (wasm) => (csound) => wasm.exports.csoundDestroy(csound); csoundDestroy.toString = () => "destroy = async () => undefined;"; /** * Returns the API version as int * @async * @function * @name getAPIVersion * @memberof CsoundObj * @return {Promise.<number>} */ const csoundGetAPIVersion = (wasm) => () => wasm.exports.csoundGetAPIVersion(); csoundGetAPIVersion.toString = () => "getAPIVersion = async () => Number;"; /** * Returns the Csound version as int * @async * @function * @name getVersion * @memberof CsoundObj * @return {Promise.<number>} */ const csoundGetVersion = (wasm) => () => wasm.exports.csoundGetVersion(); csoundGetVersion.toString = () => "getVersion = async () => Number;"; /** * Initialise Csound with specific flags. * This function is called internally by csoundCreate(), * so there is generally no need to use it explicitly * unless you need to avoid default initilization that * sets signal handlers and atexit() callbacks. * @async * @function * @name initialize * @memberof CsoundObj * @return {Promise.<number>} - Return value is zero on success, * positive if initialisation was done already, and negative on error. */ const csoundInitialize = (wasm) => (_, flags) => wasm.exports.csoundInitialize(flags); csoundInitialize.toString = () => "initialize = async () => Number;"; const decoder = new TextDecoder("utf-8"); const encoder = new TextEncoder("utf-8"); const uint2String = (uint) => decoder.decode(uint); const trimNull = (a) => { const c = a.indexOf("\0"); if (c > -1) { // eslint-disable-next-line unicorn/prefer-string-slice return a.substr(0, c); } return a; }; const freeStringPtr = (wasm, ptr) => { wasm.exports.freeStringMem(ptr); }; const ptr2string = (wasm, stringPtr) => { const { buffer } = wasm.exports.memory; const intArray = new Uint8Array(buffer, stringPtr); const result = uint2String(intArray); return trimNull(result); }; const string2ptr = (wasm, string) => { if (typeof string !== "string") { console.error("Expected string but got", typeof string); return; } const stringBuf = encoder.encode(string); const offset = wasm.exports.allocStringMem(stringBuf.length); const { buffer } = wasm.exports.memory; const outBuf = new Uint8Array(buffer, offset, stringBuf.length + 1); outBuf.set(stringBuf); return offset; }; /* csound performance module from <csound.h> https://csound.com/docs/api/modules.html */ /** * Parses a csound orchestra string * @async * @function * @name parseOrc * @memberof CsoundObj * @param {string} orc * @return {Promise.<object>} */ const csoundParseOrc = (wasm) => (csound, orc) => wasm.exports.csoundParseOrc(csound, orc); csoundParseOrc.toString = () => "parseOrc = async (orchestra) => Object;"; /** * Compiles AST tree * @async * @function * @name compileTree * @memberof CsoundObj * @param {object} tree * @return {Promise.<number>} */ const csoundCompileTree = (wasm) => (csound, tree) => wasm.exports.csoundCompileTree(csound, tree); csoundCompileTree.toString = () => "compileTree = async (tree) => Number;"; // TODO // csoundDeleteTree (CSOUND *csound, TREE *tree) /** * Compiles a csound orchestra string * @async * @function * @name compileOrc * @memberof CsoundObj * @param {string} orc * @return {Promise.<number>} */ const csoundCompileOrc = (wasm) => (csound, orc) => { const stringPtr = string2ptr(wasm, orc); const result = wasm.exports.csoundCompileOrc(csound, stringPtr); freeStringPtr(wasm, stringPtr); return result; }; csoundCompileOrc.toString = () => "compileOrc = async (orchestra) => Number;"; /** * Compiles a csound orchestra string * @async * @function * @name evalCode * @memberof CsoundObj * @param {string} orc * @return {Promise.<number>} */ const csoundEvalCode = (wasm) => (csound, orc) => { const stringPtr = string2ptr(wasm, orc); const result = wasm.exports.csoundEvalCode(csound, stringPtr); freeStringPtr(wasm, stringPtr); return result; }; csoundEvalCode.toString = () => "csoundEvalCode = async (orchestra) => Number;"; // TODO // csoundInitializeCscore (CSOUND *, FILE *insco, FILE *outsco) // TODO // csoundCompileArgs (CSOUND *, int argc, const char **argv) /** * Prepares Csound for performance * @async * @function * @name start * @memberof CsoundObj * @return {Promise.<number>} */ const csoundStart = (wasm) => (csound) => wasm.exports.csoundStartWasi(csound); csoundStart.toString = () => "start = async () => Number;"; // TODO // csoundCompile (CSOUND *, int argc, const char **argv) /** * Compiles a Csound input file but does not perform it. * @async * @function * @name compileCsd * @memberof CsoundObj * @param {string} path * @return {Promise.<number>} */ const csoundCompileCsd = (wasm) => (csound, path) => { const sandboxedPath = /^\//i.test(path) ? `/sandbox${path}` : `/sandbox/${path}`; const stringPtr = string2ptr(wasm, sandboxedPath); const result = wasm.exports.csoundCompileCsd(csound, stringPtr); freeStringPtr(wasm, stringPtr); return result; }; csoundCompileCsd.toString = () => "compileCsd = async (path) => Number;"; /** * Compiles a CSD string but does not perform it. * @async * @function * @name compileCsdText * @memberof CsoundObj * @param {string} orc * @return {Promise.<number>} */ const csoundCompileCsdText = (wasm) => (csound, orc) => { const stringPtr = string2ptr(wasm, orc); const result = wasm.exports.csoundCompileCsdText(csound, stringPtr); freeStringPtr(wasm, stringPtr); return result; }; csoundCompileCsdText.toString = () => "compileCsdText = async (csoundDocument) => Number;"; /** * Performs(plays) audio until end is reached * @async * @function * @name perform * @memberof CsoundObj * @return {Promise.<number>} */ const csoundPerform = (wasm) => (csound) => wasm.exports.csoundPerform(csound); csoundPerform.toString = () => "perform = async () => Number;"; /** * Performs(plays) 1 ksmps worth of sample(s) * @async * @function * @name performKsmps * @memberof CsoundObj * @return {Promise.<number>} */ const csoundPerformKsmps = (wasm) => (csound) => wasm.exports.csoundPerformKsmpsWasi(csound); csoundPerformKsmps.toString = () => "performKsmps = async (csound) => Number;"; /** * Performs(plays) 1 buffer worth of audio * @async * @function * @name performBuffer * @memberof CsoundObj * @return {Promise.<number>} */ const csoundPerformBuffer = (wasm) => (csound) => wasm.exports.csoundPerformBuffer(csound); csoundPerformBuffer.toString = () => "performBuffer = async (csound) => Number;"; /** * Stops a csoundPerform * @async * @function * @name stop * @memberof CsoundObj * @return {Promise.<undefined>} */ const csoundStop = (wasm) => (csound) => wasm.exports.csoundStop(csound); csoundStop.toString = () => "stop = async () => undefined;"; /** * Prints information about the end of a performance, * and closes audio and MIDI devices. * @async * @function * @name cleanup * @memberof CsoundObj * @return {Promise.<number>} */ const csoundCleanup = (wasm) => (csound) => wasm.exports.csoundCleanup(csound); csoundCleanup.toString = () => "cleanup = async () => Number;"; /** * Prints information about the end of a performance, * and closes audio and MIDI devices. * @async * @function * @name reset * @memberof CsoundObj * @return {Promise.<number>} */ const csoundReset = (wasm) => (csound) => wasm.exports.csoundResetWasi(csound); csoundReset.toString = () => "reset = async () => Number;"; const sizeOfPrimitive = { int: 4, MYFLT: 4, char: 1, }; const sizeofStruct = (jsStruct) => { const result = jsStruct.reduce((total, [_, primitive, ...rest]) => { return (total += primitive === "char" ? sizeOfPrimitive[primitive] * rest[0] : sizeOfPrimitive[primitive]); }, 0); return result; }; const structBufferToObject = (jsStruct, buffer) => { const [result] = jsStruct.reduce( ([parameters, offset], [parameterName, primitive, ...rest]) => { const currentSize = primitive === "char" ? sizeOfPrimitive[primitive] * rest[0] : sizeOfPrimitive[primitive]; const currentValue = primitive === "char" ? trimNull(uint2String(buffer.subarray(offset, currentSize))) || "" : buffer[offset]; parameters[parameterName] = currentValue; return [parameters, offset + currentSize]; }, [{}, 0], ); return result; }; /** * @typedef CSOUND_PARAMS * @property {number} debug_mode * @property {number} buffer_frames * @property {number} hardware_buffer_frames * @property {number} displays * @property {number} ascii_graphs * @property {number} postscript_graphs * @property {number} message_level * @property {number} tempo * @property {number} ring_bell * @property {number} use_cscore * @property {number} terminate_on_midi * @property {number} heartbeat * @property {number} defer_gen01_load * @property {number} midi_key * @property {number} midi_key_cps * @property {number} midi_key_oct * @property {number} midi_key_pch * @property {number} midi_velocity */ const CSOUND_PARAMS = [ /* debug mode, 0 or 1 */ ["debug_mode", "int"], /* number of frames in in/out buffers */ ["buffer_frames", "int"], /* number of frames in in/out hardware buffers */ ["hardware_buffer_frames", "int"], /* graph displays, 0 or 1 */ ["displays", "int"], /* use ASCII graphs, 0 or 1 */ ["ascii_graphs", "int"], /* use postscript graphs, 0 or 1 */ ["postscript_graphs", "int"], /* message printout control */ ["message_level", "int"], /* tempo (sets Beatmode) */ ["tempo", "int"], /* bell, 0 or 1 */ ["ring_bell", "int"], /* use cscore for processing */ ["use_cscore", "int"], /* terminate performance at the end */ ["terminate_on_midi", "int"], /* print heart beat, 0 or 1 */ ["heartbeat", "int"], /* defer GEN01 load, 0 or 1 */ ["defer_gen01_load", "int"], /* pfield to map midi key no */ ["midi_key", "int"], /* pfield to map midi key no as cps */ ["midi_key_cps", "int"], /* pfield to map midi key no as oct */ ["midi_key_oct", "int"], /* pfield to map midi key no as pch */ ["midi_key_pch", "int"], /* pfield to map midi velocity */ ["midi_velocity", "int"], /* pfield to map midi velocity as amplitude */ ["midi_velocity_amp", "int"], /* disable relative paths from files, 0 or 1 */ ["no_default_paths", "int"], /* number of threads for multicore performance */ ["number_of_threads", "int"], /* do not compile, only check syntax */ ["syntax_check_only", "int"], /* csd line error reporting */ ["csd_line_counts", "int"], /* deprecated, kept for backwards comp. */ ["compute_weights", "int"], /* use realtime priority mode, 0 or 1 */ ["realtime_mode", "int"], /* use sample-level score event accuracy */ ["sample_accurate", "int"], /* overriding sample rate */ ["sample_rate_override", "MYFLT"], /* overriding control rate */ ["control_rate_override", "MYFLT"], /* overriding number of out channels */ ["nchnls_override", "int"], /* overriding number of in channels */ ["nchnls_i_override", "int"], /* overriding 0dbfs */ ["e0dbfs_override", "MYFLT"], /* daemon mode */ ["daemon", "int"], /* ksmps override */ ["ksmps_override", "int"], /* fft_lib */ ["FFT_library", "int"], ]; /** * @typedef CS_MIDIDEVICE * @property {string} device_name * @property {string} interface_name * @property {string} device_id * @property {string} midi_module * @property {number} isOutput */ const CS_MIDIDEVICE = [ /* debug mode, 0 or 1 */ ["device_name", "char", 64], ["interface_name", "char", 64], ["device_id", "char", 64], ["midi_module", "char", 64], ["isOutput", "int"], ]; /* csound attribute module from <csound.h> https://csound.com/docs/api/modules.html */ /** * Returns the sample rate from Csound instance * @async * @function * @name getSr * @memberof CsoundObj * @return {Promise.<number>} */ const csoundGetSr = curry((wasm, csound) => wasm.exports.csoundGetSr(csound)); csoundGetSr.toString = () => "getSr = async () => Number;"; /** * Returns the control rate from Csound instance * @async * @function * @name getKr * @memberof CsoundObj * @return {Promise.<number>} */ const csoundGetKr = curry((wasm, csound) => wasm.exports.csoundGetKr(csound)); csoundGetKr.toString = () => "getKr = async () => Number;"; /** * Returns the ksmps value (kr/sr) from Csound instance * @async * @function * @name getKsmps * @memberof CsoundObj * @return {Promise.<number>} */ const csoundGetKsmps = curry((wasm, csound) => wasm.exports.csoundGetKsmps(csound)); csoundGetKsmps.toString = () => "getKsmps = async () => Number;"; /** * Returns the number of output channels from Csound instance * @async * @function * @name getNchnls * @memberof CsoundObj * @return {Promise.<number>} */ const csoundGetNchnls = curry((wasm, csound) => wasm.exports.csoundGetNchnls(csound)); csoundGetNchnls.toString = () => "getNchnls = async () => Number;"; /** * Returns the number of input channels from Csound instance * @async * @function * @name getNchnlsInput * @memberof CsoundObj * @return {Promise.<number>} */ const csoundGetNchnlsInput = curry((wasm, csound) => wasm.exports.csoundGetNchnlsInput(csound), ); csoundGetNchnlsInput.toString = () => "getNchnlsInput = async () => Number;"; /** * Returns the value of csoundGet0dBFS * @async * @function * @name get0dBFS * @memberof CsoundObj * @return {Promise.<number>} */ const csoundGet0dBFS = curry((wasm, csound) => wasm.exports.csoundGet0dBFS(csound)); csoundGet0dBFS.toString = () => "get0dBFS = async () => Number;"; /** * Returns the A4 frequency reference * @async * @function * @name getA4 * @memberof CsoundObj * @return {Promise.<number>} */ const csoundGetA4 = curry((wasm, csound) => wasm.exports.csoundGetA4(csound)); csoundGetA4.toString = () => "getA4 = async () => Number;"; /** * Return the current performance time in samples * @async * @function * @name getCurrentTimeSamples * @memberof CsoundObj * @return {Promise.<number>} */ const csoundGetCurrentTimeSamples = curry((wasm, csound) => wasm.exports.csoundGetCurrentTimeSamples(csound), ); csoundGetCurrentTimeSamples.toString = () => "getCurrentTimeSamples = async () => Number;"; /** * Return the size of MYFLT in number of bytes * @async * @function * @name getSizeOfMYFLT * @memberof CsoundObj * @return {Promise.<number>} */ const csoundGetSizeOfMYFLT = curry((wasm, csound) => wasm.exports.csoundGetSizeOfMYFLT(csound), ); csoundGetSizeOfMYFLT.toString = () => "getSizeOfMYFLT = async () => Number;"; // TODO (do these make any sense in wasm?) // csoundGetHostData // csoundSetHostData /** * Set a single csound option (flag), * no spaces are allowed in the string. * @async * @function * @name setOption * @memberof CsoundObj * @param {string} option * @return {Promise.<number>} */ const csoundSetOption = curry((wasm, csound, option) => { const stringPtr = string2ptr(wasm, option); const result = wasm.exports.csoundSetOption(csound, stringPtr); freeStringPtr(wasm, stringPtr); return result; }); csoundSetOption.toString = () => "setOption = async (option) => Number;"; /** * Configure Csound with a given set of * parameters defined in the CSOUND_PARAMS structure. * These parameters are the part of the OPARMS struct * that are configurable through command line flags. * The CSOUND_PARAMS structure can be obtained using * csoundGetParams(). * These options should only be changed before * performance has started. * @async * @function * @name setParams * @memberof CsoundObj * @param {CSOUND_PARAMS} csoundParams - csoundParams object * @return {Promise.<undefined>} */ const csoundSetParams = curry((wasm, csound, csoundParameters) => { wasm.exports.csoundSetParams(csound, csoundParameters); }); csoundSetParams.toString = () => "setParams = async (csoundParams) => undefined;"; /** * Get the current set of parameters * from a Csound instance * in a CSOUND_PARAMS structure. * @async * @function * @name getParams * @memberof CsoundObj * @return {Promise.<CSOUND_PARAMS>} - CSOUND_PARAMS object */ const csoundGetParams = curry((wasm, csound) => { const { buffer } = wasm.exports.memory; const structLength = sizeofStruct(CSOUND_PARAMS); const structOffset = wasm.exports.allocCsoundParamsStruct(); const structBuffer = new Uint8Array(buffer, structOffset, structLength); wasm.exports.csoundGetParams(csound, structOffset); const currentCsoundParameters = structBufferToObject(CSOUND_PARAMS, structBuffer); wasm.exports.freeCsoundParams(structOffset); return currentCsoundParameters; }); csoundGetParams.toString = () => "getParams = async () => CSOUND_PARAMS;"; /** * Returns whether Csound is set to print debug messages * sent through the DebugMsg() internal API function. * Anything different to 0 means true. * @async * @function * @name getDebug * @memberof CsoundObj * @return {Promise.<number>} */ const csoundGetDebug = curry((wasm, csound) => wasm.exports.csoundGetDebug(csound)); csoundGetDebug.toString = () => "getDebug = async () => Number;"; /** * Return the size of MYFLT in number of bytes * @async * @function * @name setDebug * @memberof CsoundObj * @param {number} debug * @return {Promise.<undefined>} */ const csoundSetDebug = curry((wasm, csound, debug) => { wasm.exports.csoundSetDebug(csound, debug); }); csoundSetDebug.toString = () => "setDebug = async (number) => undefined;"; /* Realtime Audio I/O module from <csound.h> https://csound.com/docs/api/modules.html */ /** * Returns the number of samples in Csound's input buffer. * @async * @function * @name getInputBufferSize * @memberof CsoundObj * @return {Promise.<number>} */ const csoundGetInputBufferSize = (wasm) => (csound) => wasm.exports.csoundGetInputBufferSize(csound); csoundGetInputBufferSize.toString = () => "getInputBufferSize = async () => Number;"; /** * Returns the number of samples in Csound's output buffer. * @async * @function * @name getOutputBufferSize * @memberof CsoundObj * @return {Promise.<number>} */ const csoundGetOutputBufferSize = (wasm) => (csound) => wasm.exports.csoundGetOutputBufferSize(csound); csoundGetOutputBufferSize.toString = () => "getOutputBufferSize = async () => Number;"; /** * Returns the address of the Csound audio input buffer. * @async * @function * @name getInputBuffer * @memberof CsoundObj * @return {Promise.<number>} */ const csoundGetInputBuffer = (wasm) => (csound) => wasm.exports.csoundGetInputBuffer(csound); csoundGetInputBuffer.toString = () => "getInputBuffer = async () => Number;"; /** * Returns the address of the Csound audio output buffer. * @async * @function * @name getOutputBuffer * @memberof CsoundObj * @return {Promise.<number>} */ const csoundGetOutputBuffer = (wasm) => (csound) => wasm.exports.csoundGetOutputBuffer(csound); csoundGetOutputBuffer.toString = () => "getOutputBuffer = async () => Number;"; /** * Returns the address of the Csound audio input working buffer (spin). * Enables external software to write audio into Csound before calling csoundPerformKsmps. * @async * @function * @name getSpin * @memberof CsoundObj * @return {Promise.<number>} */ const csoundGetSpin = (wasm) => (csound) => wasm.exports.csoundGetSpin(csound); csoundGetSpin.toString = () => "getSpin = async (csound) => Number;"; /** * Returns the address of the Csound audio output working buffer (spout). * Enables external software to read audio from Csound after calling csoundPerformKsmps. * @async * @function getSpout * @memberof CsoundObj * @return {Promise.<number>} */ const csoundGetSpout = (wasm) => (csound) => wasm.exports.csoundGetSpout(csound); csoundGetSpout.toString = () => "getSpout = async () => Number;"; // PUBLIC void csoundSetRTAudioModule (CSOUND *csound, const char *module) // PUBLIC int csoundGetModule (CSOUND *csound, int number, char **name, char **type) // PUBLIC void csoundClearSpin (CSOUND *) // PUBLIC void csoundAddSpinSample (CSOUND *csound, int frame, int channel, MYFLT sample) // PUBLIC void csoundSetSpinSample (CSOUND *csound, int frame, int channel, MYFLT sample) // PUBLIC MYFLT csoundGetSpoutSample (CSOUND *csound, int frame, int channel) // PUBLIC void ** csoundGetRtRecordUserData (CSOUND *) // PUBLIC void ** csoundGetRtPlayUserData (CSOUND *) // PUBLIC void csoundSetHostImplementedAudioIO (CSOUND *, int state, int bufSize) // PUBLIC int csoundGetAudioDevList (CSOUND *csound, CS_AUDIODEVICE *list, int isOutput) // PUBLIC void csoundSetPlayopenCallback (CSOUND *, int(*playopen__)(CSOUND *, const csRtAudioParams *parm)) // PUBLIC void csoundSetRtplayCallback (CSOUND *, void(*rtplay__)(CSOUND *, const MYFLT *outBuf, int nbytes)) // PUBLIC void csoundSetRecopenCallback (CSOUND *, int(*recopen_)(CSOUND *, const csRtAudioParams *parm)) // PUBLIC void csoundSetRtrecordCallback (CSOUND *, int(*rtrecord__)(CSOUND *, MYFLT *inBuf, int nbytes)) // PUBLIC void csoundSetRtcloseCallback (CSOUND *, void(*rtclose__)(CSOUND *)) // PUBLIC void csoundSetAudioDeviceListCallback (CSOUND *csound, int(*audiodevlist__)(CSOUND *, CS_AUDIODEVICE *list, int isOutput)) const csoundSetMidiCallbacks = (wasm) => (csound) => { wasm.exports.csoundSetMidiCallbacks(csound); }; /** * This function can be called to obtain a list of available input or output midi devices. * If list is NULL, the function will only return the number of devices * (isOutput=1 for out devices, 0 for in devices). * @async * @function * @name getMIDIDevList * @memberof CsoundObj * @param {number} isOutput * @return {Promise.<CS_MIDIDEVICE>} */ // eslint-disable-next-line unicorn/prevent-abbreviations const csoundGetMIDIDevList = (wasm) => (csound, isOutput) => { const { buffer } = wasm.exports.memory; const numberOfDevices = wasm.exports.csoundGetMIDIDevList(csound, undefined, isOutput ? 1 : 0); if (numberOfDevices === 0) return []; const structLength = sizeofStruct(CS_MIDIDEVICE); const structOffset = wasm.exports.allocCsMidiDeviceStruct(numberOfDevices); wasm.exports.csoundGetMIDIDevList(csound, structOffset, isOutput ? 1 : 0); const structBuffer = new Uint8Array(buffer, structOffset, structLength * numberOfDevices); const out = range(0, numberOfDevices).map((index) => structBufferToObject(CS_MIDIDEVICE, structBuffer.subarray(index * structLength, structLength)), ); wasm.exports.freeCsMidiDeviceStruct(structOffset); return out; }; csoundGetMIDIDevList.toString = () => "getMIDIDevList = async (isOutput) => Object;"; /** * This function can be called to obtain a list of available input or output midi devices. * If list is NULL, the function will only return the number of devices * (isOutput=1 for out devices, 0 for in devices). * @async * @function * @name getRtMidiName * @memberof CsoundObj * @return {Promise.<string>} */ const csoundGetRtMidiName = (wasm) => (csound) => { const { buffer } = wasm.exports.memory; const ptr = wasm.exports.getRtMidiName(csound); const stringBuffer = new Uint8Array(buffer, ptr, 128); return trimNull(uint2String(stringBuffer)) || ""; }; csoundGetRtMidiName.toString = () => "getRtMidiName = async () => String;"; const csoundGetMidiOutFileName = (wasm) => (csound) => { const { buffer } = wasm.exports.memory; const ptr = wasm.exports.getMidiOutFileName(csound); const stringBuffer = new Uint8Array(buffer, ptr, 128); ptr && ptr.length > 0 && freeStringPtr(ptr); return trimNull(uint2String(stringBuffer)) || ""; }; const _isRequestingRtMidiInput = (wasm) => (csound) => { return wasm.exports.isRequestingRtMidiInput(csound); }; /** * Emit a midi message with a given triplet of values * in the range of 0 to 127. * @async * @function * @name midiMessage * @memberof CsoundObj * @param {number} midi status value * @param {number} midi data1 * @param {number} midi data2 * @return {Promise.<void>} */ const csoundPushMidiMessage = (wasm) => (csound, status, data1, data2) => { wasm.exports.pushMidiMessage(csound, status, data1, data2); }; csoundPushMidiMessage.toString = () => "midiMessage = async (status, data1, data2) => undefined;"; // PUBLIC void csoundSetMIDIModule (CSOUND *csound, const char *module) // PUBLIC void csoundSetHostImplementedMIDIIO (CSOUND *csound, int state) // PUBLIC int csoundGetMIDIDevList (CSOUND *csound, CS_MIDIDEVICE *list, int isOutput) // PUBLIC void csoundSetExternalMidiInOpenCallback (CSOUND *, int(*func)(CSOUND *, void **userData, const char *devName)) // PUBLIC void csoundSetExternalMidiReadCallback (CSOUND *, int(*func)(CSOUND *, void *userData, unsigned char *buf, int nBytes)) // PUBLIC void csoundSetExternalMidiInCloseCallback (CSOUND *, int(*func)(CSOUND *, void *userData)) // PUBLIC void csoundSetExternalMidiOutOpenCallback (CSOUND *, int(*func)(CSOUND *, void **userData, const char *devName)) // PUBLIC void csoundSetExternalMidiWriteCallback (CSOUND *, int(*func)(CSOUND *, void *userData, const unsigned char *buf, int nBytes)) // PUBLIC void csoundSetExternalMidiOutCloseCallback (CSOUND *, int(*func)(CSOUND *, void *userData)) // PUBLIC void csoundSetExternalMidiErrorStringCallback (CSOUND *, const char *(*func)(int)) // PUBLIC void csoundSetMIDIDeviceListCallback (CSOUND *csound, int(*mididevlist__)(CSOUND *, CS_MIDIDEVICE *list, int isOutput)) /* csound control-events module from <csound.h> https://csound.com/docs/api/modules.html */ /** * Inputs an immediate score event * without any pre-process parsing * @async * @function * @name inputMessage * @memberof CsoundObj * @param {string} scoreEvent * @return {Promise.<number>} */ const csoundInputMessage = (wasm) => (csound, scoEvent) => { const stringPtr = string2ptr(wasm, scoEvent); const result = wasm.exports.csoundInputMessage(csound, stringPtr); freeStringPtr(wasm, stringPtr); return result; }; csoundInputMessage.toString = () => "inputMessage = async (scoreEvent) => Number;"; /** * Inputs an immediate score event * without any pre-process parsing * @async * @function * @name inputMessageAsync * @memberof CsoundObj * @param {string} scoreEvent * @return {Promise.<number>} */ const csoundInputMessageAsync = (wasm) => (csound, scoEvent) => { const stringPtr = string2ptr(wasm, scoEvent); const result = wasm.exports.csoundInputMessageAsync(csound, stringPtr); freeStringPtr(wasm, stringPtr); return result; }; csoundInputMessageAsync.toString = () => "inputMessageAsync = async (scoreEvent) => Number;"; /** * Retrieves the value of control channel identified by channelName. * If the err argument is not NULL, the error (or success) code finding * or accessing the channel is stored in it. * @async * @function * @name getControlChannel * @memberof CsoundObj * @param {string} channelName * @return {Promise.<undefined>} */ const csoundGetControlChannel = (wasm) => (csound, channelName) => { const stringPtr = string2ptr(wasm, channelName); const result = wasm.exports.csoundGetControlChannelWasi(csound, stringPtr); freeStringPtr(wasm, stringPtr); return result; }; csoundGetControlChannel.toString = () => "getControlChannel = async (channelName) => Number;"; /** * Sets the value of control channel identified by channelName * @async * @function * @name setControlChannel * @memberof CsoundObj * @param {string} channelName * @param {number} value * @return {Promise.<undefined>} */ const csoundSetControlChannel = (wasm) => (csound, channelName, value) => { const stringPtr = string2ptr(wasm, channelName); wasm.exports.csoundSetControlChannel(csound, stringPtr, value); freeStringPtr(wasm, stringPtr); }; csoundSetControlChannel.toString = () => "setControlChannel = async (channelName, value) => void;"; /** * Retrieves the string channel identified by channelName * @async * @function * @name getStringChannel * @memberof CsoundObj * @param {string} channelName * @return {Promise.<undefined>} */ const csoundGetStringChannel = (wasm) => (csound, channelName) => { const stringPtr = string2ptr(wasm, channelName); const pointerToResult = wasm.exports.csoundGetStringChannelWasi(csound, stringPtr); const result = ptr2string(wasm, pointerToResult); freeStringPtr(wasm, stringPtr); freeStringPtr(wasm, pointerToResult); return result; }; csoundGetStringChannel.toString = () => "getStringChannel = async (channelName) => String;"; /** * Sets the string channel value identified by channelName * @async * @function * @name setStringChannel * @memberof CsoundObj * @param {string} channelName * @param {string} value * @return {Promise.<undefined>} */ const csoundSetStringChannel = (wasm) => (csound, channelName, value) => { const stringPtr = string2ptr(wasm, channelName); const stringPtr2 = string2ptr(wasm, value); wasm.exports.csoundSetStringChannel(csound, stringPtr, stringPtr2); freeStringPtr(wasm, stringPtr); freeStringPtr(wasm, stringPtr2); }; csoundSetStringChannel.toString = () => "setStringChannel = async (channelName, value) => void;"; // csoundGetChannelPtr (CSOUND *, MYFLT **p, const char *name, int type) // csoundListChannels (CSOUND *, controlChannelInfo_t **lst) // csoundDeleteChannelList (CSOUND *, controlChannelInfo_t *lst) // csoundSetControlChannelHints (CSOUND *, const char *name, controlChannelHints_t hints) // csoundGetControlChannelHints (CSOUND *, const char *name, controlChannelHints_t *hints) // csoundGetChannelLock (CSOUND *, const char *name) // csoundSetControlChannel (CSOUND *csound, const char *name, MYFLT val) // csoundGetChannelDatasize (CSOUND *csound, const char *name) // csoundSetInputChannelCallback (CSOUND *csound, channelCallback_t inputChannelCalback) // csoundSetOutputChannelCallback (CSOUND *csound, channelCallback_t outputChannelCalback) // csoundSetPvsChannel (CSOUND *, const PVSDATEXT *fin, const char *name) // csoundGetPvsChannel (CSOUND *csound, PVSDATEXT *fout, const char *name) // csoundScoreEvent (CSOUND *, char type, const MYFLT *pFields, long numFields) // csoundScoreEventAsync (CSOUND *, char type, const MYFLT *pFields, long numFields) // csoundScoreEventAbsolute (CSOUND *, char type, const MYFLT *pfields, long numFields, double time_ofs) // csoundScoreEventAbsoluteAsync (CSOUND *, char type, const MYFLT *pfields, long numFields, double time_ofs) // csoundKillInstance (CSOUND *csound, MYFLT instr, char *instrName, int mode, int allow_release) // csoundRegisterSenseEventCallback (CSOUND *, void(*func)(CSOUND *, void *), void *userData) // csoundKeyPress (CSOUND *, char c) // csoundRegisterKeyboardCallback (CSOUND *, int(*func)(void *userData, void *p, unsigned int type), void *userData, unsigned int type) // csoundRemoveKeyboardCallback (CSOUND *csound, int(*func)(void *, void *, unsigned int)) /* csound general i/o module from <csound.h> https://csound.com/docs/api/modules.html */ /** * Returns the audio output name (-o) * @function * @name getOutputName * @memberof CsoundObj * @return {Promise.<string>} */ const csoundGetOutputName = (wasm) => (c