Compare commits

...

23 Commits

Author SHA1 Message Date
daslyfe d1dd895d94 Merge branch 'main' into strudel_json 2025-06-27 02:32:36 +02:00
Jade (Rose) Rowland f8124fca80 format again 2025-06-26 20:26:59 -04:00
Jade (Rose) Rowland 95fee04bea format 2025-06-26 20:02:18 -04:00
Jade (Rose) Rowland f60894f2ce working 2025-06-26 19:57:23 -04:00
Felix Roos b1aba294ad hotfix: fix upstream test 2025-06-26 15:39:35 +02:00
froos 63ac80eb79 Merge pull request 'mondo notation' (#1311) from uzu into main
Reviewed-on: https://codeberg.org/uzu/strudel/pulls/1311
2025-06-26 15:29:45 +02:00
froos 860bb58d61 Merge pull request 'allow calling all multiple times' (#1417) from multiple-all-calls into main
Reviewed-on: https://codeberg.org/uzu/strudel/pulls/1417
2025-06-24 06:14:15 +02:00
Felix Roos d58b3e490b fix: reset all transforms before eval 2025-06-24 06:12:21 +02:00
Felix Roos 0003ce174e allow calling all multiple times 2025-06-24 06:06:37 +02:00
froos 8e0f23e081 Merge pull request 'tonal: allow scales without tonic (default to C)' (#1092) from kasparsj/tonal-fix into main
Reviewed-on: https://codeberg.org/uzu/strudel/pulls/1092
2025-06-24 05:53:21 +02:00
Felix Roos 71e60ed8de add back comment 2025-06-24 05:45:36 +02:00
Felix Roos e2a29914c7 don't interpret note as n 2025-06-24 05:43:06 +02:00
Felix Roos a9a3d491a2 Merge branch 'main' into kasparsj/tonal-fix 2025-06-24 05:39:59 +02:00
yaxu a750764f88 Update CONTRIBUTING.md 2025-06-23 11:13:00 +02:00
froos 5b397009ab Merge pull request 'website intro: fix whitespace and code hosting name' (#1400) from trofi/strudel:website-intro-minor into main
Reviewed-on: https://codeberg.org/uzu/strudel/pulls/1400
2025-06-20 20:00:11 +02:00
Sergei Trofimovich e68df9e789 website intro: fix whitespace and code hosting name 2025-06-20 18:33:58 +01:00
yaxu 4d3bbd5057 Update README.md 2025-06-19 17:44:45 +02:00
Kaspars 81ca199a96 Merge branch 'upstream-main' into tonal-fix 2024-06-02 12:39:14 +03:00
Kaspars 8d8b8ab99e codeformat 2024-05-08 10:42:06 +02:00
Kaspars a4f10d5339 bug fix 2024-05-08 10:38:06 +02:00
Kaspars 33a73c37bc fix tests 2024-05-08 00:46:27 +02:00
Kaspars 4e6d39666a codeformat 2024-05-08 00:00:58 +02:00
Kaspars a5b6022506 - fix scale() to allow both n() and note() at the same time
- fix scale() to allow scale names without tonic and then default it to C
2024-05-07 23:56:39 +02:00
9 changed files with 74 additions and 10 deletions
+1 -1
View File
@@ -17,7 +17,7 @@ git remote set-url origin git@codeberg.org:uzu/strudel.git
To get in touch with the contributors, either
- [join the Tidal Discord Channel](https://discord.gg/remJ6gQA) and go to the #strudel channel
- [join the Tidal Discord Channel](https://discord.com/invite/HGEdXmRkzT) and go to the #strudel channel
- Find related discussions on the [tidal club forum](https://club.tidalcycles.org/)
## Ask a Question
+1 -1
View File
@@ -32,7 +32,7 @@ This project is organized into many [packages](./packages), which are also avail
Read more about how to use these in your own project [here](https://strudel.cc/technical-manual/project-start).
You will need to abide by the terms of the [GNU Affero Public Licence v3](LICENSE.md). As such, Strudel code can only be shared within free/open source projects under the same license -- see the license for details.
You will need to abide by the terms of the [GNU Affero Public Licence v3](LICENSE). As such, Strudel code can only be shared within free/open source projects under the same license -- see the license for details.
Licensing info for the default sound banks can be found over on the [dough-samples](https://github.com/felixroos/dough-samples/blob/main/README.md) repository.
+1
View File
@@ -4,6 +4,7 @@
"private": true,
"description": "Port of tidalcycles to javascript",
"scripts": {
"strudeljson": "node ./website/src/repl/create_strudel_json.mjs",
"setup": "pnpm i",
"pretest": "npm run jsdoc-json",
"prebuild": "npm run jsdoc-json",
+7 -3
View File
@@ -114,8 +114,9 @@ export function repl({
* all(x => x.pianoroll())
* ```
*/
let allTransforms = [];
const all = function (transform) {
allTransform = transform;
allTransforms.push(transform);
return silence;
};
/** Applies a function to each of the running patterns separately. This is intended for future use with upcoming 'stepwise' features. See `all` for a version that applies the function to all the patterns stacked together into a single pattern.
@@ -191,6 +192,7 @@ export function repl({
await injectPatternMethods();
setTime(() => scheduler.now()); // TODO: refactor?
await beforeEval?.({ code });
allTransforms = []; // reset all transforms
shouldHush && hush();
if (mondo) {
@@ -207,8 +209,10 @@ export function repl({
} else if (eachTransform) {
pattern = eachTransform(pattern);
}
if (allTransform) {
pattern = allTransform(pattern);
if (allTransforms.length) {
for (let i in allTransforms) {
pattern = allTransforms[i](pattern);
}
}
if (!isPattern(pattern)) {
const message = `got "${typeof evaluated}" instead of pattern`;
+7
View File
@@ -37,6 +37,13 @@ describe('tonal', () => {
.firstCycleValues.map((h) => h.note),
).toEqual(['C3', 'D3', 'E3']);
});
it('scale without tonic', () => {
expect(
n(seq(0, 1, 2))
.scale('major')
.firstCycleValues.map((h) => h.note),
).toEqual(['C3', 'D3', 'E3']);
});
it('scale with mininotation colon', () => {
expect(
n(seq(0, 1, 2))
+1 -1
View File
@@ -14,7 +14,7 @@ function scaleStep(step, scale) {
scale = scale.replaceAll(':', ' ');
step = Math.ceil(step);
let { intervals, tonic, empty } = Scale.get(scale);
if ((empty && isNote(scale)) || (!empty && !tonic)) {
if ((empty && isNote(scale)) || (empty && !tonic)) {
throw new Error(`incomplete scale. Make sure to use ":" instead of spaces, example: .scale("C:major")`);
} else if (empty) {
throw new Error(`invalid scale "${scale}"`);
@@ -20,7 +20,7 @@ export function WelcomeTab({ context }) {
</p>
<p>
{/* To learn more about what this all means, check out the{' '} */}
To get started, check out the
To get started, check out the{' '}
<a href={`${baseNoTrailing}/workshop/getting-started/`} target="_blank">
interactive tutorial
</a>
@@ -43,7 +43,7 @@ export function WelcomeTab({ context }) {
</a>
. You can find the source code at{' '}
<a href="https://codeberg.org/uzu/strudel" target="_blank">
github
codeberg
</a>
. You can also find <a href="https://github.com/felixroos/dough-samples/blob/main/README.md">licensing info</a>{' '}
for the default sound banks there. Please consider to{' '}
+52
View File
@@ -0,0 +1,52 @@
import { createInterface } from 'node:readline';
import * as fs from 'node:fs';
const validFileTypes = new Set(['.wav', '.mp3', '.aac', '.m4a']);
/** For automatically creating the strudel JSON that for samples hosted in a remote repo */
async function writeStrudelJson(subpath, hosturl) {
const children = await fs.promises.readdir(subpath, { recursive: true });
const name = subpath.split('/').slice(-1)[0];
const tree = { name, children };
let samples = {
_base: hosturl,
};
const files = tree.children
.filter((path) => {
const extension = path.match(/\.[0-9a-z]+$/i)?.[0];
return validFileTypes.has(extension);
})
.sort((a, b) => a.localeCompare(b));
files.forEach((path) => {
const groupName = path.match(/([^/]+)\/[^/]+$/)[1];
samples[groupName] = samples[groupName] ?? [];
samples[groupName].push(path);
});
const json = JSON.stringify(samples, null, 2);
const filepath = subpath + '/strudel.json';
await fs.promises.writeFile(filepath, json);
console.log(`wrote strudel.json with ${files.length} samples to ${subpath}`);
}
const rl = createInterface({
input: process.stdin,
output: process.stdout,
});
rl.question(`enter sample folder path: `, async (path) => {
rl.question(`enter hosted URL: `, async (hosturl) => {
const githubregex = /github\.com\/([^/]+)\/([^/]+)/;
const githubparams = hosturl.match(githubregex);
if (githubparams) {
const username = githubparams[1];
const repo = githubparams[2];
hosturl = `https://raw.githubusercontent.com/${username}/${repo}/main/`;
console.log('reformatting github URL to: ', hosturl);
}
await writeStrudelJson(path, hosturl);
rl.close();
});
});
+2 -2
View File
@@ -33,7 +33,7 @@ async function loadStrudelJson(subpath) {
});
}
async function writeStrudelJson(subpath) {
export async function writeStrudelJson(subpath) {
const children = await readDir(subpath, { dir, recursive: true });
const name = subpath.split('/').slice(-1)[0];
const tree = { name, children };
@@ -41,7 +41,7 @@ async function writeStrudelJson(subpath) {
let samples = {};
let count = 0;
walkFileTree(tree, (entry, parent) => {
if (['wav', 'mp3'].includes(entry.name.split('.').slice(-1)[0])) {
if (['wav', 'mp3', 'aac', 'm4a'].includes(entry.name.split('.').slice(-1)[0])) {
samples[parent.name] = samples[parent.name] || [];
count += 1;
samples[parent.name].push(entry.subpath.slice(1).concat([entry.name]).join('/'));