mirror of
https://codeberg.org/uzu/strudel
synced 2026-07-14 14:53:45 -04:00
Compare commits
50 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 42d7781d44 | |||
| 0416e4d212 | |||
| b9247db001 | |||
| 325152c782 | |||
| c136d12194 | |||
| 7557952155 | |||
| b0b41e6718 | |||
| 22e3067b8c | |||
| e9ab01ab06 | |||
| 058e554b0f | |||
| 6d9327aebc | |||
| c23d7850c7 | |||
| 2854f0cf34 | |||
| a89e87ca2e | |||
| 5419ca431b | |||
| e8b674badd | |||
| 8af40a9c61 | |||
| f54aa3d823 | |||
| 5e91287e3e | |||
| 4e3d4a7060 | |||
| 3d80da9816 | |||
| bf63b716af | |||
| 38d389b838 | |||
| ebdca32c80 | |||
| c06a3710c1 | |||
| a468ddb85b | |||
| 051bdaccc7 | |||
| 5dc04d9574 | |||
| 60129413d3 | |||
| d2bf9370ea | |||
| fd11aa5eec | |||
| fb7c2b61d3 | |||
| dd64bf0fc9 | |||
| 434eb3b256 | |||
| 6da98a5f31 | |||
| 8fef75385a | |||
| c66b9219a8 | |||
| 2a1f8823e8 | |||
| 3da65f90e3 | |||
| a36cc24087 | |||
| a746bf5461 | |||
| 700f0be0ba | |||
| cb59d632a8 | |||
| 9fd86458e6 | |||
| 3cd49065c8 | |||
| a7726e2334 | |||
| 26793aec91 | |||
| 7c4ed7e05f | |||
| 93cfe9802c | |||
| 0106a129c9 |
@@ -10,4 +10,5 @@ paper
|
||||
pnpm-lock.yaml
|
||||
pnpm-workspace.yaml
|
||||
**/dev-dist
|
||||
superdough-wasm
|
||||
website/.astro
|
||||
|
||||
@@ -2,12 +2,13 @@
|
||||
|
||||
[](https://github.com/tidalcycles/strudel/actions)
|
||||
|
||||
An experiment in making a [Tidal](https://github.com/tidalcycles/tidal/) using web technologies. This software is slowly stabilising, but please continue to tread carefully.
|
||||
An experiment in making a [Tidal](https://github.com/tidalcycles/tidal/) using web technologies. This software is a bit more stable now, but please continue to tread carefully.
|
||||
|
||||
- Try it here: <https://strudel.cc>
|
||||
- Docs: <https://strudel.cc/learn>
|
||||
- Technical Blog Post: <https://loophole-letters.vercel.app/strudel>
|
||||
- 1 Year of Strudel Blog Post: <https://loophole-letters.vercel.app/strudel1year>
|
||||
- 2 Years of Strudel Blog Post: <https://strudel.cc/blog/#year-2>
|
||||
|
||||
## Running Locally
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<script type="module">
|
||||
import { initStrudel } from 'https://cdn.skypack.dev/@strudel/web@0.8.2';
|
||||
initStrudel({
|
||||
prebake: () => samples('github:tidalcycles/Dirt-Samples/master'),
|
||||
prebake: () => samples('github:tidalcycles/dirt-samples'),
|
||||
});
|
||||
const click = (id, action) => document.getElementById(id).addEventListener('click', action);
|
||||
click('a', () => evaluate(`s('bd,jvbass(3,8)').jux(rev)`));
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
});
|
||||
|
||||
function getTune() {
|
||||
return `await samples('github:tidalcycles/Dirt-Samples/master')
|
||||
return `samples('github:tidalcycles/dirt-samples')
|
||||
|
||||
stack(
|
||||
// amen
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<script src="https://unpkg.com/@strudel/repl@0.9.4"></script>
|
||||
<script src="https://unpkg.com/@strudel/repl@1.0.2"></script>
|
||||
<strudel-editor>
|
||||
<!--
|
||||
// @date 23-08-15
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
<script src="https://unpkg.com/@strudel/web@1.0.3"></script>
|
||||
<button id="play">PLAY</button>
|
||||
<script>
|
||||
initStrudel({
|
||||
prebake: () => samples('github:tidalcycles/dirt-samples'),
|
||||
});
|
||||
document.getElementById('play').addEventListener('click', () => s('bd sd').play());
|
||||
</script>
|
||||
@@ -1,6 +1,6 @@
|
||||
export const bumpStreet = `// froos - "22 bump street", licensed with CC BY-NC-SA 4.0
|
||||
await samples('github:felixroos/samples/main')
|
||||
await samples('https://strudel.cc/tidal-drum-machines.json', 'github:ritchse/tidal-drum-machines/main/machines/')
|
||||
samples('github:felixroos/samples')
|
||||
samples('https://strudel.cc/tidal-drum-machines.json', 'github:ritchse/tidal-drum-machines/main/machines/')
|
||||
|
||||
"<[0,<6 7 9>,13,<17 20 22 26>]!2>/2"
|
||||
// make it 22 edo
|
||||
@@ -33,8 +33,8 @@ await samples('https://strudel.cc/tidal-drum-machines.json', 'github:ritchse/tid
|
||||
|
||||
export const trafficFlam = `// froos - "traffic flam", licensed with CC BY-NC-SA 4.0
|
||||
|
||||
await samples('github:felixroos/samples/main')
|
||||
await samples('https://strudel.cc/tidal-drum-machines.json', 'github:ritchse/tidal-drum-machines/main/machines/')
|
||||
samples('github:felixroos/samples')
|
||||
samples('https://strudel.cc/tidal-drum-machines.json', 'github:ritchse/tidal-drum-machines/main/machines/')
|
||||
|
||||
addVoicings('hip', {
|
||||
m11: ['2M 3m 4P 7m'],
|
||||
@@ -69,8 +69,8 @@ export const funk42 = `// froos - how to funk in 42 lines of code
|
||||
// adapted from "how to funk in two minutes" by marc rebillet https://www.youtube.com/watch?v=3vBwRfQbXkg
|
||||
// thanks to peach for the transcription: https://www.youtube.com/watch?v=8eiPXvIgda4
|
||||
|
||||
await samples('github:felixroos/samples/main')
|
||||
await samples('https://strudel.cc/tidal-drum-machines.json', 'github:ritchse/tidal-drum-machines/main/machines/')
|
||||
samples('github:felixroos/samples')
|
||||
samples('https://strudel.cc/tidal-drum-machines.json', 'github:ritchse/tidal-drum-machines/main/machines/')
|
||||
|
||||
setcps(.5)
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<script type="module">
|
||||
import { initStrudel } from '@strudel/web';
|
||||
initStrudel({
|
||||
prebake: () => samples('github:tidalcycles/Dirt-Samples/master'),
|
||||
prebake: () => samples('github:tidalcycles/dirt-samples'),
|
||||
});
|
||||
|
||||
const click = (id, action) => document.getElementById(id).addEventListener('click', action);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export default `await samples('github:tidalcycles/Dirt-Samples/master')
|
||||
export default `samples('github:tidalcycles/dirt-samples')
|
||||
|
||||
stack(
|
||||
// amen
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
const init = Promise.all([
|
||||
initAudioOnFirstClick(),
|
||||
samples('github:tidalcycles/Dirt-Samples/master'),
|
||||
samples('github:tidalcycles/dirt-samples'),
|
||||
registerSynthSounds(),
|
||||
]);
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import { closeBrackets } from '@codemirror/autocomplete';
|
||||
// import { search, highlightSelectionMatches } from '@codemirror/search';
|
||||
import { history } from '@codemirror/commands';
|
||||
import { javascript } from '@codemirror/lang-javascript';
|
||||
import { defaultHighlightStyle, syntaxHighlighting } from '@codemirror/language';
|
||||
import { defaultHighlightStyle, syntaxHighlighting, bracketMatching } from '@codemirror/language';
|
||||
import { Compartment, EditorState, Prec } from '@codemirror/state';
|
||||
import {
|
||||
EditorView,
|
||||
@@ -24,6 +24,7 @@ import { persistentAtom } from '@nanostores/persistent';
|
||||
|
||||
const extensions = {
|
||||
isLineWrappingEnabled: (on) => (on ? EditorView.lineWrapping : []),
|
||||
isBracketMatchingEnabled: (on) => (on ? bracketMatching({ brackets: '()[]{}<>' }) : []),
|
||||
isLineNumbersDisplayed: (on) => (on ? lineNumbers() : []),
|
||||
theme,
|
||||
isAutoCompletionEnabled,
|
||||
@@ -37,6 +38,7 @@ const compartments = Object.fromEntries(Object.keys(extensions).map((key) => [ke
|
||||
|
||||
export const defaultSettings = {
|
||||
keybindings: 'codemirror',
|
||||
isBracketMatchingEnabled: false,
|
||||
isLineNumbersDisplayed: true,
|
||||
isActiveLineHighlighted: false,
|
||||
isAutoCompletionEnabled: false,
|
||||
@@ -290,6 +292,9 @@ export class StrudelMirror {
|
||||
setLineWrappingEnabled(enabled) {
|
||||
this.reconfigureExtension('isLineWrappingEnabled', enabled);
|
||||
}
|
||||
setBracketMatchingEnabled(enabled) {
|
||||
this.reconfigureExtension('isBracketMatchingEnabled', enabled);
|
||||
}
|
||||
setLineNumbersDisplayed(enabled) {
|
||||
this.reconfigureExtension('isLineNumbersDisplayed', enabled);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
{
|
||||
"name": "@strudel/codemirror",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.1",
|
||||
"description": "Codemirror Extensions for Strudel",
|
||||
"main": "index.mjs",
|
||||
"publishConfig": {
|
||||
"main": "dist/index.js",
|
||||
"module": "dist/index.mjs"
|
||||
"main": "dist/index.mjs"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "vite build",
|
||||
|
||||
@@ -8,8 +8,8 @@ export default defineConfig({
|
||||
build: {
|
||||
lib: {
|
||||
entry: resolve(__dirname, 'index.mjs'),
|
||||
formats: ['es', 'cjs'],
|
||||
fileName: (ext) => ({ es: 'index.mjs', cjs: 'index.js' })[ext],
|
||||
formats: ['es'],
|
||||
fileName: (ext) => ({ es: 'index.mjs' })[ext],
|
||||
},
|
||||
rollupOptions: {
|
||||
external: [...Object.keys(dependencies)],
|
||||
|
||||
@@ -292,7 +292,7 @@ const generic_params = [
|
||||
* @name begin
|
||||
* @param {number | Pattern} amount between 0 and 1, where 1 is the length of the sample
|
||||
* @example
|
||||
* samples({ rave: 'rave/AREUREADY.wav' }, 'github:tidalcycles/Dirt-Samples/master/')
|
||||
* samples({ rave: 'rave/AREUREADY.wav' }, 'github:tidalcycles/dirt-samples')
|
||||
* s("rave").begin("<0 .25 .5 .75>").fast(2)
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
{
|
||||
"name": "@strudel/core",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.1",
|
||||
"description": "Port of Tidal Cycles to JavaScript",
|
||||
"main": "index.mjs",
|
||||
"type": "module",
|
||||
"publishConfig": {
|
||||
"main": "dist/index.js",
|
||||
"module": "dist/index.mjs"
|
||||
"main": "dist/index.mjs"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "vitest run",
|
||||
|
||||
@@ -2322,10 +2322,10 @@ const _loopAt = function (factor, pat, cps = 0.5) {
|
||||
* @memberof Pattern
|
||||
* @returns Pattern
|
||||
* @example
|
||||
* await samples('github:tidalcycles/Dirt-Samples/master')
|
||||
* samples('github:tidalcycles/dirt-samples')
|
||||
* s("breaks165").slice(8, "0 1 <2 2*2> 3 [4 0] 5 6 7".every(3, rev)).slow(0.75)
|
||||
* @example
|
||||
* await samples('github:tidalcycles/Dirt-Samples/master')
|
||||
* samples('github:tidalcycles/dirt-samples')
|
||||
* s("breaks125").fit().slice([0,.25,.5,.75], "0 1 1 <2 3>")
|
||||
*/
|
||||
|
||||
@@ -2351,7 +2351,7 @@ export const slice = register(
|
||||
* Works the same as slice, but changes the playback speed of each slice to match the duration of its step.
|
||||
* @name splice
|
||||
* @example
|
||||
* await samples('github:tidalcycles/Dirt-Samples/master')
|
||||
* samples('github:tidalcycles/dirt-samples')
|
||||
* s("breaks165")
|
||||
* .splice(8, "0 1 [2 3 0]@2 3 0@2 7")
|
||||
*/
|
||||
|
||||
@@ -160,8 +160,13 @@ export function pianoroll({
|
||||
maxMidi = max;
|
||||
valueExtent = maxMidi - minMidi + 1;
|
||||
}
|
||||
// foldValues = values.sort((a, b) => a - b);
|
||||
foldValues = values.sort((a, b) => String(a).localeCompare(String(b)));
|
||||
foldValues = values.sort((a, b) =>
|
||||
typeof a === 'number' && typeof b === 'number'
|
||||
? a - b
|
||||
: typeof a === 'number'
|
||||
? 1
|
||||
: String(a).localeCompare(String(b)),
|
||||
);
|
||||
barThickness = fold ? valueAxis / foldValues.length : valueAxis / valueExtent;
|
||||
ctx.fillStyle = background;
|
||||
ctx.globalAlpha = 1; // reset!
|
||||
|
||||
@@ -8,8 +8,8 @@ export default defineConfig({
|
||||
build: {
|
||||
lib: {
|
||||
entry: resolve(__dirname, 'index.mjs'),
|
||||
formats: ['es', 'cjs'],
|
||||
fileName: (ext) => ({ es: 'index.mjs', cjs: 'index.js' })[ext],
|
||||
formats: ['es'],
|
||||
fileName: (ext) => ({ es: 'index.mjs' })[ext],
|
||||
},
|
||||
rollupOptions: {
|
||||
external: [...Object.keys(dependencies)],
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"name": "@strudel/csound",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.1",
|
||||
"description": "csound bindings for strudel",
|
||||
"main": "index.mjs",
|
||||
"type": "module",
|
||||
"publishConfig": {
|
||||
"main": "dist/index.js",
|
||||
"module": "dist/index.mjs"
|
||||
"main": "dist/index.mjs"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "vite build",
|
||||
|
||||
@@ -8,8 +8,8 @@ export default defineConfig({
|
||||
build: {
|
||||
lib: {
|
||||
entry: resolve(__dirname, 'index.mjs'),
|
||||
formats: ['es', 'cjs'],
|
||||
fileName: (ext) => ({ es: 'index.mjs', cjs: 'index.js' })[ext],
|
||||
formats: ['es'],
|
||||
fileName: (ext) => ({ es: 'index.mjs' })[ext],
|
||||
},
|
||||
rollupOptions: {
|
||||
external: [...Object.keys(dependencies)],
|
||||
|
||||
@@ -6,11 +6,11 @@ const OFF_MESSAGE = 0x80;
|
||||
const CC_MESSAGE = 0xb0;
|
||||
|
||||
Pattern.prototype.midi = function (output) {
|
||||
return this.onTrigger((time, hap, currentTime) => {
|
||||
return this.onTrigger((time, hap, currentTime, cps) => {
|
||||
const { note, nrpnn, nrpv, ccn, ccv } = hap.value;
|
||||
const offset = (time - currentTime) * 1000;
|
||||
const velocity = Math.floor((hap.context?.velocity ?? 0.9) * 100); // TODO: refactor velocity
|
||||
const duration = Math.floor(hap.duration.valueOf() * 1000 - 10);
|
||||
const duration = Math.floor((hap.duration.valueOf() / cps) * 1000 - 10);
|
||||
const roundedOffset = Math.round(offset);
|
||||
const midichan = (hap.value.midichan ?? 1) - 1;
|
||||
const requestedport = output ?? 'IAC';
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"name": "@strudel/hydra",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.1",
|
||||
"description": "Hydra integration for strudel",
|
||||
"main": "hydra.mjs",
|
||||
"type": "module",
|
||||
"publishConfig": {
|
||||
"main": "dist/index.js",
|
||||
"module": "dist/index.mjs"
|
||||
"main": "dist/index.mjs"
|
||||
},
|
||||
"scripts": {
|
||||
"server": "node server.js",
|
||||
|
||||
@@ -8,8 +8,8 @@ export default defineConfig({
|
||||
build: {
|
||||
lib: {
|
||||
entry: resolve(__dirname, 'hydra.mjs'),
|
||||
formats: ['es', 'cjs'],
|
||||
fileName: (ext) => ({ es: 'index.mjs', cjs: 'index.js' })[ext],
|
||||
formats: ['es'],
|
||||
fileName: (ext) => ({ es: 'index.mjs' })[ext],
|
||||
},
|
||||
rollupOptions: {
|
||||
external: [...Object.keys(dependencies)],
|
||||
|
||||
@@ -129,7 +129,7 @@ Pattern.prototype.midi = function (output) {
|
||||
const velocity = hap.context?.velocity ?? 0.9; // TODO: refactor velocity
|
||||
|
||||
// note off messages will often a few ms arrive late, try to prevent glitching by subtracting from the duration length
|
||||
const duration = Math.floor(hap.duration.valueOf() * 1000 - 10);
|
||||
const duration = Math.floor((hap.duration.valueOf() / cps) * 1000 - 10);
|
||||
if (note != null) {
|
||||
const midiNumber = typeof note === 'number' ? note : noteToMidi(note);
|
||||
const midiNote = new Note(midiNumber, { attack: velocity, duration });
|
||||
@@ -167,10 +167,16 @@ let listeners = {};
|
||||
const refs = {};
|
||||
|
||||
export async function midin(input) {
|
||||
if (isPattern(input)) {
|
||||
throw new Error(
|
||||
`.midi does not accept Pattern input. Make sure to pass device name with single quotes. Example: .midi('${
|
||||
WebMidi.outputs?.[0]?.name || 'IAC Driver Bus 1'
|
||||
}')`,
|
||||
);
|
||||
}
|
||||
const initial = await enableWebMidi(); // only returns on first init
|
||||
const device = getDevice(input, WebMidi.inputs);
|
||||
|
||||
if (initial) {
|
||||
if (initial || WebMidi.enabled) {
|
||||
const otherInputs = WebMidi.inputs.filter((o) => o.name !== device.name);
|
||||
logger(
|
||||
`Midi enabled! Using "${device.name}". ${
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"name": "@strudel/midi",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.1",
|
||||
"description": "Midi API for strudel",
|
||||
"main": "index.mjs",
|
||||
"type": "module",
|
||||
"publishConfig": {
|
||||
"main": "dist/index.js",
|
||||
"module": "dist/index.mjs"
|
||||
"main": "dist/index.mjs"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "vite build",
|
||||
|
||||
@@ -8,8 +8,8 @@ export default defineConfig({
|
||||
build: {
|
||||
lib: {
|
||||
entry: resolve(__dirname, 'index.mjs'),
|
||||
formats: ['es', 'cjs'],
|
||||
fileName: (ext) => ({ es: 'index.mjs', cjs: 'index.js' })[ext],
|
||||
formats: ['es'],
|
||||
fileName: (ext) => ({ es: 'index.mjs' })[ext],
|
||||
},
|
||||
rollupOptions: {
|
||||
external: [...Object.keys(dependencies)],
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
{
|
||||
"name": "@strudel/mini",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.1",
|
||||
"description": "Mini notation for strudel",
|
||||
"main": "index.mjs",
|
||||
"type": "module",
|
||||
"publishConfig": {
|
||||
"main": "dist/index.js",
|
||||
"module": "dist/index.mjs"
|
||||
"main": "dist/index.mjs"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "vitest run",
|
||||
|
||||
@@ -8,8 +8,8 @@ export default defineConfig({
|
||||
build: {
|
||||
lib: {
|
||||
entry: resolve(__dirname, 'index.mjs'),
|
||||
formats: ['es', 'cjs'],
|
||||
fileName: (ext) => ({ es: 'index.mjs', cjs: 'index.js' })[ext],
|
||||
formats: ['es'],
|
||||
fileName: (ext) => ({ es: 'index.mjs' })[ext],
|
||||
},
|
||||
rollupOptions: {
|
||||
external: [...Object.keys(dependencies)],
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"name": "@strudel/osc",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.1",
|
||||
"description": "OSC messaging for strudel",
|
||||
"main": "osc.mjs",
|
||||
"type": "module",
|
||||
"publishConfig": {
|
||||
"main": "dist/index.js",
|
||||
"module": "dist/index.mjs"
|
||||
"main": "dist/index.mjs"
|
||||
},
|
||||
"scripts": {
|
||||
"server": "node server.js",
|
||||
|
||||
@@ -8,8 +8,8 @@ export default defineConfig({
|
||||
build: {
|
||||
lib: {
|
||||
entry: resolve(__dirname, 'osc.mjs'),
|
||||
formats: ['es', 'cjs'],
|
||||
fileName: (ext) => ({ es: 'index.mjs', cjs: 'index.js' })[ext],
|
||||
formats: ['es'],
|
||||
fileName: (ext) => ({ es: 'index.mjs' })[ext],
|
||||
},
|
||||
rollupOptions: {
|
||||
external: [...Object.keys(dependencies)],
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
# @strudel/repl
|
||||
|
||||
The Strudel REPL as a web component.
|
||||
|
||||
[Usage example](https://github.com/tidalcycles/strudel/blob/main/examples/buildless/web-component-no-iframe.html)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"name": "@strudel/repl",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.2",
|
||||
"description": "Strudel REPL as a Web Component",
|
||||
"main": "index.mjs",
|
||||
"module": "index.mjs",
|
||||
"publishConfig": {
|
||||
"main": "dist/index.js",
|
||||
"module": "dist/index.mjs"
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"name": "@strudel/serial",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.1",
|
||||
"description": "Webserial API for strudel",
|
||||
"main": "serial.mjs",
|
||||
"type": "module",
|
||||
"publishConfig": {
|
||||
"main": "dist/index.js",
|
||||
"module": "dist/index.mjs"
|
||||
"main": "dist/index.mjs"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "vite build",
|
||||
|
||||
@@ -8,8 +8,8 @@ export default defineConfig({
|
||||
build: {
|
||||
lib: {
|
||||
entry: resolve(__dirname, 'serial.mjs'),
|
||||
formats: ['es', 'cjs'],
|
||||
fileName: (ext) => ({ es: 'index.mjs', cjs: 'index.js' })[ext],
|
||||
formats: ['es'],
|
||||
fileName: (ext) => ({ es: 'index.mjs' })[ext],
|
||||
},
|
||||
rollupOptions: {
|
||||
external: [...Object.keys(dependencies)],
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
{
|
||||
"name": "@strudel/soundfonts",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.1",
|
||||
"description": "Soundsfont support for strudel",
|
||||
"main": "index.mjs",
|
||||
"publishConfig": {
|
||||
"main": "dist/index.js",
|
||||
"module": "dist/index.mjs"
|
||||
"main": "dist/index.mjs"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "vite build",
|
||||
|
||||
@@ -8,8 +8,8 @@ export default defineConfig({
|
||||
build: {
|
||||
lib: {
|
||||
entry: resolve(__dirname, 'index.mjs'),
|
||||
formats: ['es', 'cjs'],
|
||||
fileName: (ext) => ({ es: 'index.mjs', cjs: 'index.js' })[ext],
|
||||
formats: ['es'],
|
||||
fileName: (ext) => ({ es: 'index.mjs' })[ext],
|
||||
},
|
||||
rollupOptions: {
|
||||
external: [...Object.keys(dependencies)],
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
rustsaw/target
|
||||
@@ -0,0 +1,57 @@
|
||||
# superdough-wasm
|
||||
|
||||
This is just a very early experiment to find out how to run wasm in an AudioWorklet.
|
||||
WASM can be compiled from several languages, which are tested here..
|
||||
|
||||
## zig
|
||||
|
||||
<https://dev.to/sleibrock/webassembly-with-zig-part-1-4onm>
|
||||
|
||||
```sh
|
||||
# (re)compile dsp.zig
|
||||
brew install zig # prequisite
|
||||
cd zigsaw
|
||||
zig build-lib zigsaw.zig -target wasm32-freestanding -dynamic -rdynamic -O ReleaseSmall # build
|
||||
npx http-server .. -o # run
|
||||
```
|
||||
|
||||
wasm file size: 690B
|
||||
|
||||
## rust
|
||||
|
||||
<https://developer.mozilla.org/en-US/docs/WebAssembly/Rust_to_Wasm>
|
||||
|
||||
```sh
|
||||
# https://www.rust-lang.org/tools/install
|
||||
cargo install wasm-pack # prequisite
|
||||
cd rustsaw
|
||||
wasm-pack build --target bundler # build
|
||||
npx http-server .. -o # run
|
||||
```
|
||||
|
||||
wasm file size: 653B
|
||||
|
||||
## c
|
||||
|
||||
<https://emscripten.org/docs/getting_started/Tutorial.html>
|
||||
|
||||
```sh
|
||||
# brew install emscripten
|
||||
cd csaw
|
||||
emcc -O2 csaw.c -o csaw # build
|
||||
npx http-server .. -o
|
||||
```
|
||||
|
||||
wasm file size: 680B
|
||||
|
||||
## assemblyscript
|
||||
|
||||
<https://www.assemblyscript.org/getting-started.html#setting-up-a-new-project>
|
||||
|
||||
```sh
|
||||
cd ascsaw
|
||||
# npm i
|
||||
npm run asbuild # build
|
||||
```
|
||||
|
||||
wasm file size: 122B !
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"targets": {
|
||||
"debug": {
|
||||
"outFile": "build/debug.wasm",
|
||||
"textFile": "build/debug.wat",
|
||||
"sourceMap": true,
|
||||
"debug": true
|
||||
},
|
||||
"release": {
|
||||
"outFile": "build/release.wasm",
|
||||
"textFile": "build/release.wat",
|
||||
"sourceMap": true,
|
||||
"optimizeLevel": 3,
|
||||
"shrinkLevel": 2,
|
||||
"converge": false,
|
||||
"noAssert": false
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"bindings": "esm"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
export function saw(t: f64, f: f64): f64 {
|
||||
return (((f * t * 1.0) % 1.0) - 0.5) * 2.0;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"extends": "assemblyscript/std/assembly.json",
|
||||
"include": [
|
||||
"./**/*.ts"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
*
|
||||
!.gitignore
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
{
|
||||
"name": "ascsaw",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "ascsaw",
|
||||
"version": "1.0.0",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"assemblyscript": "^0.27.22"
|
||||
}
|
||||
},
|
||||
"node_modules/assemblyscript": {
|
||||
"version": "0.27.22",
|
||||
"resolved": "https://registry.npmjs.org/assemblyscript/-/assemblyscript-0.27.22.tgz",
|
||||
"integrity": "sha512-6ClobsR4Hxn6K0daYp/+n9qWTqVbpdVeSGSVDqRvUEz66vvFb8atS6nLm+fnQ54JXuXmzLQy0uWYYgB8G59btQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"binaryen": "116.0.0-nightly.20231102",
|
||||
"long": "^5.2.1"
|
||||
},
|
||||
"bin": {
|
||||
"asc": "bin/asc.js",
|
||||
"asinit": "bin/asinit.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16",
|
||||
"npm": ">=7"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/assemblyscript"
|
||||
}
|
||||
},
|
||||
"node_modules/binaryen": {
|
||||
"version": "116.0.0-nightly.20231102",
|
||||
"resolved": "https://registry.npmjs.org/binaryen/-/binaryen-116.0.0-nightly.20231102.tgz",
|
||||
"integrity": "sha512-aPU9tlKdw/gcXx6u4PxtDgOtGjg/ZKnYdk23ctYb70GxZgPhWnGWmnBt01aV5dt5yFFo2V4rbB7SzpSFhViFQA==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"wasm-opt": "bin/wasm-opt",
|
||||
"wasm2js": "bin/wasm2js"
|
||||
}
|
||||
},
|
||||
"node_modules/long": {
|
||||
"version": "5.2.3",
|
||||
"resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz",
|
||||
"integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"name": "ascsaw",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "node tests",
|
||||
"asbuild:debug": "asc assembly/index.ts --target debug",
|
||||
"asbuild:release": "asc assembly/index.ts --target release",
|
||||
"asbuild": "npm run asbuild:debug && npm run asbuild:release",
|
||||
"start": "npx serve ."
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"assemblyscript": "^0.27.22"
|
||||
},
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./build/release.js",
|
||||
"types": "./build/release.d.ts"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
csaw
|
||||
@@ -0,0 +1,7 @@
|
||||
#include <math.h>
|
||||
#include <emscripten.h>
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE
|
||||
double saw(double t, double f) {
|
||||
return fmod((f * t * 1.0), 1.0) - 0.5 * 2.0;
|
||||
}
|
||||
Executable
BIN
Binary file not shown.
@@ -0,0 +1,11 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>WASM AudioWorklet Demo</title>
|
||||
</head>
|
||||
<body>
|
||||
<button id="play">play</button>
|
||||
<input type="range" min="55" max="880" id="freq" />
|
||||
</body>
|
||||
<script src="./main.js"></script>
|
||||
</html>
|
||||
@@ -0,0 +1,24 @@
|
||||
let ac;
|
||||
document.getElementById('play').addEventListener('click', async () => {
|
||||
ac = ac || new AudioContext();
|
||||
await ac.resume();
|
||||
await ac.audioWorklet.addModule('./worklet.js');
|
||||
const node = new AudioWorkletNode(ac, 'saw-processor');
|
||||
|
||||
//let res = await fetch('./zigsaw/zigsaw.wasm');
|
||||
// let res = await fetch('./csaw/csaw.wasm');
|
||||
let res = await fetch('./ascsaw/build/release.wasm');
|
||||
//let res = await fetch('./rustsaw/pkg/rustsaw_bg.wasm');
|
||||
const buffer = await res.arrayBuffer();
|
||||
node.port.onmessage = (e) => {
|
||||
if (e.data === 'OK') {
|
||||
console.log('worklet ready');
|
||||
}
|
||||
};
|
||||
node.port.postMessage({ webassembly: buffer });
|
||||
node.connect(ac.destination);
|
||||
|
||||
document.getElementById('freq').addEventListener('input', async (e) => {
|
||||
node.port.postMessage({ frequency: e.target.value });
|
||||
});
|
||||
});
|
||||
+123
@@ -0,0 +1,123 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.19.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.76"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustsaw"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.48"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.89"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"wasm-bindgen-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.89"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"log",
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.89"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.89"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.89"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f"
|
||||
@@ -0,0 +1,13 @@
|
||||
[package]
|
||||
name = "rustsaw"
|
||||
version = "0.1.0"
|
||||
authors = ["Your Name <you@example.com>"]
|
||||
description = "A sample project with wasm-pack"
|
||||
license = "MIT/Apache-2.0"
|
||||
edition = "2018"
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
wasm-bindgen = "0.2"
|
||||
@@ -0,0 +1,6 @@
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn saw(t: f64, f: f64) -> f64 {
|
||||
return (((f * t * 1.0) % 1.0) - 0.5) * 2.0;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
class SawProcessor extends AudioWorkletProcessor {
|
||||
constructor() {
|
||||
super();
|
||||
this.t = 0; // samples passed
|
||||
this.f = 110;
|
||||
this.port.onmessage = (e) => {
|
||||
const key = Object.keys(e.data)[0];
|
||||
const value = e.data[key];
|
||||
switch (key) {
|
||||
case 'webassembly':
|
||||
WebAssembly.instantiate(value, this.importObject).then((result) => {
|
||||
this.api = result.instance.exports;
|
||||
this.port.postMessage('OK');
|
||||
});
|
||||
break;
|
||||
case 'frequency':
|
||||
this.f = value;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
process(inputs, outputs, parameters) {
|
||||
if (this.api) {
|
||||
const output = outputs[0];
|
||||
for (let i = 0; i < output[0].length; i++) {
|
||||
let t = this.t;
|
||||
let out = 0;
|
||||
out = this.api.saw(t / 44100, this.f);
|
||||
output.forEach((channel) => {
|
||||
channel[i] = out;
|
||||
});
|
||||
this.t++;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
registerProcessor('saw-processor', SawProcessor);
|
||||
Executable
BIN
Binary file not shown.
@@ -0,0 +1,5 @@
|
||||
const std = @import("std");
|
||||
|
||||
export fn saw(t: f64, f: f64) f64 {
|
||||
return ((@mod(f * t, 1.0)) - 0.5) * 2.0;
|
||||
}
|
||||
@@ -19,7 +19,7 @@ import { superdough, samples, initAudioOnFirstClick, registerSynthSounds } from
|
||||
|
||||
const init = Promise.all([
|
||||
initAudioOnFirstClick(),
|
||||
samples('github:tidalcycles/Dirt-Samples/master'),
|
||||
samples('github:tidalcycles/dirt-samples'),
|
||||
registerSynthSounds(),
|
||||
]);
|
||||
|
||||
@@ -148,7 +148,7 @@ The json file is expected to have the same format as described above.
|
||||
Because it is common to use github for samples, there is a short way to load a sample map from github:
|
||||
|
||||
```js
|
||||
samples('github:tidalcycles/Dirt-Samples/master')
|
||||
samples('github:tidalcycles/dirt-samples')
|
||||
```
|
||||
|
||||
The format is `github:<user>/<repo>/<branch>`.
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
{
|
||||
"name": "superdough",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.1",
|
||||
"description": "simple web audio synth and sampler intended for live coding. inspired by superdirt and webdirt.",
|
||||
"main": "index.mjs",
|
||||
"type": "module",
|
||||
"publishConfig": {
|
||||
"main": "dist/index.cjs",
|
||||
"module": "dist/index.mjs"
|
||||
"main": "dist/index.mjs"
|
||||
},
|
||||
"directories": {
|
||||
"example": "examples"
|
||||
|
||||
@@ -99,6 +99,27 @@ export const getLoadedBuffer = (url) => {
|
||||
return bufferCache[url];
|
||||
};
|
||||
|
||||
function resolveSpecialPaths(base) {
|
||||
if (base.startsWith('bubo:')) {
|
||||
const [_, repo] = base.split(':');
|
||||
base = `github:Bubobubobubobubo/dough-${repo}`;
|
||||
}
|
||||
return base;
|
||||
}
|
||||
|
||||
function githubPath(base, subpath = '') {
|
||||
if (!base.startsWith('github:')) {
|
||||
throw new Error('expected "github:" at the start of pseudoUrl');
|
||||
}
|
||||
let [_, path] = base.split('github:');
|
||||
path = path.endsWith('/') ? path.slice(0, -1) : path;
|
||||
if (path.split('/').length === 2) {
|
||||
// assume main as default branch if none set
|
||||
path += '/main';
|
||||
}
|
||||
return `https://raw.githubusercontent.com/${path}/${subpath}`;
|
||||
}
|
||||
|
||||
export const processSampleMap = (sampleMap, fn, baseUrl = sampleMap._base || '') => {
|
||||
return Object.entries(sampleMap).forEach(([key, value]) => {
|
||||
if (typeof value === 'string') {
|
||||
@@ -108,15 +129,19 @@ export const processSampleMap = (sampleMap, fn, baseUrl = sampleMap._base || '')
|
||||
throw new Error('wrong sample map format for ' + key);
|
||||
}
|
||||
baseUrl = value._base || baseUrl;
|
||||
const replaceUrl = (v) => (baseUrl + v).replace('github:', 'https://raw.githubusercontent.com/');
|
||||
baseUrl = resolveSpecialPaths(baseUrl);
|
||||
if (baseUrl.startsWith('github:')) {
|
||||
baseUrl = githubPath(baseUrl, '');
|
||||
}
|
||||
const fullUrl = (v) => baseUrl + v;
|
||||
if (Array.isArray(value)) {
|
||||
//return [key, value.map(replaceUrl)];
|
||||
value = value.map(replaceUrl);
|
||||
value = value.map(fullUrl);
|
||||
} else {
|
||||
// must be object
|
||||
value = Object.fromEntries(
|
||||
Object.entries(value).map(([note, samples]) => {
|
||||
return [note, (typeof samples === 'string' ? [samples] : samples).map(replaceUrl)];
|
||||
return [note, (typeof samples === 'string' ? [samples] : samples).map(fullUrl)];
|
||||
}),
|
||||
);
|
||||
}
|
||||
@@ -142,7 +167,7 @@ function getSamplesPrefixHandler(url) {
|
||||
/**
|
||||
* Loads a collection of samples to use with `s`
|
||||
* @example
|
||||
* samples('github:tidalcycles/Dirt-Samples/master');
|
||||
* samples('github:tidalcycles/dirt-samples');
|
||||
* s("[bd ~]*2, [~ hh]*2, ~ sd")
|
||||
* @example
|
||||
* samples({
|
||||
@@ -165,18 +190,9 @@ export const samples = async (sampleMap, baseUrl = sampleMap._base || '', option
|
||||
if (handler) {
|
||||
return handler(sampleMap);
|
||||
}
|
||||
if (sampleMap.startsWith('bubo:')) {
|
||||
const [_, repo] = sampleMap.split(':');
|
||||
sampleMap = `github:Bubobubobubobubo/dough-${repo}`;
|
||||
}
|
||||
sampleMap = resolveSpecialPaths(sampleMap);
|
||||
if (sampleMap.startsWith('github:')) {
|
||||
let [_, path] = sampleMap.split('github:');
|
||||
path = path.endsWith('/') ? path.slice(0, -1) : path;
|
||||
if (path.split('/').length === 2) {
|
||||
// assume main as default branch if none set
|
||||
path += '/main';
|
||||
}
|
||||
sampleMap = `https://raw.githubusercontent.com/${path}/strudel.json`;
|
||||
sampleMap = githubPath(sampleMap, 'strudel.json');
|
||||
}
|
||||
if (sampleMap.startsWith('shabda:')) {
|
||||
let [_, path] = sampleMap.split('shabda:');
|
||||
|
||||
@@ -253,6 +253,11 @@ function effectSend(input, effect, wet) {
|
||||
return send;
|
||||
}
|
||||
|
||||
export function resetGlobalEffects() {
|
||||
delays = {};
|
||||
reverbs = {};
|
||||
}
|
||||
|
||||
export const superdough = async (value, deadline, hapDuration) => {
|
||||
const ac = getAudioContext();
|
||||
if (typeof value !== 'object') {
|
||||
|
||||
@@ -8,7 +8,7 @@ export default defineConfig({
|
||||
build: {
|
||||
lib: {
|
||||
entry: resolve(__dirname, 'index.mjs'),
|
||||
formats: ['es', 'cjs'],
|
||||
formats: ['es'],
|
||||
fileName: (ext) => ({ es: 'index.mjs', cjs: 'index.cjs' })[ext],
|
||||
},
|
||||
rollupOptions: {
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
{
|
||||
"name": "@strudel/tonal",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.1",
|
||||
"description": "Tonal functions for strudel",
|
||||
"main": "index.mjs",
|
||||
"publishConfig": {
|
||||
"main": "dist/index.js",
|
||||
"module": "dist/index.mjs"
|
||||
"main": "dist/index.mjs"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "vite build",
|
||||
|
||||
@@ -8,8 +8,8 @@ export default defineConfig({
|
||||
build: {
|
||||
lib: {
|
||||
entry: resolve(__dirname, 'index.mjs'),
|
||||
formats: ['es', 'cjs'],
|
||||
fileName: (ext) => ({ es: 'index.mjs', cjs: 'index.js' })[ext],
|
||||
formats: ['es'],
|
||||
fileName: (ext) => ({ es: 'index.mjs' })[ext],
|
||||
},
|
||||
rollupOptions: {
|
||||
external: [...Object.keys(dependencies)],
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"name": "@strudel/transpiler",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.1",
|
||||
"description": "Transpiler for strudel user code. Converts syntactically correct but semantically meaningless JS into evaluatable strudel code.",
|
||||
"main": "index.mjs",
|
||||
"type": "module",
|
||||
"publishConfig": {
|
||||
"main": "dist/index.js",
|
||||
"module": "dist/index.mjs"
|
||||
"main": "dist/index.mjs"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "vite build",
|
||||
|
||||
@@ -23,6 +23,9 @@ describe('transpiler', () => {
|
||||
it('supports top level await', () => {
|
||||
expect(transpiler("await samples('xxx');", simple).output).toEqual("await samples('xxx');");
|
||||
});
|
||||
it('adds await to bare samples call', () => {
|
||||
expect(transpiler("samples('xxx');", simple).output).toEqual("await samples('xxx');");
|
||||
});
|
||||
/* it('parses dynamic imports', () => {
|
||||
expect(
|
||||
transpiler("const { default: foo } = await import('https://bar.com/foo.js');", {
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import escodegen from 'escodegen';
|
||||
import { parse } from 'acorn';
|
||||
import { walk } from 'estree-walker';
|
||||
import { isNoteWithOctave } from '@strudel/core';
|
||||
import { getLeafLocations } from '@strudel/mini';
|
||||
import { parse } from 'acorn';
|
||||
import escodegen from 'escodegen';
|
||||
import { walk } from 'estree-walker';
|
||||
|
||||
export function transpiler(input, options = {}) {
|
||||
const { wrapAsync = false, addReturn = true, emitMiniLocations = true, emitWidgets = true } = options;
|
||||
@@ -47,6 +46,9 @@ export function transpiler(input, options = {}) {
|
||||
});
|
||||
return this.replace(widgetWithLocation(node));
|
||||
}
|
||||
if (isBareSamplesCall(node, parent)) {
|
||||
return this.replace(withAwait(node));
|
||||
}
|
||||
},
|
||||
leave(node, parent, prop, index) {},
|
||||
});
|
||||
@@ -119,3 +121,14 @@ function widgetWithLocation(node) {
|
||||
node.callee.name = 'sliderWithID';
|
||||
return node;
|
||||
}
|
||||
|
||||
function isBareSamplesCall(node, parent) {
|
||||
return node.type === 'CallExpression' && node.callee.name === 'samples' && parent.type !== 'AwaitExpression';
|
||||
}
|
||||
|
||||
function withAwait(node) {
|
||||
return {
|
||||
type: 'AwaitExpression',
|
||||
argument: node,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -8,8 +8,8 @@ export default defineConfig({
|
||||
build: {
|
||||
lib: {
|
||||
entry: resolve(__dirname, 'index.mjs'),
|
||||
formats: ['es', 'cjs'],
|
||||
fileName: (ext) => ({ es: 'index.mjs', cjs: 'index.js' })[ext],
|
||||
formats: ['es'],
|
||||
fileName: (ext) => ({ es: 'index.mjs' })[ext],
|
||||
},
|
||||
rollupOptions: {
|
||||
external: [...Object.keys(dependencies)],
|
||||
|
||||
@@ -43,7 +43,7 @@ By default, no external samples are loaded, but you can add them like this:
|
||||
|
||||
```js
|
||||
initStrudel({
|
||||
prebake: () => samples('github:tidalcycles/Dirt-Samples/master'),
|
||||
prebake: () => samples('github:tidalcycles/dirt-samples'),
|
||||
});
|
||||
|
||||
document.getElementById('play').addEventListener('click',
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"name": "@strudel/web",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.3",
|
||||
"description": "Easy to setup, opiniated bundle of Strudel for the browser.",
|
||||
"main": "web.mjs",
|
||||
"module": "web.mjs",
|
||||
"publishConfig": {
|
||||
"main": "dist/index.js",
|
||||
"module": "dist/index.mjs"
|
||||
@@ -37,7 +37,8 @@
|
||||
"@strudel/mini": "workspace:*",
|
||||
"@strudel/tonal": "workspace:*",
|
||||
"@strudel/transpiler": "workspace:*",
|
||||
"@strudel/webaudio": "workspace:*"
|
||||
"@strudel/webaudio": "workspace:*",
|
||||
"@rollup/plugin-replace": "^5.0.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"vite": "^5.0.10"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { defineConfig } from 'vite';
|
||||
import { dependencies } from './package.json';
|
||||
import { resolve } from 'path';
|
||||
import replace from '@rollup/plugin-replace';
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
@@ -8,11 +9,18 @@ export default defineConfig({
|
||||
build: {
|
||||
lib: {
|
||||
entry: resolve(__dirname, 'web.mjs'),
|
||||
formats: ['es', 'cjs'],
|
||||
fileName: (ext) => ({ es: 'index.mjs', cjs: 'index.js' })[ext],
|
||||
name: 'strudel',
|
||||
formats: ['es', 'iife'],
|
||||
fileName: (ext) => ({ es: 'index.mjs', iife: 'index.js' })[ext],
|
||||
},
|
||||
rollupOptions: {
|
||||
external: [...Object.keys(dependencies)],
|
||||
// external: [...Object.keys(dependencies)],
|
||||
plugins: [
|
||||
replace({
|
||||
'process.env.NODE_ENV': JSON.stringify('production'),
|
||||
preventAssignment: true,
|
||||
}),
|
||||
],
|
||||
},
|
||||
target: 'esnext',
|
||||
},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strudel/webaudio",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.1",
|
||||
"description": "Web Audio helpers for Strudel",
|
||||
"main": "index.mjs",
|
||||
"type": "module",
|
||||
@@ -8,8 +8,7 @@
|
||||
"example": "examples"
|
||||
},
|
||||
"publishConfig": {
|
||||
"main": "dist/index.js",
|
||||
"module": "dist/index.mjs"
|
||||
"main": "dist/index.mjs"
|
||||
},
|
||||
"scripts": {
|
||||
"example": "npx parcel examples/repl.html",
|
||||
|
||||
@@ -8,8 +8,8 @@ export default defineConfig({
|
||||
build: {
|
||||
lib: {
|
||||
entry: resolve(__dirname, 'index.mjs'),
|
||||
formats: ['es', 'cjs'],
|
||||
fileName: (ext) => ({ es: 'index.mjs', cjs: 'index.js' })[ext],
|
||||
formats: ['es'],
|
||||
fileName: (ext) => ({ es: 'index.mjs' })[ext],
|
||||
},
|
||||
rollupOptions: {
|
||||
external: [...Object.keys(dependencies)],
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"name": "@strudel/xen",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.1",
|
||||
"description": "Xenharmonic API for strudel",
|
||||
"main": "index.mjs",
|
||||
"type": "module",
|
||||
"publishConfig": {
|
||||
"main": "dist/index.js",
|
||||
"module": "dist/index.mjs"
|
||||
"main": "dist/index.mjs"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "vite build",
|
||||
|
||||
@@ -8,8 +8,8 @@ export default defineConfig({
|
||||
build: {
|
||||
lib: {
|
||||
entry: resolve(__dirname, 'index.mjs'),
|
||||
formats: ['es', 'cjs'],
|
||||
fileName: (ext) => ({ es: 'index.mjs', cjs: 'index.js' })[ext],
|
||||
formats: ['es'],
|
||||
fileName: (ext) => ({ es: 'index.mjs' })[ext],
|
||||
},
|
||||
rollupOptions: {
|
||||
external: [...Object.keys(dependencies)],
|
||||
|
||||
Generated
+3
-3
@@ -430,6 +430,9 @@ importers:
|
||||
|
||||
packages/web:
|
||||
dependencies:
|
||||
'@rollup/plugin-replace':
|
||||
specifier: ^5.0.5
|
||||
version: 5.0.5
|
||||
'@strudel/core':
|
||||
specifier: workspace:*
|
||||
version: link:../core
|
||||
@@ -3691,7 +3694,6 @@ packages:
|
||||
dependencies:
|
||||
'@rollup/pluginutils': 5.1.0
|
||||
magic-string: 0.30.5
|
||||
dev: true
|
||||
|
||||
/@rollup/pluginutils@3.1.0(rollup@2.79.1):
|
||||
resolution: {integrity: sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==}
|
||||
@@ -3717,7 +3719,6 @@ packages:
|
||||
'@types/estree': 1.0.0
|
||||
estree-walker: 2.0.2
|
||||
picomatch: 2.3.1
|
||||
dev: true
|
||||
|
||||
/@rollup/rollup-android-arm-eabi@4.9.2:
|
||||
resolution: {integrity: sha512-RKzxFxBHq9ysZ83fn8Iduv3A283K7zPPYuhL/z9CQuyFrjwpErJx0h4aeb/bnJ+q29GRLgJpY66ceQ/Wcsn3wA==}
|
||||
@@ -7118,7 +7119,6 @@ packages:
|
||||
|
||||
/estree-walker@2.0.2:
|
||||
resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
|
||||
dev: true
|
||||
|
||||
/estree-walker@3.0.3:
|
||||
resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==}
|
||||
|
||||
Vendored
+7
@@ -262,6 +262,13 @@ declare module 'astro:content' {
|
||||
collection: "blog";
|
||||
data: InferEntrySchema<"blog">
|
||||
} & { render(): Render[".mdx"] };
|
||||
"release-1.0.0-geburtstagskuchen.mdx": {
|
||||
id: "release-1.0.0-geburtstagskuchen.mdx";
|
||||
slug: "release-100-geburtstagskuchen";
|
||||
body: string;
|
||||
collection: "blog";
|
||||
data: InferEntrySchema<"blog">
|
||||
} & { render(): Render[".mdx"] };
|
||||
"year-2.mdx": {
|
||||
id: "year-2.mdx";
|
||||
slug: "year-2";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
title: 'Release Notes v0.0.2 Schwindlig'
|
||||
title: 'Release Notes v0.0.2'
|
||||
description: ''
|
||||
date: '2022-03-28'
|
||||
tags: ['meta']
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
title: 'Release Notes v0.0.3 Stürmisch'
|
||||
title: 'Release Notes v0.0.3'
|
||||
date: '2022-05-20'
|
||||
tags: ['meta']
|
||||
author: froos
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
title: 'Release Notes v0.0.3 Maelstrom'
|
||||
title: 'Release Notes v0.0.3'
|
||||
description: ''
|
||||
date: '2022-06-18'
|
||||
tags: ['meta']
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
title: 'Release Notes v0.0.4 Gischt'
|
||||
title: 'Release Notes v0.0.4'
|
||||
description: ''
|
||||
date: '2022-08-14'
|
||||
tags: ['meta']
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
title: 'Release Notes v0.3.0 Donauwelle'
|
||||
title: 'Release Notes v0.3.0'
|
||||
description: ''
|
||||
date: '2022-11-06'
|
||||
tags: ['meta']
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
title: 'Release Notes v0.4.0 Brandung'
|
||||
title: 'Release Notes v0.4.0'
|
||||
description: ''
|
||||
date: '2022-11-13'
|
||||
tags: ['meta']
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
title: 'Release Notes v0.5.0 Wirbel'
|
||||
title: 'Release Notes v0.5.0'
|
||||
description: ''
|
||||
date: '2022-12-13'
|
||||
tags: ['meta']
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
title: 'Release Notes v0.6.0 Zimtschnecke'
|
||||
title: 'Release Notes v0.6.0'
|
||||
description: ''
|
||||
date: '2023-02-01'
|
||||
tags: ['meta']
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
title: 'Release Notes v0.7.0 Zuckerguss'
|
||||
title: 'Release Notes v0.7.0'
|
||||
description: ''
|
||||
date: '2023-03-23'
|
||||
tags: ['meta']
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
title: 'Release Notes v0.8.0 Himbeermuffin'
|
||||
title: 'Release Notes v0.8.0'
|
||||
description: ''
|
||||
date: '2023-06-30'
|
||||
tags: ['meta']
|
||||
@@ -29,7 +29,7 @@ edit: the desktop app performance on linux is currently not that great.. the web
|
||||
The desktop App has the same features as the webapp, with the additional ability to load samples from disk. It is currently not documented yet, but you can do something like
|
||||
|
||||
```js
|
||||
await samples('~/music/xxx');
|
||||
samples('~/music/xxx');
|
||||
|
||||
s('my_sound');
|
||||
```
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
title: 'Release Notes v0.9.0 Bananenbrot'
|
||||
title: 'Release Notes v0.9.0'
|
||||
description: ''
|
||||
date: '2023-09-17'
|
||||
tags: ['meta']
|
||||
|
||||
@@ -0,0 +1,238 @@
|
||||
---
|
||||
title: 'Release Notes v1.0.0'
|
||||
description: ''
|
||||
date: '2024-01-22'
|
||||
tags: ['meta']
|
||||
author: froos
|
||||
---
|
||||
|
||||
import BlogVideo from '../../components/BlogVideo.astro';
|
||||
|
||||
These are the release notes for Strudel 1.0.0 aka "Geburtstagskuchen"
|
||||
|
||||
This release marks the 2 year anniversary of the project, the first commit was on the 22nd January 2022 by Alex McLean.
|
||||
|
||||
If you generally need a heads up on what happened to Strudel in the last year, read the [2023 recap](/blog/#year-2)
|
||||
|
||||
import { Youtube } from '@src/components/Youtube';
|
||||
|
||||
<Youtube client:only="react" id="ByPFmSBqQk0" />
|
||||
|
||||
A lot has happened since then, and also since the last release 16 weeks ago.
|
||||
|
||||
Let me write up some of the highlights:
|
||||
|
||||
## Breaking Change
|
||||
|
||||
This version changes the default cps value from 1 to 0.5 to give patterns a little bit more time by default.
|
||||
If you find your existing patterns to be suddenly half the speed, just add a `setcps(1)` to the top and it should sound as it did before!
|
||||
|
||||
- make 0.5hz cps the default by @yaxu in https://github.com/tidalcycles/strudel/pull/931
|
||||
|
||||
## New Domain
|
||||
|
||||
Strudel is now available under [strudel.cc](https://strudel.cc/). The old domain still works but you might not get the most recent version.
|
||||
|
||||
- replace strudel.tidalcycles.org with strudel.cc by @felixroos in https://github.com/tidalcycles/strudel/pull/768
|
||||
|
||||
## Strudel on Mastodon
|
||||
|
||||
Strudel now has a mastodon presence: https://social.toplap.org/@strudel
|
||||
|
||||
## New Audio Engine Features
|
||||
|
||||
superdough, the audio engine of strudel has gotten some new features:
|
||||
|
||||
- Create phaser effect by @daslyfe in https://github.com/tidalcycles/strudel/pull/798
|
||||
- Multichannel audio by @daslyfe in https://github.com/tidalcycles/strudel/pull/820
|
||||
- Audio device selection by @daslyfe in https://github.com/tidalcycles/strudel/pull/854
|
||||
- Better convolution reverb by generating impulse responses by @Bubobubobubobubo and @felixroos in https://github.com/tidalcycles/strudel/pull/718
|
||||
- Add 'white', 'pink' and 'brown' oscillators + refactor synth by @Bubobubobubobubo and @felixroos in https://github.com/tidalcycles/strudel/pull/713
|
||||
- New noise type: "crackle" by @Bubobubobubobubo in https://github.com/tidalcycles/strudel/pull/806
|
||||
- Add support for using samples as impulse response buffers for the reverb by @vasilymilovidov in https://github.com/tidalcycles/strudel/pull/717
|
||||
- Compressor by @felixroos in https://github.com/tidalcycles/strudel/pull/729
|
||||
- Adding vibrato to Superdough sampler by @Bubobubobubobubo and @felixroos in https://github.com/tidalcycles/strudel/pull/706
|
||||
- Further Envelope improvements by @daslyfe in https://github.com/tidalcycles/strudel/pull/868
|
||||
- Add more vowel qualities for the vowels function by @fnordomat in https://github.com/tidalcycles/strudel/pull/907
|
||||
- pitch envelope by @felixroos in https://github.com/tidalcycles/strudel/pull/913
|
||||
|
||||
## Slider Controls
|
||||
|
||||
The new `slider` function inlines a draggable slider element into the code, bridging the gap between code and GUI.
|
||||
|
||||
- widgets by @felixroos in https://github.com/tidalcycles/strudel/pull/714
|
||||
- Slider afterthoughts by @felixroos in https://github.com/tidalcycles/strudel/pull/723
|
||||
- add xfade by @felixroos in https://github.com/tidalcycles/strudel/pull/780
|
||||
|
||||
## Improved MIDI integration
|
||||
|
||||
Pattern params [can now be controlled with cc messages](https://www.youtube.com/watch?v=e2-Sv_jjDQk) + you can now send a MIDI clock to sync your DAW with strudel.
|
||||
|
||||
- Midi in by @felixroos in https://github.com/tidalcycles/strudel/pull/699
|
||||
- add midi clock support by @felixroos in https://github.com/tidalcycles/strudel/pull/710
|
||||
|
||||
## hydra
|
||||
|
||||
[hydra](https://hydra.ojack.xyz), the live coding video synth [can now be used directly inside the strudel REPL](https://strudel.cc/learn/hydra/).
|
||||
|
||||
- Hydra integration by @felixroos in https://github.com/tidalcycles/strudel/pull/759
|
||||
- add options param to initHydra by @kasparsj in https://github.com/tidalcycles/strudel/pull/808
|
||||
- Hydra fixes and improvements by @atfornes in https://github.com/tidalcycles/strudel/pull/818
|
||||
|
||||
## Vanilla REPL
|
||||
|
||||
The codemirror editor and the repl abstraction have been refactored from react to vanilla JS!
|
||||
This should give some performance improvements and less dependency / maintenance burden:
|
||||
|
||||
- Vanilla repl 2 by @felixroos in https://github.com/tidalcycles/strudel/pull/863
|
||||
- Vanilla repl 3 by @felixroos in https://github.com/tidalcycles/strudel/pull/865
|
||||
- more work on vanilla repl: repl web component + package + MicroRepl by @felixroos in https://github.com/tidalcycles/strudel/pull/866
|
||||
- main repl vanillification by @felixroos in https://github.com/tidalcycles/strudel/pull/873
|
||||
- final vanillification by @felixroos in https://github.com/tidalcycles/strudel/pull/876
|
||||
|
||||
## Doc Changes
|
||||
|
||||
Plenty of things have been added to the docs, including a [showcase of what people have been done with strudel](https://strudel.cc/intro/showcase/) and the new [Community Bakery](/bakery/)!
|
||||
|
||||
<details>
|
||||
<summary>show PRs</summary>
|
||||
|
||||
- Showcase by @felixroos in https://github.com/tidalcycles/strudel/pull/885
|
||||
- Recipes by @felixroos in https://github.com/tidalcycles/strudel/pull/742
|
||||
- Document striate function by @ilesinge in https://github.com/tidalcycles/strudel/pull/766
|
||||
- Document adsr function by @ilesinge in https://github.com/tidalcycles/strudel/pull/767
|
||||
- Add function params in reference tab by @ilesinge in https://github.com/tidalcycles/strudel/pull/785
|
||||
- Update first-sounds.mdx by @bwagner in https://github.com/tidalcycles/strudel/pull/794
|
||||
- Update recap.mdx by @bwagner in https://github.com/tidalcycles/strudel/pull/797
|
||||
- Update pattern-effects.mdx by @bwagner in https://github.com/tidalcycles/strudel/pull/796
|
||||
- Update first-effects.mdx by @bwagner in https://github.com/tidalcycles/strudel/pull/795
|
||||
- Document pianoroll by @ilesinge in https://github.com/tidalcycles/strudel/pull/784
|
||||
- Add doc for euclidLegatoRot, wordfall and slider by @ilesinge in https://github.com/tidalcycles/strudel/pull/801
|
||||
- Improve documentation for synonym functions by @ilesinge in https://github.com/tidalcycles/strudel/pull/800
|
||||
- Add and style algolia search by @ilesinge in https://github.com/tidalcycles/strudel/pull/827
|
||||
- Fix a typo by @drewgbarnes in https://github.com/tidalcycles/strudel/pull/830
|
||||
- add mastodon link by @felixroos in https://github.com/tidalcycles/strudel/pull/884
|
||||
- adds a blog by @felixroos in https://github.com/tidalcycles/strudel/pull/911
|
||||
- community bakery by @felixroos in https://github.com/tidalcycles/strudel/pull/923
|
||||
- Blog improvements by @felixroos in https://github.com/tidalcycles/strudel/pull/919
|
||||
- 2 years blog post by @felixroos in https://github.com/tidalcycles/strudel/pull/929
|
||||
|
||||
</details>
|
||||
|
||||
## Other Features
|
||||
|
||||
<details>
|
||||
<summary>There is a lot more</summary>
|
||||
|
||||
- mini notation: international alphabets support by @ilesinge in https://github.com/tidalcycles/strudel/pull/751
|
||||
- Add shabda shortcut by @ilesinge in https://github.com/tidalcycles/strudel/pull/740
|
||||
- add play function by @felixroos in https://github.com/tidalcycles/strudel/pull/758 (superseded by next)
|
||||
- tidal style d1 ... d9 functions + more by @felixroos in https://github.com/tidalcycles/strudel/pull/805
|
||||
- add vscode bindings by @Dsm0 in https://github.com/tidalcycles/strudel/pull/773
|
||||
- Implement optional hover tooltip with function documentation by @ilesinge in https://github.com/tidalcycles/strudel/pull/783
|
||||
- samples loading shortcuts: by @felixroos in https://github.com/tidalcycles/strudel/pull/788
|
||||
- add option to disable active line highlighting in Code Settings by @kasparsj in https://github.com/tidalcycles/strudel/pull/804
|
||||
- Color hsl by @felixroos in https://github.com/tidalcycles/strudel/pull/815
|
||||
- Patterns tab + Refactor Panel by @felixroos in https://github.com/tidalcycles/strudel/pull/769
|
||||
- patterns tab: import patterns + style by @felixroos in https://github.com/tidalcycles/strudel/pull/852
|
||||
- Export patterns + ui tweaks by @felixroos in https://github.com/tidalcycles/strudel/pull/855
|
||||
- Pattern organization by @felixroos in https://github.com/tidalcycles/strudel/pull/858
|
||||
- Sound Import from local file system by @daslyfe in https://github.com/tidalcycles/strudel/pull/839
|
||||
- bugfix: suspend and close exisiting audio context when changing interface by @daslyfe in https://github.com/tidalcycles/strudel/pull/882
|
||||
- add root mode for voicings by @felixroos in https://github.com/tidalcycles/strudel/pull/887
|
||||
- scales can now be anchored by @felixroos in https://github.com/tidalcycles/strudel/pull/888
|
||||
- add dough function for raw dsp by @felixroos in https://github.com/tidalcycles/strudel/pull/707 (experimental)
|
||||
- support mininotation '..' range operator, fixes #715 by @yaxu in https://github.com/tidalcycles/strudel/pull/716
|
||||
- Add pick and squeeze functions by @daslyfe in https://github.com/tidalcycles/strudel/pull/771
|
||||
- support , in < > by @felixroos in https://github.com/tidalcycles/strudel/pull/886
|
||||
- public sharing by @felixroos in https://github.com/tidalcycles/strudel/pull/910
|
||||
- pick, pickmod, inhabit, inhabitmod by @yaxu in https://github.com/tidalcycles/strudel/pull/921
|
||||
- Mini-notation additions towards tidal compatibility by @yaxu in https://github.com/tidalcycles/strudel/pull/926
|
||||
- add pickF and pickmodF by @geikha in https://github.com/tidalcycles/strudel/pull/924
|
||||
- Make splice cps-aware by @yaxu in https://github.com/tidalcycles/strudel/pull/932
|
||||
- Refactor cps functions by @felixroos in https://github.com/tidalcycles/strudel/pull/933
|
||||
- Add useful pattern selection behavior for performing. by @daslyfe in https://github.com/tidalcycles/strudel/pull/897
|
||||
|
||||
</details>
|
||||
|
||||
## Other Fixes
|
||||
|
||||
<details>
|
||||
<summary>show</summary>
|
||||
|
||||
- fix: finally repair envelopes by @felixroos in https://github.com/tidalcycles/strudel/pull/861
|
||||
- fix: reverb regenerate loophole by @felixroos in https://github.com/tidalcycles/strudel/pull/726
|
||||
- fix: reverb roomsize not required by @felixroos in https://github.com/tidalcycles/strudel/pull/731
|
||||
- fix: reverb sampleRate by @felixroos in https://github.com/tidalcycles/strudel/pull/732
|
||||
- consume n with scale by @felixroos in https://github.com/tidalcycles/strudel/pull/727
|
||||
- fix: hashes in urls by @felixroos in https://github.com/tidalcycles/strudel/pull/728
|
||||
- [Bug Fix] chooseWith: prevent pattern from stopping audio when selection is >= 1 or < 0 by @daslyfe in https://github.com/tidalcycles/strudel/pull/741
|
||||
- Fix addivite synthesis phases by @felixroos in https://github.com/tidalcycles/strudel/pull/762
|
||||
- fix: scale offset by @felixroos in https://github.com/tidalcycles/strudel/pull/764
|
||||
- fix zen mode logo overlap by @felixroos in https://github.com/tidalcycles/strudel/pull/760
|
||||
- fix: share copy to clipboard + alert by @felixroos in https://github.com/tidalcycles/strudel/pull/774
|
||||
- fix: style issues by @felixroos in https://github.com/tidalcycles/strudel/pull/781
|
||||
- Fix scope pos + document by @felixroos in https://github.com/tidalcycles/strudel/pull/786
|
||||
- don't use anchor links for reference by @felixroos in https://github.com/tidalcycles/strudel/pull/791
|
||||
- remove unwanted cm6 outline for strudelTheme by @kasparsj in https://github.com/tidalcycles/strudel/pull/802
|
||||
- FIXES: palindrome abc -> abccba by @bwagner in https://github.com/tidalcycles/strudel/pull/831
|
||||
- Bug Fix #119: Clock drift by @daslyfe in https://github.com/tidalcycles/strudel/pull/874
|
||||
- bugfix: sound select indexes out of bounds by @daslyfe in https://github.com/tidalcycles/strudel/pull/871
|
||||
- Error tolerance by @felixroos in https://github.com/tidalcycles/strudel/pull/880
|
||||
- fix: make sure n is never undefined before nanFallback by @felixroos in https://github.com/tidalcycles/strudel/pull/881
|
||||
- fix: invisible selection on vim + emacs mode by @felixroos in https://github.com/tidalcycles/strudel/pull/889
|
||||
- fix: autocomplete / tooltip code example bug by @felixroos in https://github.com/tidalcycles/strudel/pull/898
|
||||
- Fix examples page, piano() and a few workshop imgs by @shiyouganai in https://github.com/tidalcycles/strudel/pull/848
|
||||
- fix: trailing slash confusion by @felixroos in https://github.com/tidalcycles/strudel/pull/743
|
||||
- fix: try different trailing slash behavior by @felixroos in https://github.com/tidalcycles/strudel/pull/744
|
||||
- Fix krill build command in README by @ilesinge in https://github.com/tidalcycles/strudel/pull/748
|
||||
- Fix for #1. Enables named instruments for csoundm. by @gogins in https://github.com/tidalcycles/strudel/pull/662
|
||||
- fix: missing hash for links starting with / by @felixroos in https://github.com/tidalcycles/strudel/pull/845
|
||||
- fix: swatch png src by @felixroos in https://github.com/tidalcycles/strudel/pull/846
|
||||
- Fix edge case with rehype-urls and trailing slashes in image file paths by @shiyouganai in https://github.com/tidalcycles/strudel/pull/849
|
||||
- fix: multiple repls by @felixroos in https://github.com/tidalcycles/strudel/pull/813
|
||||
- Fix chunk, add fastChunk and repeatCycles by @yaxu in https://github.com/tidalcycles/strudel/pull/712
|
||||
- Update tauri.yml workflow file by @vasilymilovidov in https://github.com/tidalcycles/strudel/pull/705
|
||||
- vite-vanilla-repl readme fix by @felixroos in https://github.com/tidalcycles/strudel/pull/737
|
||||
- completely revert config mess by @felixroos in https://github.com/tidalcycles/strudel/pull/745
|
||||
- hopefully fix trainling slashes bug by @felixroos in https://github.com/tidalcycles/strudel/pull/753
|
||||
- Update vite pwa by @felixroos in https://github.com/tidalcycles/strudel/pull/772
|
||||
- Update to Astro 3 by @felixroos in https://github.com/tidalcycles/strudel/pull/775
|
||||
- support multiple named serial connections, change default baudrate by @yaxu in https://github.com/tidalcycles/strudel/pull/551
|
||||
- CHANGES: github action checkout v2 -> v4 by @bwagner in https://github.com/tidalcycles/strudel/pull/837
|
||||
- CHANGES: pin pnpm to version 8.3.1 by @bwagner in https://github.com/tidalcycles/strudel/pull/834
|
||||
- CHANGES: github action pnpm version from 7 to 8.3.1 by @bwagner in https://github.com/tidalcycles/strudel/pull/835
|
||||
- ADDS: JetBrains IDE files and directories to .gitignore by @bwagner in https://github.com/tidalcycles/strudel/pull/840
|
||||
- Prevent 404 on Algolia crawls by @ilesinge in https://github.com/tidalcycles/strudel/pull/838
|
||||
- Add in fixes from my fork to slashocalypse branch by @shiyouganai in https://github.com/tidalcycles/strudel/pull/843
|
||||
- improve slashing + base href behavior by @felixroos in https://github.com/tidalcycles/strudel/pull/842
|
||||
- CHANGES: pnpm 8.1.3 to 8.11.0 by @bwagner in https://github.com/tidalcycles/strudel/pull/850
|
||||
- add missing trailing slashes by @felixroos in https://github.com/tidalcycles/strudel/pull/860
|
||||
- move all examples to separate examples folder by @felixroos in https://github.com/tidalcycles/strudel/pull/878
|
||||
- Dependency update by @felixroos in https://github.com/tidalcycles/strudel/pull/879
|
||||
- Update Vite version so hot reload works properly with newest pnpm version by @daslyfe in https://github.com/tidalcycles/strudel/pull/892
|
||||
- prevent vite from complaining about additional exports in jsx files by @daslyfe in https://github.com/tidalcycles/strudel/pull/891
|
||||
- fix some build warnings by @felixroos in https://github.com/tidalcycles/strudel/pull/902
|
||||
- Remove hideHeader for better mobile UI and consistency by @rjulian in https://github.com/tidalcycles/strudel/pull/894
|
||||
- Fix: swatch/[name].png.js static path by @oscarbyrne in https://github.com/tidalcycles/strudel/pull/916
|
||||
- rename @strudel.cycles/_ packages to @strudel/_ by @felixroos in https://github.com/tidalcycles/strudel/pull/917
|
||||
- `pick` now accepts lookup tables, with alternate cycle squeezing behaviour as new `inhabit` function by @yaxu in https://github.com/tidalcycles/strudel/pull/918
|
||||
- Revert "`pick` now accepts lookup tables, with alternate cycle squeezing behaviour as new `inhabit` function" by @yaxu in https://github.com/tidalcycles/strudel/pull/920
|
||||
- Fix pattern tab not showing patterns without created date by @daslyfe in https://github.com/tidalcycles/strudel/pull/934
|
||||
|
||||
</details>
|
||||
|
||||
## New Contributors
|
||||
|
||||
- @ilesinge made their first contribution in https://github.com/tidalcycles/strudel/pull/748
|
||||
- @Dsm0 made their first contribution in https://github.com/tidalcycles/strudel/pull/773
|
||||
- @kasparsj made their first contribution in https://github.com/tidalcycles/strudel/pull/802
|
||||
- @atfornes made their first contribution in https://github.com/tidalcycles/strudel/pull/818
|
||||
- @drewgbarnes made their first contribution in https://github.com/tidalcycles/strudel/pull/830
|
||||
- @shiyouganai made their first contribution in https://github.com/tidalcycles/strudel/pull/843
|
||||
- @rjulian made their first contribution in https://github.com/tidalcycles/strudel/pull/894
|
||||
- @fnordomat made their first contribution in https://github.com/tidalcycles/strudel/pull/907
|
||||
- @oscarbyrne made their first contribution in https://github.com/tidalcycles/strudel/pull/916
|
||||
- @geikha made their first contribution in https://github.com/tidalcycles/strudel/pull/924
|
||||
|
||||
**Full Changelog**: https://github.com/tidalcycles/strudel/compare/v0.9.0...v1.0.0
|
||||
@@ -1,6 +1,6 @@
|
||||
export const examples = [
|
||||
`// "coastline" @by eddyflux
|
||||
await samples('github:eddyflux/crate')
|
||||
samples('github:eddyflux/crate')
|
||||
setcps(.75)
|
||||
let chords = chord("<Bbm9 Fm9>/4").dict('ireal')
|
||||
stack(
|
||||
@@ -30,7 +30,7 @@ stack(
|
||||
.late("[0 .01]*4").late("[0 .01]*2").size(4)`,
|
||||
`// "broken cut 1" @by froos
|
||||
|
||||
await samples('github:tidalcycles/Dirt-Samples/master')
|
||||
samples('github:tidalcycles/dirt-samples')
|
||||
samples({
|
||||
'slap': 'https://cdn.freesound.org/previews/495/495416_10350281-lq.mp3',
|
||||
'whirl': 'https://cdn.freesound.org/previews/495/495313_10350281-lq.mp3',
|
||||
|
||||
@@ -51,7 +51,7 @@ Alternatively, you can get a taste of what Strudel can do by clicking play on th
|
||||
bd: ['bd/BT0AADA.wav','bd/BT0AAD0.wav','bd/BT0A0DA.wav','bd/BT0A0D3.wav','bd/BT0A0D0.wav','bd/BT0A0A7.wav'],
|
||||
sd: ['sd/rytm-01-classic.wav','sd/rytm-00-hard.wav'],
|
||||
hh: ['hh27/000_hh27closedhh.wav','hh/000_hh3closedhh.wav'],
|
||||
}, 'github:tidalcycles/Dirt-Samples/master/');
|
||||
}, 'github:tidalcycles/dirt-samples');
|
||||
stack(
|
||||
s("bd,[~ <sd!3 sd(3,4,2)>],hh*8") // drums
|
||||
.speed(perlin.range(.7,.9)) // random sample speed variation
|
||||
|
||||
@@ -143,7 +143,7 @@ Because GitHub is a popular place for uploading open source samples, it has its
|
||||
bd: 'bd/BT0AADA.wav',
|
||||
sd: 'sd/rytm-01-classic.wav',
|
||||
hh: 'hh27/000_hh27closedhh.wav',
|
||||
}, 'github:tidalcycles/Dirt-Samples/master/');
|
||||
}, 'github:tidalcycles/dirt-samples');
|
||||
s("bd sd bd sd,hh*16")`}
|
||||
/>
|
||||
|
||||
@@ -174,7 +174,7 @@ It is also possible, to declare multiple files for one sound, using the array no
|
||||
bd: ['bd/BT0AADA.wav','bd/BT0AAD0.wav'],
|
||||
sd: ['sd/rytm-01-classic.wav','sd/rytm-00-hard.wav'],
|
||||
hh: ['hh27/000_hh27closedhh.wav','hh/000_hh3closedhh.wav'],
|
||||
}, 'github:tidalcycles/Dirt-Samples/master/');
|
||||
}, 'github:tidalcycles/dirt-samples');
|
||||
s("bd:0 bd:1,~ <sd:0 sd:1> ~ sd:0,[hh:0 hh:1]*4")`}
|
||||
/>
|
||||
|
||||
@@ -187,7 +187,7 @@ The sample number can also be set using `n`:
|
||||
bd: ['bd/BT0AADA.wav','bd/BT0AAD0.wav'],
|
||||
sd: ['sd/rytm-01-classic.wav','sd/rytm-00-hard.wav'],
|
||||
hh: ['hh27/000_hh27closedhh.wav','hh/000_hh3closedhh.wav'],
|
||||
}, 'github:tidalcycles/Dirt-Samples/master/');
|
||||
}, 'github:tidalcycles/dirt-samples');
|
||||
s("bd bd,~ sd ~ sd,hh*8").n("<0 1>")`}
|
||||
/>
|
||||
|
||||
@@ -231,7 +231,7 @@ For pitched sounds, you can use `note`, just like with synths:
|
||||
client:idle
|
||||
tune={`samples({
|
||||
'gtr': 'gtr/0001_cleanC.wav',
|
||||
}, 'github:tidalcycles/Dirt-Samples/master/');
|
||||
}, 'github:tidalcycles/dirt-samples');
|
||||
note("g3 [bb3 c4] <g4 f4 eb4 f3>@2").s('gtr').gain(.5)`}
|
||||
/>
|
||||
|
||||
@@ -242,7 +242,7 @@ If we want them to behave more like a synth, we can add `clip(1)`:
|
||||
client:idle
|
||||
tune={`samples({
|
||||
'gtr': 'gtr/0001_cleanC.wav',
|
||||
}, 'github:tidalcycles/Dirt-Samples/master/');
|
||||
}, 'github:tidalcycles/dirt-samples');
|
||||
note("g3 [bb3 c4] <g4 f4 eb4 f3>@2").s('gtr').clip(1)
|
||||
.gain(.5)`}
|
||||
/>
|
||||
@@ -256,7 +256,7 @@ If we have 2 samples with different base pitches, we can make them in tune by sp
|
||||
tune={`samples({
|
||||
'gtr': 'gtr/0001_cleanC.wav',
|
||||
'moog': { 'g3': 'moog/005_Mighty%20Moog%20G3.wav' },
|
||||
}, 'github:tidalcycles/Dirt-Samples/master/');
|
||||
}, 'github:tidalcycles/dirt-samples');
|
||||
note("g3 [bb3 c4] <g4 f4 eb4 f3>@2").s("gtr,moog").clip(1)
|
||||
.gain(.5)`}
|
||||
/>
|
||||
@@ -272,7 +272,7 @@ We can also declare different samples for different regions of the keyboard:
|
||||
'g2': 'moog/004_Mighty%20Moog%20G2.wav',
|
||||
'g3': 'moog/005_Mighty%20Moog%20G3.wav',
|
||||
'g4': 'moog/006_Mighty%20Moog%20G4.wav',
|
||||
}}, 'github:tidalcycles/Dirt-Samples/master/');
|
||||
}}, 'github:tidalcycles/dirt-samples');
|
||||
note("g2!2 <bb2 c3>!2, <c4@3 [<eb4 bb3> g4 f4]>")
|
||||
.s('moog').clip(1)
|
||||
.gain(.5).cpm(60)`}
|
||||
@@ -287,7 +287,7 @@ With it, you can enter any sample name(s) to query from [freesound.org](https://
|
||||
|
||||
<MiniRepl
|
||||
client:idle
|
||||
tune={`await samples('shabda:bass:4,hihat:4,rimshot:2')
|
||||
tune={`samples('shabda:bass:4,hihat:4,rimshot:2')
|
||||
stack(
|
||||
n("0 1 2 3 0 1 2 3").s('bass'),
|
||||
n("0 1*2 2 3*2").s('hihat'),
|
||||
@@ -300,8 +300,8 @@ Note that the language code and the gender parameters are optional and default t
|
||||
|
||||
<MiniRepl
|
||||
client:idle
|
||||
tune={`await samples('shabda/speech:the_drum,forever')
|
||||
await samples('shabda/speech/fr-FR/m:magnifique')
|
||||
tune={`samples('shabda/speech:the_drum,forever')
|
||||
samples('shabda/speech/fr-FR/m:magnifique')
|
||||
stack(
|
||||
s("the_drum*2").chop(16).speed(rand.range(0.85,1.1)),
|
||||
s("forever magnifique").slow(4).late(0.125)
|
||||
|
||||
@@ -60,7 +60,7 @@ A sample can be looped and chopped like this:
|
||||
|
||||
<MiniRepl
|
||||
client:visible
|
||||
tune={`await samples('github:yaxu/clean-breaks/main')
|
||||
tune={`samples('github:yaxu/clean-breaks')
|
||||
s("amen/4").fit().chop(32)`}
|
||||
punchcard
|
||||
/>
|
||||
@@ -71,7 +71,7 @@ Let's add randmized doubling + reversing:
|
||||
|
||||
<MiniRepl
|
||||
client:visible
|
||||
tune={`await samples('github:yaxu/clean-breaks/main')
|
||||
tune={`samples('github:yaxu/clean-breaks')
|
||||
s("amen/4").fit().chop(16).cut(1)
|
||||
.sometimesBy(.5, ply("2"))
|
||||
.sometimesBy(.25, mul(speed("-1")))`}
|
||||
@@ -82,7 +82,7 @@ If we want to specify the order of samples, we can replace `chop` with `slice`:
|
||||
|
||||
<MiniRepl
|
||||
client:visible
|
||||
tune={`await samples('github:yaxu/clean-breaks/main')
|
||||
tune={`samples('github:yaxu/clean-breaks')
|
||||
s("amen/4").fit()
|
||||
.slice(8, "<0 1 2 3 4*2 5 6 [6 7]>*2")
|
||||
.cut(1).rarely(ply("2"))`}
|
||||
@@ -93,7 +93,7 @@ If we use `splice` instead of `slice`, the speed adjusts to the duration of the
|
||||
|
||||
<MiniRepl
|
||||
client:visible
|
||||
tune={`await samples('github:yaxu/clean-breaks/main')
|
||||
tune={`samples('github:yaxu/clean-breaks')
|
||||
s("amen")
|
||||
.splice(8, "<0 1 2 3 4*2 5 6 [6 7]>*2")
|
||||
.cut(1).rarely(ply("2"))`}
|
||||
@@ -213,7 +213,7 @@ Using `run` with `n`, we can rush through a sample bank:
|
||||
|
||||
<MiniRepl
|
||||
client:visible
|
||||
tune={`await samples('bubo:fox')
|
||||
tune={`samples('bubo:fox')
|
||||
n(run(8)).s("ftabla")`}
|
||||
punchcard
|
||||
/>
|
||||
@@ -224,7 +224,7 @@ In this case, I hear the beginning at the third sample, which can be accounted f
|
||||
|
||||
<MiniRepl
|
||||
client:visible
|
||||
tune={`await samples('bubo:fox')
|
||||
tune={`samples('bubo:fox')
|
||||
n(run(8)).s("ftabla").early(2/8)`}
|
||||
/>
|
||||
|
||||
@@ -232,7 +232,7 @@ Let's add some randomness:
|
||||
|
||||
<MiniRepl
|
||||
client:visible
|
||||
tune={`await samples('bubo:fox')
|
||||
tune={`samples('bubo:fox')
|
||||
n(run(8)).s("ftabla").early(2/8)
|
||||
.sometimes(mul(speed("1.5")))`}
|
||||
/>
|
||||
@@ -299,7 +299,7 @@ To simplify loading wavetables, any sample that starts with `wt_` will be looped
|
||||
|
||||
<MiniRepl
|
||||
client:visible
|
||||
tune={`await samples('github:bubobubobubobubo/dough-waveforms/main')
|
||||
tune={`samples('github:bubobubobubobubo/dough-waveforms')
|
||||
note("c eb g bb").s("wt_dbass").clip(2)`}
|
||||
/>
|
||||
|
||||
@@ -307,7 +307,7 @@ Running through different wavetables can also give interesting variations:
|
||||
|
||||
<MiniRepl
|
||||
client:visible
|
||||
tune={`await samples('github:bubobubobubobubo/dough-waveforms/main')
|
||||
tune={`samples('github:bubobubobubobubo/dough-waveforms')
|
||||
note("c2*8").s("wt_dbass").n(run(8))`}
|
||||
/>
|
||||
|
||||
@@ -315,7 +315,7 @@ note("c2*8").s("wt_dbass").n(run(8))`}
|
||||
|
||||
<MiniRepl
|
||||
client:visible
|
||||
tune={`await samples('github:bubobubobubobubo/dough-waveforms/main')
|
||||
tune={`samples('github:bubobubobubobubo/dough-waveforms')
|
||||
note("c2*8").s("wt_dbass").n(run(8))
|
||||
.lpf(perlin.range(200,2000).slow(8))
|
||||
.lpenv(-3).lpa(.1).room(.5)`}
|
||||
|
||||
@@ -8,7 +8,7 @@ import { MiniRepl } from '../../docs/MiniRepl';
|
||||
Note:
|
||||
|
||||
- this has been (partly) translated from https://tidalcycles.org/docs/patternlib/howtos/buildrhythms
|
||||
- this only sounds good with `samples('github:tidalcycles/Dirt-Samples/master')` in prebake
|
||||
- this only sounds good with `samples('github:tidalcycles/dirt-samples')` in prebake
|
||||
|
||||
# Build Rhythms
|
||||
|
||||
|
||||
@@ -139,7 +139,7 @@ The content of a sequence will be squished into what's called a cycle.
|
||||
|
||||
cpm = cycles per minute
|
||||
|
||||
By default, the tempo is 60 cycles per minute = 1 cycle per second.
|
||||
By default, the tempo is 30 cycles per minute = 1 half cycle per second.
|
||||
|
||||
</Box>
|
||||
|
||||
|
||||
@@ -64,3 +64,8 @@
|
||||
#code .cm-focused {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
#code .cm-matchingBracket {
|
||||
text-decoration: underline 0.18rem;
|
||||
text-underline-offset: 0.22rem;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,13 @@ This program is free software: you can redistribute it and/or modify it under th
|
||||
import { code2hash, getDrawContext, logger, silence } from '@strudel/core';
|
||||
import cx from '@src/cx.mjs';
|
||||
import { transpiler } from '@strudel/transpiler';
|
||||
import { getAudioContext, initAudioOnFirstClick, webaudioOutput } from '@strudel/webaudio';
|
||||
import {
|
||||
getAudioContext,
|
||||
initAudioOnFirstClick,
|
||||
webaudioOutput,
|
||||
resetGlobalEffects,
|
||||
resetLoadedSounds,
|
||||
} from '@strudel/webaudio';
|
||||
import { defaultAudioDeviceName } from '../settings.mjs';
|
||||
import { getAudioDevices, setAudioDevice } from './util.mjs';
|
||||
import { StrudelMirror, defaultSettings } from '@strudel/codemirror';
|
||||
@@ -157,6 +163,7 @@ export function Repl({ embedded = false }) {
|
||||
};
|
||||
|
||||
const resetEditor = async () => {
|
||||
resetGlobalEffects();
|
||||
clearCanvas();
|
||||
resetLoadedSounds();
|
||||
editorRef.current.repl.setCps(0.5);
|
||||
@@ -183,6 +190,7 @@ export function Repl({ embedded = false }) {
|
||||
setViewingPatternData(patternData);
|
||||
clearCanvas();
|
||||
resetLoadedSounds();
|
||||
resetGlobalEffects();
|
||||
await prebake(); // declare default samples
|
||||
editorRef.current.setCode(code);
|
||||
editorRef.current.repl.evaluate(code);
|
||||
|
||||
@@ -77,6 +77,7 @@ export function SettingsTab({ started }) {
|
||||
const {
|
||||
theme,
|
||||
keybindings,
|
||||
isBracketMatchingEnabled,
|
||||
isLineNumbersDisplayed,
|
||||
isPatternHighlightingEnabled,
|
||||
isActiveLineHighlighted,
|
||||
@@ -137,6 +138,11 @@ export function SettingsTab({ started }) {
|
||||
></ButtonGroup>
|
||||
</FormItem>
|
||||
<FormItem label="Code Settings">
|
||||
<Checkbox
|
||||
label="Enable bracket matching"
|
||||
onChange={(cbEvent) => settingsMap.setKey('isBracketMatchingEnabled', cbEvent.target.checked)}
|
||||
value={isBracketMatchingEnabled}
|
||||
/>
|
||||
<Checkbox
|
||||
label="Display line numbers"
|
||||
onChange={(cbEvent) => settingsMap.setKey('isLineNumbersDisplayed', cbEvent.target.checked)}
|
||||
|
||||
@@ -115,13 +115,12 @@ export async function prebake() {
|
||||
'numbers/8.wav',
|
||||
],
|
||||
},
|
||||
'github:tidalcycles/Dirt-Samples/master/',
|
||||
'github:tidalcycles/dirt-samples',
|
||||
{
|
||||
prebake: true,
|
||||
},
|
||||
),
|
||||
]);
|
||||
// await samples('github:tidalcycles/Dirt-Samples/master');
|
||||
}
|
||||
|
||||
const maxPan = noteToMidi('C8');
|
||||
|
||||
@@ -527,7 +527,7 @@ export const meltingsubmarine = `// "Melting submarine"
|
||||
// @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||
// @by Felix Roos
|
||||
|
||||
await samples('github:tidalcycles/Dirt-Samples/master/')
|
||||
samples('github:tidalcycles/dirt-samples')
|
||||
stack(
|
||||
s("bd:5,[~ <sd:1!3 sd:1(3,4,3)>],hh27(3,4,1)") // drums
|
||||
.speed(perlin.range(.7,.9)) // random sample speed variation
|
||||
@@ -574,7 +574,7 @@ samples({
|
||||
sd: ['sd/rytm-01-classic.wav','sd/rytm-00-hard.wav'],
|
||||
hh: ['hh27/000_hh27closedhh.wav','hh/000_hh3closedhh.wav'],
|
||||
perc: ['perc/002_perc2.wav'],
|
||||
}, 'github:tidalcycles/Dirt-Samples/master/');
|
||||
}, 'github:tidalcycles/dirt-samples');
|
||||
|
||||
chord("<C^7 Am7 Dm7 G7>*2").dict('lefthand').anchor("G4").voicing()
|
||||
.stack(n("0@6 [<1 2> <2 0> 1]@2").scale('C5 major'))
|
||||
@@ -608,7 +608,7 @@ samples({
|
||||
bd: ['bd/BT0AADA.wav','bd/BT0AAD0.wav','bd/BT0A0DA.wav','bd/BT0A0D3.wav','bd/BT0A0D0.wav','bd/BT0A0A7.wav'],
|
||||
sd: ['sd/rytm-01-classic.wav','sd/rytm-00-hard.wav'],
|
||||
hh: ['hh27/000_hh27closedhh.wav','hh/000_hh3closedhh.wav'],
|
||||
}, 'github:tidalcycles/Dirt-Samples/master/');
|
||||
}, 'github:tidalcycles/dirt-samples');
|
||||
|
||||
note("<8(3,8) <7 7*2> [4 5@3] 8>".sub(1) // sub 1 -> 1-indexed
|
||||
.layer(
|
||||
@@ -797,7 +797,7 @@ export const amensister = `// "Amensister"
|
||||
// @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||
// @by Felix Roos
|
||||
|
||||
await samples('github:tidalcycles/Dirt-Samples/master')
|
||||
samples('github:tidalcycles/dirt-samples')
|
||||
|
||||
stack(
|
||||
// amen
|
||||
@@ -906,7 +906,7 @@ export const arpoon = `// "Arpoon"
|
||||
// @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||
// @by Felix Roos
|
||||
|
||||
await samples('github:tidalcycles/Dirt-Samples/master')
|
||||
samples('github:tidalcycles/dirt-samples')
|
||||
|
||||
n("[0,3] 2 [1,3] 2".fast(3).lastOf(4, fast(2))).clip(2)
|
||||
.offset("<<1 2> 2 1 1>")
|
||||
|
||||
@@ -7,6 +7,7 @@ export const defaultAudioDeviceName = 'System Standard';
|
||||
export const defaultSettings = {
|
||||
activeFooter: 'intro',
|
||||
keybindings: 'codemirror',
|
||||
isBracketMatchingEnabled: true,
|
||||
isLineNumbersDisplayed: true,
|
||||
isActiveLineHighlighted: true,
|
||||
isAutoCompletionEnabled: false,
|
||||
@@ -40,6 +41,7 @@ export function useSettings() {
|
||||
return {
|
||||
...state,
|
||||
isZen: [true, 'true'].includes(state.isZen) ? true : false,
|
||||
isBracketMatchingEnabled: [true, 'true'].includes(state.isBracketMatchingEnabled) ? true : false,
|
||||
isLineNumbersDisplayed: [true, 'true'].includes(state.isLineNumbersDisplayed) ? true : false,
|
||||
isActiveLineHighlighted: [true, 'true'].includes(state.isActiveLineHighlighted) ? true : false,
|
||||
isAutoCompletionEnabled: [true, 'true'].includes(state.isAutoCompletionEnabled) ? true : false,
|
||||
|
||||
Reference in New Issue
Block a user