mirror of
https://github.com/eliasstepanik/strudel-docker.git
synced 2026-01-11 13:48:34 +00:00
Add GamePad Module
This commit is contained in:
parent
726abf76ce
commit
d741b4d17a
93
packages/gamepad/README.md
Normal file
93
packages/gamepad/README.md
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
# @strudel/gamepad
|
||||||
|
|
||||||
|
This package adds gamepad input functionality to strudel Patterns.
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm i @strudel/gamepad --save
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import { gamepad } from '@strudel/gamepad';
|
||||||
|
|
||||||
|
// Initialize gamepad (optional index parameter, defaults to 0)
|
||||||
|
const pad = gamepad(0);
|
||||||
|
|
||||||
|
// Use gamepad inputs in patterns
|
||||||
|
const pattern = sequence([
|
||||||
|
// Button inputs
|
||||||
|
pad.a, // A button value (0-1)
|
||||||
|
pad.tglA, // A button toggle (0 or 1)
|
||||||
|
|
||||||
|
// Analog stick inputs
|
||||||
|
pad.x1, // Left stick X (0-1)
|
||||||
|
pad.x1_2, // Left stick X (-1 to 1)
|
||||||
|
]);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Available Controls
|
||||||
|
|
||||||
|
### Buttons
|
||||||
|
- Face Buttons
|
||||||
|
- `a`, `b`, `x`, `y` (or uppercase `A`, `B`, `X`, `Y`)
|
||||||
|
- Toggle versions: `tglA`, `tglB`, `tglX`, `tglY`
|
||||||
|
- Shoulder Buttons
|
||||||
|
- `lb`, `rb`, `lt`, `rt` (or uppercase `LB`, `RB`, `LT`, `RT`)
|
||||||
|
- Toggle versions: `tglLB`, `tglRB`, `tglLT`, `tglRT`
|
||||||
|
- D-Pad
|
||||||
|
- `up`, `down`, `left`, `right` (or `u`, `d`, `l`, `r` or uppercase)
|
||||||
|
- Toggle versions: `tglUp`, `tglDown`, `tglLeft`, `tglRight`(or `tglU`, `tglD`, `tglL`, `tglR`)
|
||||||
|
|
||||||
|
### Analog Sticks
|
||||||
|
- Left Stick
|
||||||
|
- `x1`, `y1` (0 to 1 range)
|
||||||
|
- `x1_2`, `y1_2` (-1 to 1 range)
|
||||||
|
- Right Stick
|
||||||
|
- `x2`, `y2` (0 to 1 range)
|
||||||
|
- `x2_2`, `y2_2` (-1 to 1 range)
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// Use button values to control amplitude
|
||||||
|
$: sequence([
|
||||||
|
note("bd").gain(pad.X), // X button controls gain
|
||||||
|
note("[hh oh]").gain(pad.tglY), // Y button toggles gain
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Use analog stick for continuous control
|
||||||
|
$: note("c4*4".add(pad.y1_2.range(-24,24))) // Left stick Y controls pitch shift
|
||||||
|
.pan(pad.x1_2); // Left stick X controls panning
|
||||||
|
|
||||||
|
// Use toggle buttons to switch patterns on/off
|
||||||
|
|
||||||
|
// Define button sequences
|
||||||
|
const HADOKEN = [
|
||||||
|
'd', // Down
|
||||||
|
'r', // Right
|
||||||
|
'a', // A
|
||||||
|
];
|
||||||
|
|
||||||
|
const KONAMI = 'uuddlrlrba' //Konami Code ↑↑↓↓←→←→BA
|
||||||
|
|
||||||
|
// Add these lines to enable buttons(but why?)
|
||||||
|
$:pad.D.segment(16).gain(0)
|
||||||
|
$:pad.R.segment(16).gain(0)
|
||||||
|
$:pad.A.segment(16).gain(0)
|
||||||
|
|
||||||
|
// Check button sequence (returns 1 when detected, 0 when not within last 1 second)
|
||||||
|
$: sound("hadoken").gain(pad.checkSequence(HADOKEN))
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## Multiple Gamepads
|
||||||
|
|
||||||
|
You can connect multiple gamepads by specifying the gamepad index:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const pad1 = gamepad(0); // First gamepad
|
||||||
|
const pad2 = gamepad(1); // Second gamepad
|
||||||
|
```
|
||||||
237
packages/gamepad/gamepad.mjs
Normal file
237
packages/gamepad/gamepad.mjs
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
// @strudel/gamepad/index.mjs
|
||||||
|
|
||||||
|
import { signal } from '@strudel/core';
|
||||||
|
|
||||||
|
// Button mapping for Logitech Dual Action (STANDARD GAMEPAD Vendor: 046d Product: c216)
|
||||||
|
export const buttonMap = {
|
||||||
|
a: 0,
|
||||||
|
b: 1,
|
||||||
|
x: 2,
|
||||||
|
y: 3,
|
||||||
|
lb: 4,
|
||||||
|
rb: 5,
|
||||||
|
lt: 6,
|
||||||
|
rt: 7,
|
||||||
|
back: 8,
|
||||||
|
start: 9,
|
||||||
|
u: 12,
|
||||||
|
up: 12,
|
||||||
|
d: 13,
|
||||||
|
down: 13,
|
||||||
|
l: 14,
|
||||||
|
left: 14,
|
||||||
|
r: 15,
|
||||||
|
right: 15,
|
||||||
|
};
|
||||||
|
|
||||||
|
class ButtonSequenceDetector {
|
||||||
|
constructor(timeWindow = 1000) {
|
||||||
|
this.sequence = [];
|
||||||
|
this.timeWindow = timeWindow;
|
||||||
|
this.lastInputTime = 0;
|
||||||
|
this.buttonStates = Array(16).fill(0); // Track previous state of each button
|
||||||
|
// Button mapping for character inputs
|
||||||
|
}
|
||||||
|
|
||||||
|
addInput(buttonIndex, buttonValue) {
|
||||||
|
const currentTime = Date.now();
|
||||||
|
|
||||||
|
// Only add input on button press (rising edge)
|
||||||
|
if (buttonValue === 1 && this.buttonStates[buttonIndex] === 0) {
|
||||||
|
// Clear sequence if too much time has passed
|
||||||
|
if (currentTime - this.lastInputTime > this.timeWindow) {
|
||||||
|
this.sequence = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store the button name instead of index
|
||||||
|
const buttonName = Object.keys(buttonMap).find((key) => buttonMap[key] === buttonIndex) || buttonIndex.toString();
|
||||||
|
|
||||||
|
this.sequence.push({
|
||||||
|
input: buttonName,
|
||||||
|
timestamp: currentTime,
|
||||||
|
});
|
||||||
|
|
||||||
|
this.lastInputTime = currentTime;
|
||||||
|
|
||||||
|
//console.log(this.sequence);
|
||||||
|
// Keep only inputs within the time window
|
||||||
|
this.sequence = this.sequence.filter((entry) => currentTime - entry.timestamp <= this.timeWindow);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update button state
|
||||||
|
this.buttonStates[buttonIndex] = buttonValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkSequence(targetSequence) {
|
||||||
|
if (!Array.isArray(targetSequence) && typeof targetSequence !== 'string') {
|
||||||
|
console.error('ButtonSequenceDetector: targetSequence must be an array or string');
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.sequence.length < targetSequence.length) return 0;
|
||||||
|
|
||||||
|
// Convert string input to array if needed
|
||||||
|
const sequence =
|
||||||
|
typeof targetSequence === 'string'
|
||||||
|
? targetSequence.toLowerCase().split('')
|
||||||
|
: targetSequence.map((s) => s.toString().toLowerCase());
|
||||||
|
|
||||||
|
// Get the last n inputs where n is the target sequence length
|
||||||
|
const lastInputs = this.sequence.slice(-targetSequence.length).map((entry) => entry.input);
|
||||||
|
|
||||||
|
// Compare sequences
|
||||||
|
return lastInputs.every((input, index) => {
|
||||||
|
const target = sequence[index];
|
||||||
|
// Check if either the input matches directly or they refer to the same button in the map
|
||||||
|
return (
|
||||||
|
input === target ||
|
||||||
|
buttonMap[input] === buttonMap[target] ||
|
||||||
|
// Also check if the numerical index matches
|
||||||
|
buttonMap[input] === parseInt(target)
|
||||||
|
);
|
||||||
|
})
|
||||||
|
? 1
|
||||||
|
: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class GamepadHandler {
|
||||||
|
constructor(index = 0) {
|
||||||
|
// Add index parameter
|
||||||
|
this._gamepads = {};
|
||||||
|
this._activeGamepad = index; // Use provided index
|
||||||
|
this._axes = [0, 0, 0, 0];
|
||||||
|
this._buttons = Array(16).fill(0);
|
||||||
|
this.setupEventListeners();
|
||||||
|
this.startPolling();
|
||||||
|
}
|
||||||
|
|
||||||
|
setupEventListeners() {
|
||||||
|
window.addEventListener('gamepadconnected', (e) => {
|
||||||
|
this._gamepads[e.gamepad.index] = e.gamepad;
|
||||||
|
if (!this._activeGamepad) {
|
||||||
|
this._activeGamepad = e.gamepad.index;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
window.addEventListener('gamepaddisconnected', (e) => {
|
||||||
|
delete this._gamepads[e.gamepad.index];
|
||||||
|
if (this._activeGamepad === e.gamepad.index) {
|
||||||
|
this._activeGamepad = Object.keys(this._gamepads)[0] || null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
startPolling() {
|
||||||
|
const poll = () => {
|
||||||
|
if (this._activeGamepad !== null) {
|
||||||
|
const gamepad = navigator.getGamepads()[this._activeGamepad];
|
||||||
|
if (gamepad) {
|
||||||
|
// Update axes (normalized to 0-1 range)
|
||||||
|
this._axes = gamepad.axes.map((axis) => (axis + 1) / 2);
|
||||||
|
// Update buttons
|
||||||
|
this._buttons = gamepad.buttons.map((button) => button.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
requestAnimationFrame(poll);
|
||||||
|
};
|
||||||
|
poll();
|
||||||
|
}
|
||||||
|
|
||||||
|
getAxes() {
|
||||||
|
return this._axes;
|
||||||
|
}
|
||||||
|
getButtons() {
|
||||||
|
return this._buttons;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store gamepadValues globally
|
||||||
|
export const gamepadValues = {};
|
||||||
|
|
||||||
|
// Replace singleton with factory function
|
||||||
|
export const gamepad = (index = 0) => {
|
||||||
|
const handler = new GamepadHandler(index);
|
||||||
|
const sequenceDetector = new ButtonSequenceDetector(2000);
|
||||||
|
|
||||||
|
// Initialize state for this gamepad if it doesn't exist
|
||||||
|
if (!gamepadValues[index]) {
|
||||||
|
gamepadValues[index] = Array(16).fill(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create signals for this specific gamepad instance
|
||||||
|
const axes = {
|
||||||
|
x1: signal(() => handler.getAxes()[0]),
|
||||||
|
y1: signal(() => handler.getAxes()[1]),
|
||||||
|
x2: signal(() => handler.getAxes()[2]),
|
||||||
|
y2: signal(() => handler.getAxes()[3]),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add bipolar versions
|
||||||
|
axes.x1_2 = axes.x1.toBipolar();
|
||||||
|
axes.y1_2 = axes.y1.toBipolar();
|
||||||
|
axes.x2_2 = axes.x2.toBipolar();
|
||||||
|
axes.y2_2 = axes.y2.toBipolar();
|
||||||
|
|
||||||
|
// Create button signals
|
||||||
|
const buttons = Array(16)
|
||||||
|
.fill(null)
|
||||||
|
.map((_, i) => {
|
||||||
|
const btn = signal(() => {
|
||||||
|
const value = handler.getButtons()[i];
|
||||||
|
sequenceDetector.addInput(i, value);
|
||||||
|
return value;
|
||||||
|
});
|
||||||
|
let lastButtonState = 0;
|
||||||
|
const toggle = signal(() => {
|
||||||
|
const currentState = handler.getButtons()[i];
|
||||||
|
if (currentState === 1 && lastButtonState === 0) {
|
||||||
|
// Toggle the state
|
||||||
|
const newValue = gamepadValues[index][i] === 0 ? 1 : 0;
|
||||||
|
gamepadValues[index][i] = newValue;
|
||||||
|
// Broadcast the change
|
||||||
|
window.postMessage({
|
||||||
|
type: 'gamepad-toggle',
|
||||||
|
gamepadIndex: index,
|
||||||
|
buttonIndex: i,
|
||||||
|
value: newValue,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
lastButtonState = currentState;
|
||||||
|
return gamepadValues[index][i];
|
||||||
|
});
|
||||||
|
return { value: btn, toggle };
|
||||||
|
});
|
||||||
|
|
||||||
|
const checkSequence = (sequence) => {
|
||||||
|
return signal(() => sequenceDetector.checkSequence(sequence));
|
||||||
|
};
|
||||||
|
|
||||||
|
// Return an object with all controls
|
||||||
|
return {
|
||||||
|
...axes,
|
||||||
|
buttons,
|
||||||
|
...Object.fromEntries(
|
||||||
|
Object.entries(buttonMap).flatMap(([key, index]) => [
|
||||||
|
[key.toLowerCase(), buttons[index].value],
|
||||||
|
[key.toUpperCase(), buttons[index].value],
|
||||||
|
[`tgl${key.toLowerCase()}`, buttons[index].toggle],
|
||||||
|
[`tgl${key.toUpperCase()}`, buttons[index].toggle],
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
checkSequence,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Message-based state updates (add this at the bottom of the file)
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
window.addEventListener('message', (e) => {
|
||||||
|
if (e.data.type === 'gamepad-toggle') {
|
||||||
|
const { gamepadIndex, buttonIndex, value } = e.data;
|
||||||
|
if (!gamepadValues[gamepadIndex]) {
|
||||||
|
gamepadValues[gamepadIndex] = Array(16).fill(0);
|
||||||
|
}
|
||||||
|
gamepadValues[gamepadIndex][buttonIndex] = value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
3
packages/gamepad/index.mjs
Normal file
3
packages/gamepad/index.mjs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import './gamepad.mjs';
|
||||||
|
|
||||||
|
export * from './gamepad.mjs';
|
||||||
38
packages/gamepad/package.json
Normal file
38
packages/gamepad/package.json
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
"name": "@strudel/gamepad",
|
||||||
|
"version": "1.1.0",
|
||||||
|
"description": "Gamepad Inputs for strudel",
|
||||||
|
"main": "index.mjs",
|
||||||
|
"type": "module",
|
||||||
|
"publishConfig": {
|
||||||
|
"main": "dist/index.mjs"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"build": "vite build",
|
||||||
|
"prepublishOnly": "npm run build"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/tidalcycles/strudel.git"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"titdalcycles",
|
||||||
|
"strudel",
|
||||||
|
"pattern",
|
||||||
|
"livecoding",
|
||||||
|
"algorave"
|
||||||
|
],
|
||||||
|
"author": "Yuta Nakayama <nkymut@gmail.com>",
|
||||||
|
"license": "AGPL-3.0-or-later",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/tidalcycles/strudel/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/tidalcycles/strudel#readme",
|
||||||
|
"dependencies": {
|
||||||
|
"@strudel/core": "workspace:*"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"vite": "^5.0.10"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
19
packages/gamepad/vite.config.js
Normal file
19
packages/gamepad/vite.config.js
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
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'],
|
||||||
|
fileName: (ext) => ({ es: 'index.mjs' })[ext],
|
||||||
|
},
|
||||||
|
rollupOptions: {
|
||||||
|
external: [...Object.keys(dependencies)],
|
||||||
|
},
|
||||||
|
target: 'esnext',
|
||||||
|
},
|
||||||
|
});
|
||||||
@ -565,6 +565,69 @@ exports[`runs examples > example "_euclidRot" example index 20 1`] = `
|
|||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`runs examples > example "absoluteOrientationAlpha" example index 0 1`] = `
|
||||||
|
[
|
||||||
|
"[ 0/1 → 1/4 | note:C3 ]",
|
||||||
|
"[ 1/4 → 1/2 | note:C3 ]",
|
||||||
|
"[ 1/2 → 3/4 | note:C3 ]",
|
||||||
|
"[ 3/4 → 1/1 | note:C3 ]",
|
||||||
|
"[ 1/1 → 5/4 | note:C3 ]",
|
||||||
|
"[ 5/4 → 3/2 | note:C3 ]",
|
||||||
|
"[ 3/2 → 7/4 | note:C3 ]",
|
||||||
|
"[ 7/4 → 2/1 | note:C3 ]",
|
||||||
|
"[ 2/1 → 9/4 | note:C3 ]",
|
||||||
|
"[ 9/4 → 5/2 | note:C3 ]",
|
||||||
|
"[ 5/2 → 11/4 | note:C3 ]",
|
||||||
|
"[ 11/4 → 3/1 | note:C3 ]",
|
||||||
|
"[ 3/1 → 13/4 | note:C3 ]",
|
||||||
|
"[ 13/4 → 7/2 | note:C3 ]",
|
||||||
|
"[ 7/2 → 15/4 | note:C3 ]",
|
||||||
|
"[ 15/4 → 4/1 | note:C3 ]",
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`runs examples > example "absoluteOrientationBeta" example index 0 1`] = `
|
||||||
|
[
|
||||||
|
"[ 0/1 → 1/4 | note:C3 ]",
|
||||||
|
"[ 1/4 → 1/2 | note:C3 ]",
|
||||||
|
"[ 1/2 → 3/4 | note:C3 ]",
|
||||||
|
"[ 3/4 → 1/1 | note:C3 ]",
|
||||||
|
"[ 1/1 → 5/4 | note:C3 ]",
|
||||||
|
"[ 5/4 → 3/2 | note:C3 ]",
|
||||||
|
"[ 3/2 → 7/4 | note:C3 ]",
|
||||||
|
"[ 7/4 → 2/1 | note:C3 ]",
|
||||||
|
"[ 2/1 → 9/4 | note:C3 ]",
|
||||||
|
"[ 9/4 → 5/2 | note:C3 ]",
|
||||||
|
"[ 5/2 → 11/4 | note:C3 ]",
|
||||||
|
"[ 11/4 → 3/1 | note:C3 ]",
|
||||||
|
"[ 3/1 → 13/4 | note:C3 ]",
|
||||||
|
"[ 13/4 → 7/2 | note:C3 ]",
|
||||||
|
"[ 7/2 → 15/4 | note:C3 ]",
|
||||||
|
"[ 15/4 → 4/1 | note:C3 ]",
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`runs examples > example "absoluteOrientationGamma" example index 0 1`] = `
|
||||||
|
[
|
||||||
|
"[ 0/1 → 1/4 | note:C3 ]",
|
||||||
|
"[ 1/4 → 1/2 | note:C3 ]",
|
||||||
|
"[ 1/2 → 3/4 | note:C3 ]",
|
||||||
|
"[ 3/4 → 1/1 | note:C3 ]",
|
||||||
|
"[ 1/1 → 5/4 | note:C3 ]",
|
||||||
|
"[ 5/4 → 3/2 | note:C3 ]",
|
||||||
|
"[ 3/2 → 7/4 | note:C3 ]",
|
||||||
|
"[ 7/4 → 2/1 | note:C3 ]",
|
||||||
|
"[ 2/1 → 9/4 | note:C3 ]",
|
||||||
|
"[ 9/4 → 5/2 | note:C3 ]",
|
||||||
|
"[ 5/2 → 11/4 | note:C3 ]",
|
||||||
|
"[ 11/4 → 3/1 | note:C3 ]",
|
||||||
|
"[ 3/1 → 13/4 | note:C3 ]",
|
||||||
|
"[ 13/4 → 7/2 | note:C3 ]",
|
||||||
|
"[ 7/2 → 15/4 | note:C3 ]",
|
||||||
|
"[ 15/4 → 4/1 | note:C3 ]",
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`runs examples > example "accelerate" example index 0 1`] = `
|
exports[`runs examples > example "accelerate" example index 0 1`] = `
|
||||||
[
|
[
|
||||||
"[ 0/1 → 2/1 | s:sax accelerate:0 ]",
|
"[ 0/1 → 2/1 | s:sax accelerate:0 ]",
|
||||||
@ -572,6 +635,69 @@ exports[`runs examples > example "accelerate" example index 0 1`] = `
|
|||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`runs examples > example "accelerationX" example index 0 1`] = `
|
||||||
|
[
|
||||||
|
"[ 0/1 → 1/4 | note:C3 ]",
|
||||||
|
"[ 1/4 → 1/2 | note:C3 ]",
|
||||||
|
"[ 1/2 → 3/4 | note:C3 ]",
|
||||||
|
"[ 3/4 → 1/1 | note:C3 ]",
|
||||||
|
"[ 1/1 → 5/4 | note:C3 ]",
|
||||||
|
"[ 5/4 → 3/2 | note:C3 ]",
|
||||||
|
"[ 3/2 → 7/4 | note:C3 ]",
|
||||||
|
"[ 7/4 → 2/1 | note:C3 ]",
|
||||||
|
"[ 2/1 → 9/4 | note:C3 ]",
|
||||||
|
"[ 9/4 → 5/2 | note:C3 ]",
|
||||||
|
"[ 5/2 → 11/4 | note:C3 ]",
|
||||||
|
"[ 11/4 → 3/1 | note:C3 ]",
|
||||||
|
"[ 3/1 → 13/4 | note:C3 ]",
|
||||||
|
"[ 13/4 → 7/2 | note:C3 ]",
|
||||||
|
"[ 7/2 → 15/4 | note:C3 ]",
|
||||||
|
"[ 15/4 → 4/1 | note:C3 ]",
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`runs examples > example "accelerationY" example index 0 1`] = `
|
||||||
|
[
|
||||||
|
"[ 0/1 → 1/4 | note:C3 ]",
|
||||||
|
"[ 1/4 → 1/2 | note:C3 ]",
|
||||||
|
"[ 1/2 → 3/4 | note:C3 ]",
|
||||||
|
"[ 3/4 → 1/1 | note:C3 ]",
|
||||||
|
"[ 1/1 → 5/4 | note:C3 ]",
|
||||||
|
"[ 5/4 → 3/2 | note:C3 ]",
|
||||||
|
"[ 3/2 → 7/4 | note:C3 ]",
|
||||||
|
"[ 7/4 → 2/1 | note:C3 ]",
|
||||||
|
"[ 2/1 → 9/4 | note:C3 ]",
|
||||||
|
"[ 9/4 → 5/2 | note:C3 ]",
|
||||||
|
"[ 5/2 → 11/4 | note:C3 ]",
|
||||||
|
"[ 11/4 → 3/1 | note:C3 ]",
|
||||||
|
"[ 3/1 → 13/4 | note:C3 ]",
|
||||||
|
"[ 13/4 → 7/2 | note:C3 ]",
|
||||||
|
"[ 7/2 → 15/4 | note:C3 ]",
|
||||||
|
"[ 15/4 → 4/1 | note:C3 ]",
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`runs examples > example "accelerationZ" example index 0 1`] = `
|
||||||
|
[
|
||||||
|
"[ 0/1 → 1/4 | note:C3 ]",
|
||||||
|
"[ 1/4 → 1/2 | note:C3 ]",
|
||||||
|
"[ 1/2 → 3/4 | note:C3 ]",
|
||||||
|
"[ 3/4 → 1/1 | note:C3 ]",
|
||||||
|
"[ 1/1 → 5/4 | note:C3 ]",
|
||||||
|
"[ 5/4 → 3/2 | note:C3 ]",
|
||||||
|
"[ 3/2 → 7/4 | note:C3 ]",
|
||||||
|
"[ 7/4 → 2/1 | note:C3 ]",
|
||||||
|
"[ 2/1 → 9/4 | note:C3 ]",
|
||||||
|
"[ 9/4 → 5/2 | note:C3 ]",
|
||||||
|
"[ 5/2 → 11/4 | note:C3 ]",
|
||||||
|
"[ 11/4 → 3/1 | note:C3 ]",
|
||||||
|
"[ 3/1 → 13/4 | note:C3 ]",
|
||||||
|
"[ 13/4 → 7/2 | note:C3 ]",
|
||||||
|
"[ 7/2 → 15/4 | note:C3 ]",
|
||||||
|
"[ 15/4 → 4/1 | note:C3 ]",
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`runs examples > example "add" example index 0 1`] = `
|
exports[`runs examples > example "add" example index 0 1`] = `
|
||||||
[
|
[
|
||||||
"[ 0/1 → 1/3 | note:C3 ]",
|
"[ 0/1 → 1/3 | note:C3 ]",
|
||||||
@ -742,6 +868,8 @@ exports[`runs examples > example "almostNever" example index 0 1`] = `
|
|||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`runs examples > example "altitude" example index 0 1`] = `[]`;
|
||||||
|
|
||||||
exports[`runs examples > example "always" example index 0 1`] = `
|
exports[`runs examples > example "always" example index 0 1`] = `
|
||||||
[
|
[
|
||||||
"[ 0/1 → 1/8 | s:hh speed:0.5 ]",
|
"[ 0/1 → 1/8 | s:hh speed:0.5 ]",
|
||||||
@ -3337,6 +3465,75 @@ exports[`runs examples > example "gain" example index 0 1`] = `
|
|||||||
|
|
||||||
exports[`runs examples > example "gap" example index 0 1`] = `[]`;
|
exports[`runs examples > example "gap" example index 0 1`] = `[]`;
|
||||||
|
|
||||||
|
exports[`runs examples > example "geoHeading" example index 0 1`] = `[]`;
|
||||||
|
|
||||||
|
exports[`runs examples > example "geoSpeed" example index 0 1`] = `[]`;
|
||||||
|
|
||||||
|
exports[`runs examples > example "gravityX" example index 0 1`] = `
|
||||||
|
[
|
||||||
|
"[ 0/1 → 1/4 | note:C3 ]",
|
||||||
|
"[ 1/4 → 1/2 | note:C3 ]",
|
||||||
|
"[ 1/2 → 3/4 | note:C3 ]",
|
||||||
|
"[ 3/4 → 1/1 | note:C3 ]",
|
||||||
|
"[ 1/1 → 5/4 | note:C3 ]",
|
||||||
|
"[ 5/4 → 3/2 | note:C3 ]",
|
||||||
|
"[ 3/2 → 7/4 | note:C3 ]",
|
||||||
|
"[ 7/4 → 2/1 | note:C3 ]",
|
||||||
|
"[ 2/1 → 9/4 | note:C3 ]",
|
||||||
|
"[ 9/4 → 5/2 | note:C3 ]",
|
||||||
|
"[ 5/2 → 11/4 | note:C3 ]",
|
||||||
|
"[ 11/4 → 3/1 | note:C3 ]",
|
||||||
|
"[ 3/1 → 13/4 | note:C3 ]",
|
||||||
|
"[ 13/4 → 7/2 | note:C3 ]",
|
||||||
|
"[ 7/2 → 15/4 | note:C3 ]",
|
||||||
|
"[ 15/4 → 4/1 | note:C3 ]",
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`runs examples > example "gravityY" example index 0 1`] = `
|
||||||
|
[
|
||||||
|
"[ 0/1 → 1/4 | note:C3 ]",
|
||||||
|
"[ 1/4 → 1/2 | note:C3 ]",
|
||||||
|
"[ 1/2 → 3/4 | note:C3 ]",
|
||||||
|
"[ 3/4 → 1/1 | note:C3 ]",
|
||||||
|
"[ 1/1 → 5/4 | note:C3 ]",
|
||||||
|
"[ 5/4 → 3/2 | note:C3 ]",
|
||||||
|
"[ 3/2 → 7/4 | note:C3 ]",
|
||||||
|
"[ 7/4 → 2/1 | note:C3 ]",
|
||||||
|
"[ 2/1 → 9/4 | note:C3 ]",
|
||||||
|
"[ 9/4 → 5/2 | note:C3 ]",
|
||||||
|
"[ 5/2 → 11/4 | note:C3 ]",
|
||||||
|
"[ 11/4 → 3/1 | note:C3 ]",
|
||||||
|
"[ 3/1 → 13/4 | note:C3 ]",
|
||||||
|
"[ 13/4 → 7/2 | note:C3 ]",
|
||||||
|
"[ 7/2 → 15/4 | note:C3 ]",
|
||||||
|
"[ 15/4 → 4/1 | note:C3 ]",
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`runs examples > example "gravityZ" example index 0 1`] = `
|
||||||
|
[
|
||||||
|
"[ 0/1 → 1/4 | note:C3 ]",
|
||||||
|
"[ 1/4 → 1/2 | note:C3 ]",
|
||||||
|
"[ 1/2 → 3/4 | note:C3 ]",
|
||||||
|
"[ 3/4 → 1/1 | note:C3 ]",
|
||||||
|
"[ 1/1 → 5/4 | note:C3 ]",
|
||||||
|
"[ 5/4 → 3/2 | note:C3 ]",
|
||||||
|
"[ 3/2 → 7/4 | note:C3 ]",
|
||||||
|
"[ 7/4 → 2/1 | note:C3 ]",
|
||||||
|
"[ 2/1 → 9/4 | note:C3 ]",
|
||||||
|
"[ 9/4 → 5/2 | note:C3 ]",
|
||||||
|
"[ 5/2 → 11/4 | note:C3 ]",
|
||||||
|
"[ 11/4 → 3/1 | note:C3 ]",
|
||||||
|
"[ 3/1 → 13/4 | note:C3 ]",
|
||||||
|
"[ 13/4 → 7/2 | note:C3 ]",
|
||||||
|
"[ 7/2 → 15/4 | note:C3 ]",
|
||||||
|
"[ 15/4 → 4/1 | note:C3 ]",
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`runs examples > example "heading" example index 0 1`] = `[]`;
|
||||||
|
|
||||||
exports[`runs examples > example "hpattack" example index 0 1`] = `
|
exports[`runs examples > example "hpattack" example index 0 1`] = `
|
||||||
[
|
[
|
||||||
"[ 0/1 → 1/4 | note:c2 s:sawtooth hcutoff:500 hpattack:0.5 hpenv:4 ]",
|
"[ 0/1 → 1/4 | note:c2 s:sawtooth hcutoff:500 hpattack:0.5 hpenv:4 ]",
|
||||||
@ -4099,6 +4296,8 @@ exports[`runs examples > example "late" example index 0 1`] = `
|
|||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`runs examples > example "latitude" example index 0 1`] = `[]`;
|
||||||
|
|
||||||
exports[`runs examples > example "layer" example index 0 1`] = `
|
exports[`runs examples > example "layer" example index 0 1`] = `
|
||||||
[
|
[
|
||||||
"[ 0/1 → 1/8 | note:C3 ]",
|
"[ 0/1 → 1/8 | note:C3 ]",
|
||||||
@ -4202,6 +4401,8 @@ exports[`runs examples > example "linger" example index 0 1`] = `
|
|||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`runs examples > example "longitude" example index 0 1`] = `[]`;
|
||||||
|
|
||||||
exports[`runs examples > example "loop" example index 0 1`] = `
|
exports[`runs examples > example "loop" example index 0 1`] = `
|
||||||
[
|
[
|
||||||
"[ 0/1 → 1/1 | s:casio loop:1 ]",
|
"[ 0/1 → 1/1 | s:casio loop:1 ]",
|
||||||
@ -4939,6 +5140,69 @@ exports[`runs examples > example "orbit" example index 0 1`] = `
|
|||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`runs examples > example "orientationAlpha" example index 0 1`] = `
|
||||||
|
[
|
||||||
|
"[ 0/1 → 1/4 | note:C3 ]",
|
||||||
|
"[ 1/4 → 1/2 | note:C3 ]",
|
||||||
|
"[ 1/2 → 3/4 | note:C3 ]",
|
||||||
|
"[ 3/4 → 1/1 | note:C3 ]",
|
||||||
|
"[ 1/1 → 5/4 | note:C3 ]",
|
||||||
|
"[ 5/4 → 3/2 | note:C3 ]",
|
||||||
|
"[ 3/2 → 7/4 | note:C3 ]",
|
||||||
|
"[ 7/4 → 2/1 | note:C3 ]",
|
||||||
|
"[ 2/1 → 9/4 | note:C3 ]",
|
||||||
|
"[ 9/4 → 5/2 | note:C3 ]",
|
||||||
|
"[ 5/2 → 11/4 | note:C3 ]",
|
||||||
|
"[ 11/4 → 3/1 | note:C3 ]",
|
||||||
|
"[ 3/1 → 13/4 | note:C3 ]",
|
||||||
|
"[ 13/4 → 7/2 | note:C3 ]",
|
||||||
|
"[ 7/2 → 15/4 | note:C3 ]",
|
||||||
|
"[ 15/4 → 4/1 | note:C3 ]",
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`runs examples > example "orientationBeta" example index 0 1`] = `
|
||||||
|
[
|
||||||
|
"[ 0/1 → 1/4 | note:C3 ]",
|
||||||
|
"[ 1/4 → 1/2 | note:C3 ]",
|
||||||
|
"[ 1/2 → 3/4 | note:C3 ]",
|
||||||
|
"[ 3/4 → 1/1 | note:C3 ]",
|
||||||
|
"[ 1/1 → 5/4 | note:C3 ]",
|
||||||
|
"[ 5/4 → 3/2 | note:C3 ]",
|
||||||
|
"[ 3/2 → 7/4 | note:C3 ]",
|
||||||
|
"[ 7/4 → 2/1 | note:C3 ]",
|
||||||
|
"[ 2/1 → 9/4 | note:C3 ]",
|
||||||
|
"[ 9/4 → 5/2 | note:C3 ]",
|
||||||
|
"[ 5/2 → 11/4 | note:C3 ]",
|
||||||
|
"[ 11/4 → 3/1 | note:C3 ]",
|
||||||
|
"[ 3/1 → 13/4 | note:C3 ]",
|
||||||
|
"[ 13/4 → 7/2 | note:C3 ]",
|
||||||
|
"[ 7/2 → 15/4 | note:C3 ]",
|
||||||
|
"[ 15/4 → 4/1 | note:C3 ]",
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`runs examples > example "orientationGamma" example index 0 1`] = `
|
||||||
|
[
|
||||||
|
"[ 0/1 → 1/4 | note:C3 ]",
|
||||||
|
"[ 1/4 → 1/2 | note:C3 ]",
|
||||||
|
"[ 1/2 → 3/4 | note:C3 ]",
|
||||||
|
"[ 3/4 → 1/1 | note:C3 ]",
|
||||||
|
"[ 1/1 → 5/4 | note:C3 ]",
|
||||||
|
"[ 5/4 → 3/2 | note:C3 ]",
|
||||||
|
"[ 3/2 → 7/4 | note:C3 ]",
|
||||||
|
"[ 7/4 → 2/1 | note:C3 ]",
|
||||||
|
"[ 2/1 → 9/4 | note:C3 ]",
|
||||||
|
"[ 9/4 → 5/2 | note:C3 ]",
|
||||||
|
"[ 5/2 → 11/4 | note:C3 ]",
|
||||||
|
"[ 11/4 → 3/1 | note:C3 ]",
|
||||||
|
"[ 3/1 → 13/4 | note:C3 ]",
|
||||||
|
"[ 13/4 → 7/2 | note:C3 ]",
|
||||||
|
"[ 7/2 → 15/4 | note:C3 ]",
|
||||||
|
"[ 15/4 → 4/1 | note:C3 ]",
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`runs examples > example "outside" example index 0 1`] = `
|
exports[`runs examples > example "outside" example index 0 1`] = `
|
||||||
[
|
[
|
||||||
"[ 0/1 → 1/1 | note:A3 ]",
|
"[ 0/1 → 1/1 | note:A3 ]",
|
||||||
@ -6343,6 +6607,69 @@ exports[`runs examples > example "rootNotes" example index 0 1`] = `
|
|||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`runs examples > example "rotationAlpha" example index 0 1`] = `
|
||||||
|
[
|
||||||
|
"[ 0/1 → 1/4 | note:C3 ]",
|
||||||
|
"[ 1/4 → 1/2 | note:C3 ]",
|
||||||
|
"[ 1/2 → 3/4 | note:C3 ]",
|
||||||
|
"[ 3/4 → 1/1 | note:C3 ]",
|
||||||
|
"[ 1/1 → 5/4 | note:C3 ]",
|
||||||
|
"[ 5/4 → 3/2 | note:C3 ]",
|
||||||
|
"[ 3/2 → 7/4 | note:C3 ]",
|
||||||
|
"[ 7/4 → 2/1 | note:C3 ]",
|
||||||
|
"[ 2/1 → 9/4 | note:C3 ]",
|
||||||
|
"[ 9/4 → 5/2 | note:C3 ]",
|
||||||
|
"[ 5/2 → 11/4 | note:C3 ]",
|
||||||
|
"[ 11/4 → 3/1 | note:C3 ]",
|
||||||
|
"[ 3/1 → 13/4 | note:C3 ]",
|
||||||
|
"[ 13/4 → 7/2 | note:C3 ]",
|
||||||
|
"[ 7/2 → 15/4 | note:C3 ]",
|
||||||
|
"[ 15/4 → 4/1 | note:C3 ]",
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`runs examples > example "rotationBeta" example index 0 1`] = `
|
||||||
|
[
|
||||||
|
"[ 0/1 → 1/4 | note:C3 ]",
|
||||||
|
"[ 1/4 → 1/2 | note:C3 ]",
|
||||||
|
"[ 1/2 → 3/4 | note:C3 ]",
|
||||||
|
"[ 3/4 → 1/1 | note:C3 ]",
|
||||||
|
"[ 1/1 → 5/4 | note:C3 ]",
|
||||||
|
"[ 5/4 → 3/2 | note:C3 ]",
|
||||||
|
"[ 3/2 → 7/4 | note:C3 ]",
|
||||||
|
"[ 7/4 → 2/1 | note:C3 ]",
|
||||||
|
"[ 2/1 → 9/4 | note:C3 ]",
|
||||||
|
"[ 9/4 → 5/2 | note:C3 ]",
|
||||||
|
"[ 5/2 → 11/4 | note:C3 ]",
|
||||||
|
"[ 11/4 → 3/1 | note:C3 ]",
|
||||||
|
"[ 3/1 → 13/4 | note:C3 ]",
|
||||||
|
"[ 13/4 → 7/2 | note:C3 ]",
|
||||||
|
"[ 7/2 → 15/4 | note:C3 ]",
|
||||||
|
"[ 15/4 → 4/1 | note:C3 ]",
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`runs examples > example "rotationGamma" example index 0 1`] = `
|
||||||
|
[
|
||||||
|
"[ 0/1 → 1/4 | note:C3 ]",
|
||||||
|
"[ 1/4 → 1/2 | note:C3 ]",
|
||||||
|
"[ 1/2 → 3/4 | note:C3 ]",
|
||||||
|
"[ 3/4 → 1/1 | note:C3 ]",
|
||||||
|
"[ 1/1 → 5/4 | note:C3 ]",
|
||||||
|
"[ 5/4 → 3/2 | note:C3 ]",
|
||||||
|
"[ 3/2 → 7/4 | note:C3 ]",
|
||||||
|
"[ 7/4 → 2/1 | note:C3 ]",
|
||||||
|
"[ 2/1 → 9/4 | note:C3 ]",
|
||||||
|
"[ 9/4 → 5/2 | note:C3 ]",
|
||||||
|
"[ 5/2 → 11/4 | note:C3 ]",
|
||||||
|
"[ 11/4 → 3/1 | note:C3 ]",
|
||||||
|
"[ 3/1 → 13/4 | note:C3 ]",
|
||||||
|
"[ 13/4 → 7/2 | note:C3 ]",
|
||||||
|
"[ 7/2 → 15/4 | note:C3 ]",
|
||||||
|
"[ 15/4 → 4/1 | note:C3 ]",
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`runs examples > example "round" example index 0 1`] = `
|
exports[`runs examples > example "round" example index 0 1`] = `
|
||||||
[
|
[
|
||||||
"[ 0/1 → 1/3 | note:D3 ]",
|
"[ 0/1 → 1/3 | note:D3 ]",
|
||||||
@ -7537,6 +7864,8 @@ exports[`runs examples > example "speed" example index 0 1`] = `
|
|||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`runs examples > example "speed" example index 0 2`] = `[]`;
|
||||||
|
|
||||||
exports[`runs examples > example "speed" example index 1 1`] = `
|
exports[`runs examples > example "speed" example index 1 1`] = `
|
||||||
[
|
[
|
||||||
"[ 0/1 → 1/3 | speed:1 s:piano clip:1 ]",
|
"[ 0/1 → 1/3 | speed:1 s:piano clip:1 ]",
|
||||||
|
|||||||
@ -21,6 +21,9 @@ import '@strudel/xen/xen.mjs';
|
|||||||
// import '@strudel/webaudio/webaudio.mjs';
|
// import '@strudel/webaudio/webaudio.mjs';
|
||||||
// import '@strudel/serial/serial.mjs';
|
// import '@strudel/serial/serial.mjs';
|
||||||
import '../website/src/repl/piano';
|
import '../website/src/repl/piano';
|
||||||
|
//import * as motionHelpers from '../packages/motion/index.mjs';
|
||||||
|
//import * as geolocationHelpers from '../packages/geolocation/index.mjs';
|
||||||
|
import * as gamepadHelpers from '../packages/gamepad/index.mjs';
|
||||||
|
|
||||||
class MockedNode {
|
class MockedNode {
|
||||||
chain() {
|
chain() {
|
||||||
@ -169,6 +172,7 @@ evalScope(
|
|||||||
uiHelpersMocked,
|
uiHelpersMocked,
|
||||||
webaudio,
|
webaudio,
|
||||||
tonalHelpers,
|
tonalHelpers,
|
||||||
|
gamepadHelpers,
|
||||||
/*
|
/*
|
||||||
toneHelpers,
|
toneHelpers,
|
||||||
voicingHelpers,
|
voicingHelpers,
|
||||||
|
|||||||
@ -30,17 +30,18 @@
|
|||||||
"@strudel/csound": "workspace:*",
|
"@strudel/csound": "workspace:*",
|
||||||
"@strudel/desktopbridge": "workspace:*",
|
"@strudel/desktopbridge": "workspace:*",
|
||||||
"@strudel/draw": "workspace:*",
|
"@strudel/draw": "workspace:*",
|
||||||
|
"@strudel/gamepad": "workspace:*",
|
||||||
"@strudel/hydra": "workspace:*",
|
"@strudel/hydra": "workspace:*",
|
||||||
"@strudel/midi": "workspace:*",
|
"@strudel/midi": "workspace:*",
|
||||||
"@strudel/mini": "workspace:*",
|
"@strudel/mini": "workspace:*",
|
||||||
"@strudel/osc": "workspace:*",
|
"@strudel/osc": "workspace:*",
|
||||||
"@strudel/serial": "workspace:*",
|
"@strudel/serial": "workspace:*",
|
||||||
"@strudel/soundfonts": "workspace:*",
|
"@strudel/soundfonts": "workspace:*",
|
||||||
|
"@strudel/tidal": "workspace:*",
|
||||||
"@strudel/tonal": "workspace:*",
|
"@strudel/tonal": "workspace:*",
|
||||||
"@strudel/transpiler": "workspace:*",
|
"@strudel/transpiler": "workspace:*",
|
||||||
"@strudel/webaudio": "workspace:*",
|
"@strudel/webaudio": "workspace:*",
|
||||||
"@strudel/xen": "workspace:*",
|
"@strudel/xen": "workspace:*",
|
||||||
"@strudel/tidal": "workspace:*",
|
|
||||||
"@supabase/supabase-js": "^2.39.1",
|
"@supabase/supabase-js": "^2.39.1",
|
||||||
"@tailwindcss/forms": "^0.5.7",
|
"@tailwindcss/forms": "^0.5.7",
|
||||||
"@tailwindcss/typography": "^0.5.10",
|
"@tailwindcss/typography": "^0.5.10",
|
||||||
|
|||||||
@ -81,6 +81,7 @@ export function loadModules() {
|
|||||||
import('@strudel/soundfonts'),
|
import('@strudel/soundfonts'),
|
||||||
import('@strudel/csound'),
|
import('@strudel/csound'),
|
||||||
import('@strudel/tidal'),
|
import('@strudel/tidal'),
|
||||||
|
import('@strudel/gamepad'),
|
||||||
];
|
];
|
||||||
if (isTauri()) {
|
if (isTauri()) {
|
||||||
modules = modules.concat([
|
modules = modules.concat([
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user