diff --git a/README.md b/README.md index 42e517d0..0949b687 100644 --- a/README.md +++ b/README.md @@ -24,8 +24,8 @@ There are multiple npm packages you can use to use strudel, or only parts of it, - [`core`](./packages/core/): tidal pattern engine - [`mini`](./packages/mini): mini notation parser + core binding -- [`eval`](./packages/eval): user code evaluator. syntax sugar + highlighting -- [`tone`](./packages/tone): bindings for Tone.js instruments and effects +- [`transpiler`](./packages/transpiler): user code transpiler +- [`webaudio`](./packages/webaudio): webaudio output - [`osc`](./packages/osc): bindings to communicate via OSC - [`midi`](./packages/midi): webmidi bindings - [`serial`](./packages/serial): webserial bindings diff --git a/index.mjs b/index.mjs index 79729e91..aeb5ff1b 100644 --- a/index.mjs +++ b/index.mjs @@ -2,7 +2,6 @@ export * from './packages/core/index.mjs'; export * from './packages/csound/index.mjs'; export * from './packages/embed/index.mjs'; -export * from './packages/eval/index.mjs'; export * from './packages/midi/index.mjs'; export * from './packages/mini/index.mjs'; export * from './packages/osc/index.mjs'; @@ -10,8 +9,6 @@ export * from './packages/react/index.mjs'; export * from './packages/serial/index.mjs'; export * from './packages/soundfonts/index.mjs'; export * from './packages/tonal/index.mjs'; -export * from './packages/tone/index.mjs'; export * from './packages/transpiler/index.mjs'; export * from './packages/webaudio/index.mjs'; -export * from './packages/webdirt/index.mjs'; export * from './packages/xen/index.mjs'; diff --git a/packages/core/evaluate.mjs b/packages/core/evaluate.mjs index 0dada761..9627a2ad 100644 --- a/packages/core/evaluate.mjs +++ b/packages/core/evaluate.mjs @@ -1,6 +1,6 @@ /* evaluate.mjs - -Copyright (C) 2022 Strudel contributors - see +Copyright (C) 2022 Strudel contributors - see This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ diff --git a/packages/core/pianoroll.mjs b/packages/core/pianoroll.mjs index 02aac373..2c16eb7d 100644 --- a/packages/core/pianoroll.mjs +++ b/packages/core/pianoroll.mjs @@ -1,6 +1,6 @@ /* pianoroll.mjs - -Copyright (C) 2022 Strudel contributors - see +Copyright (C) 2022 Strudel contributors - see This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ diff --git a/packages/core/ui.mjs b/packages/core/ui.mjs index df8230ec..141d3c83 100644 --- a/packages/core/ui.mjs +++ b/packages/core/ui.mjs @@ -1,6 +1,6 @@ /* ui.mjs - -Copyright (C) 2022 Strudel contributors - see +Copyright (C) 2022 Strudel contributors - see This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ diff --git a/packages/eval/.gitignore b/packages/eval/.gitignore deleted file mode 100644 index b8244cfb..00000000 --- a/packages/eval/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -shift-parser -shift-reducer -!shift-traverser \ No newline at end of file diff --git a/packages/eval/README.md b/packages/eval/README.md deleted file mode 100644 index e0984706..00000000 --- a/packages/eval/README.md +++ /dev/null @@ -1,50 +0,0 @@ -# @strudel.cycles/eval - -This package contains the strudel code transformer and evaluator. -It allows creating strudel patterns from input code that is optimized for minimal keystrokes and human readability. - -## Deprecation Note - -This package will not be developed further. Consider using `@strudel.cycles/transpiler` as a replacement. - -## Install - -```sh -npm i @strudel.cycles/eval --save -``` - -## Example - -```js -import { evalScope } from '@strudel.cycles/core'; -import { evaluate } from '@strudel.cycles/eval'; - -evalScope( - import('@strudel.cycles/core'), - // import other strudel packages here -); // add strudel to eval scope - -async function run(code) { - const { pattern } = await evaluate(code); - const events = pattern.firstCycle(); - console.log(events.map((e) => e.show()).join('\n')); -} - -run('sequence([a3, [b3, c4]])'); -``` - -yields: - -```js -(0/1 -> 1/2, 0/1 -> 1/2, a3) -(1/2 -> 3/4, 1/2 -> 3/4, b3) -(3/4 -> 1/1, 3/4 -> 1/1, c4) -``` - -[play with @strudel.cycles/eval on codesandbox](https://codesandbox.io/s/strudel-eval-example-ndz1d8?file=/src/index.js) - -## Dev Notes - -shift-traverser is currently monkey patched because its package.json uses estraverse@^4.2.0, -which does not support the spread operator (Error: Unknown node type SpreadProperty.). -By monkey patched, I mean I copied the source of shift-traverser to a subfolder and installed the dependencies (shift-spec + estraverse@^5.3.0) diff --git a/packages/eval/evaluate.mjs b/packages/eval/evaluate.mjs deleted file mode 100644 index 23132225..00000000 --- a/packages/eval/evaluate.mjs +++ /dev/null @@ -1,12 +0,0 @@ -/* -evaluate.mjs - -Copyright (C) 2022 Strudel contributors - see -This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . -*/ - -import { evaluate as _evaluate } from '@strudel.cycles/core'; -import shapeshifter from './shapeshifter.mjs'; - -export const evaluate = async (code) => { - return _evaluate(code, shapeshifter); -}; diff --git a/packages/eval/index.mjs b/packages/eval/index.mjs deleted file mode 100644 index 8b2718dd..00000000 --- a/packages/eval/index.mjs +++ /dev/null @@ -1 +0,0 @@ -export * from './evaluate.mjs'; diff --git a/packages/eval/package.json b/packages/eval/package.json deleted file mode 100644 index 705cfc7e..00000000 --- a/packages/eval/package.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "name": "@strudel.cycles/eval", - "version": "0.8.0", - "description": "Code evaluator for strudel", - "main": "index.mjs", - "publishConfig": { - "main": "dist/index.js", - "module": "dist/index.mjs" - }, - "scripts": { - "build": "vite build", - "test": "vitest run", - "prepublishOnly": "npm run build" - }, - "type": "module", - "directories": { - "test": "test" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/tidalcycles/strudel.git" - }, - "keywords": [ - "tidalcycles", - "strudel", - "pattern", - "livecoding", - "algorave" - ], - "author": "Felix Roos ", - "license": "AGPL-3.0-or-later", - "bugs": { - "url": "https://github.com/tidalcycles/strudel/issues" - }, - "homepage": "https://github.com/tidalcycles/strudel#readme", - "dependencies": { - "@strudel.cycles/core": "workspace:*", - "estraverse": "^5.3.0", - "shift-ast": "^7.0.0", - "shift-codegen": "^8.1.0", - "shift-parser": "^8.0.0", - "shift-spec": "^2019.0.0", - "shift-traverser": "^1.0.0" - }, - "devDependencies": { - "@strudel.cycles/mini": "workspace:*", - "vite": "^4.3.3", - "vitest": "^0.28.0" - } -} diff --git a/packages/eval/shapeshifter.mjs b/packages/eval/shapeshifter.mjs deleted file mode 100644 index 19907341..00000000 --- a/packages/eval/shapeshifter.mjs +++ /dev/null @@ -1,296 +0,0 @@ -/* -shapeshifter.mjs - -Copyright (C) 2022 Strudel contributors - see -This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . -*/ - -/* import { parseScriptWithLocation } from './shift-parser/index.js'; // npm module does not work in the browser -import traverser from './shift-traverser/index.js'; // npm module does not work in the browser */ -import { parseScriptWithLocation } from 'shift-parser'; -import traverser from './shift-traverser/index.js'; -const { replace } = traverser; -import { - LiteralStringExpression, - IdentifierExpression, - CallExpression, - StaticMemberExpression, - ReturnStatement, - ArrayExpression, - LiteralNumericExpression, -} from 'shift-ast'; -import shiftCodegen from 'shift-codegen'; -const codegen = shiftCodegen.default || shiftCodegen; // parcel module resolution fuckup - -import * as strudel from '@strudel.cycles/core'; - -const { Pattern } = strudel; - -const isNote = (name) => /^[a-gC-G][bs]?[0-9]$/.test(name); - -const addLocations = true; -export const addMiniLocations = true; -export const minifyStrings = true; -export const wrappedAsync = false; // this is now handled by core evaluate by default -export const shouldAddReturn = true; - -export default (_code) => { - const { code, addReturn } = wrapAsync(_code); - const ast = parseScriptWithLocation(disguiseImports(code)); - const artificialNodes = []; - const parents = []; - const shifted = replace(ast.tree, { - enter(node, parent) { - parents.push(parent); - const isSynthetic = parents.some((p) => artificialNodes.includes(p)); - if (isSynthetic) { - return node; - } - - // replace template string `xxx` with mini(`xxx`) - if (minifyStrings && isBackTickString(node)) { - return minifyWithLocation(node, node, ast.locations, artificialNodes); - } - // allows to use top level strings, which are normally directives... but we don't need directives - if (minifyStrings && node.directives?.length === 1 && !node.statements?.length) { - const str = new LiteralStringExpression({ value: node.directives[0].rawValue }); - const wrapped = minifyWithLocation(str, node.directives[0], ast.locations, artificialNodes); - return { ...node, directives: [], statements: [wrapped] }; - } - - // replace double quote string "xxx" with mini('xxx') - if (minifyStrings && isStringWithDoubleQuotes(node, ast.locations, code)) { - return minifyWithLocation(node, node, ast.locations, artificialNodes); - } - - // operator overloading => still not done - const operators = { - '*': 'fast', - '/': 'slow', - '&': 'stack', - '&&': 'append', - }; - if ( - node.type === 'BinaryExpression' && - operators[node.operator] && - ['LiteralNumericExpression', 'LiteralStringExpression', 'IdentifierExpression'].includes(node.right?.type) && - canBeOverloaded(node.left) - ) { - let arg = node.left; - if (node.left.type === 'IdentifierExpression') { - arg = wrapFunction('reify', node.left); - } - return new CallExpression({ - callee: new StaticMemberExpression({ - property: operators[node.operator], - object: wrapFunction('reify', arg), - }), - arguments: [node.right], - }); - } - - const isMarkable = isPatternArg(parents) || hasModifierCall(parent); - // add to location to pure(x) calls - if (node.type === 'CallExpression' && node.callee.name === 'pure') { - const literal = node.arguments[0]; - // const value = literal[{ LiteralNumericExpression: 'value', LiteralStringExpression: 'name' }[literal.type]]; - return reifyWithLocation(literal, node.arguments[0], ast.locations, artificialNodes); - } - // replace pseudo note variables - if (node.type === 'IdentifierExpression') { - if (isNote(node.name)) { - const value = node.name[1] === 's' ? node.name.replace('s', '#') : node.name; - if (addLocations && isMarkable) { - return reifyWithLocation(new LiteralStringExpression({ value }), node, ast.locations, artificialNodes); - } - return new LiteralStringExpression({ value }); - } - if (node.name === 'r') { - return new IdentifierExpression({ name: 'silence' }); - } - } - if ( - addLocations && - ['LiteralStringExpression' /* , 'LiteralNumericExpression' */].includes(node.type) && - isMarkable - ) { - // TODO: to make LiteralNumericExpression work, we need to make sure we're not inside timeCat... - return reifyWithLocation(node, node, ast.locations, artificialNodes); - } - if (addMiniLocations) { - return addMiniNotationLocations(node, ast.locations, artificialNodes); - } - return node; - }, - leave() { - parents.pop(); - }, - }); - // add return to last statement (because it's wrapped in an async function artificially) - if (shouldAddReturn) { - addReturn(shifted); - } - const output = undisguiseImports(codegen(shifted)); - return { output }; -}; - -// renames all import statements to "_mport" as Shift doesn't support dynamic import. -// there shouldn't be any side-effects from this as this change does not affect -// the syntax & will be undone by the equivalent replace in "undisguiseImports". -function disguiseImports(code) { - return code.replaceAll('import', '_mport'); // Must be the same length! -} - -// Rename the renamed import statements back to "import" -function undisguiseImports(code) { - return code.replaceAll('_mport', 'import'); -} - -function wrapAsync(code) { - // wrap code in async to make await work on top level => this will create 1 line offset to locations - // this is why line offset is -1 in getLocationObject calls below - if (wrappedAsync) { - code = `(async () => { -${code} -})()`; - } - const addReturn = (ast) => { - const body = wrappedAsync ? ast.statements[0].expression.callee.body : ast; - body.statements = body.statements - .slice(0, -1) - .concat([new ReturnStatement({ expression: body.statements.slice(-1)[0] })]); - }; - return { - code, - addReturn, - }; -} - -function addMiniNotationLocations(node, locations, artificialNodes) { - const miniFunctions = ['mini', 'm']; - // const isAlreadyWrapped = parent?.type === 'CallExpression' && parent.callee.name === 'withLocationOffset'; - if (node.type === 'CallExpression' && miniFunctions.includes(node.callee.name)) { - // mini('c3') - if (node.arguments.length > 1) { - // TODO: transform mini(...args) to cat(...args.map(mini)) ? - console.warn('multi arg mini locations not supported yet...'); - return node; - } - const str = node.arguments[0]; - return minifyWithLocation(str, str, locations, artificialNodes); - } - if (node.type === 'StaticMemberExpression' && miniFunctions.includes(node.property)) { - // 'c3'.mini or 'c3'.m - return minifyWithLocation(node.object, node, locations, artificialNodes); - } - return node; -} - -function wrapFunction(name, ...args) { - return new CallExpression({ - callee: new IdentifierExpression({ name }), - arguments: args, - }); -} - -function isBackTickString(node) { - return node.type === 'TemplateExpression' && node.elements.length === 1; -} - -function isStringWithDoubleQuotes(node, locations, code) { - if (node.type !== 'LiteralStringExpression') { - return false; - } - const loc = locations.get(node); - const snippet = code.slice(loc.start.offset, loc.end.offset); - return snippet[0] === '"'; // we can trust the end is also ", as the parsing did not fail -} - -// returns true if the given parents belong to a pattern argument node -// this is used to check if a node should receive a location for highlighting -function isPatternArg(parents) { - if (!parents.length) { - return false; - } - const ancestors = parents.slice(0, -1); - const parent = parents[parents.length - 1]; - if (isPatternFactory(parent)) { - return true; - } - if (parent?.type === 'ArrayExpression') { - return isPatternArg(ancestors); - } - return false; -} - -function hasModifierCall(parent) { - // TODO: modifiers are more than composables, for example every is not composable but should be seen as modifier.. - // need all prototypes of Pattern - return parent?.type === 'StaticMemberExpression'; - // && Object.keys(Pattern.prototype.composable).includes(parent.property) -} -const factories = Object.keys(Pattern.prototype.factories).concat(['mini']); - -function isPatternFactory(node) { - return node?.type === 'CallExpression' && factories.includes(node.callee.name); -} - -function canBeOverloaded(node) { - return (node.type === 'IdentifierExpression' && isNote(node.name)) || isPatternFactory(node); - // TODO: support sequence(c3).transpose(3).x.y.z -} - -// turns node in reify(value).withLocation(location), where location is the node's location in the source code -// with this, the reified pattern can pass its location to the event, to know where to highlight when it's active -function reifyWithLocation(literalNode, node, locations, artificialNodes) { - const args = getLocationArguments(node, locations); - const withLocation = new CallExpression({ - callee: new StaticMemberExpression({ - object: wrapFunction('reify', literalNode), - property: 'withLocation', - }), - arguments: args, - }); - artificialNodes.push(withLocation); - return withLocation; -} - -// turns node in reify(value).withLocation(location), where location is the node's location in the source code -// with this, the reified pattern can pass its location to the event, to know where to highlight when it's active -function minifyWithLocation(literalNode, node, locations, artificialNodes) { - const args = getLocationArguments(node, locations); - const wrapped = wrapFunction('mini', literalNode); - if (!addMiniLocations) { - artificialNodes.push(wrapped); - return wrapped; - } - const withLocation = new CallExpression({ - callee: new StaticMemberExpression({ - object: wrapped, - property: 'withMiniLocation', - }), - arguments: args, - }); - artificialNodes.push(withLocation); - return withLocation; -} - -function getLocationArguments(node, locations) { - const loc = locations.get(node); - const lineOffset = wrappedAsync ? -1 : 0; - return [ - new ArrayExpression({ - elements: [ - new LiteralNumericExpression({ value: loc.start.line + lineOffset }), // the minus 1 assumes the code has been wrapped in async iife - new LiteralNumericExpression({ value: loc.start.column }), - new LiteralNumericExpression({ value: loc.start.offset }), - ], - }), - new ArrayExpression({ - elements: [ - new LiteralNumericExpression({ value: loc.end.line + lineOffset }), // the minus 1 assumes the code has been wrapped in async iife - new LiteralNumericExpression({ value: loc.end.column }), - new LiteralNumericExpression({ value: loc.end.offset }), - ], - }), - ]; -} diff --git a/packages/eval/shift-traverser/index.js b/packages/eval/shift-traverser/index.js deleted file mode 100644 index 5ef0977f..00000000 --- a/packages/eval/shift-traverser/index.js +++ /dev/null @@ -1,68 +0,0 @@ -/* -index.js - -Copyright (C) 2022 Strudel contributors - see -This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . -*/ - -/* - Copyright (C) 2014 Yusuke Suzuki - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -import _Spec from 'shift-spec'; -const Spec = _Spec.default || _Spec; // parcel module resolution fuckup -// import { version } from '../package.json' - -// Loading uncached estraverse for changing estraverse.Syntax. -import _estraverse from 'estraverse'; - -const estraverse = _estraverse.cloneEnvironment(); - -// Adjust estraverse members. - -Object.keys(estraverse.Syntax) - .filter((key) => key !== 'Property') - .forEach((key) => { - delete estraverse.Syntax[key]; - delete estraverse.VisitorKeys[key]; - }); - -Object.assign( - estraverse.Syntax, - Object.keys(Spec).reduce((result, key) => { - result[key] = key; - return result; - }, {}), -); - -Object.assign( - estraverse.VisitorKeys, - Object.keys(Spec).reduce((result, key) => { - result[key] = Spec[key].fields.map((field) => field.name); - return result; - }, {}), -); - -// estraverse.version = version; -export default estraverse; - -/* vim: set sw=4 ts=4 et tw=80 : */ diff --git a/packages/eval/vite.config.js b/packages/eval/vite.config.js deleted file mode 100644 index 0fc63a6b..00000000 --- a/packages/eval/vite.config.js +++ /dev/null @@ -1,19 +0,0 @@ -import { defineConfig } from 'vite'; -import { dependencies } from './package.json'; -import { resolve } from 'path'; - -// https://vitejs.dev/config/ -export default defineConfig({ - plugins: [], - build: { - lib: { - entry: resolve(__dirname, 'index.mjs'), - formats: ['es', 'cjs'], - fileName: (ext) => ({ es: 'index.mjs', cjs: 'index.js' }[ext]), - }, - rollupOptions: { - external: [...Object.keys(dependencies)], - }, - target: 'esnext', - }, -}); diff --git a/packages/react/vite.config.js b/packages/react/vite.config.js index 9f7ee09e..be289dab 100644 --- a/packages/react/vite.config.js +++ b/packages/react/vite.config.js @@ -22,8 +22,6 @@ export default defineConfig({ ...Object.keys(peerDependencies), ...Object.keys(dependencies), // TODO: find out which of below names are obsolete now - '@strudel.cycles/tone', - '@strudel.cycles/eval', '@strudel.cycles/transpiler', 'acorn', '@strudel.cycles/core', diff --git a/packages/tone/README.md b/packages/tone/README.md deleted file mode 100644 index 90e4385f..00000000 --- a/packages/tone/README.md +++ /dev/null @@ -1,34 +0,0 @@ -# @strudel.cycles/tone - -This package adds Tone.js functions to strudel Patterns. - -## Deprecation Note - -This package will not be developed further. Consider using `@strudel.cycles/webaudio` as a replacement. - -## Install - -```sh -npm i @strudel.cycles/tone --save -``` - -## Example - -The following example will create a pattern and play it back with tone.js: - -```js -import { sequence, stack, State, TimeSpan } from '@strudel.cycles/core'; -import { Tone, polysynth, osc, out } from '@strudel.cycles/tone'; - -const pattern = sequence('c3', ['eb3', stack('g3', 'bb3')]).tone(polysynth().set(osc('sawtooth4')).chain(out())); - -document.getElementById('play').addEventListener('click', async () => { - await Tone.start(); - Tone.getTransport().stop(); - const events = pattern.query(new State(new TimeSpan(0, 4))).filter((e) => e.whole.begin.equals(e.part.begin)); - events.forEach((event) => - Tone.getTransport().schedule((time) => event.context.onTrigger(time, event), event.whole.begin.valueOf()), - ); - Tone.getTransport().start('+0.1'); -}); -``` diff --git a/packages/tone/index.mjs b/packages/tone/index.mjs deleted file mode 100644 index 021d7718..00000000 --- a/packages/tone/index.mjs +++ /dev/null @@ -1 +0,0 @@ -export * from './tone.mjs'; diff --git a/packages/tone/package.json b/packages/tone/package.json deleted file mode 100644 index 583b2821..00000000 --- a/packages/tone/package.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "name": "@strudel.cycles/tone", - "version": "0.8.0", - "description": "Tone.js API for strudel", - "main": "index.mjs", - "type": "module", - "publishConfig": { - "main": "dist/index.js", - "module": "dist/index.mjs" - }, - "scripts": { - "build": "vite build", - "prepublishOnly": "npm run build" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/tidalcycles/strudel.git" - }, - "keywords": [ - "tidalcycles", - "strudel", - "pattern", - "livecoding", - "algorave" - ], - "author": "Felix Roos ", - "license": "AGPL-3.0-or-later", - "bugs": { - "url": "https://github.com/tidalcycles/strudel/issues" - }, - "homepage": "https://github.com/tidalcycles/strudel#readme", - "dependencies": { - "@strudel.cycles/core": "workspace:*", - "tone": "^14.7.77" - }, - "devDependencies": { - "vite": "^4.3.3", - "vitest": "^0.28.0" - } -} diff --git a/packages/tone/test/tone.test.mjs b/packages/tone/test/tone.test.mjs deleted file mode 100644 index 42feb676..00000000 --- a/packages/tone/test/tone.test.mjs +++ /dev/null @@ -1,18 +0,0 @@ -/* -tone.test.mjs - -Copyright (C) 2022 Strudel contributors - see -This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . -*/ - -import '../tone.mjs'; -import { pure } from '@strudel.cycles/core'; -import { describe, it, expect } from 'vitest'; - -describe('tone', () => { - it('Should have working tone function', () => { - // const s = synth().chain(out()); // TODO: mock audio context? - // assert.deepStrictEqual(s, new Tone.Synth().chain(out())); - const s = {}; - expect(pure('c3').tone(s).firstCycleValues).toEqual(['c3']); - }); -}); diff --git a/packages/tone/tone.mjs b/packages/tone/tone.mjs deleted file mode 100644 index d57c1f2a..00000000 --- a/packages/tone/tone.mjs +++ /dev/null @@ -1,106 +0,0 @@ -/* -tone.mjs - -Copyright (C) 2022 Strudel contributors - see -This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . -*/ - -import { register } from '@strudel.cycles/core'; -import * as _Tone from 'tone'; - -// import Tone from here, to make sure to get the same AudioContext -export const Tone = _Tone; - -const { - Filter, - Gain, - Synth, - PolySynth, - MembraneSynth, - MetalSynth, - MonoSynth, - AMSynth, - DuoSynth, - FMSynth, - NoiseSynth, - PluckSynth, - Sampler, - getDestination, - Players, -} = Tone; -import { getPlayableNoteValue } from '@strudel.cycles/core/util.mjs'; - -// "balanced" | "interactive" | "playback"; -// Tone.setContext(new Tone.Context({ latencyHint: 'playback', lookAhead: 1 })); -export const getDefaultSynth = () => { - const s = new PolySynth().chain(new Gain(0.5), getDestination()); - s.set({ - oscillator: { type: 'triangle' }, - envelope: { - release: 0.01, - }, - }); - return s; -}; - -// what about -// https://www.charlie-roberts.com/gibberish/playground/ - -// with this function, you can play the pattern with any tone synth -export const tone = register('tone', function (instrument, pat) { - return pat.onTrigger((time, hap) => { - let note; - let velocity = hap.context?.velocity ?? 0.75; - if (instrument instanceof PluckSynth) { - note = getPlayableNoteValue(hap); - instrument.triggerAttack(note, time); - } else if (instrument instanceof NoiseSynth) { - instrument.triggerAttackRelease(hap.duration.valueOf(), time); // noise has no value - } else if (instrument instanceof Sampler) { - note = getPlayableNoteValue(hap); - instrument.triggerAttackRelease(note, hap.duration.valueOf(), time, velocity); - } else if (instrument instanceof Players) { - if (!instrument.has(hap.value)) { - throw new Error(`name "${hap.value}" not defined for players`); - } - const player = instrument.player(hap.value); - // velocity ? - player.start(time); - player.stop(time + hap.duration.valueOf()); - } else { - note = getPlayableNoteValue(hap); - instrument.triggerAttackRelease(note, hap.duration.valueOf(), time, velocity); - } - }); -}); - -// synth helpers -export const amsynth = (options) => new AMSynth(options); -export const duosynth = (options) => new DuoSynth(options); -export const fmsynth = (options) => new FMSynth(options); -export const membrane = (options) => new MembraneSynth(options); -export const metal = (options) => new MetalSynth(options); -export const monosynth = (options) => new MonoSynth(options); -export const noise = (options) => new NoiseSynth(options); -export const pluck = (options) => new PluckSynth(options); -export const polysynth = (options) => new PolySynth(options); -export const sampler = (options, baseUrl) => - new Promise((resolve) => { - const s = new Sampler(options, () => resolve(s), baseUrl); - }); -export const players = (options, baseUrl = '') => { - options = !baseUrl - ? options - : Object.fromEntries(Object.entries(options).map(([key, value]) => [key, baseUrl + value])); - return new Promise((resolve) => { - const s = new Players(options, () => resolve(s)); - }); -}; -export const synth = (options) => new Synth(options); - -// effect helpers -export const vol = (v) => new Gain(v); -export const lowpass = (v) => new Filter(v, 'lowpass'); -export const highpass = (v) => new Filter(v, 'highpass'); -export const adsr = (a, d = 0.1, s = 0.4, r = 0.01) => ({ envelope: { attack: a, decay: d, sustain: s, release: r } }); -export const osc = (type) => ({ oscillator: { type } }); -export const out = () => getDestination(); diff --git a/packages/tone/vite.config.js b/packages/tone/vite.config.js deleted file mode 100644 index 0fc63a6b..00000000 --- a/packages/tone/vite.config.js +++ /dev/null @@ -1,19 +0,0 @@ -import { defineConfig } from 'vite'; -import { dependencies } from './package.json'; -import { resolve } from 'path'; - -// https://vitejs.dev/config/ -export default defineConfig({ - plugins: [], - build: { - lib: { - entry: resolve(__dirname, 'index.mjs'), - formats: ['es', 'cjs'], - fileName: (ext) => ({ es: 'index.mjs', cjs: 'index.js' }[ext]), - }, - rollupOptions: { - external: [...Object.keys(dependencies)], - }, - target: 'esnext', - }, -}); diff --git a/packages/webdirt/README.md b/packages/webdirt/README.md deleted file mode 100644 index 1cfc8396..00000000 --- a/packages/webdirt/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# @strudel.cycles/webdirt - -This package adds [webdirt](https://github.com/dktr0/WebDirt) support to strudel! - -## Deprecation Note - -This package will not be developed further. Consider using `@strudel.cycles/webaudio` as a replacement. diff --git a/packages/webdirt/index.mjs b/packages/webdirt/index.mjs deleted file mode 100644 index edafebd8..00000000 --- a/packages/webdirt/index.mjs +++ /dev/null @@ -1 +0,0 @@ -export * from './webdirt.mjs'; diff --git a/packages/webdirt/makeSampleMap.sh b/packages/webdirt/makeSampleMap.sh deleted file mode 100755 index 7b399b6e..00000000 --- a/packages/webdirt/makeSampleMap.sh +++ /dev/null @@ -1,32 +0,0 @@ -#/bin/sh -printf "{\n" -dircount=0 -# for d in $searchRoot/*; do -find $1 -mindepth 1 -maxdepth 1 -iname "*" | sort | while read d; do - if [ -d "$d" ] - then - if [ $dircount -ne 0 ] - then - printf ",\n" - fi - (( dircount++ )) - dirname=`basename $d` - printf "\"%s\": [" "$dirname" - search2=$searchRoot/$dirname/*.WAV - filecount=0 - find "$d" -iname "*.wav" | sort | while read f; do - # for f in $search2; do - filename=$(printf %q "$f") - basename=${f##*/} - if [[ ${basename:0:1} != "." ]]; then - if [ $filecount -ne 0 ]; then - printf "," - fi - (( filecount++ )) - printf "\"%s/%s\"" "$dirname" "$basename" - fi - done - printf "]" - fi -done -printf "\n}\n" diff --git a/packages/webdirt/package.json b/packages/webdirt/package.json deleted file mode 100644 index 3d8fab7b..00000000 --- a/packages/webdirt/package.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "name": "@strudel.cycles/webdirt", - "version": "0.8.0", - "description": "WebDirt integration for Strudel", - "main": "index.mjs", - "type": "module", - "publishConfig": { - "main": "dist/index.js", - "module": "dist/index.mjs" - }, - "scripts": { - "build": "vite build", - "prepublishOnly": "npm run build" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/tidalcycles/strudel.git" - }, - "keywords": [ - "tidalcycles", - "strudel", - "pattern", - "livecoding", - "algorave" - ], - "author": "Felix Roos ", - "license": "AGPL-3.0-or-later", - "bugs": { - "url": "https://github.com/tidalcycles/strudel/issues" - }, - "homepage": "https://github.com/tidalcycles/strudel#readme", - "dependencies": { - "@strudel.cycles/core": "workspace:*", - "@strudel.cycles/webaudio": "workspace:*", - "WebDirt": "github:dktr0/WebDirt" - }, - "devDependencies": { - "vite": "^4.3.3", - "vitest": "^0.28.0" - } -} diff --git a/packages/webdirt/vite.config.js b/packages/webdirt/vite.config.js deleted file mode 100644 index 0fc63a6b..00000000 --- a/packages/webdirt/vite.config.js +++ /dev/null @@ -1,19 +0,0 @@ -import { defineConfig } from 'vite'; -import { dependencies } from './package.json'; -import { resolve } from 'path'; - -// https://vitejs.dev/config/ -export default defineConfig({ - plugins: [], - build: { - lib: { - entry: resolve(__dirname, 'index.mjs'), - formats: ['es', 'cjs'], - fileName: (ext) => ({ es: 'index.mjs', cjs: 'index.js' }[ext]), - }, - rollupOptions: { - external: [...Object.keys(dependencies)], - }, - target: 'esnext', - }, -}); diff --git a/packages/webdirt/webdirt.mjs b/packages/webdirt/webdirt.mjs deleted file mode 100644 index bf1284f8..00000000 --- a/packages/webdirt/webdirt.mjs +++ /dev/null @@ -1,97 +0,0 @@ -import * as strudel from '@strudel.cycles/core'; -const { Pattern } = strudel; -import * as WebDirt from 'WebDirt'; -//import { loadBuffer, getLoadedBuffer } from '@strudel.cycles/webaudio'; - -let webDirt; - -/* -example config: -{ - sampleMapUrl: 'EmuSP12.json', - sampleFolder: 'EmuSP12', -} -*/ -export function loadWebDirt(config) { - webDirt = new WebDirt.WebDirt(config); - webDirt.initializeWebAudio(); -} - -/** - * - * Uses [webdirt](https://github.com/dktr0/WebDirt) as output. - * - *
- * show supported Webdirt controls - * - * - s :: String, -- name of sample bank - * - n :: Int, -- number of sample within a bank - * - {@link gain} :: Number, -- clamped from 0 to 2; 1 is default and full-scale - * - overgain :: Number, -- additional gain added to gain to go past clamp at 2 - * - {@link pan} :: Number, -- range: 0 to 1 - * - nudge :: Number, -- nudge the time of the sample forwards/backwards in seconds - * - {@link speed} :: Number, -- speed / pitch of the sample - * - {@link unit} :: String - * - note :: Number, -- pitch offset in semitones - * - {@link begin} :: Number, -- cut from sample start, normalized - * - {@link end} :: Number, -- cut from sample end, normalized - * - {@link cut} :: Int, -- samples with same cut number will interupt each other - * - {@link cutoff} :: Number, -- lowpass filter frequency - * - {@link resonance} :: Number, -- lowpass filter resonance - * - {@link hcutoff} :: Number, -- highpass filter frequency - * - {@link hresonance} :: Number, -- highpass filter resonance - * - {@link bandf} :: Number, -- bandpass filter frequency - * - {@link bandq} :: Number, -- bandpass filter resonance - * - {@link vowel} :: String, -- name of vowel ('a' | 'e' | 'i' | 'o' | 'u') - * - delay :: Number, -- delay wet/dry mix - * - delaytime :: Number, -- delay time in seconds - * - delayfeedback :: Number, -- delay feedback - * - {@link loop} :: Number, -- loop sample n times (relative to sample length) - * - {@link crush} :: Number, -- bitcrusher (currently not working) - * - {@link coarse} :: Number, -- coarse effect (currently not working) - * - {@link shape} :: Number, -- (currently not working) - - * - *
- * - * @name webdirt - * @memberof Pattern - * @returns Pattern - * @example - * s("bd*2 hh sd hh").n("<0 1>").webdirt() - * @noAutocomplete - */ -Pattern.prototype.webdirt = function () { - throw new Error('webdirt support has been dropped..'); - // create a WebDirt object and initialize Web Audio context - /* return this.onTrigger(async (time, e, currentTime) => { - if (!webDirt) { - throw new Error('WebDirt not initialized!'); - } - const deadline = time - currentTime; - const { s, n = 0, ...rest } = e.value || {}; - if (!s) { - console.warn('Pattern.webdirt: no "s" was set!'); - } - const samples = getLoadedSamples(); - if (!samples?.[s]) { - // try default samples - webDirt.playSample({ s, n, ...rest }, deadline); - return; - } - if (!samples?.[s]) { - console.warn(`Pattern.webdirt: sample "${s}" not found in loaded samples`, samples); - } else { - const bank = samples[s]; - const sampleUrl = bank[n % bank.length]; - const buffer = getLoadedBuffer(sampleUrl); - if (!buffer) { - console.log(`Pattern.webdirt: load ${s}:${n} from ${sampleUrl}`); - loadBuffer(sampleUrl, webDirt.ac); - } else { - const msg = { buffer: { buffer }, ...rest }; - webDirt.playSample(msg, deadline); - } - } - }); */ -}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 88355655..21a50f9e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -178,40 +178,6 @@ importers: packages/embed: {} - packages/eval: - dependencies: - '@strudel.cycles/core': - specifier: workspace:* - version: link:../core - estraverse: - specifier: ^5.3.0 - version: 5.3.0 - shift-ast: - specifier: ^7.0.0 - version: 7.0.0 - shift-codegen: - specifier: ^8.1.0 - version: 8.1.0 - shift-parser: - specifier: ^8.0.0 - version: 8.0.0 - shift-spec: - specifier: ^2019.0.0 - version: 2019.0.0 - shift-traverser: - specifier: ^1.0.0 - version: 1.0.0 - devDependencies: - '@strudel.cycles/mini': - specifier: workspace:* - version: link:../mini - vite: - specifier: ^4.3.3 - version: 4.3.3(@types/node@18.16.3) - vitest: - specifier: ^0.28.0 - version: 0.28.0(@vitest/ui@0.28.0) - packages/midi: dependencies: '@strudel.cycles/core': @@ -442,22 +408,6 @@ importers: specifier: ^0.28.0 version: 0.28.0(@vitest/ui@0.28.0) - packages/tone: - dependencies: - '@strudel.cycles/core': - specifier: workspace:* - version: link:../core - tone: - specifier: ^14.7.77 - version: 14.7.77 - devDependencies: - vite: - specifier: ^4.3.3 - version: 4.3.3(@types/node@18.16.3) - vitest: - specifier: ^0.28.0 - version: 0.28.0(@vitest/ui@0.28.0) - packages/transpiler: dependencies: '@strudel.cycles/core': @@ -528,25 +478,6 @@ importers: specifier: ^4.3.3 version: 4.3.3(@types/node@18.16.3) - packages/webdirt: - dependencies: - '@strudel.cycles/core': - specifier: workspace:* - version: link:../core - '@strudel.cycles/webaudio': - specifier: workspace:* - version: link:../webaudio - WebDirt: - specifier: github:dktr0/WebDirt - version: github.com/dktr0/WebDirt/d2ce441e82a11036455e93643af5938a844eee27 - devDependencies: - vite: - specifier: ^4.3.3 - version: 4.3.3(@types/node@18.16.3) - vitest: - specifier: ^0.28.0 - version: 0.28.0(@vitest/ui@0.28.0) - packages/xen: dependencies: '@strudel.cycles/core': @@ -6783,11 +6714,6 @@ packages: dependencies: estraverse: 5.3.0 - /estraverse@4.2.0: - resolution: {integrity: sha512-VHvyaGnJy+FuGfcfaM7W7OZw4mQiKW73jPHwQXx2VnMSUBajYmytOT5sKEfsBvNPtGX6YDwcrGDz2eocoHg0JA==} - engines: {node: '>=0.10.0'} - dev: false - /estraverse@5.3.0: resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} engines: {node: '>=4.0'} @@ -9791,10 +9717,6 @@ packages: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} dev: true - /multimap@1.1.0: - resolution: {integrity: sha512-0ZIR9PasPxGXmRsEF8jsDzndzHDj7tIav+JUmvIFB/WHswliFnquxECT/De7GR4yg99ky/NlRKJT82G1y271bw==} - dev: false - /multimatch@5.0.0: resolution: {integrity: sha512-ypMKuglUrZUD99Tk2bUQ+xNQj43lPEfAeX2o9cTteAmShXy2VHDJpuwu1o0xqoKCt9jLVAvwyFKdLTPXKAfJyA==} engines: {node: '>=10'} @@ -11842,56 +11764,6 @@ packages: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} - /shift-ast@7.0.0: - resolution: {integrity: sha512-O0INwsZa1XH/lMSf52udGnjNOxKBLxFiZHt0Ys3i6bqtwuGEA3eDR4+e0qJELIsCy8+BiTtlTgQzP76K1ehipQ==} - dev: false - - /shift-codegen@8.1.0: - resolution: {integrity: sha512-hV48SiFM0pgTLCueh0iwqbvqElXPtZL69nb+3eXOU3iZZnLP+AlBQSLKKvHSPr/Onmk0lcUEkAM7RA6V6Wj1GQ==} - dependencies: - esutils: 2.0.3 - object-assign: 4.1.1 - shift-reducer: 7.0.0 - dev: false - - /shift-parser@8.0.0: - resolution: {integrity: sha512-IShW1wGhvA5e+SPNVQ+Dwi/Be6651F2jZc6wwYHbYW7PiswAYfvR/v3Q+CjjxsVCna5L6J5OtR6y+tkkCzvCfw==} - dependencies: - multimap: 1.1.0 - shift-ast: 7.0.0 - shift-reducer: 7.0.0 - shift-regexp-acceptor: 3.0.0 - dev: false - - /shift-reducer@7.0.0: - resolution: {integrity: sha512-9igIDMHzp1+CkQZITGHM1sAd9jqMPV0vhqHuh8jlYumHSMIwsYcrDeo1tlpzNRUnfbEq1nLyh8Bf1YU8HGUE7g==} - dependencies: - shift-ast: 7.0.0 - dev: false - - /shift-regexp-acceptor@3.0.0: - resolution: {integrity: sha512-98UKizBjHY6SjjLUr51YYw4rtR+vxjGFm8znqNsoahesAI8Y9+WVAyiBCxxkov1KSDhW0Wz8FwwUqHnlFnjdUg==} - dependencies: - unicode-match-property-ecmascript: 1.0.4 - unicode-match-property-value-ecmascript: 1.0.2 - unicode-property-aliases-ecmascript: 1.0.4 - dev: false - - /shift-spec@2018.0.0: - resolution: {integrity: sha512-/aiPOkj7dbe+CV2VZhIMTHQToZmgniofpRG7Yr7x2/0sO6CSVC++py1Wzf+s+rWSTDHKcLvziVAxjRRV4i4EoQ==} - dev: false - - /shift-spec@2019.0.0: - resolution: {integrity: sha512-vYfKl+afWPUj/wfr5T/+mdYvWx0nn8LY6hVdfZmFENdGEBpAfQyOTo4/5i+rs8mj+Jz4+0MnsP4vXagjEoHfEw==} - dev: false - - /shift-traverser@1.0.0: - resolution: {integrity: sha512-DMY3512wJbdC+IC+nhLH3/Stgr2BbxbNcg7qyZ6+e5qNnNs8TBQJWdMsRgHlX1JXwF4C0ONKS8VUxsPT0Tf7aw==} - dependencies: - estraverse: 4.2.0 - shift-spec: 2018.0.0 - dev: false - /shiki@0.11.1: resolution: {integrity: sha512-EugY9VASFuDqOexOgXR18ZV+TbFrQHeCpEYaXamO+SZlsnT/2LxuLBX25GGtIrwaEVFXUAbUQ601SWE2rMwWHA==} dependencies: @@ -12624,13 +12496,6 @@ packages: dependencies: is-number: 7.0.0 - /tone@14.7.77: - resolution: {integrity: sha512-tCfK73IkLHyzoKUvGq47gyDyxiKLFvKiVCOobynGgBB9Dl0NkxTM2p+eRJXyCYrjJwy9Y0XCMqD3uOYsYt2Fdg==} - dependencies: - standardized-audio-context: 25.3.37 - tslib: 2.5.0 - dev: false - /totalist@3.0.0: resolution: {integrity: sha512-eM+pCBxXO/njtF7vdFsHuqb+ElbxqtI4r5EAvk6grfAFyJ6IvWlSkfZ5T9ozC6xWw3Fj1fGoSmrl0gUs46JVIw==} engines: {node: '>=6'} @@ -12880,24 +12745,11 @@ packages: /unherit@3.0.1: resolution: {integrity: sha512-akOOQ/Yln8a2sgcLj4U0Jmx0R5jpIg2IUyRrWOzmEbjBtGzBdHtSeFKgoEcoH4KYIG/Pb8GQ/BwtYm0GCq1Sqg==} - /unicode-canonical-property-names-ecmascript@1.0.4: - resolution: {integrity: sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==} - engines: {node: '>=4'} - dev: false - /unicode-canonical-property-names-ecmascript@2.0.0: resolution: {integrity: sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==} engines: {node: '>=4'} dev: true - /unicode-match-property-ecmascript@1.0.4: - resolution: {integrity: sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==} - engines: {node: '>=4'} - dependencies: - unicode-canonical-property-names-ecmascript: 1.0.4 - unicode-property-aliases-ecmascript: 1.0.4 - dev: false - /unicode-match-property-ecmascript@2.0.0: resolution: {integrity: sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==} engines: {node: '>=4'} @@ -12906,21 +12758,11 @@ packages: unicode-property-aliases-ecmascript: 2.1.0 dev: true - /unicode-match-property-value-ecmascript@1.0.2: - resolution: {integrity: sha512-Rx7yODZC1L/T8XKo/2kNzVAQaRE88AaMvI1EF/Xnj3GW2wzN6fop9DDWuFAKUVFH7vozkz26DzP0qyWLKLIVPQ==} - engines: {node: '>=4'} - dev: false - /unicode-match-property-value-ecmascript@2.1.0: resolution: {integrity: sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==} engines: {node: '>=4'} dev: true - /unicode-property-aliases-ecmascript@1.0.4: - resolution: {integrity: sha512-2WSLa6OdYd2ng8oqiGIWnJqyFArvhn+5vgx5GTxMbUYjCYKUcuKS62YLFF0R/BDGlB1yzXjQOLtPAfHsgirEpg==} - engines: {node: '>=4'} - dev: false - /unicode-property-aliases-ecmascript@2.1.0: resolution: {integrity: sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==} engines: {node: '>=4'} @@ -13897,9 +13739,3 @@ packages: /zwitch@2.0.4: resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} - - github.com/dktr0/WebDirt/d2ce441e82a11036455e93643af5938a844eee27: - resolution: {tarball: https://codeload.github.com/dktr0/WebDirt/tar.gz/d2ce441e82a11036455e93643af5938a844eee27} - name: webdirt - version: 1.0.1 - dev: false diff --git a/test/runtime.mjs b/test/runtime.mjs index 94b5f659..43097c6d 100644 --- a/test/runtime.mjs +++ b/test/runtime.mjs @@ -3,7 +3,6 @@ // it might require mocking more stuff when tunes added that use other functions // import * as tunes from './tunes.mjs'; -// import { evaluate } from '@strudel.cycles/eval'; import { evaluate } from '@strudel.cycles/transpiler'; import { evalScope } from '@strudel.cycles/core'; import * as strudel from '@strudel.cycles/core'; @@ -11,20 +10,14 @@ import * as webaudio from '@strudel.cycles/webaudio'; import controls from '@strudel.cycles/core/controls.mjs'; // import gist from '@strudel.cycles/core/gist.js'; import { mini, m } from '@strudel.cycles/mini/mini.mjs'; -// import * as toneHelpers from '@strudel.cycles/tone/tone.mjs'; // import * as voicingHelpers from '@strudel.cycles/tonal/voicings.mjs'; -// import * as uiHelpers from '@strudel.cycles/tone/ui.mjs'; -// import * as drawHelpers from '@strudel.cycles/tone/draw.mjs'; // import euclid from '@strudel.cycles/core/euclid.mjs'; -// import '@strudel.cycles/tone/tone.mjs'; // import '@strudel.cycles/midi/midi.mjs'; import * as tonalHelpers from '@strudel.cycles/tonal'; import '@strudel.cycles/xen/xen.mjs'; // import '@strudel.cycles/xen/tune.mjs'; // import '@strudel.cycles/core/euclid.mjs'; // import '@strudel.cycles/core/speak.mjs'; // window is not defined -// import '@strudel.cycles/tone/pianoroll.mjs'; -// import '@strudel.cycles/tone/draw.mjs'; // import '@strudel.cycles/osc/osc.mjs'; // import '@strudel.cycles/webaudio/webaudio.mjs'; // import '@strudel.cycles/serial/serial.mjs'; diff --git a/undocumented.json b/undocumented.json index 7735b34d..0d28835d 100644 --- a/undocumented.json +++ b/undocumented.json @@ -156,17 +156,6 @@ ], "/home/felix/projects/strudel/packages/core/gist.js": [], "/home/felix/projects/strudel/packages/core/index.mjs": [], - "/home/felix/projects/strudel/packages/eval/shift-traverser/index.js": [], - "/home/felix/projects/strudel/packages/eval/shapeshifter.mjs": [ - "addMiniLocations", - "minifyStrings", - "wrappedAsync", - "shouldAddReturn" - ], - "/home/felix/projects/strudel/packages/eval/evaluate.mjs": [ - "evaluate" - ], - "/home/felix/projects/strudel/packages/eval/index.mjs": [], "/home/felix/projects/strudel/packages/midi/midi.mjs": [ "WebMidi", "enableWebMidi" @@ -199,29 +188,6 @@ "setVoicingRange" ], "/home/felix/projects/strudel/packages/tonal/index.mjs": [], - "/home/felix/projects/strudel/packages/tone/tone.mjs": [ - "Tone", - "getDefaultSynth", - "tone", - "amsynth", - "duosynth", - "fmsynth", - "membrane", - "metal", - "monosynth", - "noise", - "pluck", - "polysynth", - "sampler", - "players", - "synth", - "vol", - "lowpass", - "highpass", - "adsr", - "out" - ], - "/home/felix/projects/strudel/packages/tone/index.mjs": [], "/home/felix/projects/strudel/packages/transpiler/transpiler.mjs": [ "transpiler" ], @@ -251,10 +217,6 @@ "webaudioOutputTrigger" ], "/home/felix/projects/strudel/packages/webaudio/index.mjs": [], - "/home/felix/projects/strudel/packages/webdirt/webdirt.mjs": [ - "loadWebDirt" - ], - "/home/felix/projects/strudel/packages/webdirt/index.mjs": [], "/home/felix/projects/strudel/packages/xen/xen.mjs": [ "edo", "xen", diff --git a/website/src/docs/old.mdx b/website/src/docs/old.mdx deleted file mode 100644 index c11e8e58..00000000 --- a/website/src/docs/old.mdx +++ /dev/null @@ -1,152 +0,0 @@ -# Old APIs - -These APIs are outdated and might break in the future. - -## Webdirt API (deprecated) - -You can use the powerful sampling engine [Webdirt](https://github.com/dktr0/WebDirt) with Strudel. - -{{ 'Pattern.webdirt' | jsdoc }} - -
-
- -## Tone API (deprecated) - -The Tone API uses Tone.js instruments ands effects to create sounds. - - - -### tone(instrument) - -To change the instrument of a pattern, you can pass any [Tone.js Source](https://tonejs.github.io/docs/14.7.77/index.html) to .tone: - - - -While this works, it is a little bit verbose. To simplify things, all Tone Synths have a shortcut: - -```js -const amsynth = (options) => new AMSynth(options); -const duosynth = (options) => new DuoSynth(options); -const fmsynth = (options) => new FMSynth(options); -const membrane = (options) => new MembraneSynth(options); -const metal = (options) => new MetalSynth(options); -const monosynth = (options) => new MonoSynth(options); -const noise = (options) => new NoiseSynth(options); -const pluck = (options) => new PluckSynth(options); -const polysynth = (options) => new PolySynth(options); -const synth = (options) => new Synth(options); -const sampler = (options, baseUrl?) => new Sampler(options); // promisified, see below -const players = (options, baseUrl?) => new Sampler(options); // promisified, see below -``` - -### sampler - -With sampler, you can create tonal instruments from samples: - - - saw.struct("x*8").mul(16).round() - .legato(4).scale('D dorian').slow(2) - .tone(kalimba.toDestination()) -)`} -/> - -The sampler function promisifies [Tone.js Sampler](https://tonejs.github.io/docs/14.7.77/Sampler). - -Note that this function currently only works with this promise notation, but in the future, -it will be possible to use async instruments in a synchronous fashion. - -### players - -With players, you can create sound banks: - - - "bd hh sn hh".tone(drums.toDestination()) -) - `} -/> - -The sampler function promisifies [Tone.js Players](https://tonejs.github.io/docs/14.7.77/Players). - -Note that this function currently only works with this promise notation, but in the future, -it will be possible to use async instruments in a synchronous fashion. - -### out - -Shortcut for Tone.Destination. Intended to be used with Tone's .chain: - - - -This alone is not really useful, so read on.. - -### vol(volume) - -Helper that returns a Gain Node with the given volume. Intended to be used with Tone's .chain: - - - -### osc(type) - -Helper to set the waveform of a synth, monosynth or polysynth: - - - -The base types are `sine`, `square`, `sawtooth`, `triangle`. You can also append a number between 1 and 32 to reduce the harmonic partials. - -### lowpass(cutoff) - -Helper that returns a Filter Node of type lowpass with the given cutoff. Intended to be used with Tone's .chain: - - - -### highpass(cutoff) - -Helper that returns a Filter Node of type highpass with the given cutoff. Intended to be used with Tone's .chain: - - - -### adsr - -Helper to set the envelope of a Tone.js instrument. Intended to be used with Tone's .set: - - diff --git a/website/src/pages/technical-manual/packages.mdx b/website/src/pages/technical-manual/packages.mdx index 4b3a6077..9c7204d9 100644 --- a/website/src/pages/technical-manual/packages.mdx +++ b/website/src/pages/technical-manual/packages.mdx @@ -52,9 +52,9 @@ These packages provide bindings for different ways to output strudel patterns: ### No Longer Maintained -- [eval](https://github.com/tidalcycles/strudel/tree/main/packages/eval): old code transpiler -- [tone](https://github.com/tidalcycles/strudel/tree/main/packages/tone#strudelcyclestone): bindings for Tone.js instruments and effects -- [webdirt](https://github.com/tidalcycles/strudel/tree/main/packages/webdirt): webdirt bindings, replaced by webaudio package +- [eval](https://www.npmjs.com/package/@strudel.cycles/eval): old code transpiler +- [tone](https://www.npmjs.com/package/@strudel.cycles/tone): bindings for Tone.js instruments and effects +- [webdirt](https://www.npmjs.com/package/@strudel.cycles/webdirt): webdirt bindings, replaced by webaudio package ## Tools