Compare commits

...

12 Commits

Author SHA1 Message Date
alex 24ac74e0ca make cpm a global control (like cps), and deal with it in cyclist 2026-11-01 11:25:06 +00:00
yaxu fdaa559377 Update README.md 2026-10-26 15:13:52 +01:00
Alex McLean 064cf07e26 Merge pull request 'Minor edit: change "human" to "person"' (#2162) from gamar3is/strudel:main into main
Reviewed-on: https://codeberg.org/uzu/strudel/pulls/2162
2026-10-25 11:02:53 +01:00
gamar3is d5362c208c Minor edit: change "human" to "person"
The use of the term "humans" to refer to people reinforces the anthropomorphisation of LLM's, suggesting they are specific entities instead of tools in a strange sci-fi way. Replacing "humans" with "people" can address this.
2026-10-25 10:56:50 +01:00
Alex McLean 7dd20fee57 Merge pull request 'humane dev policy' (#2158) from post-ai into main
Reviewed-on: https://codeberg.org/uzu/strudel/pulls/2158
2026-10-24 00:45:07 +02:00
yaxu 6b347af304 Clarify scope of llm corner 2026-10-24 00:44:34 +02:00
yaxu 6a64db0bc4 Update POLICY.md 2026-10-24 00:40:53 +02:00
Alex McLean 5ab79f2c6f Merge pull request 'gitignore .vscode except for settings.json' (#2160) from tyow/localstrudel:gitignore-vscode into main
Reviewed-on: https://codeberg.org/uzu/strudel/pulls/2160
2026-10-24 00:37:55 +02:00
tyow 67ce7c8ad6 gitignore .vscode except for settings.json 2026-10-23 17:30:15 -04:00
alex c84e5fd8fa tweaks 2026-10-23 11:45:43 +01:00
Alex McLean e00b6f6216 Merge pull request 'Update contributors in 'getting started' page' (#2157) from contributors into main
Reviewed-on: https://codeberg.org/uzu/strudel/pulls/2157
2026-10-19 21:22:53 +02:00
alex a2811ba35b draft of humane dev policy 2026-10-18 21:10:36 +01:00
9 changed files with 150 additions and 54 deletions
+3
View File
@@ -131,3 +131,6 @@ fabric.properties
samples/*
!samples/README.md
.idea/
.vscode
!settings.json
+7 -6
View File
@@ -2,6 +2,10 @@
Thanks for wanting to contribute!!! There are many ways you can add value to this project
## Humane interaction
Please read [POLICY.md](POLICY.md) for important details of our Code of Conduct, and policy around AI/LLM use.
## Move to codeberg
Along with many other live coding projects, we have moved from Microsoft's Github platform to Codeberg for ethical reasons. Please don't fork the project back to github.
@@ -34,7 +38,7 @@ Use one of the Communication Channels listed above.
## Improve the Docs
If you find some weak spots in the [docs](https://strudel.cc/workshop/getting-started/), you can edit each file directly on codeberg. There are "Edit this page" links in the right sidebar that take you to the right place.
If you find some weak spots in the [docs](https://strudel.cc/workshop/getting-started/), you can edit each file directly on codeberg. There are "Edit this page" links in the right sidebar that take you to the right place. If you're unfamiliar with codeberg/git, please ask questions.
## Propose a Feature
@@ -48,11 +52,7 @@ At the time of writing we have a PR backlog, and generally prioritise bugfixes a
### AI/LLM policy
Strudel is a project handmade by humans, with thought and nuance.
If you have used LLMs (so called 'AI'), please detail that in the pull request. We are still developing our response to the onslaught of LLM technology, but for practical and legal reasons are currently not accepting wholly LLM-generated code. We are also not accepting PRs that add LLM features to strudel itself.
There are #llm-chat and #llm-share channels on [our discord](https://discord.com/invite/HGEdXmRkzT). Please do not discuss or share LLM-related things outside of those channels.
Strudel is a project handmade by humans, with thought and nuance. See [Policy](POLICY.md) for our policy on LLM use.
## Creating and sharing a new project using strudel
@@ -254,3 +254,4 @@ ORDER BY created_at ASC;
## Have Fun
Remember to have fun, and that this project is driven by the passion of volunteers!
+41
View File
@@ -0,0 +1,41 @@
# Code of Conduct
## The Short Version
We are dedicated to providing a harassment-free experience for everyone, regardless of gender, gender identity and expression, age, sexual orientation, disability, physical appearance, body size, race, ethnicity, religion (or lack thereof), technology choices, and so on. This applies both in person or via online media.
## The Less Short Version
Harassment includes offensive verbal comments related to gender, gender identity and expression, age, sexual orientation, disability, physical appearance, body size, race, ethnicity, religion, technology choices, deliberate intimidation, stalking, following, disruption of performances, inappropriate physical contact, and unwelcome sexual attention.
If you are being harassed, notice that someone else is being harassed, or have any other concerns, please contact an admin immediately.
If you report an incident of harassment you can expect to be listened to and taken seriously. The admin will take action they deem appropriate in response depending on the scale and severity of the incident. For example:
1. Discuss the perpetrator's behaviour with them and ask them to stop. Explain what they have done and why it is unacceptable. Remind the perpetrator of the code of conduct. Monitor the perpetrator's behaviour and if it improves then they will continue to be welcome.
2. Temporarily exclude the perpetrator from the forum for a cool-off period. Explain what they have done and why it is unacceptable and remind them of the code of conduct. Monitor the person's behaviour and if it improves then they will continue to be welcome.
3. Remove the perpetrator from the forum. Explain what they have done and why it is unacceptable and remind them of the code of conduct.
# Post-AI humane policy for live coding development
Please follow the following policy on AI/LLM use.
## Community
All community members should be treated with respect and kindness. We welcome contributors to the community who are ready to follow this policy as well as the above code of conduct.
## Principles
* We wish to protect the humanity of our communities and projects, to support the motivation and well-being of all of its contributors and users.
* To this end, contributors and other users of our projects should not have to engage with LLM-generated code and text as part of their community work.
* We recognise that LLM-based scraping and generation of (A)GPL code shared by ourselves and others is of questionable legality. For example, under many juristictions, LLM-generated work does not have a copyright holder and can therefore not be licensed under the (A)GPL.
* A contributor's personal use of LLMs and related technology is their own business, whether for research, analysis, bug discovery or other assistive technology, so long as the output is not included in any contributions to our projects.
## In practice
* Contributions including LLM-generated content will be declined.
* LLM-generated text (e.g. commit messages, issue comments, forum posts etc) generated by LLMs will be flagged, and ultimately deleted.
* We encourage asking each other questions and working through problems to promote collective knowledge and creative ideas (never telling each other to "just google it").
* We strongly discourage others from forking/importing our projects into corporate AI platforms, including Microsoft Github.
* All contributions must be submitted by a person who understands the changes, is happy to answer questions about them, and where possible, help maintain the code in the future.
* In community discussion channels (at the time of writing, this refers to the uzu discord server), all discussion (including criticism) of LLM technology and use should be kept to designated channels.
+3 -3
View File
@@ -43,10 +43,10 @@ There are many ways to contribute to this project! See [contribution guide](./CO
## Community
There is a #strudel channel on the TidalCycles discord: <https://discord.com/invite/HGEdXmRkzT>
Strudel is a member of the 'Uzu' family of pattern-based live coding languages, along with TidalCycles and friends.
You can also ask questions and find related discussions on the tidal club forum: <https://club.tidalcycles.org/>
There are a range of strudel channels on the Uzu discord: <https://discord.com/invite/HGEdXmRkzT>
The discord and forum is shared with the haskell (tidal) and python (vortex) siblings of this project.
You can also ask questions and find related discussions on the Uzu web forum: <https://uzu.lurk.org/>
We also have a mastodon account: <a rel="me" href="https://social.toplap.org/@strudel">social.toplap.org/@strudel</a>
+25
View File
@@ -2702,7 +2702,32 @@ export const { seconds } = registerControl('seconds');
export const { songPtr } = registerControl('songPtr');
export const { uid } = registerControl('uid');
export const { val } = registerControl('val');
/**
* Plays the pattern at the given cycles per second. The cps can be patterned. This changes the global tempo, so it generally
* makes sense to have either `cps` (or `cpm` - cycles per minute) set by only one of your patterns.
* Note that this currently does not work when the 'Sync across Browser Tabs / Windows' setting is switched on.
* @tags temporal
* @example
* s("bd hh sd hh").cps(0.5) // = 1 cycle every 2 seconds
* @example
* // a smooth change over 4 cycles
* s("bd hh sd hh").cps(sine.slow(4).range(0.5,1.5))
*/
export const { cps } = registerControl('cps');
/**
* Plays the pattern at the given cycles per minute. The cpm can be patterned. This changes the global tempo, so it generally
* makes sense to have either `cpm` (or `cps` - cycles per second) set by only one of your patterns.
* Note that this currently does not work when the 'Sync across Browser Tabs / Windows' setting is switched on.
* @tags temporal
* @example
* s("bd hh sd hh").cpm(90) // = feels like 180 bpm
* // a smooth change over 4 cycles
* s("bd hh sd hh").cpm(sine.slow(4).range(30,70))
*/
export const { cpm } = registerControl('cpm');
/**
* Multiplies the duration with the given number. Also cuts samples off at the end if they exceed the duration.
*
+8 -6
View File
@@ -84,10 +84,10 @@ export class Cyclist {
// cps changes first, so the durations of the simultaneous haps
// are adjusted accordingly.
if (aBegin.eq(bBegin)) {
if (a.value.cps !== undefined) {
return b.value.cps !== undefined ? 0 : -1;
if (a.value.cps !== undefined || a.value.cpm !== undefined) {
return b.value.cps !== undefined || b.value.cpm !== undefined ? 0 : -1;
}
if (b.value.cps !== undefined) {
if (b.value.cps !== undefined || b.value.cpm !== undefined) {
return 1;
}
return 0;
@@ -97,6 +97,8 @@ export class Cyclist {
haps.forEach((hap) => {
const targetTime = (hap.whole.begin - this.checkpoint.cycles) / this.cps + this.checkpoint.seconds;
let hapCps = hap.value.cps;
hapCps ??= hap.value.cpm != null ? hap.value.cpm / 60 : undefined;
if (tickEndTime < targetTime) {
// If the targetTime exceeds the tickEndTime, this means
// the cps has slowed down, and the latter haps from the query
@@ -104,10 +106,10 @@ export class Cyclist {
// They'll be scheduled during the next tick.
return;
}
onSchedule?.(hap, targetTime + this.latency, hap.value.cps ?? this.cps);
if (hap.value.cps !== undefined && this.cps != hap.value.cps) {
onSchedule?.(hap, targetTime + this.latency, hapCps ?? this.cps);
if (hapCps !== undefined && this.cps != hapCps) {
cpsChanged = true;
this.cps = hap.value.cps;
this.cps = hapCps;
this.num_ticks_since_checkpoint = 0;
this.checkpoint = {
cycles: hap.whole.begin,
-12
View File
@@ -2476,18 +2476,6 @@ export const apply = register('apply', function (func, pat) {
return func(pat);
});
/**
* Plays the pattern at the given cycles per minute.
* @tags temporal
* @deprecated
* @example
* s("<bd sd>,hh*2").cpm(90) // = 90 bpm
*/
// this is redefined in repl.mjs, using the current cps as divisor
export const cpm = register('cpm', function (cpm, pat) {
return pat._fast(cpm / 60 / 1);
});
/**
* Nudge a pattern to start earlier in time. Equivalent of Tidal's <~ operator
*
-4
View File
@@ -217,14 +217,10 @@ export function repl({
} catch (err) {
console.warn('injectPatternMethods: error:', err);
}
const cpm = register('cpm', function (cpm, pat) {
return pat._fast(cpm / 60 / scheduler.cps);
});
return evalScope({
all,
each,
hush,
cpm,
setCps,
setcps: setCps,
setCpm,
+63 -23
View File
@@ -1,5 +1,68 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`runs examples > example "" example index 0 1`] = `
[
"[ 0/1 → 1/4 | s:bd cps:0.5 ]",
"[ 1/4 → 1/2 | s:hh cps:0.5 ]",
"[ 1/2 → 3/4 | s:sd cps:0.5 ]",
"[ 3/4 → 1/1 | s:hh cps:0.5 ]",
"[ 1/1 → 5/4 | s:bd cps:0.5 ]",
"[ 5/4 → 3/2 | s:hh cps:0.5 ]",
"[ 3/2 → 7/4 | s:sd cps:0.5 ]",
"[ 7/4 → 2/1 | s:hh cps:0.5 ]",
"[ 2/1 → 9/4 | s:bd cps:0.5 ]",
"[ 9/4 → 5/2 | s:hh cps:0.5 ]",
"[ 5/2 → 11/4 | s:sd cps:0.5 ]",
"[ 11/4 → 3/1 | s:hh cps:0.5 ]",
"[ 3/1 → 13/4 | s:bd cps:0.5 ]",
"[ 13/4 → 7/2 | s:hh cps:0.5 ]",
"[ 7/2 → 15/4 | s:sd cps:0.5 ]",
"[ 15/4 → 4/1 | s:hh cps:0.5 ]",
]
`;
exports[`runs examples > example "" example index 0 2`] = `
[
"[ 0/1 → 1/4 | s:bd cpm:50 ]",
"[ 1/4 → 1/2 | s:hh cpm:57.6536686473018 ]",
"[ 1/2 → 3/4 | s:sd cpm:64.14213562373095 ]",
"[ 3/4 → 1/1 | s:hh cpm:68.47759065022574 ]",
"[ 1/1 → 5/4 | s:bd cpm:70 ]",
"[ 5/4 → 3/2 | s:hh cpm:68.47759065022574 ]",
"[ 3/2 → 7/4 | s:sd cpm:64.14213562373095 ]",
"[ 7/4 → 2/1 | s:hh cpm:57.6536686473018 ]",
"[ 2/1 → 9/4 | s:bd cpm:50 ]",
"[ 9/4 → 5/2 | s:hh cpm:42.34633135269821 ]",
"[ 5/2 → 11/4 | s:sd cpm:35.85786437626905 ]",
"[ 11/4 → 3/1 | s:hh cpm:31.52240934977427 ]",
"[ 3/1 → 13/4 | s:bd cpm:30 ]",
"[ 13/4 → 7/2 | s:hh cpm:31.522409349774268 ]",
"[ 7/2 → 15/4 | s:sd cpm:35.85786437626905 ]",
"[ 15/4 → 4/1 | s:hh cpm:42.34633135269819 ]",
]
`;
exports[`runs examples > example "" example index 1 1`] = `
[
"[ 0/1 → 1/4 | s:bd cps:1 ]",
"[ 1/4 → 1/2 | s:hh cps:1.1913417161825448 ]",
"[ 1/2 → 3/4 | s:sd cps:1.3535533905932737 ]",
"[ 3/4 → 1/1 | s:hh cps:1.4619397662556435 ]",
"[ 1/1 → 5/4 | s:bd cps:1.5 ]",
"[ 5/4 → 3/2 | s:hh cps:1.4619397662556435 ]",
"[ 3/2 → 7/4 | s:sd cps:1.3535533905932737 ]",
"[ 7/4 → 2/1 | s:hh cps:1.1913417161825448 ]",
"[ 2/1 → 9/4 | s:bd cps:1 ]",
"[ 9/4 → 5/2 | s:hh cps:0.8086582838174552 ]",
"[ 5/2 → 11/4 | s:sd cps:0.6464466094067263 ]",
"[ 11/4 → 3/1 | s:hh cps:0.5380602337443567 ]",
"[ 3/1 → 13/4 | s:bd cps:0.5 ]",
"[ 13/4 → 7/2 | s:hh cps:0.5380602337443567 ]",
"[ 7/2 → 15/4 | s:sd cps:0.6464466094067262 ]",
"[ 15/4 → 4/1 | s:hh cps:0.8086582838174547 ]",
]
`;
exports[`runs examples > example "_euclidRot" example index 0 1`] = `
[
"[ 0/1 → 1/5 | note:c3 ]",
@@ -2789,29 +2852,6 @@ exports[`runs examples > example "cosine" example index 0 1`] = `
]
`;
exports[`runs examples > example "cpm" example index 0 1`] = `
[
"[ 0/1 → 1/3 | s:hh ]",
"[ 0/1 → 2/3 | s:bd ]",
"[ 1/3 → 2/3 | s:hh ]",
"[ 2/3 → 1/1 | s:hh ]",
"[ 2/3 → 4/3 | s:sd ]",
"[ 1/1 → 4/3 | s:hh ]",
"[ 4/3 → 5/3 | s:hh ]",
"[ 4/3 → 2/1 | s:bd ]",
"[ 5/3 → 2/1 | s:hh ]",
"[ 2/1 → 7/3 | s:hh ]",
"[ 2/1 → 8/3 | s:sd ]",
"[ 7/3 → 8/3 | s:hh ]",
"[ 8/3 → 3/1 | s:hh ]",
"[ 8/3 → 10/3 | s:bd ]",
"[ 3/1 → 10/3 | s:hh ]",
"[ 10/3 → 11/3 | s:hh ]",
"[ 10/3 → 4/1 | s:sd ]",
"[ 11/3 → 4/1 | s:hh ]",
]
`;
exports[`runs examples > example "crush" example index 0 1`] = `
[
"[ 0/1 → 1/6 | s:hh crush:16 ]",