Merge branch 'main' into cycler

This commit is contained in:
Alex McLean
2025-10-01 11:58:19 +01:00
316 changed files with 16001 additions and 3789 deletions
@@ -1,169 +0,0 @@
---
// fetch all commits for just this page's path
type Props = {
path: string;
};
const { path } = Astro.props as Props;
const resolvedPath = `website/src/pages${path}.mdx`;
const url = `https://api.github.com/repos/tidalcycles/strudel/commits?path=${resolvedPath}`;
const commitsURL = `https://github.com/tidalcycles/strudel/commits/main/${resolvedPath}`;
type Commit = {
author: {
id: string;
login: string;
};
};
async function getCommits(url: string) {
try {
const token = import.meta.env.SNOWPACK_PUBLIC_GITHUB_TOKEN ?? 'hello';
if (!token) {
throw new Error('Cannot find "SNOWPACK_PUBLIC_GITHUB_TOKEN" used for escaping rate-limiting.');
}
const auth = `Basic ${Buffer.from(token, 'binary').toString('base64')}`;
const res = await fetch(url, {
method: 'GET',
headers: {
Authorization: auth,
'User-Agent': 'astro-docs/1.0',
},
});
const data = await res.json();
if (!res.ok) {
throw new Error(
`Request to fetch commits failed. Reason: ${res.statusText}
Message: ${data.message}`,
);
}
return data as Commit[];
} catch (e) {
console.warn(`[error] /src/components/AvatarList.astro
${(e as any)?.message ?? e}`);
return [] as Commit[];
}
}
function removeDups(arr: Commit[]) {
const map = new Map<string, Commit['author']>();
for (let item of arr) {
const author = item.author;
// Deduplicate based on author.id
//map.set(author.id, { login: author.login, id: author.id });
author && map.set(author.id, { login: author.login, id: author.id });
}
return [...map.values()];
}
const data = await getCommits(url);
const unique = removeDups(data);
const recentContributors = unique.slice(0, 3); // only show avatars for the 3 most recent contributors
const additionalContributors = unique.length - recentContributors.length; // list the rest of them as # of extra contributors
---
<!-- Thanks to @5t3ph for https://smolcss.dev/#smol-avatar-list! -->
<div class="contributors px-4 mb-8">
<ul class="avatar-list" style={`--avatar-count: ${recentContributors.length}`}>
{
recentContributors.map((item) => (
<li>
<a href={`https://github.com/${item.login}`}>
<img
alt={`Contributor ${item.login}`}
title={`Contributor ${item.login}`}
width="64"
height="64"
src={`https://avatars.githubusercontent.com/u/${item.id}`}
/>
</a>
</li>
))
}
</ul>
{
additionalContributors > 0 && (
<span>
<a href={commitsURL}>{`and ${additionalContributors} additional contributor${
additionalContributors > 1 ? 's' : ''
}.`}</a>
</span>
)
}
{unique.length === 0 && <a href={commitsURL}>Contributors</a>}
</div>
<style>
.avatar-list {
--avatar-size: 2.5rem;
--avatar-count: 3;
display: grid;
list-style: none;
/* Default to displaying most of the avatar to
enable easier access on touch devices, ensuring
the WCAG touch target size is met or exceeded */
grid-template-columns: repeat(var(--avatar-count), max(44px, calc(var(--avatar-size) / 1.15)));
/* `padding` matches added visual dimensions of
the `box-shadow` to help create a more accurate
computed component size */
padding: 0.08em;
font-size: var(--avatar-size);
}
@media (any-hover: hover) and (any-pointer: fine) {
.avatar-list {
/* We create 1 extra cell to enable the computed
width to match the final visual width */
grid-template-columns: repeat(calc(var(--avatar-count) + 1), calc(var(--avatar-size) / 1.75));
}
}
.avatar-list li {
width: var(--avatar-size);
height: var(--avatar-size);
}
.avatar-list li:hover ~ li a,
.avatar-list li:focus-within ~ li a {
transform: translateX(33%);
}
.avatar-list img,
.avatar-list a {
display: block;
border-radius: 50%;
}
.avatar-list a {
transition: transform 180ms ease-in-out;
}
.avatar-list img {
width: 100%;
height: 100%;
object-fit: cover;
background-color: #fff;
box-shadow: 0 0 0 0.05em #fff, 0 0 0 0.08em rgba(0, 0, 0, 0.15);
}
.avatar-list a:focus {
outline: 2px solid transparent;
/* Double-layer trick to work for dark and light backgrounds */
box-shadow: 0 0 0 0.08em var(--theme-accent), 0 0 0 0.12em white;
}
.contributors {
display: flex;
align-items: center;
}
.contributors > * + * {
margin-left: 0.75rem;
}
</style>
+1 -1
View File
@@ -82,7 +82,7 @@ export default function Search() {
appId={ALGOLIA.appId}
apiKey={ALGOLIA.apiKey}
getMissingResultsUrl={({ query }) => {
return `https://github.com/tidalcycles/strudel/issues/new?title=Missing doc for ${query}`;
return `https://codeberg.org/uzu/strudel/issues/new?title=Missing%20doc%20for${encodeURIComponent(query)}`;
}}
transformItems={(items) => {
return items.map((item) => {
@@ -18,5 +18,4 @@ currentPage = currentPage.endsWith('/') ? currentPage.slice(0, -1) : currentPage
<nav aria-labelledby="grid-right" class="w-64 text-foreground">
<TableOfContents client:media="(min-width: 50em)" headings={headings} currentPage={currentPage} />
<MoreMenu editHref={githubEditUrl} />
<!-- <AvatarList path={currentPage} /> -->
</nav>
+2 -2
View File
@@ -9,11 +9,11 @@ import UserFacingErrorMessage from '@src/repl/components/UserFacingErrorMessage'
// }
export default function UdelsEditor(Props) {
const { context } = Props;
const { context, ...editorProps } = Props;
const { containerRef, editorRef, error, init, pending, started, handleTogglePlay } = context;
return (
<div className={'h-full flex w-full flex-col relative'}>
<div className={'h-full flex w-full flex-col relative'} {...editorProps}>
<Loader active={pending} />
<BigPlayButton started={started} handleTogglePlay={handleTogglePlay} />
<div className="grow flex relative overflow-hidden">
+1 -1
View File
@@ -4,7 +4,7 @@ export default function UdelsHeader(Props) {
const { numWindows, setNumWindows } = Props;
return (
<header id="header" className="flex text-white z-[100] text-lg select-none bg-neutral-900">
<header id="header" className="flex text-white z-[100] text-lg select-none bg-neutral-800">
<div className="px-4 items-center gap-2 flex space-x-2 md:pt-0 select-none">
<h1 onClick={() => {}} className={'text-l cursor-pointer flex gap-4'}>
<div className={'mt-[1px] cursor-pointer'}>🌀</div>
+5 -2
View File
@@ -28,7 +28,7 @@ export const KNOWN_LANGUAGES = {
} as const;
export const KNOWN_LANGUAGE_CODES = Object.values(KNOWN_LANGUAGES);
export const GITHUB_EDIT_URL = `https://github.com/tidalcycles/strudel/tree/main/website`;
export const GITHUB_EDIT_URL = `https://codeberg.org/uzu/strudel/src/branch/main/website`;
export const COMMUNITY_INVITE_URL = `https://discord.com/invite/HGEdXmRkzT`;
@@ -58,7 +58,7 @@ export const SIDEBAR: Sidebar = {
{ text: 'What is Strudel?', link: 'workshop/getting-started' },
{ text: 'Showcase', link: 'intro/showcase' },
{ text: 'Blog', link: 'blog' },
{ text: 'Community Bakery', link: 'bakery' },
/* { text: 'Community Bakery', link: 'bakery' }, */
],
Workshop: [
// { text: 'Getting Started', link: 'workshop/getting-started' },
@@ -81,9 +81,11 @@ export const SIDEBAR: Sidebar = {
{ text: 'Visual Feedback', link: 'learn/visual-feedback' },
{ text: 'Offline', link: 'learn/pwa' },
{ text: 'Patterns', link: 'technical-manual/patterns' },
{ text: 'Mondo Notation', link: 'learn/mondo-notation' },
{ text: 'Music metadata', link: 'learn/metadata' },
{ text: 'CSound', link: 'learn/csound' },
{ text: 'Hydra', link: 'learn/hydra' },
{ text: 'Input Devices', link: 'learn/input-devices' },
{ text: 'Device Motion', link: 'learn/devicemotion' },
],
'Pattern Functions': [
@@ -101,6 +103,7 @@ export const SIDEBAR: Sidebar = {
Understand: [
{ text: 'Coding syntax', link: 'learn/code' },
{ text: 'Pitch', link: 'understand/pitch' },
{ text: 'Xen Harmonic Functions', link: 'learn/xen' },
{ text: 'Cycles', link: 'understand/cycles' },
{ text: 'Voicings', link: 'understand/voicings' },
{ text: 'Pattern Alignment', link: 'technical-manual/alignment' },
@@ -8,33 +8,33 @@ author: froos
## What's Changed
- Most work done as [commits to main](https://github.com/tidalcycles/strudel/commits/2a0d8c3f77ff7b34e82602e2d02400707f367316)
- repl + reify functions by @felixroos in https://github.com/tidalcycles/strudel/pull/2
- Fix path by @yaxu in https://github.com/tidalcycles/strudel/pull/3
- update readme for local dev by @kindohm in https://github.com/tidalcycles/strudel/pull/4
- Patternify all the things by @yaxu in https://github.com/tidalcycles/strudel/pull/5
- krill parser + improved repl by @felixroos in https://github.com/tidalcycles/strudel/pull/6
- fixed editor crash by @felixroos in https://github.com/tidalcycles/strudel/pull/7
- timeCat by @yaxu in https://github.com/tidalcycles/strudel/pull/8
- Bugfix every, and create more top level functions by @yaxu in https://github.com/tidalcycles/strudel/pull/9
- Failing test for `when` WIP by @yaxu in https://github.com/tidalcycles/strudel/pull/10
- Added mask() and struct() by @yaxu in https://github.com/tidalcycles/strudel/pull/11
- Add continuous signals (sine, cosine, saw, etc) by @yaxu in https://github.com/tidalcycles/strudel/pull/13
- add apply and layer, and missing div/mul methods by @yaxu in https://github.com/tidalcycles/strudel/pull/15
- higher latencyHint by @felixroos in https://github.com/tidalcycles/strudel/pull/16
- test: 📦 Add missing dependency and a CI check, to prevent oversights ;p by @puria in https://github.com/tidalcycles/strudel/pull/17
- fix: 💄 Enhance visualisation of the Tutorial on mobile by @puria in https://github.com/tidalcycles/strudel/pull/19
- Stateful queries and events (WIP) by @yaxu in https://github.com/tidalcycles/strudel/pull/14
- Fix resolveState by @yaxu in https://github.com/tidalcycles/strudel/pull/22
- added \_asNumber + interpret numbers as midi by @felixroos in https://github.com/tidalcycles/strudel/pull/21
- Update package.json by @ChiakiUehira in https://github.com/tidalcycles/strudel/pull/23
- packaging by @felixroos in https://github.com/tidalcycles/strudel/pull/24
- Most work done as [commits to main](https://codeberg.org/uzu/strudel/commit/2a0d8c3f77ff7b34e82602e2d02400707f367316)
- repl + reify functions by @felixroos in https://codeberg.org/uzu/strudel/pulls/2
- Fix path by @yaxu in https://codeberg.org/uzu/strudel/pulls/3
- update readme for local dev by @kindohm in https://codeberg.org/uzu/strudel/pulls/4
- Patternify all the things by @yaxu in https://codeberg.org/uzu/strudel/pulls/5
- krill parser + improved repl by @felixroos in https://codeberg.org/uzu/strudel/pulls/6
- fixed editor crash by @felixroos in https://codeberg.org/uzu/strudel/pulls/7
- timeCat by @yaxu in https://codeberg.org/uzu/strudel/pulls/8
- Bugfix every, and create more top level functions by @yaxu in https://codeberg.org/uzu/strudel/pulls/9
- Failing test for `when` WIP by @yaxu in https://codeberg.org/uzu/strudel/pulls/10
- Added mask() and struct() by @yaxu in https://codeberg.org/uzu/strudel/pulls/11
- Add continuous signals (sine, cosine, saw, etc) by @yaxu in https://codeberg.org/uzu/strudel/pulls/13
- add apply and layer, and missing div/mul methods by @yaxu in https://codeberg.org/uzu/strudel/pulls/15
- higher latencyHint by @felixroos in https://codeberg.org/uzu/strudel/pulls/16
- test: 📦 Add missing dependency and a CI check, to prevent oversights ;p by @puria in https://codeberg.org/uzu/strudel/pulls/17
- fix: 💄 Enhance visualisation of the Tutorial on mobile by @puria in https://codeberg.org/uzu/strudel/pulls/19
- Stateful queries and events (WIP) by @yaxu in https://codeberg.org/uzu/strudel/pulls/14
- Fix resolveState by @yaxu in https://codeberg.org/uzu/strudel/pulls/22
- added \_asNumber + interpret numbers as midi by @felixroos in https://codeberg.org/uzu/strudel/pulls/21
- Update package.json by @ChiakiUehira in https://codeberg.org/uzu/strudel/pulls/23
- packaging by @felixroos in https://codeberg.org/uzu/strudel/pulls/24
## New Contributors
- @felixroos made their first contribution in https://github.com/tidalcycles/strudel/pull/2
- @kindohm made their first contribution in https://github.com/tidalcycles/strudel/pull/4
- @puria made their first contribution in https://github.com/tidalcycles/strudel/pull/17
- @ChiakiUehira made their first contribution in https://github.com/tidalcycles/strudel/pull/23
- @felixroos made their first contribution in https://codeberg.org/uzu/strudel/pulls/2
- @kindohm made their first contribution in https://codeberg.org/uzu/strudel/pulls/4
- @puria made their first contribution in https://codeberg.org/uzu/strudel/pulls/17
- @ChiakiUehira made their first contribution in https://codeberg.org/uzu/strudel/pulls/23
**Full Changelog**: https://github.com/tidalcycles/strudel/commits/2a0d8c3f77ff7b34e82602e2d02400707f367316
**Full Changelog**: https://codeberg.org/uzu/strudel/commit/2a0d8c3f77ff7b34e82602e2d02400707f367316
@@ -7,47 +7,47 @@ author: froos
## What's Changed
- Add chunk, chunkBack and iterBack by @yaxu in https://github.com/tidalcycles/strudel/pull/25
- Update tutorial.mdx by @bwagner in https://github.com/tidalcycles/strudel/pull/37
- Update tutorial.mdx by @bwagner in https://github.com/tidalcycles/strudel/pull/38
- Compose by @felixroos in https://github.com/tidalcycles/strudel/pull/40
- Fix polymeter by @yaxu in https://github.com/tidalcycles/strudel/pull/44
- First run at squeezeBind, ref #32 by @yaxu in https://github.com/tidalcycles/strudel/pull/48
- Implement `chop()` by @yaxu in https://github.com/tidalcycles/strudel/pull/50
- OSC and SuperDirt support by @yaxu in https://github.com/tidalcycles/strudel/pull/27
- More functions by @yaxu in https://github.com/tidalcycles/strudel/pull/56
- More functions by @yaxu in https://github.com/tidalcycles/strudel/pull/61
- Separate out strudel.mjs, make index.mjs aggregate module by @yaxu in https://github.com/tidalcycles/strudel/pull/62
- Speech output by @felixroos in https://github.com/tidalcycles/strudel/pull/67
- use new fixed version of osc-js package by @felixroos in https://github.com/tidalcycles/strudel/pull/68
- First effort at rand() by @yaxu in https://github.com/tidalcycles/strudel/pull/69
- More randomness, fix `rand`, and add `brand`, `irand` and `choose` by @yaxu in https://github.com/tidalcycles/strudel/pull/70
- webaudio package by @felixroos in https://github.com/tidalcycles/strudel/pull/26
- Port `perlin` noise, `rangex`, and `palindrome` by @yaxu in https://github.com/tidalcycles/strudel/pull/73
- More random functions by @yaxu in https://github.com/tidalcycles/strudel/pull/74
- Try to fix appLeft / appRight by @yaxu in https://github.com/tidalcycles/strudel/pull/75
- Basic webserial support by @yaxu in https://github.com/tidalcycles/strudel/pull/80
- Webaudio in REPL by @felixroos in https://github.com/tidalcycles/strudel/pull/77
- add `striate()` by @yaxu in https://github.com/tidalcycles/strudel/pull/76
- Tidy up a couple of old files by @mindofmatthew in https://github.com/tidalcycles/strudel/pull/84
- Add pattern composers, implements #82 by @yaxu in https://github.com/tidalcycles/strudel/pull/83
- Fiddles with cat/stack by @yaxu in https://github.com/tidalcycles/strudel/pull/90
- Paper by @felixroos in https://github.com/tidalcycles/strudel/pull/98
- Change to Affero GPL by @yaxu in https://github.com/tidalcycles/strudel/pull/101
- Work on Codemirror 6 highlighting by @mindofmatthew in https://github.com/tidalcycles/strudel/pull/102
- Codemirror 6 by @felixroos in https://github.com/tidalcycles/strudel/pull/97
- Tune tests by @felixroos in https://github.com/tidalcycles/strudel/pull/104
- /embed package: web component for repl by @felixroos in https://github.com/tidalcycles/strudel/pull/106
- Reset, Restart and other composers by @felixroos in https://github.com/tidalcycles/strudel/pull/88
- Embed style by @felixroos in https://github.com/tidalcycles/strudel/pull/109
- In source doc by @yaxu in https://github.com/tidalcycles/strudel/pull/105
- `.brak()`, `.inside()` and `.outside()` by @yaxu in https://github.com/tidalcycles/strudel/pull/112
- loopAt by @yaxu in https://github.com/tidalcycles/strudel/pull/114
- Osc timing improvements by @yaxu in https://github.com/tidalcycles/strudel/pull/113
- Add chunk, chunkBack and iterBack by @yaxu in https://codeberg.org/uzu/strudel/pulls/25
- Update tutorial.mdx by @bwagner in https://codeberg.org/uzu/strudel/pulls/37
- Update tutorial.mdx by @bwagner in https://codeberg.org/uzu/strudel/pulls/38
- Compose by @felixroos in https://codeberg.org/uzu/strudel/pulls/40
- Fix polymeter by @yaxu in https://codeberg.org/uzu/strudel/pulls/44
- First run at squeezeBind, ref #32 by @yaxu in https://codeberg.org/uzu/strudel/pulls/48
- Implement `chop()` by @yaxu in https://codeberg.org/uzu/strudel/pulls/50
- OSC and SuperDirt support by @yaxu in https://codeberg.org/uzu/strudel/pulls/27
- More functions by @yaxu in https://codeberg.org/uzu/strudel/pulls/56
- More functions by @yaxu in https://codeberg.org/uzu/strudel/pulls/61
- Separate out strudel.mjs, make index.mjs aggregate module by @yaxu in https://codeberg.org/uzu/strudel/pulls/62
- Speech output by @felixroos in https://codeberg.org/uzu/strudel/pulls/67
- use new fixed version of osc-js package by @felixroos in https://codeberg.org/uzu/strudel/pulls/68
- First effort at rand() by @yaxu in https://codeberg.org/uzu/strudel/pulls/69
- More randomness, fix `rand`, and add `brand`, `irand` and `choose` by @yaxu in https://codeberg.org/uzu/strudel/pulls/70
- webaudio package by @felixroos in https://codeberg.org/uzu/strudel/pulls/26
- Port `perlin` noise, `rangex`, and `palindrome` by @yaxu in https://codeberg.org/uzu/strudel/pulls/73
- More random functions by @yaxu in https://codeberg.org/uzu/strudel/pulls/74
- Try to fix appLeft / appRight by @yaxu in https://codeberg.org/uzu/strudel/pulls/75
- Basic webserial support by @yaxu in https://codeberg.org/uzu/strudel/pulls/80
- Webaudio in REPL by @felixroos in https://codeberg.org/uzu/strudel/pulls/77
- add `striate()` by @yaxu in https://codeberg.org/uzu/strudel/pulls/76
- Tidy up a couple of old files by @mindofmatthew in https://codeberg.org/uzu/strudel/pulls/84
- Add pattern composers, implements #82 by @yaxu in https://codeberg.org/uzu/strudel/pulls/83
- Fiddles with cat/stack by @yaxu in https://codeberg.org/uzu/strudel/pulls/90
- Paper by @felixroos in https://codeberg.org/uzu/strudel/pulls/98
- Change to Affero GPL by @yaxu in https://codeberg.org/uzu/strudel/pulls/101
- Work on Codemirror 6 highlighting by @mindofmatthew in https://codeberg.org/uzu/strudel/pulls/102
- Codemirror 6 by @felixroos in https://codeberg.org/uzu/strudel/pulls/97
- Tune tests by @felixroos in https://codeberg.org/uzu/strudel/pulls/104
- /embed package: web component for repl by @felixroos in https://codeberg.org/uzu/strudel/pulls/106
- Reset, Restart and other composers by @felixroos in https://codeberg.org/uzu/strudel/pulls/88
- Embed style by @felixroos in https://codeberg.org/uzu/strudel/pulls/109
- In source doc by @yaxu in https://codeberg.org/uzu/strudel/pulls/105
- `.brak()`, `.inside()` and `.outside()` by @yaxu in https://codeberg.org/uzu/strudel/pulls/112
- loopAt by @yaxu in https://codeberg.org/uzu/strudel/pulls/114
- Osc timing improvements by @yaxu in https://codeberg.org/uzu/strudel/pulls/113
## New Contributors
- @bwagner made their first contribution in https://github.com/tidalcycles/strudel/pull/37
- @mindofmatthew made their first contribution in https://github.com/tidalcycles/strudel/pull/84
- @bwagner made their first contribution in https://codeberg.org/uzu/strudel/pulls/37
- @mindofmatthew made their first contribution in https://codeberg.org/uzu/strudel/pulls/84
**Full Changelog**: https://github.com/tidalcycles/strudel/compare/v0.0.2...@strudel.cycles/core@0.1.0
**Full Changelog**: https://codeberg.org/uzu/strudel/compare/v0.0.2...@strudel.cycles/core@0.1.0
@@ -8,59 +8,59 @@ author: froos
## What's Changed
- Add chunk, chunkBack and iterBack by @yaxu in https://github.com/tidalcycles/strudel/pull/25
- Update tutorial.mdx by @bwagner in https://github.com/tidalcycles/strudel/pull/37
- Update tutorial.mdx by @bwagner in https://github.com/tidalcycles/strudel/pull/38
- Compose by @felixroos in https://github.com/tidalcycles/strudel/pull/40
- Fix polymeter by @yaxu in https://github.com/tidalcycles/strudel/pull/44
- First run at squeezeBind, ref #32 by @yaxu in https://github.com/tidalcycles/strudel/pull/48
- Implement `chop()` by @yaxu in https://github.com/tidalcycles/strudel/pull/50
- OSC and SuperDirt support by @yaxu in https://github.com/tidalcycles/strudel/pull/27
- More functions by @yaxu in https://github.com/tidalcycles/strudel/pull/56
- More functions by @yaxu in https://github.com/tidalcycles/strudel/pull/61
- Separate out strudel.mjs, make index.mjs aggregate module by @yaxu in https://github.com/tidalcycles/strudel/pull/62
- Speech output by @felixroos in https://github.com/tidalcycles/strudel/pull/67
- use new fixed version of osc-js package by @felixroos in https://github.com/tidalcycles/strudel/pull/68
- First effort at rand() by @yaxu in https://github.com/tidalcycles/strudel/pull/69
- More randomness, fix `rand`, and add `brand`, `irand` and `choose` by @yaxu in https://github.com/tidalcycles/strudel/pull/70
- webaudio package by @felixroos in https://github.com/tidalcycles/strudel/pull/26
- Port `perlin` noise, `rangex`, and `palindrome` by @yaxu in https://github.com/tidalcycles/strudel/pull/73
- More random functions by @yaxu in https://github.com/tidalcycles/strudel/pull/74
- Try to fix appLeft / appRight by @yaxu in https://github.com/tidalcycles/strudel/pull/75
- Basic webserial support by @yaxu in https://github.com/tidalcycles/strudel/pull/80
- Webaudio in REPL by @felixroos in https://github.com/tidalcycles/strudel/pull/77
- add `striate()` by @yaxu in https://github.com/tidalcycles/strudel/pull/76
- Tidy up a couple of old files by @mindofmatthew in https://github.com/tidalcycles/strudel/pull/84
- Add pattern composers, implements #82 by @yaxu in https://github.com/tidalcycles/strudel/pull/83
- Fiddles with cat/stack by @yaxu in https://github.com/tidalcycles/strudel/pull/90
- Paper by @felixroos in https://github.com/tidalcycles/strudel/pull/98
- Change to Affero GPL by @yaxu in https://github.com/tidalcycles/strudel/pull/101
- Work on Codemirror 6 highlighting by @mindofmatthew in https://github.com/tidalcycles/strudel/pull/102
- Codemirror 6 by @felixroos in https://github.com/tidalcycles/strudel/pull/97
- Tune tests by @felixroos in https://github.com/tidalcycles/strudel/pull/104
- /embed package: web component for repl by @felixroos in https://github.com/tidalcycles/strudel/pull/106
- Reset, Restart and other composers by @felixroos in https://github.com/tidalcycles/strudel/pull/88
- Embed style by @felixroos in https://github.com/tidalcycles/strudel/pull/109
- In source doc by @yaxu in https://github.com/tidalcycles/strudel/pull/105
- `.brak()`, `.inside()` and `.outside()` by @yaxu in https://github.com/tidalcycles/strudel/pull/112
- loopAt by @yaxu in https://github.com/tidalcycles/strudel/pull/114
- Osc timing improvements by @yaxu in https://github.com/tidalcycles/strudel/pull/113
- react package + vite build by @felixroos in https://github.com/tidalcycles/strudel/pull/116
- In source doc by @felixroos in https://github.com/tidalcycles/strudel/pull/117
- fix: #108 by @felixroos in https://github.com/tidalcycles/strudel/pull/123
- fix: #122 ctrl enter would add newline by @felixroos in https://github.com/tidalcycles/strudel/pull/124
- Webdirt by @felixroos in https://github.com/tidalcycles/strudel/pull/121
- Fix link to contributing to tutorial docs by @stephendwolff in https://github.com/tidalcycles/strudel/pull/129
- Pianoroll enhancements by @felixroos in https://github.com/tidalcycles/strudel/pull/131
- add createParam + createParams by @felixroos in https://github.com/tidalcycles/strudel/pull/110
- remove cycle + delta from onTrigger by @felixroos in https://github.com/tidalcycles/strudel/pull/135
- Scheduler improvements by @felixroos in https://github.com/tidalcycles/strudel/pull/134
- add onTrigger helper by @felixroos in https://github.com/tidalcycles/strudel/pull/136
- Add chunk, chunkBack and iterBack by @yaxu in https://codeberg.org/uzu/strudel/pulls/25
- Update tutorial.mdx by @bwagner in https://codeberg.org/uzu/strudel/pulls/37
- Update tutorial.mdx by @bwagner in https://codeberg.org/uzu/strudel/pulls/38
- Compose by @felixroos in https://codeberg.org/uzu/strudel/pulls/40
- Fix polymeter by @yaxu in https://codeberg.org/uzu/strudel/pulls/44
- First run at squeezeBind, ref #32 by @yaxu in https://codeberg.org/uzu/strudel/pulls/48
- Implement `chop()` by @yaxu in https://codeberg.org/uzu/strudel/pulls/50
- OSC and SuperDirt support by @yaxu in https://codeberg.org/uzu/strudel/pulls/27
- More functions by @yaxu in https://codeberg.org/uzu/strudel/pulls/56
- More functions by @yaxu in https://codeberg.org/uzu/strudel/pulls/61
- Separate out strudel.mjs, make index.mjs aggregate module by @yaxu in https://codeberg.org/uzu/strudel/pulls/62
- Speech output by @felixroos in https://codeberg.org/uzu/strudel/pulls/67
- use new fixed version of osc-js package by @felixroos in https://codeberg.org/uzu/strudel/pulls/68
- First effort at rand() by @yaxu in https://codeberg.org/uzu/strudel/pulls/69
- More randomness, fix `rand`, and add `brand`, `irand` and `choose` by @yaxu in https://codeberg.org/uzu/strudel/pulls/70
- webaudio package by @felixroos in https://codeberg.org/uzu/strudel/pulls/26
- Port `perlin` noise, `rangex`, and `palindrome` by @yaxu in https://codeberg.org/uzu/strudel/pulls/73
- More random functions by @yaxu in https://codeberg.org/uzu/strudel/pulls/74
- Try to fix appLeft / appRight by @yaxu in https://codeberg.org/uzu/strudel/pulls/75
- Basic webserial support by @yaxu in https://codeberg.org/uzu/strudel/pulls/80
- Webaudio in REPL by @felixroos in https://codeberg.org/uzu/strudel/pulls/77
- add `striate()` by @yaxu in https://codeberg.org/uzu/strudel/pulls/76
- Tidy up a couple of old files by @mindofmatthew in https://codeberg.org/uzu/strudel/pulls/84
- Add pattern composers, implements #82 by @yaxu in https://codeberg.org/uzu/strudel/pulls/83
- Fiddles with cat/stack by @yaxu in https://codeberg.org/uzu/strudel/pulls/90
- Paper by @felixroos in https://codeberg.org/uzu/strudel/pulls/98
- Change to Affero GPL by @yaxu in https://codeberg.org/uzu/strudel/pulls/101
- Work on Codemirror 6 highlighting by @mindofmatthew in https://codeberg.org/uzu/strudel/pulls/102
- Codemirror 6 by @felixroos in https://codeberg.org/uzu/strudel/pulls/97
- Tune tests by @felixroos in https://codeberg.org/uzu/strudel/pulls/104
- /embed package: web component for repl by @felixroos in https://codeberg.org/uzu/strudel/pulls/106
- Reset, Restart and other composers by @felixroos in https://codeberg.org/uzu/strudel/pulls/88
- Embed style by @felixroos in https://codeberg.org/uzu/strudel/pulls/109
- In source doc by @yaxu in https://codeberg.org/uzu/strudel/pulls/105
- `.brak()`, `.inside()` and `.outside()` by @yaxu in https://codeberg.org/uzu/strudel/pulls/112
- loopAt by @yaxu in https://codeberg.org/uzu/strudel/pulls/114
- Osc timing improvements by @yaxu in https://codeberg.org/uzu/strudel/pulls/113
- react package + vite build by @felixroos in https://codeberg.org/uzu/strudel/pulls/116
- In source doc by @felixroos in https://codeberg.org/uzu/strudel/pulls/117
- fix: #108 by @felixroos in https://codeberg.org/uzu/strudel/pulls/123
- fix: #122 ctrl enter would add newline by @felixroos in https://codeberg.org/uzu/strudel/pulls/124
- Webdirt by @felixroos in https://codeberg.org/uzu/strudel/pulls/121
- Fix link to contributing to tutorial docs by @stephendwolff in https://codeberg.org/uzu/strudel/pulls/129
- Pianoroll enhancements by @felixroos in https://codeberg.org/uzu/strudel/pulls/131
- add createParam + createParams by @felixroos in https://codeberg.org/uzu/strudel/pulls/110
- remove cycle + delta from onTrigger by @felixroos in https://codeberg.org/uzu/strudel/pulls/135
- Scheduler improvements by @felixroos in https://codeberg.org/uzu/strudel/pulls/134
- add onTrigger helper by @felixroos in https://codeberg.org/uzu/strudel/pulls/136
## New Contributors
- @bwagner made their first contribution in https://github.com/tidalcycles/strudel/pull/37
- @mindofmatthew made their first contribution in https://github.com/tidalcycles/strudel/pull/84
- @stephendwolff made their first contribution in https://github.com/tidalcycles/strudel/pull/129
- @bwagner made their first contribution in https://codeberg.org/uzu/strudel/pulls/37
- @mindofmatthew made their first contribution in https://codeberg.org/uzu/strudel/pulls/84
- @stephendwolff made their first contribution in https://codeberg.org/uzu/strudel/pulls/129
**Full Changelog**: https://github.com/tidalcycles/strudel/compare/v0.0.2...v0.0.3
**Full Changelog**: https://codeberg.org/uzu/strudel/compare/v0.0.2...v0.0.3
@@ -8,38 +8,38 @@ author: froos
## What's Changed
- Webaudio rewrite by @felixroos in https://github.com/tidalcycles/strudel/pull/138
- Fix createParam() by @yaxu in https://github.com/tidalcycles/strudel/pull/140
- Soundfont Support by @felixroos in https://github.com/tidalcycles/strudel/pull/139
- Serial twiddles by @yaxu in https://github.com/tidalcycles/strudel/pull/141
- Pianoroll Object Support by @felixroos in https://github.com/tidalcycles/strudel/pull/142
- flash effect on ctrl enter by @felixroos in https://github.com/tidalcycles/strudel/pull/144
- can now generate short link for sharing by @felixroos in https://github.com/tidalcycles/strudel/pull/146
- Sampler optimizations and more by @felixroos in https://github.com/tidalcycles/strudel/pull/148
- Final update to demo.pdf by @yaxu in https://github.com/tidalcycles/strudel/pull/151
- add webdirt drum samples to prebake for general availability by @larkob in https://github.com/tidalcycles/strudel/pull/150
- update to tutorial documentation by @larkob in https://github.com/tidalcycles/strudel/pull/162
- add chooseInWith/chooseCycles by @yaxu in https://github.com/tidalcycles/strudel/pull/166
- fix: jsdoc comments by @felixroos in https://github.com/tidalcycles/strudel/pull/169
- Pianoroll fixes by @felixroos in https://github.com/tidalcycles/strudel/pull/163
- Talk fixes by @felixroos in https://github.com/tidalcycles/strudel/pull/164
- Amend shapeshifter to allow use of dynamic import by @debrisapron in https://github.com/tidalcycles/strudel/pull/171
- add more shapeshifter flags by @felixroos in https://github.com/tidalcycles/strudel/pull/99
- Replace react-codemirror6 with @uiw/react-codemirror by @felixroos in https://github.com/tidalcycles/strudel/pull/173
- fix some annoying bugs by @felixroos in https://github.com/tidalcycles/strudel/pull/177
- incorporate elements of randomness to the mini notation by @bpow in https://github.com/tidalcycles/strudel/pull/165
- replace mocha with vitest by @felixroos in https://github.com/tidalcycles/strudel/pull/175
- scheduler improvements by @felixroos in https://github.com/tidalcycles/strudel/pull/181
- Fix codemirror bug by @felixroos in https://github.com/tidalcycles/strudel/pull/186
- wait for prebake to finish before evaluating by @felixroos in https://github.com/tidalcycles/strudel/pull/189
- fix regression: old way of setting frequencies was broken by @felixroos in https://github.com/tidalcycles/strudel/pull/190
- Soundfont file support by @felixroos in https://github.com/tidalcycles/strudel/pull/183
- change "stride"/"offset" of successive degradeBy/chooseIn by @bpow in https://github.com/tidalcycles/strudel/pull/185
- Webaudio rewrite by @felixroos in https://codeberg.org/uzu/strudel/pulls/138
- Fix createParam() by @yaxu in https://codeberg.org/uzu/strudel/pulls/140
- Soundfont Support by @felixroos in https://codeberg.org/uzu/strudel/pulls/139
- Serial twiddles by @yaxu in https://codeberg.org/uzu/strudel/pulls/141
- Pianoroll Object Support by @felixroos in https://codeberg.org/uzu/strudel/pulls/142
- flash effect on ctrl enter by @felixroos in https://codeberg.org/uzu/strudel/pulls/144
- can now generate short link for sharing by @felixroos in https://codeberg.org/uzu/strudel/pulls/146
- Sampler optimizations and more by @felixroos in https://codeberg.org/uzu/strudel/pulls/148
- Final update to demo.pdf by @yaxu in https://codeberg.org/uzu/strudel/pulls/151
- add webdirt drum samples to prebake for general availability by @larkob in https://codeberg.org/uzu/strudel/pulls/150
- update to tutorial documentation by @larkob in https://codeberg.org/uzu/strudel/pulls/162
- add chooseInWith/chooseCycles by @yaxu in https://codeberg.org/uzu/strudel/pulls/166
- fix: jsdoc comments by @felixroos in https://codeberg.org/uzu/strudel/pulls/169
- Pianoroll fixes by @felixroos in https://codeberg.org/uzu/strudel/pulls/163
- Talk fixes by @felixroos in https://codeberg.org/uzu/strudel/pulls/164
- Amend shapeshifter to allow use of dynamic import by @debrisapron in https://codeberg.org/uzu/strudel/pulls/171
- add more shapeshifter flags by @felixroos in https://codeberg.org/uzu/strudel/pulls/99
- Replace react-codemirror6 with @uiw/react-codemirror by @felixroos in https://codeberg.org/uzu/strudel/pulls/173
- fix some annoying bugs by @felixroos in https://codeberg.org/uzu/strudel/pulls/177
- incorporate elements of randomness to the mini notation by @bpow in https://codeberg.org/uzu/strudel/pulls/165
- replace mocha with vitest by @felixroos in https://codeberg.org/uzu/strudel/pulls/175
- scheduler improvements by @felixroos in https://codeberg.org/uzu/strudel/pulls/181
- Fix codemirror bug by @felixroos in https://codeberg.org/uzu/strudel/pulls/186
- wait for prebake to finish before evaluating by @felixroos in https://codeberg.org/uzu/strudel/pulls/189
- fix regression: old way of setting frequencies was broken by @felixroos in https://codeberg.org/uzu/strudel/pulls/190
- Soundfont file support by @felixroos in https://codeberg.org/uzu/strudel/pulls/183
- change "stride"/"offset" of successive degradeBy/chooseIn by @bpow in https://codeberg.org/uzu/strudel/pulls/185
## New Contributors
- @larkob made their first contribution in https://github.com/tidalcycles/strudel/pull/150
- @debrisapron made their first contribution in https://github.com/tidalcycles/strudel/pull/171
- @bpow made their first contribution in https://github.com/tidalcycles/strudel/pull/165
- @larkob made their first contribution in https://codeberg.org/uzu/strudel/pulls/150
- @debrisapron made their first contribution in https://codeberg.org/uzu/strudel/pulls/171
- @bpow made their first contribution in https://codeberg.org/uzu/strudel/pulls/165
**Full Changelog**: https://github.com/tidalcycles/strudel/compare/v0.0.3...v0.0.4
**Full Changelog**: https://codeberg.org/uzu/strudel/compare/v0.0.3...v0.0.4
@@ -22,44 +22,44 @@ author: froos
## What's Changed
- Fix numbers in sampler by @felixroos in https://github.com/tidalcycles/strudel/pull/196
- document random functions by @felixroos in https://github.com/tidalcycles/strudel/pull/199
- add rollup-plugin-visualizer to build by @felixroos in https://github.com/tidalcycles/strudel/pull/200
- add vowel to .out by @felixroos in https://github.com/tidalcycles/strudel/pull/201
- Coarse crush shape by @felixroos in https://github.com/tidalcycles/strudel/pull/205
- Webaudio guide by @felixroos in https://github.com/tidalcycles/strudel/pull/207
- Even more docs by @felixroos in https://github.com/tidalcycles/strudel/pull/212
- Just another docs PR by @felixroos in https://github.com/tidalcycles/strudel/pull/215
- sampler features + fixes by @felixroos in https://github.com/tidalcycles/strudel/pull/217
- samples now have envelopes by @felixroos in https://github.com/tidalcycles/strudel/pull/218
- encapsulate webaudio output by @felixroos in https://github.com/tidalcycles/strudel/pull/219
- Fix squeeze join by @yaxu in https://github.com/tidalcycles/strudel/pull/220
- Feedback Delay by @felixroos in https://github.com/tidalcycles/strudel/pull/213
- support negative speeds by @felixroos in https://github.com/tidalcycles/strudel/pull/222
- focus tweak for squeezeJoin - another go at fixing #216 by @yaxu in https://github.com/tidalcycles/strudel/pull/221
- Reverb by @felixroos in https://github.com/tidalcycles/strudel/pull/224
- fix fastgap for events that go across cycle boundaries by @yaxu in https://github.com/tidalcycles/strudel/pull/225
- Core util tests by @mystery-house in https://github.com/tidalcycles/strudel/pull/226
- Refactor tunes away from tone by @felixroos in https://github.com/tidalcycles/strudel/pull/230
- Just another docs branch by @felixroos in https://github.com/tidalcycles/strudel/pull/228
- Patternify range by @yaxu in https://github.com/tidalcycles/strudel/pull/231
- Out by default by @felixroos in https://github.com/tidalcycles/strudel/pull/232
- Fix zero length queries WIP by @yaxu in https://github.com/tidalcycles/strudel/pull/234
- add vcsl sample library by @felixroos in https://github.com/tidalcycles/strudel/pull/235
- fx on stereo speakers by @felixroos in https://github.com/tidalcycles/strudel/pull/236
- Tidal drum machines by @felixroos in https://github.com/tidalcycles/strudel/pull/237
- Object arithmetic by @felixroos in https://github.com/tidalcycles/strudel/pull/238
- Load samples from url by @felixroos in https://github.com/tidalcycles/strudel/pull/239
- feat: support github: links by @felixroos in https://github.com/tidalcycles/strudel/pull/240
- in source example tests by @felixroos in https://github.com/tidalcycles/strudel/pull/242
- Readme + TLC by @felixroos in https://github.com/tidalcycles/strudel/pull/244
- patchday by @felixroos in https://github.com/tidalcycles/strudel/pull/246
- Some tunes by @felixroos in https://github.com/tidalcycles/strudel/pull/247
- snapshot tests on shared snippets by @felixroos in https://github.com/tidalcycles/strudel/pull/243
- General purpose scheduler by @felixroos in https://github.com/tidalcycles/strudel/pull/248
- Fix numbers in sampler by @felixroos in https://codeberg.org/uzu/strudel/pulls/196
- document random functions by @felixroos in https://codeberg.org/uzu/strudel/pulls/199
- add rollup-plugin-visualizer to build by @felixroos in https://codeberg.org/uzu/strudel/pulls/200
- add vowel to .out by @felixroos in https://codeberg.org/uzu/strudel/pulls/201
- Coarse crush shape by @felixroos in https://codeberg.org/uzu/strudel/pulls/205
- Webaudio guide by @felixroos in https://codeberg.org/uzu/strudel/pulls/207
- Even more docs by @felixroos in https://codeberg.org/uzu/strudel/pulls/212
- Just another docs PR by @felixroos in https://codeberg.org/uzu/strudel/pulls/215
- sampler features + fixes by @felixroos in https://codeberg.org/uzu/strudel/pulls/217
- samples now have envelopes by @felixroos in https://codeberg.org/uzu/strudel/pulls/218
- encapsulate webaudio output by @felixroos in https://codeberg.org/uzu/strudel/pulls/219
- Fix squeeze join by @yaxu in https://codeberg.org/uzu/strudel/pulls/220
- Feedback Delay by @felixroos in https://codeberg.org/uzu/strudel/pulls/213
- support negative speeds by @felixroos in https://codeberg.org/uzu/strudel/pulls/222
- focus tweak for squeezeJoin - another go at fixing #216 by @yaxu in https://codeberg.org/uzu/strudel/pulls/221
- Reverb by @felixroos in https://codeberg.org/uzu/strudel/pulls/224
- fix fastgap for events that go across cycle boundaries by @yaxu in https://codeberg.org/uzu/strudel/pulls/225
- Core util tests by @mystery-house in https://codeberg.org/uzu/strudel/pulls/226
- Refactor tunes away from tone by @felixroos in https://codeberg.org/uzu/strudel/pulls/230
- Just another docs branch by @felixroos in https://codeberg.org/uzu/strudel/pulls/228
- Patternify range by @yaxu in https://codeberg.org/uzu/strudel/pulls/231
- Out by default by @felixroos in https://codeberg.org/uzu/strudel/pulls/232
- Fix zero length queries WIP by @yaxu in https://codeberg.org/uzu/strudel/pulls/234
- add vcsl sample library by @felixroos in https://codeberg.org/uzu/strudel/pulls/235
- fx on stereo speakers by @felixroos in https://codeberg.org/uzu/strudel/pulls/236
- Tidal drum machines by @felixroos in https://codeberg.org/uzu/strudel/pulls/237
- Object arithmetic by @felixroos in https://codeberg.org/uzu/strudel/pulls/238
- Load samples from url by @felixroos in https://codeberg.org/uzu/strudel/pulls/239
- feat: support github: links by @felixroos in https://codeberg.org/uzu/strudel/pulls/240
- in source example tests by @felixroos in https://codeberg.org/uzu/strudel/pulls/242
- Readme + TLC by @felixroos in https://codeberg.org/uzu/strudel/pulls/244
- patchday by @felixroos in https://codeberg.org/uzu/strudel/pulls/246
- Some tunes by @felixroos in https://codeberg.org/uzu/strudel/pulls/247
- snapshot tests on shared snippets by @felixroos in https://codeberg.org/uzu/strudel/pulls/243
- General purpose scheduler by @felixroos in https://codeberg.org/uzu/strudel/pulls/248
## New Contributors
- @mystery-house made their first contribution in https://github.com/tidalcycles/strudel/pull/226
- @mystery-house made their first contribution in https://codeberg.org/uzu/strudel/pulls/226
**Full Changelog**: https://github.com/tidalcycles/strudel/compare/v0.0.4...v0.3.0
**Full Changelog**: https://codeberg.org/uzu/strudel/compare/v0.0.4...v0.3.0
@@ -8,8 +8,8 @@ author: froos
## What's Changed
- new transpiler based on acorn by @felixroos in https://github.com/tidalcycles/strudel/pull/249
- Webaudio build by @felixroos in https://github.com/tidalcycles/strudel/pull/250
- Repl refactoring by @felixroos in https://github.com/tidalcycles/strudel/pull/255
- new transpiler based on acorn by @felixroos in https://codeberg.org/uzu/strudel/pulls/249
- Webaudio build by @felixroos in https://codeberg.org/uzu/strudel/pulls/250
- Repl refactoring by @felixroos in https://codeberg.org/uzu/strudel/pulls/255
**Full Changelog**: https://github.com/tidalcycles/strudel/compare/v0.3.0...v0.4.0
**Full Changelog**: https://codeberg.org/uzu/strudel/compare/v0.3.0...v0.4.0
@@ -26,34 +26,34 @@ author: froos
## What's Changed
- Binaries by @felixroos in https://github.com/tidalcycles/strudel/pull/254
- fix tutorial bugs by @felixroos in https://github.com/tidalcycles/strudel/pull/263
- fix performance bottleneck by @felixroos in https://github.com/tidalcycles/strudel/pull/266
- Tidying up core by @yaxu in https://github.com/tidalcycles/strudel/pull/256
- tonal update with fixed memory leak by @felixroos in https://github.com/tidalcycles/strudel/pull/272
- add eslint by @felixroos in https://github.com/tidalcycles/strudel/pull/271
- release version bumps by @felixroos in https://github.com/tidalcycles/strudel/pull/273
- Support sending CRC16 bytes with serial messages by @yaxu in https://github.com/tidalcycles/strudel/pull/276
- add licenses / credits to all tunes + remove some by @felixroos in https://github.com/tidalcycles/strudel/pull/277
- add basic csound output by @felixroos in https://github.com/tidalcycles/strudel/pull/275
- do not recompile orc by @felixroos in https://github.com/tidalcycles/strudel/pull/278
- implement collect + arp function by @felixroos in https://github.com/tidalcycles/strudel/pull/281
- Switch 'operators' from .whatHow to .what.how by @yaxu in https://github.com/tidalcycles/strudel/pull/285
- Fancy hap show, include part in snapshots by @yaxu in https://github.com/tidalcycles/strudel/pull/291
- Reorganise pattern.mjs with a 'toplevel first' regime by @yaxu in https://github.com/tidalcycles/strudel/pull/286
- add prettier task by @felixroos in https://github.com/tidalcycles/strudel/pull/296
- Move stuff to new register function by @felixroos in https://github.com/tidalcycles/strudel/pull/295
- can now add bare numbers to numeral object props by @felixroos in https://github.com/tidalcycles/strudel/pull/287
- update vitest by @felixroos in https://github.com/tidalcycles/strudel/pull/297
- remove whitespace from highlighted region by @felixroos in https://github.com/tidalcycles/strudel/pull/298
- .defragmentHaps() for merging touching haps that share a whole and value by @yaxu in https://github.com/tidalcycles/strudel/pull/299
- fix whitespace trimming by @felixroos in https://github.com/tidalcycles/strudel/pull/300
- add freq support to sampler by @felixroos in https://github.com/tidalcycles/strudel/pull/301
- add lint + prettier check before test by @felixroos in https://github.com/tidalcycles/strudel/pull/305
- Updated csoundm to use the register facility . by @gogins in https://github.com/tidalcycles/strudel/pull/303
- Binaries by @felixroos in https://codeberg.org/uzu/strudel/pulls/254
- fix tutorial bugs by @felixroos in https://codeberg.org/uzu/strudel/pulls/263
- fix performance bottleneck by @felixroos in https://codeberg.org/uzu/strudel/pulls/266
- Tidying up core by @yaxu in https://codeberg.org/uzu/strudel/pulls/256
- tonal update with fixed memory leak by @felixroos in https://codeberg.org/uzu/strudel/pulls/272
- add eslint by @felixroos in https://codeberg.org/uzu/strudel/pulls/271
- release version bumps by @felixroos in https://codeberg.org/uzu/strudel/pulls/273
- Support sending CRC16 bytes with serial messages by @yaxu in https://codeberg.org/uzu/strudel/pulls/276
- add licenses / credits to all tunes + remove some by @felixroos in https://codeberg.org/uzu/strudel/pulls/277
- add basic csound output by @felixroos in https://codeberg.org/uzu/strudel/pulls/275
- do not recompile orc by @felixroos in https://codeberg.org/uzu/strudel/pulls/278
- implement collect + arp function by @felixroos in https://codeberg.org/uzu/strudel/pulls/281
- Switch 'operators' from .whatHow to .what.how by @yaxu in https://codeberg.org/uzu/strudel/pulls/285
- Fancy hap show, include part in snapshots by @yaxu in https://codeberg.org/uzu/strudel/pulls/291
- Reorganise pattern.mjs with a 'toplevel first' regime by @yaxu in https://codeberg.org/uzu/strudel/pulls/286
- add prettier task by @felixroos in https://codeberg.org/uzu/strudel/pulls/296
- Move stuff to new register function by @felixroos in https://codeberg.org/uzu/strudel/pulls/295
- can now add bare numbers to numeral object props by @felixroos in https://codeberg.org/uzu/strudel/pulls/287
- update vitest by @felixroos in https://codeberg.org/uzu/strudel/pulls/297
- remove whitespace from highlighted region by @felixroos in https://codeberg.org/uzu/strudel/pulls/298
- .defragmentHaps() for merging touching haps that share a whole and value by @yaxu in https://codeberg.org/uzu/strudel/pulls/299
- fix whitespace trimming by @felixroos in https://codeberg.org/uzu/strudel/pulls/300
- add freq support to sampler by @felixroos in https://codeberg.org/uzu/strudel/pulls/301
- add lint + prettier check before test by @felixroos in https://codeberg.org/uzu/strudel/pulls/305
- Updated csoundm to use the register facility . by @gogins in https://codeberg.org/uzu/strudel/pulls/303
## New Contributors
- @gogins made their first contribution in https://github.com/tidalcycles/strudel/pull/303
- @gogins made their first contribution in https://codeberg.org/uzu/strudel/pulls/303
**Full Changelog**: https://github.com/tidalcycles/strudel/compare/v0.4.0...v0.5.0
**Full Changelog**: https://codeberg.org/uzu/strudel/compare/v0.4.0...v0.5.0
@@ -26,59 +26,59 @@ author: froos
## What's Changed
- support freq in pianoroll by @felixroos in https://github.com/tidalcycles/strudel/pull/308
- ICLC2023 paper WIP by @yaxu in https://github.com/tidalcycles/strudel/pull/306
- fix: copy share link to clipboard was broken for some browsers by @felixroos in https://github.com/tidalcycles/strudel/pull/311
- Jsdoc component by @felixroos in https://github.com/tidalcycles/strudel/pull/312
- object support for .scale by @felixroos in https://github.com/tidalcycles/strudel/pull/307
- Astro build by @felixroos in https://github.com/tidalcycles/strudel/pull/315
- Reference tab sort by @felixroos in https://github.com/tidalcycles/strudel/pull/318
- tutorial updates by @jarmitage in https://github.com/tidalcycles/strudel/pull/320
- support notes without octave by @felixroos in https://github.com/tidalcycles/strudel/pull/323
- mini repl improvements by @felixroos in https://github.com/tidalcycles/strudel/pull/324
- fix: workaround Object.assign globalThis by @felixroos in https://github.com/tidalcycles/strudel/pull/326
- add examples route by @felixroos in https://github.com/tidalcycles/strudel/pull/327
- add my-patterns by @felixroos in https://github.com/tidalcycles/strudel/pull/328
- my-patterns build + deploy by @felixroos in https://github.com/tidalcycles/strudel/pull/329
- my-patterns: fix paths + update readme by @felixroos in https://github.com/tidalcycles/strudel/pull/330
- improve displaying 's' in pianoroll by @felixroos in https://github.com/tidalcycles/strudel/pull/331
- fix: can now multiply floats in mini notation by @felixroos in https://github.com/tidalcycles/strudel/pull/332
- Embed mode improvements by @felixroos in https://github.com/tidalcycles/strudel/pull/333
- testing + docs docs by @felixroos in https://github.com/tidalcycles/strudel/pull/334
- animate mvp by @felixroos in https://github.com/tidalcycles/strudel/pull/335
- Tidy parser, implement polymeters by @yaxu in https://github.com/tidalcycles/strudel/pull/336
- animation options by @felixroos in https://github.com/tidalcycles/strudel/pull/337
- move /my-patterns to /swatch by @yaxu in https://github.com/tidalcycles/strudel/pull/338
- more animate functions + mini repl fix by @felixroos in https://github.com/tidalcycles/strudel/pull/340
- Patternify euclid, fast, slow and polymeter step parameters in mininotation by @yaxu in https://github.com/tidalcycles/strudel/pull/341
- fixes #346 by @felixroos in https://github.com/tidalcycles/strudel/pull/347
- Fix prebake base path by @felixroos in https://github.com/tidalcycles/strudel/pull/345
- Fix Bjorklund by @yaxu in https://github.com/tidalcycles/strudel/pull/343
- docs: tidal comparison + add global fx + add missing sampler fx by @felixroos in https://github.com/tidalcycles/strudel/pull/356
- Fix .out(), renaming webaudio's out() to webaudio() by @yaxu in https://github.com/tidalcycles/strudel/pull/361
- Support for multiple mininotation operators by @yaxu in https://github.com/tidalcycles/strudel/pull/350
- doc structuring by @felixroos in https://github.com/tidalcycles/strudel/pull/360
- add https to url by @urswilke in https://github.com/tidalcycles/strudel/pull/364
- document more functions + change arp join by @felixroos in https://github.com/tidalcycles/strudel/pull/369
- improve new draw logic by @felixroos in https://github.com/tidalcycles/strudel/pull/372
- Draw fixes by @felixroos in https://github.com/tidalcycles/strudel/pull/377
- update my-patterns instructions by @felixroos in https://github.com/tidalcycles/strudel/pull/384
- docs: use note instead of n to mitigate confusion by @felixroos in https://github.com/tidalcycles/strudel/pull/385
- add run + test + docs by @felixroos in https://github.com/tidalcycles/strudel/pull/386
- Rename a to angle by @felixroos in https://github.com/tidalcycles/strudel/pull/387
- document csound by @felixroos in https://github.com/tidalcycles/strudel/pull/391
- Notes are not essential :) by @yaxu in https://github.com/tidalcycles/strudel/pull/393
- add ribbon + test + docs by @felixroos in https://github.com/tidalcycles/strudel/pull/388
- Add tidal-drum-patterns to examples by @urswilke in https://github.com/tidalcycles/strudel/pull/379
- add pattern methods hurry, press and pressBy by @yaxu in https://github.com/tidalcycles/strudel/pull/397
- proper builds + use pnpm workspaces by @felixroos in https://github.com/tidalcycles/strudel/pull/396
- fix: minirepl styles by @felixroos in https://github.com/tidalcycles/strudel/pull/398
- can now await initAudio + initAudioOnFirstClick by @felixroos in https://github.com/tidalcycles/strudel/pull/399
- release webaudio by @felixroos in https://github.com/tidalcycles/strudel/pull/400
- support freq in pianoroll by @felixroos in https://codeberg.org/uzu/strudel/pulls/308
- ICLC2023 paper WIP by @yaxu in https://codeberg.org/uzu/strudel/pulls/306
- fix: copy share link to clipboard was broken for some browsers by @felixroos in https://codeberg.org/uzu/strudel/pulls/311
- Jsdoc component by @felixroos in https://codeberg.org/uzu/strudel/pulls/312
- object support for .scale by @felixroos in https://codeberg.org/uzu/strudel/pulls/307
- Astro build by @felixroos in https://codeberg.org/uzu/strudel/pulls/315
- Reference tab sort by @felixroos in https://codeberg.org/uzu/strudel/pulls/318
- tutorial updates by @jarmitage in https://codeberg.org/uzu/strudel/pulls/320
- support notes without octave by @felixroos in https://codeberg.org/uzu/strudel/pulls/323
- mini repl improvements by @felixroos in https://codeberg.org/uzu/strudel/pulls/324
- fix: workaround Object.assign globalThis by @felixroos in https://codeberg.org/uzu/strudel/pulls/326
- add examples route by @felixroos in https://codeberg.org/uzu/strudel/pulls/327
- add my-patterns by @felixroos in https://codeberg.org/uzu/strudel/pulls/328
- my-patterns build + deploy by @felixroos in https://codeberg.org/uzu/strudel/pulls/329
- my-patterns: fix paths + update readme by @felixroos in https://codeberg.org/uzu/strudel/pulls/330
- improve displaying 's' in pianoroll by @felixroos in https://codeberg.org/uzu/strudel/pulls/331
- fix: can now multiply floats in mini notation by @felixroos in https://codeberg.org/uzu/strudel/pulls/332
- Embed mode improvements by @felixroos in https://codeberg.org/uzu/strudel/pulls/333
- testing + docs docs by @felixroos in https://codeberg.org/uzu/strudel/pulls/334
- animate mvp by @felixroos in https://codeberg.org/uzu/strudel/pulls/335
- Tidy parser, implement polymeters by @yaxu in https://codeberg.org/uzu/strudel/pulls/336
- animation options by @felixroos in https://codeberg.org/uzu/strudel/pulls/337
- move /my-patterns to /swatch by @yaxu in https://codeberg.org/uzu/strudel/pulls/338
- more animate functions + mini repl fix by @felixroos in https://codeberg.org/uzu/strudel/pulls/340
- Patternify euclid, fast, slow and polymeter step parameters in mininotation by @yaxu in https://codeberg.org/uzu/strudel/pulls/341
- fixes #346 by @felixroos in https://codeberg.org/uzu/strudel/pulls/347
- Fix prebake base path by @felixroos in https://codeberg.org/uzu/strudel/pulls/345
- Fix Bjorklund by @yaxu in https://codeberg.org/uzu/strudel/pulls/343
- docs: tidal comparison + add global fx + add missing sampler fx by @felixroos in https://codeberg.org/uzu/strudel/pulls/356
- Fix .out(), renaming webaudio's out() to webaudio() by @yaxu in https://codeberg.org/uzu/strudel/pulls/361
- Support for multiple mininotation operators by @yaxu in https://codeberg.org/uzu/strudel/pulls/350
- doc structuring by @felixroos in https://codeberg.org/uzu/strudel/pulls/360
- add https to url by @urswilke in https://codeberg.org/uzu/strudel/pulls/364
- document more functions + change arp join by @felixroos in https://codeberg.org/uzu/strudel/pulls/369
- improve new draw logic by @felixroos in https://codeberg.org/uzu/strudel/pulls/372
- Draw fixes by @felixroos in https://codeberg.org/uzu/strudel/pulls/377
- update my-patterns instructions by @felixroos in https://codeberg.org/uzu/strudel/pulls/384
- docs: use note instead of n to mitigate confusion by @felixroos in https://codeberg.org/uzu/strudel/pulls/385
- add run + test + docs by @felixroos in https://codeberg.org/uzu/strudel/pulls/386
- Rename a to angle by @felixroos in https://codeberg.org/uzu/strudel/pulls/387
- document csound by @felixroos in https://codeberg.org/uzu/strudel/pulls/391
- Notes are not essential :) by @yaxu in https://codeberg.org/uzu/strudel/pulls/393
- add ribbon + test + docs by @felixroos in https://codeberg.org/uzu/strudel/pulls/388
- Add tidal-drum-patterns to examples by @urswilke in https://codeberg.org/uzu/strudel/pulls/379
- add pattern methods hurry, press and pressBy by @yaxu in https://codeberg.org/uzu/strudel/pulls/397
- proper builds + use pnpm workspaces by @felixroos in https://codeberg.org/uzu/strudel/pulls/396
- fix: minirepl styles by @felixroos in https://codeberg.org/uzu/strudel/pulls/398
- can now await initAudio + initAudioOnFirstClick by @felixroos in https://codeberg.org/uzu/strudel/pulls/399
- release webaudio by @felixroos in https://codeberg.org/uzu/strudel/pulls/400
## New Contributors
- @jarmitage made their first contribution in https://github.com/tidalcycles/strudel/pull/320
- @urswilke made their first contribution in https://github.com/tidalcycles/strudel/pull/364
- @jarmitage made their first contribution in https://codeberg.org/uzu/strudel/pulls/320
- @urswilke made their first contribution in https://codeberg.org/uzu/strudel/pulls/364
**Full Changelog**: https://github.com/tidalcycles/strudel/compare/v0.5.0...v0.6.0
**Full Changelog**: https://codeberg.org/uzu/strudel/compare/v0.5.0...v0.6.0
@@ -23,66 +23,66 @@ author: froos
## What's Changed
- pin @csound/browser to 6.18.3 + bump by @felixroos in https://github.com/tidalcycles/strudel/pull/403
- update csound + fix sound output by @felixroos in https://github.com/tidalcycles/strudel/pull/404
- fix: share url on subpath by @felixroos in https://github.com/tidalcycles/strudel/pull/405
- add shabda doc by @felixroos in https://github.com/tidalcycles/strudel/pull/407
- Update effects.mdx by @bwagner in https://github.com/tidalcycles/strudel/pull/410
- improve effects doc by @felixroos in https://github.com/tidalcycles/strudel/pull/409
- google gtfo by @felixroos in https://github.com/tidalcycles/strudel/pull/413
- improve samples doc by @felixroos in https://github.com/tidalcycles/strudel/pull/411
- PWA with offline support by @felixroos in https://github.com/tidalcycles/strudel/pull/417
- add caching strategy for missing file types + cache all samples loaded from github by @felixroos in https://github.com/tidalcycles/strudel/pull/419
- add more offline caching by @felixroos in https://github.com/tidalcycles/strudel/pull/421
- add cdn.freesound to cache list by @felixroos in https://github.com/tidalcycles/strudel/pull/425
- minirepl: add keyboard shortcuts by @felixroos in https://github.com/tidalcycles/strudel/pull/429
- Themes by @felixroos in https://github.com/tidalcycles/strudel/pull/431
- autocomplete preparations by @felixroos in https://github.com/tidalcycles/strudel/pull/427
- Fix anchors by @felixroos in https://github.com/tidalcycles/strudel/pull/433
- Update code.mdx by @bwagner in https://github.com/tidalcycles/strudel/pull/436
- Update mini-notation.mdx by @bwagner in https://github.com/tidalcycles/strudel/pull/437
- Update synths.mdx by @bwagner in https://github.com/tidalcycles/strudel/pull/438
- FIXES: Warning about jsxBracketSameLine deprecation by @bwagner in https://github.com/tidalcycles/strudel/pull/461
- Composable functions by @yaxu in https://github.com/tidalcycles/strudel/pull/390
- weave and weaveWith by @yaxu in https://github.com/tidalcycles/strudel/pull/465
- slice and splice by @yaxu in https://github.com/tidalcycles/strudel/pull/466
- fix: osc should not return a promise by @felixroos in https://github.com/tidalcycles/strudel/pull/472
- FIXES: freqs instead of pitches by @bwagner in https://github.com/tidalcycles/strudel/pull/464
- Update input-output.mdx by @bwagner in https://github.com/tidalcycles/strudel/pull/471
- settings tab with vim / emacs modes + additional themes and fonts by @felixroos in https://github.com/tidalcycles/strudel/pull/467
- fix: hash links by @felixroos in https://github.com/tidalcycles/strudel/pull/473
- midi cc support by @felixroos in https://github.com/tidalcycles/strudel/pull/478
- Fix array args by @felixroos in https://github.com/tidalcycles/strudel/pull/480
- docs: packages + offline by @felixroos in https://github.com/tidalcycles/strudel/pull/482
- Update mini-notation.mdx by @yaxu in https://github.com/tidalcycles/strudel/pull/365
- Revert "Another attempt at composable functions - WIP (#390)" by @felixroos in https://github.com/tidalcycles/strudel/pull/484
- fix app height by @felixroos in https://github.com/tidalcycles/strudel/pull/485
- add algolia creds + optimize sidebar for crawling by @felixroos in https://github.com/tidalcycles/strudel/pull/488
- refactor react package by @felixroos in https://github.com/tidalcycles/strudel/pull/490
- react style fixes by @felixroos in https://github.com/tidalcycles/strudel/pull/491
- implement cps in scheduler by @felixroos in https://github.com/tidalcycles/strudel/pull/493
- Add control aliases by @yaxu in https://github.com/tidalcycles/strudel/pull/497
- fix: nano-repl highlighting by @felixroos in https://github.com/tidalcycles/strudel/pull/501
- Reinstate slice and splice by @yaxu in https://github.com/tidalcycles/strudel/pull/500
- can now use : as a replacement for space in scales by @felixroos in https://github.com/tidalcycles/strudel/pull/502
- Support list syntax in mininotation by @yaxu in https://github.com/tidalcycles/strudel/pull/512
- update react to 18 by @felixroos in https://github.com/tidalcycles/strudel/pull/514
- add arrange function by @felixroos in https://github.com/tidalcycles/strudel/pull/508
- Update README.md by @bwagner in https://github.com/tidalcycles/strudel/pull/474
- add 2 illegible fonts by @felixroos in https://github.com/tidalcycles/strudel/pull/518
- registerSound API + improved sounds tab + regroup soundfonts by @felixroos in https://github.com/tidalcycles/strudel/pull/516
- fix: envelopes in chrome by @felixroos in https://github.com/tidalcycles/strudel/pull/521
- Update samples.mdx by @bwagner in https://github.com/tidalcycles/strudel/pull/524
- Update intro.mdx by @bwagner in https://github.com/tidalcycles/strudel/pull/525
- fix(footer): fix link to tidalcycles by @revolunet in https://github.com/tidalcycles/strudel/pull/529
- FIXES: alias pm for polymeter by @bwagner in https://github.com/tidalcycles/strudel/pull/527
- Maintain random seed state in parser, not globally by @ijc8 in https://github.com/tidalcycles/strudel/pull/531
- feat: add freq support to gm soundfonts by @felixroos in https://github.com/tidalcycles/strudel/pull/534
- Update lerna by @felixroos in https://github.com/tidalcycles/strudel/pull/535
- pin @csound/browser to 6.18.3 + bump by @felixroos in https://codeberg.org/uzu/strudel/pulls/403
- update csound + fix sound output by @felixroos in https://codeberg.org/uzu/strudel/pulls/404
- fix: share url on subpath by @felixroos in https://codeberg.org/uzu/strudel/pulls/405
- add shabda doc by @felixroos in https://codeberg.org/uzu/strudel/pulls/407
- Update effects.mdx by @bwagner in https://codeberg.org/uzu/strudel/pulls/410
- improve effects doc by @felixroos in https://codeberg.org/uzu/strudel/pulls/409
- google gtfo by @felixroos in https://codeberg.org/uzu/strudel/pulls/413
- improve samples doc by @felixroos in https://codeberg.org/uzu/strudel/pulls/411
- PWA with offline support by @felixroos in https://codeberg.org/uzu/strudel/pulls/417
- add caching strategy for missing file types + cache all samples loaded from github by @felixroos in https://codeberg.org/uzu/strudel/pulls/419
- add more offline caching by @felixroos in https://codeberg.org/uzu/strudel/pulls/421
- add cdn.freesound to cache list by @felixroos in https://codeberg.org/uzu/strudel/pulls/425
- minirepl: add keyboard shortcuts by @felixroos in https://codeberg.org/uzu/strudel/pulls/429
- Themes by @felixroos in https://codeberg.org/uzu/strudel/pulls/431
- autocomplete preparations by @felixroos in https://codeberg.org/uzu/strudel/pulls/427
- Fix anchors by @felixroos in https://codeberg.org/uzu/strudel/pulls/433
- Update code.mdx by @bwagner in https://codeberg.org/uzu/strudel/pulls/436
- Update mini-notation.mdx by @bwagner in https://codeberg.org/uzu/strudel/pulls/437
- Update synths.mdx by @bwagner in https://codeberg.org/uzu/strudel/pulls/438
- FIXES: Warning about jsxBracketSameLine deprecation by @bwagner in https://codeberg.org/uzu/strudel/pulls/461
- Composable functions by @yaxu in https://codeberg.org/uzu/strudel/pulls/390
- weave and weaveWith by @yaxu in https://codeberg.org/uzu/strudel/pulls/465
- slice and splice by @yaxu in https://codeberg.org/uzu/strudel/pulls/466
- fix: osc should not return a promise by @felixroos in https://codeberg.org/uzu/strudel/pulls/472
- FIXES: freqs instead of pitches by @bwagner in https://codeberg.org/uzu/strudel/pulls/464
- Update input-output.mdx by @bwagner in https://codeberg.org/uzu/strudel/pulls/471
- settings tab with vim / emacs modes + additional themes and fonts by @felixroos in https://codeberg.org/uzu/strudel/pulls/467
- fix: hash links by @felixroos in https://codeberg.org/uzu/strudel/pulls/473
- midi cc support by @felixroos in https://codeberg.org/uzu/strudel/pulls/478
- Fix array args by @felixroos in https://codeberg.org/uzu/strudel/pulls/480
- docs: packages + offline by @felixroos in https://codeberg.org/uzu/strudel/pulls/482
- Update mini-notation.mdx by @yaxu in https://codeberg.org/uzu/strudel/pulls/365
- Revert "Another attempt at composable functions - WIP (#390)" by @felixroos in https://codeberg.org/uzu/strudel/pulls/484
- fix app height by @felixroos in https://codeberg.org/uzu/strudel/pulls/485
- add algolia creds + optimize sidebar for crawling by @felixroos in https://codeberg.org/uzu/strudel/pulls/488
- refactor react package by @felixroos in https://codeberg.org/uzu/strudel/pulls/490
- react style fixes by @felixroos in https://codeberg.org/uzu/strudel/pulls/491
- implement cps in scheduler by @felixroos in https://codeberg.org/uzu/strudel/pulls/493
- Add control aliases by @yaxu in https://codeberg.org/uzu/strudel/pulls/497
- fix: nano-repl highlighting by @felixroos in https://codeberg.org/uzu/strudel/pulls/501
- Reinstate slice and splice by @yaxu in https://codeberg.org/uzu/strudel/pulls/500
- can now use : as a replacement for space in scales by @felixroos in https://codeberg.org/uzu/strudel/pulls/502
- Support list syntax in mininotation by @yaxu in https://codeberg.org/uzu/strudel/pulls/512
- update react to 18 by @felixroos in https://codeberg.org/uzu/strudel/pulls/514
- add arrange function by @felixroos in https://codeberg.org/uzu/strudel/pulls/508
- Update README.md by @bwagner in https://codeberg.org/uzu/strudel/pulls/474
- add 2 illegible fonts by @felixroos in https://codeberg.org/uzu/strudel/pulls/518
- registerSound API + improved sounds tab + regroup soundfonts by @felixroos in https://codeberg.org/uzu/strudel/pulls/516
- fix: envelopes in chrome by @felixroos in https://codeberg.org/uzu/strudel/pulls/521
- Update samples.mdx by @bwagner in https://codeberg.org/uzu/strudel/pulls/524
- Update intro.mdx by @bwagner in https://codeberg.org/uzu/strudel/pulls/525
- fix(footer): fix link to tidalcycles by @revolunet in https://codeberg.org/uzu/strudel/pulls/529
- FIXES: alias pm for polymeter by @bwagner in https://codeberg.org/uzu/strudel/pulls/527
- Maintain random seed state in parser, not globally by @ijc8 in https://codeberg.org/uzu/strudel/pulls/531
- feat: add freq support to gm soundfonts by @felixroos in https://codeberg.org/uzu/strudel/pulls/534
- Update lerna by @felixroos in https://codeberg.org/uzu/strudel/pulls/535
## New Contributors
- @revolunet made their first contribution in https://github.com/tidalcycles/strudel/pull/529
- @ijc8 made their first contribution in https://github.com/tidalcycles/strudel/pull/531
- @revolunet made their first contribution in https://codeberg.org/uzu/strudel/pulls/529
- @ijc8 made their first contribution in https://codeberg.org/uzu/strudel/pulls/531
**Full Changelog**: https://github.com/tidalcycles/strudel/compare/v0.6.0...v0.7.0
**Full Changelog**: https://codeberg.org/uzu/strudel/compare/v0.6.0...v0.7.0
@@ -6,7 +6,7 @@ tags: ['meta']
author: froos
---
import BlogVideo from '../../components/BlogVideo.astro';
import { Youtube } from '@src/components/Youtube';
These are the release notes for Strudel 0.8.0 aka "Himbeermuffin"!
@@ -18,11 +18,11 @@ Let me write up some of the highlights:
Besides the REPL (https://strudel.tidalcycles.org/), Strudel is now also distributed as a Desktop App via https://tauri.app/! Thanks to [vasilymilovidov](https://github.com/vasilymilovidov)!
- [Linux: Debian based](https://github.com/tidalcycles/strudel/releases/download/v0.8.0/strudel_0.1.0_amd64.deb)
- [Linux: AppImage](https://github.com/tidalcycles/strudel/releases/download/v0.8.0/strudel_0.1.0_amd64.AppImage)
- [MacOS](https://github.com/tidalcycles/strudel/releases/download/v0.8.0/Strudel_0.1.0_x64.dmg)
- [Windows .exe](https://github.com/tidalcycles/strudel/releases/download/v0.8.0/Strudel_0.1.0_x64-setup.exe)
- [Windows .msi](https://github.com/tidalcycles/strudel/releases/download/v0.8.0/Strudel_0.1.0_x64_en-US.msi)
- [Linux: Debian based](https://codeberg.org/uzu/strudel/releases/download/v0.8.0/strudel_0.1.0_amd64.deb)
- [Linux: AppImage](https://codeberg.org/uzu/strudel/releases/download/v0.8.0/strudel_0.1.0_amd64.AppImage)
- [MacOS](https://codeberg.org/uzu/strudel/releases/download/v0.8.0/Strudel_0.1.0_x64.dmg)
- [Windows .exe](https://codeberg.org/uzu/strudel/releases/download/v0.8.0/Strudel_0.1.0_x64-setup.exe)
- [Windows .msi](https://codeberg.org/uzu/strudel/releases/download/v0.8.0/Strudel_0.1.0_x64_en-US.msi)
edit: the desktop app performance on linux is currently not that great.. the web REPL runs much smoother (using firefox or chromium)
@@ -43,7 +43,7 @@ I would be very happy to collect some feedback on how it works across different
Also still undocumented, but you can now visualize patterns as a spiral via `.spiral()`:
<BlogVideo src="https://github.com/tidalcycles/strudel/assets/12023032/05bc2dba-b304-4298-9465-a1a6fafe5ded" />
<Youtube client:only="react" id="24bSHhEdUeM" />
This is especially nice because strudel is not only the name of a dessert but also the german word for vortex! The spiral is very fitting to visualize cycles because you can align cycles vertically, while surfing along an infinite twisted timeline.
@@ -82,49 +82,49 @@ A big thanks to all the contributors!
## What's Changed
- fix period key for dvorak + remove duplicated code by @felixroos in https://github.com/tidalcycles/strudel/pull/537
- improve initial loading + wait before eval by @felixroos in https://github.com/tidalcycles/strudel/pull/538
- do not reset cps before eval #517 by @felixroos in https://github.com/tidalcycles/strudel/pull/539
- feat: add loader bar to animate loading state by @felixroos in https://github.com/tidalcycles/strudel/pull/542
- add firacode font by @felixroos in https://github.com/tidalcycles/strudel/pull/544
- fix: allow whitespace at the end of a mini pattern by @felixroos in https://github.com/tidalcycles/strudel/pull/547
- fix: reset time on stop by @felixroos in https://github.com/tidalcycles/strudel/pull/548
- fix: load soundfonts in prebake by @felixroos in https://github.com/tidalcycles/strudel/pull/550
- fix: colorable highlighting by @felixroos in https://github.com/tidalcycles/strudel/pull/553
- fix: make soundfonts import dynamic by @felixroos in https://github.com/tidalcycles/strudel/pull/556
- add basic triads and guidetone voicings by @felixroos in https://github.com/tidalcycles/strudel/pull/557
- Patchday by @felixroos in https://github.com/tidalcycles/strudel/pull/559
- Vanilla JS Refactoring by @felixroos in https://github.com/tidalcycles/strudel/pull/563
- repl: add option to display line numbers by @roipoussiere in https://github.com/tidalcycles/strudel/pull/582
- learn/tonal: fix typo in "scaleTran[s]pose" by @srenatus in https://github.com/tidalcycles/strudel/pull/585
- Music metadata by @roipoussiere in https://github.com/tidalcycles/strudel/pull/580
- New Workshop by @felixroos in https://github.com/tidalcycles/strudel/pull/587
- Fix option dot by @felixroos in https://github.com/tidalcycles/strudel/pull/596
- fix: allow f for flat notes like tidal by @felixroos in https://github.com/tidalcycles/strudel/pull/593
- fix: division by zero by @felixroos in https://github.com/tidalcycles/strudel/pull/591
- Solmization added by @dariacotocu in https://github.com/tidalcycles/strudel/pull/570
- improve cursor by @felixroos in https://github.com/tidalcycles/strudel/pull/597
- enable auto-completion by @roipoussiere in https://github.com/tidalcycles/strudel/pull/588
- add ratio function by @felixroos in https://github.com/tidalcycles/strudel/pull/602
- editor: enable line wrapping by @roipoussiere in https://github.com/tidalcycles/strudel/pull/581
- tonal fixes by @felixroos in https://github.com/tidalcycles/strudel/pull/607
- fix: flatten scale lists by @felixroos in https://github.com/tidalcycles/strudel/pull/605
- clip now works like legato in tidal by @felixroos in https://github.com/tidalcycles/strudel/pull/598
- fix: doc links by @felixroos in https://github.com/tidalcycles/strudel/pull/612
- tauri desktop app by @vasilymilovidov in https://github.com/tidalcycles/strudel/pull/613
- add spiral viz by @felixroos in https://github.com/tidalcycles/strudel/pull/614
- patterning ui settings by @felixroos in https://github.com/tidalcycles/strudel/pull/606
- Fix typo on packages.mdx by @paikwiki in https://github.com/tidalcycles/strudel/pull/520
- cps dependent functions by @felixroos in https://github.com/tidalcycles/strudel/pull/620
- desktop: play samples from disk by @felixroos in https://github.com/tidalcycles/strudel/pull/621
- fix: midi clock drift by @felixroos in https://github.com/tidalcycles/strudel/pull/627
- fix period key for dvorak + remove duplicated code by @felixroos in https://codeberg.org/uzu/strudel/pulls/537
- improve initial loading + wait before eval by @felixroos in https://codeberg.org/uzu/strudel/pulls/538
- do not reset cps before eval #517 by @felixroos in https://codeberg.org/uzu/strudel/pulls/539
- feat: add loader bar to animate loading state by @felixroos in https://codeberg.org/uzu/strudel/pulls/542
- add firacode font by @felixroos in https://codeberg.org/uzu/strudel/pulls/544
- fix: allow whitespace at the end of a mini pattern by @felixroos in https://codeberg.org/uzu/strudel/pulls/547
- fix: reset time on stop by @felixroos in https://codeberg.org/uzu/strudel/pulls/548
- fix: load soundfonts in prebake by @felixroos in https://codeberg.org/uzu/strudel/pulls/550
- fix: colorable highlighting by @felixroos in https://codeberg.org/uzu/strudel/pulls/553
- fix: make soundfonts import dynamic by @felixroos in https://codeberg.org/uzu/strudel/pulls/556
- add basic triads and guidetone voicings by @felixroos in https://codeberg.org/uzu/strudel/pulls/557
- Patchday by @felixroos in https://codeberg.org/uzu/strudel/pulls/559
- Vanilla JS Refactoring by @felixroos in https://codeberg.org/uzu/strudel/pulls/563
- repl: add option to display line numbers by @roipoussiere in https://codeberg.org/uzu/strudel/pulls/582
- learn/tonal: fix typo in "scaleTran[s]pose" by @srenatus in https://codeberg.org/uzu/strudel/pulls/585
- Music metadata by @roipoussiere in https://codeberg.org/uzu/strudel/pulls/580
- New Workshop by @felixroos in https://codeberg.org/uzu/strudel/pulls/587
- Fix option dot by @felixroos in https://codeberg.org/uzu/strudel/pulls/596
- fix: allow f for flat notes like tidal by @felixroos in https://codeberg.org/uzu/strudel/pulls/593
- fix: division by zero by @felixroos in https://codeberg.org/uzu/strudel/pulls/591
- Solmization added by @dariacotocu in https://codeberg.org/uzu/strudel/pulls/570
- improve cursor by @felixroos in https://codeberg.org/uzu/strudel/pulls/597
- enable auto-completion by @roipoussiere in https://codeberg.org/uzu/strudel/pulls/588
- add ratio function by @felixroos in https://codeberg.org/uzu/strudel/pulls/602
- editor: enable line wrapping by @roipoussiere in https://codeberg.org/uzu/strudel/pulls/581
- tonal fixes by @felixroos in https://codeberg.org/uzu/strudel/pulls/607
- fix: flatten scale lists by @felixroos in https://codeberg.org/uzu/strudel/pulls/605
- clip now works like legato in tidal by @felixroos in https://codeberg.org/uzu/strudel/pulls/598
- fix: doc links by @felixroos in https://codeberg.org/uzu/strudel/pulls/612
- tauri desktop app by @vasilymilovidov in https://codeberg.org/uzu/strudel/pulls/613
- add spiral viz by @felixroos in https://codeberg.org/uzu/strudel/pulls/614
- patterning ui settings by @felixroos in https://codeberg.org/uzu/strudel/pulls/606
- Fix typo on packages.mdx by @paikwiki in https://codeberg.org/uzu/strudel/pulls/520
- cps dependent functions by @felixroos in https://codeberg.org/uzu/strudel/pulls/620
- desktop: play samples from disk by @felixroos in https://codeberg.org/uzu/strudel/pulls/621
- fix: midi clock drift by @felixroos in https://codeberg.org/uzu/strudel/pulls/627
## New Contributors
- @roipoussiere made their first contribution in https://github.com/tidalcycles/strudel/pull/582
- @srenatus made their first contribution in https://github.com/tidalcycles/strudel/pull/585
- @dariacotocu made their first contribution in https://github.com/tidalcycles/strudel/pull/570
- @vasilymilovidov made their first contribution in https://github.com/tidalcycles/strudel/pull/613
- @paikwiki made their first contribution in https://github.com/tidalcycles/strudel/pull/520
- @roipoussiere made their first contribution in https://codeberg.org/uzu/strudel/pulls/582
- @srenatus made their first contribution in https://codeberg.org/uzu/strudel/pulls/585
- @dariacotocu made their first contribution in https://codeberg.org/uzu/strudel/pulls/570
- @vasilymilovidov made their first contribution in https://codeberg.org/uzu/strudel/pulls/613
- @paikwiki made their first contribution in https://codeberg.org/uzu/strudel/pulls/520
**Full Changelog**: https://github.com/tidalcycles/strudel/compare/v0.7.0...v0.8.0
**Full Changelog**: https://codeberg.org/uzu/strudel/compare/v0.7.0...v0.8.0
@@ -6,8 +6,6 @@ tags: ['meta']
author: froos
---
import BlogVideo from '../../components/BlogVideo.astro';
These are the release notes for Strudel 0.9.0 aka "Bananenbrot"!
The last release was over 11 weeks ago, so a lot of things have happened!
@@ -25,18 +23,20 @@ Main new features include:
- [vibrato](https://strudel.tidalcycles.org/learn/synths#vibrato)
- an integration of [ZZFX](https://strudel.tidalcycles.org/learn/synths#zzfx)
<BlogVideo src="https://github.com/tidalcycles/strudel/assets/12023032/652e7042-f296-496b-95cd-b2a4987fe238" />
import { Youtube } from '@src/components/Youtube';
<Youtube client:only="react" id="5ByKVG7jiO4" />
Related PRs:
- superdough: encapsulates web audio output by @felixroos in https://github.com/tidalcycles/strudel/pull/664
- basic fm by @felixroos in https://github.com/tidalcycles/strudel/pull/669
- Wave Selection and Global Envelope on the FM Synth Modulator by @Bubobubobubobubo in https://github.com/tidalcycles/strudel/pull/683
- control osc partial count with n by @felixroos in https://github.com/tidalcycles/strudel/pull/674
- ZZFX Synth support by @Bubobubobubobubo in https://github.com/tidalcycles/strudel/pull/684
- Adding filter envelopes and filter order selection by @Bubobubobubobubo in https://github.com/tidalcycles/strudel/pull/692
- Adding loop points and thus wavetable synthesis by @Bubobubobubobubo in https://github.com/tidalcycles/strudel/pull/698
- Adding vibrato to base oscillators by @Bubobubobubobubo in https://github.com/tidalcycles/strudel/pull/693
- superdough: encapsulates web audio output by @felixroos in https://codeberg.org/uzu/strudel/pulls/664
- basic fm by @felixroos in https://codeberg.org/uzu/strudel/pulls/669
- Wave Selection and Global Envelope on the FM Synth Modulator by @Bubobubobubobubo in https://codeberg.org/uzu/strudel/pulls/683
- control osc partial count with n by @felixroos in https://codeberg.org/uzu/strudel/pulls/674
- ZZFX Synth support by @Bubobubobubobubo in https://codeberg.org/uzu/strudel/pulls/684
- Adding filter envelopes and filter order selection by @Bubobubobubobubo in https://codeberg.org/uzu/strudel/pulls/692
- Adding loop points and thus wavetable synthesis by @Bubobubobubobubo in https://codeberg.org/uzu/strudel/pulls/698
- Adding vibrato to base oscillators by @Bubobubobubobubo in https://codeberg.org/uzu/strudel/pulls/693
## Desktop App Improvements
@@ -45,70 +45,70 @@ which do not depend on browser APIs!
You can see superdough, superdirt via OSC + hardware synths via MIDI all together playing in harmony in this [awesome video](https://www.youtube.com/watch?v=lxQgBeLQBgk). These are the related PRs:
- Create Midi Integration for Tauri Desktop app by @daslyfe in https://github.com/tidalcycles/strudel/pull/685
- add sleep timer + improve message iterating by @daslyfe in https://github.com/tidalcycles/strudel/pull/688
- fix MIDI CC messages by @vasilymilovidov in https://github.com/tidalcycles/strudel/pull/690
- Direct OSC Support in Tauri by @daslyfe in https://github.com/tidalcycles/strudel/pull/694
- Add logging from tauri by @daslyfe in https://github.com/tidalcycles/strudel/pull/697
- fix osc bundle timestamp glitches caused by drifting clock by @daslyfe in https://github.com/tidalcycles/strudel/pull/666
- Midi time fixes by @daslyfe in https://github.com/tidalcycles/strudel/pull/668
- [Bug Fix] Account for numeral notation when converting to midi by @daslyfe in https://github.com/tidalcycles/strudel/pull/656
- [Bug Fix] Midi: Don't treat note 0 as false by @daslyfe in https://github.com/tidalcycles/strudel/pull/657
- Create Midi Integration for Tauri Desktop app by @daslyfe in https://codeberg.org/uzu/strudel/pulls/685
- add sleep timer + improve message iterating by @daslyfe in https://codeberg.org/uzu/strudel/pulls/688
- fix MIDI CC messages by @vasilymilovidov in https://codeberg.org/uzu/strudel/pulls/690
- Direct OSC Support in Tauri by @daslyfe in https://codeberg.org/uzu/strudel/pulls/694
- Add logging from tauri by @daslyfe in https://codeberg.org/uzu/strudel/pulls/697
- fix osc bundle timestamp glitches caused by drifting clock by @daslyfe in https://codeberg.org/uzu/strudel/pulls/666
- Midi time fixes by @daslyfe in https://codeberg.org/uzu/strudel/pulls/668
- [Bug Fix] Account for numeral notation when converting to midi by @daslyfe in https://codeberg.org/uzu/strudel/pulls/656
- [Bug Fix] Midi: Don't treat note 0 as false by @daslyfe in https://codeberg.org/uzu/strudel/pulls/657
## Visuals
- 2 new FFT based vizualisations have now landed: [scope and fscope](https://github.com/tidalcycles/strudel/pull/677) (featured in the video at the top).
- pianoroll has new options, see [PR](https://github.com/tidalcycles/strudel/pull/679)
- 2 new FFT based vizualisations have now landed: [scope and fscope](https://codeberg.org/uzu/strudel/pulls/677) (featured in the video at the top).
- pianoroll has new options, see [PR](https://codeberg.org/uzu/strudel/pulls/679)
Related PRs:
- Scope by @felixroos in https://github.com/tidalcycles/strudel/pull/677 ([demo](https://strudel.tidalcycles.org/?hXVQF-KxMI8p))
- Pianoroll improvements by @felixroos in https://github.com/tidalcycles/strudel/pull/679 ([demo](https://strudel.tidalcycles.org/?aPMKqXGVMgSM))
- Scope by @felixroos in https://codeberg.org/uzu/strudel/pulls/677 ([demo](https://strudel.tidalcycles.org/?hXVQF-KxMI8p))
- Pianoroll improvements by @felixroos in https://codeberg.org/uzu/strudel/pulls/679 ([demo](https://strudel.tidalcycles.org/?aPMKqXGVMgSM))
## Voicings
There is now a new way to play chord voicings + a huge selection of chord voicings available. Find out more in these PRs:
- stateless voicings + tonleiter lib by @felixroos in https://github.com/tidalcycles/strudel/pull/647 ([demo](https://strudel.tidalcycles.org/?FoILM0Hs9y9f))
- ireal voicings by @felixroos in https://github.com/tidalcycles/strudel/pull/653 ([demo](https://strudel.tidalcycles.org/?bv_TjY9hOC28))
- stateless voicings + tonleiter lib by @felixroos in https://codeberg.org/uzu/strudel/pulls/647 ([demo](https://strudel.tidalcycles.org/?FoILM0Hs9y9f))
- ireal voicings by @felixroos in https://codeberg.org/uzu/strudel/pulls/653 ([demo](https://strudel.tidalcycles.org/?bv_TjY9hOC28))
## Adaptive Highlighting
Thanks to @mindofmatthew , the highlighting will adapt to edits instantly! Related PRs:
- More work on highlight IDs by @mindofmatthew in https://github.com/tidalcycles/strudel/pull/636
- Adaptive Highlighting by @felixroos in https://github.com/tidalcycles/strudel/pull/634
- More work on highlight IDs by @mindofmatthew in https://codeberg.org/uzu/strudel/pulls/636
- Adaptive Highlighting by @felixroos in https://codeberg.org/uzu/strudel/pulls/634
## UI Changes
- teletext theme + fonts by @felixroos in https://github.com/tidalcycles/strudel/pull/681 (featured in video at the top)
- togglable panel position by @felixroos in https://github.com/tidalcycles/strudel/pull/667
- teletext theme + fonts by @felixroos in https://codeberg.org/uzu/strudel/pulls/681 (featured in video at the top)
- togglable panel position by @felixroos in https://codeberg.org/uzu/strudel/pulls/667
## Other New Features
- slice: list mode by @felixroos in https://github.com/tidalcycles/strudel/pull/645 ([demo](https://strudel.tidalcycles.org/?bAYIqz5NLjRr))
- add emoji support by @felixroos in https://github.com/tidalcycles/strudel/pull/680 ([demo](https://strudel.tidalcycles.org/?a6FgLz475gN9))
- slice: list mode by @felixroos in https://codeberg.org/uzu/strudel/pulls/645 ([demo](https://strudel.tidalcycles.org/?bAYIqz5NLjRr))
- add emoji support by @felixroos in https://codeberg.org/uzu/strudel/pulls/680 ([demo](https://strudel.tidalcycles.org/?a6FgLz475gN9))
## Articles
- Understand pitch by @felixroos in https://github.com/tidalcycles/strudel/pull/652
- Understand pitch by @felixroos in https://codeberg.org/uzu/strudel/pulls/652
## Other Fixes & Enhancements
- fix: out of range error by @felixroos in https://github.com/tidalcycles/strudel/pull/630
- fix: update canvas size on window resize by @felixroos in https://github.com/tidalcycles/strudel/pull/631
- FIXES: TODO in rotateChroma by @bwagner in https://github.com/tidalcycles/strudel/pull/650
- snapshot tests: sort haps by part by @felixroos in https://github.com/tidalcycles/strudel/pull/637
- Delete old packages by @felixroos in https://github.com/tidalcycles/strudel/pull/639
- update vitest by @felixroos in https://github.com/tidalcycles/strudel/pull/651
- fix: welcome message for latestCode by @felixroos in https://github.com/tidalcycles/strudel/pull/659
- fix: always run previous trigger by @felixroos in https://github.com/tidalcycles/strudel/pull/660
- fix: out of range error by @felixroos in https://codeberg.org/uzu/strudel/pulls/630
- fix: update canvas size on window resize by @felixroos in https://codeberg.org/uzu/strudel/pulls/631
- FIXES: TODO in rotateChroma by @bwagner in https://codeberg.org/uzu/strudel/pulls/650
- snapshot tests: sort haps by part by @felixroos in https://codeberg.org/uzu/strudel/pulls/637
- Delete old packages by @felixroos in https://codeberg.org/uzu/strudel/pulls/639
- update vitest by @felixroos in https://codeberg.org/uzu/strudel/pulls/651
- fix: welcome message for latestCode by @felixroos in https://codeberg.org/uzu/strudel/pulls/659
- fix: always run previous trigger by @felixroos in https://codeberg.org/uzu/strudel/pulls/660
## New Contributors
- @daslyfe made their first contribution in https://github.com/tidalcycles/strudel/pull/656
- @Bubobubobubobubo made their first contribution in https://github.com/tidalcycles/strudel/pull/683
- @daslyfe made their first contribution in https://codeberg.org/uzu/strudel/pulls/656
- @Bubobubobubobubo made their first contribution in https://codeberg.org/uzu/strudel/pulls/683
**Full Changelog**: https://github.com/tidalcycles/strudel/compare/v0.8.0...v0.9.0
**Full Changelog**: https://codeberg.org/uzu/strudel/compare/v0.8.0...v0.9.0
A big thanks to all the contributors!
@@ -6,8 +6,6 @@ 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.
@@ -27,13 +25,13 @@ Let me write up some of the highlights:
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
- make 0.5hz cps the default by @yaxu in https://codeberg.org/uzu/strudel/pulls/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
- replace strudel.tidalcycles.org with strudel.cc by @felixroos in https://codeberg.org/uzu/strudel/pulls/768
## Strudel on Mastodon
@@ -43,52 +41,52 @@ Strudel now has a mastodon presence: https://social.toplap.org/@strudel
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
- Create phaser effect by @daslyfe in https://codeberg.org/uzu/strudel/pulls/798
- Multichannel audio by @daslyfe in https://codeberg.org/uzu/strudel/pulls/820
- Audio device selection by @daslyfe in https://codeberg.org/uzu/strudel/pulls/854
- Better convolution reverb by generating impulse responses by @Bubobubobubobubo and @felixroos in https://codeberg.org/uzu/strudel/pulls/718
- Add 'white', 'pink' and 'brown' oscillators + refactor synth by @Bubobubobubobubo and @felixroos in https://codeberg.org/uzu/strudel/pulls/713
- New noise type: "crackle" by @Bubobubobubobubo in https://codeberg.org/uzu/strudel/pulls/806
- Add support for using samples as impulse response buffers for the reverb by @vasilymilovidov in https://codeberg.org/uzu/strudel/pulls/717
- Compressor by @felixroos in https://codeberg.org/uzu/strudel/pulls/729
- Adding vibrato to Superdough sampler by @Bubobubobubobubo and @felixroos in https://codeberg.org/uzu/strudel/pulls/706
- Further Envelope improvements by @daslyfe in https://codeberg.org/uzu/strudel/pulls/868
- Add more vowel qualities for the vowels function by @fnordomat in https://codeberg.org/uzu/strudel/pulls/907
- pitch envelope by @felixroos in https://codeberg.org/uzu/strudel/pulls/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
- widgets by @felixroos in https://codeberg.org/uzu/strudel/pulls/714
- Slider afterthoughts by @felixroos in https://codeberg.org/uzu/strudel/pulls/723
- add xfade by @felixroos in https://codeberg.org/uzu/strudel/pulls/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
- Midi in by @felixroos in https://codeberg.org/uzu/strudel/pulls/699
- add midi clock support by @felixroos in https://codeberg.org/uzu/strudel/pulls/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
- Hydra integration by @felixroos in https://codeberg.org/uzu/strudel/pulls/759
- add options param to initHydra by @kasparsj in https://codeberg.org/uzu/strudel/pulls/808
- Hydra fixes and improvements by @atfornes in https://codeberg.org/uzu/strudel/pulls/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
- Vanilla repl 2 by @felixroos in https://codeberg.org/uzu/strudel/pulls/863
- Vanilla repl 3 by @felixroos in https://codeberg.org/uzu/strudel/pulls/865
- more work on vanilla repl: repl web component + package + MicroRepl by @felixroos in https://codeberg.org/uzu/strudel/pulls/866
- main repl vanillification by @felixroos in https://codeberg.org/uzu/strudel/pulls/873
- final vanillification by @felixroos in https://codeberg.org/uzu/strudel/pulls/876
## Doc Changes
@@ -97,25 +95,25 @@ Plenty of things have been added to the docs, including a [showcase of what peop
<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
- Showcase by @felixroos in https://codeberg.org/uzu/strudel/pulls/885
- Recipes by @felixroos in https://codeberg.org/uzu/strudel/pulls/742
- Document striate function by @ilesinge in https://codeberg.org/uzu/strudel/pulls/766
- Document adsr function by @ilesinge in https://codeberg.org/uzu/strudel/pulls/767
- Add function params in reference tab by @ilesinge in https://codeberg.org/uzu/strudel/pulls/785
- Update first-sounds.mdx by @bwagner in https://codeberg.org/uzu/strudel/pulls/794
- Update recap.mdx by @bwagner in https://codeberg.org/uzu/strudel/pulls/797
- Update pattern-effects.mdx by @bwagner in https://codeberg.org/uzu/strudel/pulls/796
- Update first-effects.mdx by @bwagner in https://codeberg.org/uzu/strudel/pulls/795
- Document pianoroll by @ilesinge in https://codeberg.org/uzu/strudel/pulls/784
- Add doc for euclidLegatoRot, wordfall and slider by @ilesinge in https://codeberg.org/uzu/strudel/pulls/801
- Improve documentation for synonym functions by @ilesinge in https://codeberg.org/uzu/strudel/pulls/800
- Add and style algolia search by @ilesinge in https://codeberg.org/uzu/strudel/pulls/827
- Fix a typo by @drewgbarnes in https://codeberg.org/uzu/strudel/pulls/830
- add mastodon link by @felixroos in https://codeberg.org/uzu/strudel/pulls/884
- adds a blog by @felixroos in https://codeberg.org/uzu/strudel/pulls/911
- community bakery by @felixroos in https://codeberg.org/uzu/strudel/pulls/923
- Blog improvements by @felixroos in https://codeberg.org/uzu/strudel/pulls/919
- 2 years blog post by @felixroos in https://codeberg.org/uzu/strudel/pulls/929
</details>
@@ -124,34 +122,34 @@ Plenty of things have been added to the docs, including a [showcase of what peop
<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 existing 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
- mini notation: international alphabets support by @ilesinge in https://codeberg.org/uzu/strudel/pulls/751
- Add shabda shortcut by @ilesinge in https://codeberg.org/uzu/strudel/pulls/740
- add play function by @felixroos in https://codeberg.org/uzu/strudel/pulls/758 (superseded by next)
- tidal style d1 ... d9 functions + more by @felixroos in https://codeberg.org/uzu/strudel/pulls/805
- add vscode bindings by @Dsm0 in https://codeberg.org/uzu/strudel/pulls/773
- Implement optional hover tooltip with function documentation by @ilesinge in https://codeberg.org/uzu/strudel/pulls/783
- samples loading shortcuts: by @felixroos in https://codeberg.org/uzu/strudel/pulls/788
- add option to disable active line highlighting in Code Settings by @kasparsj in https://codeberg.org/uzu/strudel/pulls/804
- Color hsl by @felixroos in https://codeberg.org/uzu/strudel/pulls/815
- Patterns tab + Refactor Panel by @felixroos in https://codeberg.org/uzu/strudel/pulls/769
- patterns tab: import patterns + style by @felixroos in https://codeberg.org/uzu/strudel/pulls/852
- Export patterns + ui tweaks by @felixroos in https://codeberg.org/uzu/strudel/pulls/855
- Pattern organization by @felixroos in https://codeberg.org/uzu/strudel/pulls/858
- Sound Import from local file system by @daslyfe in https://codeberg.org/uzu/strudel/pulls/839
- bugfix: suspend and close existing audio context when changing interface by @daslyfe in https://codeberg.org/uzu/strudel/pulls/882
- add root mode for voicings by @felixroos in https://codeberg.org/uzu/strudel/pulls/887
- scales can now be anchored by @felixroos in https://codeberg.org/uzu/strudel/pulls/888
- add dough function for raw dsp by @felixroos in https://codeberg.org/uzu/strudel/pulls/707 (experimental)
- support mininotation '..' range operator, fixes #715 by @yaxu in https://codeberg.org/uzu/strudel/pulls/716
- Add pick and squeeze functions by @daslyfe in https://codeberg.org/uzu/strudel/pulls/771
- support , in < > by @felixroos in https://codeberg.org/uzu/strudel/pulls/886
- public sharing by @felixroos in https://codeberg.org/uzu/strudel/pulls/910
- pick, pickmod, inhabit, inhabitmod by @yaxu in https://codeberg.org/uzu/strudel/pulls/921
- Mini-notation additions towards tidal compatibility by @yaxu in https://codeberg.org/uzu/strudel/pulls/926
- add pickF and pickmodF by @geikha in https://codeberg.org/uzu/strudel/pulls/924
- Make splice cps-aware by @yaxu in https://codeberg.org/uzu/strudel/pulls/932
- Refactor cps functions by @felixroos in https://codeberg.org/uzu/strudel/pulls/933
- Add useful pattern selection behavior for performing. by @daslyfe in https://codeberg.org/uzu/strudel/pulls/897
</details>
@@ -160,79 +158,79 @@ Plenty of things have been added to the docs, including a [showcase of what peop
<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 trailing 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
- fix: finally repair envelopes by @felixroos in https://codeberg.org/uzu/strudel/pulls/861
- fix: reverb regenerate loophole by @felixroos in https://codeberg.org/uzu/strudel/pulls/726
- fix: reverb roomsize not required by @felixroos in https://codeberg.org/uzu/strudel/pulls/731
- fix: reverb sampleRate by @felixroos in https://codeberg.org/uzu/strudel/pulls/732
- consume n with scale by @felixroos in https://codeberg.org/uzu/strudel/pulls/727
- fix: hashes in urls by @felixroos in https://codeberg.org/uzu/strudel/pulls/728
- [Bug Fix] chooseWith: prevent pattern from stopping audio when selection is >= 1 or < 0 by @daslyfe in https://codeberg.org/uzu/strudel/pulls/741
- Fix addivite synthesis phases by @felixroos in https://codeberg.org/uzu/strudel/pulls/762
- fix: scale offset by @felixroos in https://codeberg.org/uzu/strudel/pulls/764
- fix zen mode logo overlap by @felixroos in https://codeberg.org/uzu/strudel/pulls/760
- fix: share copy to clipboard + alert by @felixroos in https://codeberg.org/uzu/strudel/pulls/774
- fix: style issues by @felixroos in https://codeberg.org/uzu/strudel/pulls/781
- Fix scope pos + document by @felixroos in https://codeberg.org/uzu/strudel/pulls/786
- don't use anchor links for reference by @felixroos in https://codeberg.org/uzu/strudel/pulls/791
- remove unwanted cm6 outline for strudelTheme by @kasparsj in https://codeberg.org/uzu/strudel/pulls/802
- FIXES: palindrome abc -> abccba by @bwagner in https://codeberg.org/uzu/strudel/pulls/831
- Bug Fix #119: Clock drift by @daslyfe in https://codeberg.org/uzu/strudel/pulls/874
- bugfix: sound select indexes out of bounds by @daslyfe in https://codeberg.org/uzu/strudel/pulls/871
- Error tolerance by @felixroos in https://codeberg.org/uzu/strudel/pulls/880
- fix: make sure n is never undefined before nanFallback by @felixroos in https://codeberg.org/uzu/strudel/pulls/881
- fix: invisible selection on vim + emacs mode by @felixroos in https://codeberg.org/uzu/strudel/pulls/889
- fix: autocomplete / tooltip code example bug by @felixroos in https://codeberg.org/uzu/strudel/pulls/898
- Fix examples page, piano() and a few workshop imgs by @shiyouganai in https://codeberg.org/uzu/strudel/pulls/848
- fix: trailing slash confusion by @felixroos in https://codeberg.org/uzu/strudel/pulls/743
- fix: try different trailing slash behavior by @felixroos in https://codeberg.org/uzu/strudel/pulls/744
- Fix krill build command in README by @ilesinge in https://codeberg.org/uzu/strudel/pulls/748
- Fix for #1. Enables named instruments for csoundm. by @gogins in https://codeberg.org/uzu/strudel/pulls/662
- fix: missing hash for links starting with / by @felixroos in https://codeberg.org/uzu/strudel/pulls/845
- fix: swatch png src by @felixroos in https://codeberg.org/uzu/strudel/pulls/846
- Fix edge case with rehype-urls and trailing slashes in image file paths by @shiyouganai in https://codeberg.org/uzu/strudel/pulls/849
- fix: multiple repls by @felixroos in https://codeberg.org/uzu/strudel/pulls/813
- Fix chunk, add fastChunk and repeatCycles by @yaxu in https://codeberg.org/uzu/strudel/pulls/712
- Update tauri.yml workflow file by @vasilymilovidov in https://codeberg.org/uzu/strudel/pulls/705
- vite-vanilla-repl readme fix by @felixroos in https://codeberg.org/uzu/strudel/pulls/737
- completely revert config mess by @felixroos in https://codeberg.org/uzu/strudel/pulls/745
- hopefully fix trailing slashes bug by @felixroos in https://codeberg.org/uzu/strudel/pulls/753
- Update vite pwa by @felixroos in https://codeberg.org/uzu/strudel/pulls/772
- Update to Astro 3 by @felixroos in https://codeberg.org/uzu/strudel/pulls/775
- support multiple named serial connections, change default baudrate by @yaxu in https://codeberg.org/uzu/strudel/pulls/551
- CHANGES: github action checkout v2 -> v4 by @bwagner in https://codeberg.org/uzu/strudel/pulls/837
- CHANGES: pin pnpm to version 8.3.1 by @bwagner in https://codeberg.org/uzu/strudel/pulls/834
- CHANGES: github action pnpm version from 7 to 8.3.1 by @bwagner in https://codeberg.org/uzu/strudel/pulls/835
- ADDS: JetBrains IDE files and directories to .gitignore by @bwagner in https://codeberg.org/uzu/strudel/pulls/840
- Prevent 404 on Algolia crawls by @ilesinge in https://codeberg.org/uzu/strudel/pulls/838
- Add in fixes from my fork to slashocalypse branch by @shiyouganai in https://codeberg.org/uzu/strudel/pulls/843
- improve slashing + base href behavior by @felixroos in https://codeberg.org/uzu/strudel/pulls/842
- CHANGES: pnpm 8.1.3 to 8.11.0 by @bwagner in https://codeberg.org/uzu/strudel/pulls/850
- add missing trailing slashes by @felixroos in https://codeberg.org/uzu/strudel/pulls/860
- move all examples to separate examples folder by @felixroos in https://codeberg.org/uzu/strudel/pulls/878
- Dependency update by @felixroos in https://codeberg.org/uzu/strudel/pulls/879
- Update Vite version so hot reload works properly with newest pnpm version by @daslyfe in https://codeberg.org/uzu/strudel/pulls/892
- prevent vite from complaining about additional exports in jsx files by @daslyfe in https://codeberg.org/uzu/strudel/pulls/891
- fix some build warnings by @felixroos in https://codeberg.org/uzu/strudel/pulls/902
- Remove hideHeader for better mobile UI and consistency by @rjulian in https://codeberg.org/uzu/strudel/pulls/894
- Fix: swatch/[name].png.js static path by @oscarbyrne in https://codeberg.org/uzu/strudel/pulls/916
- rename @strudel.cycles/_ packages to @strudel/_ by @felixroos in https://codeberg.org/uzu/strudel/pulls/917
- `pick` now accepts lookup tables, with alternate cycle squeezing behaviour as new `inhabit` function by @yaxu in https://codeberg.org/uzu/strudel/pulls/918
- Revert "`pick` now accepts lookup tables, with alternate cycle squeezing behaviour as new `inhabit` function" by @yaxu in https://codeberg.org/uzu/strudel/pulls/920
- Fix pattern tab not showing patterns without created date by @daslyfe in https://codeberg.org/uzu/strudel/pulls/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
- @ilesinge made their first contribution in https://codeberg.org/uzu/strudel/pulls/748
- @Dsm0 made their first contribution in https://codeberg.org/uzu/strudel/pulls/773
- @kasparsj made their first contribution in https://codeberg.org/uzu/strudel/pulls/802
- @atfornes made their first contribution in https://codeberg.org/uzu/strudel/pulls/818
- @drewgbarnes made their first contribution in https://codeberg.org/uzu/strudel/pulls/830
- @shiyouganai made their first contribution in https://codeberg.org/uzu/strudel/pulls/843
- @rjulian made their first contribution in https://codeberg.org/uzu/strudel/pulls/894
- @fnordomat made their first contribution in https://codeberg.org/uzu/strudel/pulls/907
- @oscarbyrne made their first contribution in https://codeberg.org/uzu/strudel/pulls/916
- @geikha made their first contribution in https://codeberg.org/uzu/strudel/pulls/924
**Full Changelog**: https://github.com/tidalcycles/strudel/compare/v0.9.0...v1.0.0
**Full Changelog**: https://codeberg.org/uzu/strudel/compare/v0.9.0...v1.0.0
@@ -0,0 +1,317 @@
---
title: 'Release Notes v1.1.0'
description: ''
date: '2024-06-02'
tags: ['meta']
author: froos
---
These are the release notes for Strudel 1.1.0 aka "Bananensplit".
The last release was over 19 weeks ago, so a lot of things have happened!
First, here's a little demo, teasing some of the new features:
import { Youtube } from '@src/components/Youtube';
<Youtube client:only="react" id="2Qu5lMHruio" />
Let's write up some of the highlights:
## New DSP Features
### Stereo Supersaw
with spread, unison, and detune parameters
```plaintext
note("d f a a# a d3").fast(2)
.s("supersaw").spread(".8").detune(.3).unison("2 7")
```
### Analog "ladder" filter type
works great for acid basslines and vibey tones
```plaintext
note("{d d d a a# d3 f4}%16".sub(12)).gain(1).s("sawtooth")
.lpf(200).lpenv(slider(1.36,0,8)).lpq(7).distort("1.5:.7")`
.ftype('ladder')
```
### stereo distortion effect
```plaintext
note("{g g a# g g4}%8".add("{0 7 12 0}%8")).lpf(500)
.s("supersaw").dist("4:.2")
```
## Editor Features
### inline viz
The editor now supports multiple visuals within the code, using the `_` prefix for viz functions:
<img
width="595"
alt="Screenshot 2024-06-01 at 01 23 51"
src="https://codeberg.org/uzu/strudel/assets/12023032/978fee85-e533-4da6-a245-d20d0083f57e"
/>
- `._pianoroll()`: inline pianoroll
- `._punchcard()`: inline punchcard
- `._scope()`: inline scope
- `._pitchwheel()`: inline pitchwheel
For more info, check out the new [Visual Feedback Page](https://strudel.cc/learn/visual-feedback/)
### label notation
This new notation simplifies writing patterns at the top level:
```plaintext
d1: s("bd*4")
d2: s("[- hh]*4")
```
This is equivalent to:
```plaintext
stack(
s("bd*4"),
s("[- hh]*4")
)
```
The labels you choose are arbitrary, the above `d1` and `d2` are a typical thing you'd write in tidal, for example `d1 $ s "bd*4"`.
If the same label is used multiple times, the last one wins:
```plaintext
d1: s("bd*4")
d1: s("[- hh]*4") // <-- only this plays
```
There is a special label anonymous label `$`, which can appear multiple times without overriding itself:
```plaintext
// both of these will play:
$: s("bd*4")
$: s("[- hh]*4")
```
You can mute a pattern by prefixing `_`:
```plaintext
_$: s("bd*4") // <-- this one is muted
$: s("[- hh]*4")
```
To run a transformation on all patterns, you can use `all`:
```plaintext
$: s("bd*4")
$: s("[- hh]*4")
all(x=>x.room(.5))
```
This notation is now the recommended way to [play patterns in parallel](https://strudel.cc/workshop/first-notes/#playing-multiple-patterns)
### Clock sync between multiple instances
timing has received a major overhaul, and is now much more accurate on all browsers. Additionally, you can now sync timing across multiple windows.
![Screenshot 2024-06-02 at 11 24 40PM](https://codeberg.org/uzu/strudel/assets/47068718/840be744-a13e-4d7b-ab09-50d3a70b1f85)
### Better sample upload support
you can now upload large amounts of samples much faster across all browsers including on IOS devices. supported filetypes now include: ogg flac mp3 wav aac m4a
### experimental tidal syntax
The new `tidal` function allows you to write strudel patterns in tidal syntax:
```plaintext
await initTidal()
tidal`
d1 $ s "bd*4"
d2 $ s "[- hh]*4"
`
```
As we're looking to improve compatibility with tidal, we're happy to hear feedback.
## breaking changes
This release comes with a bunch of breaking changes. If you find your patterns to sound different, check out the PRs below for guidance on how to update them. Most of these changes shouldn't affect a lot of patterns.
In case of doubt, add the line `// @version 1.0` to your old pattern.
If you're having problems, please let us know!
- remove legacy legato + duration implementations by @felixroos in https://codeberg.org/uzu/strudel/pull/965
- Velocity in value by @felixroos in https://codeberg.org/uzu/strudel/pull/974
- use ireal as default voicing dict by @felixroos https://codeberg.org/uzu/strudel/pull/967
- Color in hap value by @felixroos https://codeberg.org/uzu/strudel/pull/1007
- rename trig -> reset, trigzero -> restart by @felixroos https://codeberg.org/uzu/strudel/pull/1010
- remove dangerous arithmetic feature by @felixroos https://codeberg.org/uzu/strudel/pull/1030
- change fanchor to 0 by @daslyfe https://codeberg.org/uzu/strudel/pull/1107
## superdough features
- replace shape with distort in learn doc by @daslyfe https://codeberg.org/uzu/strudel/pull/982
- Worklet Improvents / fixes by @daslyfe https://codeberg.org/uzu/strudel/pull/963
- supersaw oscillator by @daslyfe https://codeberg.org/uzu/strudel/pull/978
- Add analog-style ladder filter by @daslyfe https://codeberg.org/uzu/strudel/pull/1103
- Calculate phaser modulation phase based on time by @daslyfe https://codeberg.org/uzu/strudel/pull/1110
- rollback phaser by @daslyfe https://codeberg.org/uzu/strudel/pull/1113
## editor / ui features
- 'Enable Bracket Matching' option in Codemirror by @eefano https://codeberg.org/uzu/strudel/pull/956
- REPL sync between windows by @daslyfe https://codeberg.org/uzu/strudel/pull/900
- inline viz / widgets package by @felixroos https://codeberg.org/uzu/strudel/pull/989
- Inline punchcard + spiral by @felixroos https://codeberg.org/uzu/strudel/pull/1008
- More fonts by @felixroos https://codeberg.org/uzu/strudel/pull/1023
- better theme integration for visuals + various fixes by @felixroos https://codeberg.org/uzu/strudel/pull/1024
- add setting for sync flag by @felixroos https://codeberg.org/uzu/strudel/pull/1025
- add closeBrackets setting by @felixroos https://codeberg.org/uzu/strudel/pull/1031
- add font file types to offline cache by @felixroos https://codeberg.org/uzu/strudel/pull/1032
- pitchwheel visual by @felixroos https://codeberg.org/uzu/strudel/pull/1041
- repl: set document.title from @title by @kasparsj https://codeberg.org/uzu/strudel/pull/1090
- Samples tab improvements by @daslyfe https://codeberg.org/uzu/strudel/pull/1102
## language features
- pickOut(), pickRestart(), pickReset() by @eefano https://codeberg.org/uzu/strudel/pull/950
- Auto await samples by @felixroos https://codeberg.org/uzu/strudel/pull/955
- feat: can now invert euclid pulses with negative numbers by @felixroos https://codeberg.org/uzu/strudel/pull/959
- Nested controls by @felixroos https://codeberg.org/uzu/strudel/pull/973
- alias - for ~ by @yaxu https://codeberg.org/uzu/strudel/pull/981
- Beat-oriented functionality by @yaxu https://codeberg.org/uzu/strudel/pull/976
- Labeled statements by @felixroos https://codeberg.org/uzu/strudel/pull/991
- accidentals in scale degrees by @eefano https://codeberg.org/uzu/strudel/pull/1000
- Feature: tactus marking by @yaxu https://codeberg.org/uzu/strudel/pull/1021
- Tactus tidy by @yaxu https://codeberg.org/uzu/strudel/pull/1027
- Wax, wane, taper and taperlist by @yaxu https://codeberg.org/uzu/strudel/pull/1042
- transpose: support all combinations of numbers and strings for notes and intervals by @felixroos https://codeberg.org/uzu/strudel/pull/1048
- anonymous patterns + muting by @felixroos https://codeberg.org/uzu/strudel/pull/1059
- add swing + swingBy by @felixroos https://codeberg.org/uzu/strudel/pull/1038
- Stepwise functions from Tidal by @yaxu https://codeberg.org/uzu/strudel/pull/1060
- Tactus tweaks - fixes for maintaining tactus and highlight locations by @yaxu https://codeberg.org/uzu/strudel/pull/1065
- Fix stepjoin by @yaxu https://codeberg.org/uzu/strudel/pull/1067
- More tactus tidying by @yaxu https://codeberg.org/uzu/strudel/pull/1071
- Tactus calculation toggle and breaking change to tactus calculation in fast/slow/hurry by @yaxu https://codeberg.org/uzu/strudel/pull/1081
- hs2js package / tidal parser by @felixroos https://codeberg.org/uzu/strudel/pull/870
- Add the mousex and mousey signal by @Enelg52 https://codeberg.org/uzu/strudel/pull/1112
- can now access strudelMirror from repl by @felixroos https://codeberg.org/uzu/strudel/pull/1117
## sampler
If you have nodejs installed on your system, you can now use [@strudel/sampler](https://www.npmjs.com/package/@strudel/sampler) to serve samples from disk to the REPL or flok.
- local sample server cli by @felixroos https://codeberg.org/uzu/strudel/pull/1033
- Fix sampler paths by @felixroos https://codeberg.org/uzu/strudel/pull/1034
- Fix sampler windows by @felixroos https://codeberg.org/uzu/strudel/pull/1108
- fix sampler on windows by @geikha https://codeberg.org/uzu/strudel/pull/1109
## docs
- V1 release notes by @felixroos https://codeberg.org/uzu/strudel/pull/935
- Minor documentation error: Update first-sounds.mdx by @mhetrick https://codeberg.org/uzu/strudel/pull/941
- Update synths.mdx by @andresgottlieb https://codeberg.org/uzu/strudel/pull/984
- using strudel in your project guide + cleanup examples by @felixroos https://codeberg.org/uzu/strudel/pull/1006
- Document signals by @ilesinge https://codeberg.org/uzu/strudel/pull/1015
- improve tutorial + custom samples doc by @felixroos https://codeberg.org/uzu/strudel/pull/1053
- fix cr typo on first-sounds.mdx by @cleary https://codeberg.org/uzu/strudel/pull/1068
- fix first sounds typo by @cleary https://codeberg.org/uzu/strudel/pull/1069
- add `<...>` to first-sounds.mdx recap by @cleary https://codeberg.org/uzu/strudel/pull/1070
- add nesting to `off` example variation in pattern-effects.mdx by @cleary https://codeberg.org/uzu/strudel/pull/1075
- fix translation issue in first-effects.mdx by @cleary https://codeberg.org/uzu/strudel/pull/1072
- add signals to recap in first-effects.mdx by @cleary https://codeberg.org/uzu/strudel/pull/1073
- fix docs on alignment.mdx by @diegodorado https://codeberg.org/uzu/strudel/pull/1076
- fix little dub tune example by @lukad https://codeberg.org/uzu/strudel/pull/1104
- clarify `off` in pattern-effects.mdx by @cleary https://codeberg.org/uzu/strudel/pull/1074
- Fixes drawPianoroll import in codemirror example by @giohappy https://codeberg.org/uzu/strudel/pull/1116
- Migrate tutorial fanchor by @felixroos https://codeberg.org/uzu/strudel/pull/1122
## internals
- remove cjs builds by @felixroos https://codeberg.org/uzu/strudel/pull/945
- controls refactoring: simplify exports by @felixroos https://codeberg.org/uzu/strudel/pull/962
- move canvas related helpers from core to new draw package by @felixroos https://codeberg.org/uzu/strudel/pull/971
- remove canvas, externalize samples, delete junk by @felixroos https://codeberg.org/uzu/strudel/pull/1003
- Improve performance of ! (replicate) by @yaxu https://codeberg.org/uzu/strudel/pull/1084
- Benchmarks by @yaxu https://codeberg.org/uzu/strudel/pull/1079
## fixes
- fix midi issue on firefox and added quote error by @Enelg52 https://codeberg.org/uzu/strudel/pull/936
- fix: pianoroll sorting by @felixroos https://codeberg.org/uzu/strudel/pull/938
- account for cps in midi time duration by @daslyfe https://codeberg.org/uzu/strudel/pull/954
- fix script importable packages (web + repl) by @felixroos https://codeberg.org/uzu/strudel/pull/957
- fix: reset global fx on pattern change by @felixroos https://codeberg.org/uzu/strudel/pull/960
- add debounce to logger by @felixroos https://codeberg.org/uzu/strudel/pull/968
- fix for transpose(): preserve hap value object structure by @eefano https://codeberg.org/uzu/strudel/pull/966
- fix: clear hydra on reset by @felixroos https://codeberg.org/uzu/strudel/pull/983
- little fix for withVal by @eefano https://codeberg.org/uzu/strudel/pull/980
- fix: share now shares what's visible instead of active by @felixroos https://codeberg.org/uzu/strudel/pull/985
- Fix pure mini highlight by @yaxu https://codeberg.org/uzu/strudel/pull/994
- fix: await injectPatternMethods by @felixroos https://codeberg.org/uzu/strudel/pull/1012
- update undocumented script by @felixroos https://codeberg.org/uzu/strudel/pull/1013
- eliminate chromium clock jitter by @felixroos https://codeberg.org/uzu/strudel/pull/1004
- Repl sync fixes by @daslyfe https://codeberg.org/uzu/strudel/pull/1014
- hotfix for 1017 by @daslyfe https://codeberg.org/uzu/strudel/pull/1020
- fix cyclist fizzling out by @felixroos https://codeberg.org/uzu/strudel/pull/1046
- Midi Time hotfix for scheduler updates by @daslyfe https://codeberg.org/uzu/strudel/pull/1047
- fix: do not reset cc input values on each eval by @felixroos https://codeberg.org/uzu/strudel/pull/1054
- Fix wchooseCycles not picking the whole pattern by @ilesinge https://codeberg.org/uzu/strudel/pull/1061
- fix OSC timing for recent scheduler updates by @daslyfe https://codeberg.org/uzu/strudel/pull/1062
- clarify license by @yaxu https://codeberg.org/uzu/strudel/pull/1064
- fix failing format test by @daslyfe https://codeberg.org/uzu/strudel/pull/1077
- fix: url parsing with extra params by @felixroos https://codeberg.org/uzu/strudel/pull/1083
- fix: csound + dough timing by @felixroos https://codeberg.org/uzu/strudel/pull/1086
- fix: missing events due to premature worklet cleanup by @felixroos https://codeberg.org/uzu/strudel/pull/1089
- Use sessionStorage for viewingPatternData and activePattern by @kasparsj https://codeberg.org/uzu/strudel/pull/1091
- osc: couple of fixes by @kasparsj https://codeberg.org/uzu/strudel/pull/1093
- web package fixes by @felixroos https://codeberg.org/uzu/strudel/pull/1044
- Fix audio worklets by @daslyfe https://codeberg.org/uzu/strudel/pull/1114
- fix: use full repl in web package by @felixroos https://codeberg.org/uzu/strudel/pull/1119
- [BUG FIX] Audio worklets sometimes dont load by @daslyfe https://codeberg.org/uzu/strudel/pull/1121
## New Contributors
- @mhetrick made their first contribution https://codeberg.org/uzu/strudel/pull/941
- @eefano made their first contribution https://codeberg.org/uzu/strudel/pull/956
- @Enelg52 made their first contribution https://codeberg.org/uzu/strudel/pull/936
- @andresgottlieb made their first contribution https://codeberg.org/uzu/strudel/pull/984
- @cleary made their first contribution https://codeberg.org/uzu/strudel/pull/1068
- @diegodorado made their first contribution https://codeberg.org/uzu/strudel/pull/1076
- @lukad made their first contribution https://codeberg.org/uzu/strudel/pull/1104
- @giohappy made their first contribution https://codeberg.org/uzu/strudel/pull/1116
A huge thanks to all contributors!!!
## Packages
- @strudel/codemirror@1.1.0
- @strudel/core@1.1.0
- @strudel/csound@1.1.0
- @strudel/draw@1.1.0
- @strudel/embed@1.1.0
- hs2js@0.1.0
- @strudel/hydra@1.1.0
- @strudel/midi@1.1.0
- @strudel/mini@1.1.0
- @strudel/osc@1.1.0
- @strudel/repl@1.1.0
- @strudel/sampler@0.1.0
- @strudel/serial@1.1.0
- @strudel/soundfonts@1.1.0
- superdough@1.1.0
- @strudel/tidal@0.1.0
- @strudel/tonal@1.1.0
- @strudel/transpiler@1.1.0
- @strudel/web@1.1.0
- @strudel/webaudio@1.1.0
- @strudel/xen@1.1.0
**Full Changelog**: https://codeberg.org/uzu/strudel/compare/v1.0.0...v1.1.0
@@ -0,0 +1,186 @@
---
title: 'Release Notes v1.2.0'
description: ''
date: '2025-05-01'
tags: ['meta']
author: froos
---
## What's Changed
## highlights
- [stepwise functions](https://strudel.cc/learn/stepwise/) ([PR](https://github.com/tidalcycles/strudel/pull/1262))
- [midimaps](https://strudel.cc/learn/input-output/#midimaps) ([PR](https://github.com/tidalcycles/strudel/pull/1274))
- [spectrum](https://strudel.cc/learn/visual-feedback/#spectrum) ([PR](https://github.com/tidalcycles/strudel/pull/1213))
- [mqtt](https://strudel.cc/learn/input-output/#mqtt) ([PR](https://github.com/tidalcycles/strudel/pull/1224))
- pulse oscillator (todo: https://github.com/tidalcycles/strudel/issues/1336) ([PR](https://github.com/tidalcycles/strudel/pull/1304))
- theme improvements
## breaking changes
- [breaking change] Sample signals from query onset, rather than midpoint by @yaxu in https://github.com/tidalcycles/strudel/pull/1278
- change behaviour of polymeter, and remove polymeterSteps by @yaxu in https://github.com/tidalcycles/strudel/pull/1302
- Polish, rename, and document stepwise functions by @yaxu in https://github.com/tidalcycles/strudel/pull/1262
### superdough
- feat: Create Pulse Oscillator with variable PWM by @daslyfe in https://github.com/tidalcycles/strudel/pull/1304
- add num samples (edited numbers) by @yaxu in https://github.com/tidalcycles/strudel/pull/1309
- Add num samples from 0 up to 20 by @yaxu in https://github.com/tidalcycles/strudel/pull/1310
- feat: add max polyphony feature for superdough by @daslyfe in https://github.com/tidalcycles/strudel/pull/1317
### docs
- doc: visual functions + refactor onPaint by @felixroos in https://github.com/tidalcycles/strudel/pull/1125
- Labeled statements doc by @felixroos in https://github.com/tidalcycles/strudel/pull/1126
- Correct spelling mistakes by @EdwardBetts in https://github.com/tidalcycles/strudel/pull/1183
- remove redundant example for cat, update snapshot by @kdiab in https://github.com/tidalcycles/strudel/pull/1189
- chore: Edit run locally instructions in README.md by @ChinoUkaegbu in https://github.com/tidalcycles/strudel/pull/1206
- suggested changes to voicings.mdx by @bwagner in https://github.com/tidalcycles/strudel/pull/1231
- Documentation for all/each, and bugfix for each by @yaxu in https://github.com/tidalcycles/strudel/pull/1233
- Update documentation for param value modification by @gillespi314 in https://github.com/tidalcycles/strudel/pull/1238
- fix docs for beat function by @daslyfe in https://github.com/tidalcycles/strudel/pull/1248
- understand voicings page by @felixroos in https://github.com/tidalcycles/strudel/pull/1230
- add reference package by @felixroos in https://github.com/tidalcycles/strudel/pull/1252
- Stepwise documentation tweaks, with mridangam samples by @yaxu in https://github.com/tidalcycles/strudel/pull/1275
- showcase tweaks by @yaxu in https://github.com/tidalcycles/strudel/pull/1291
- Signpost licenses for source code and samples a bit more, ref #1277 by @yaxu in https://github.com/tidalcycles/strudel/pull/1289
- Fix misplaced ending sentence by @makmanalp in https://github.com/tidalcycles/strudel/pull/1296
- Fix typo pattnr by @ReneNyffenegger in https://github.com/tidalcycles/strudel/pull/1316
- update docs to reflect import sounds tab change by @hpunq in https://github.com/tidalcycles/strudel/pull/1332
### ui improvements
- Udels (MultiFrame Strudel) Revisited by @daslyfe in https://github.com/tidalcycles/strudel/pull/1132
- Create audio target selector for OSC/Superdirt by @daslyfe in https://github.com/tidalcycles/strudel/pull/1160
- Add a search bar to the REPL Reference tab by @netux in https://github.com/tidalcycles/strudel/pull/1165
- Adding search bar (soundtab.jsx) by @Bubobubobubobubo in https://github.com/tidalcycles/strudel/pull/1185
- add 2 new ui settings by @felixroos in https://github.com/tidalcycles/strudel/pull/1200
- Theme glowup by @felixroos in https://github.com/tidalcycles/strudel/pull/1268
- Create Pattern Page Pagination by @daslyfe in https://github.com/tidalcycles/strudel/pull/1287
- feat: Theme improvements by @daslyfe in https://github.com/tidalcycles/strudel/pull/1295
- feat: new themes + theme improvements by @daslyfe in https://github.com/tidalcycles/strudel/pull/1326
- Add new "import-sounds" tab with explanation on folder import by @hpunq in https://github.com/tidalcycles/strudel/pull/1329
- Add Icon to import sample button by @daslyfe in https://github.com/tidalcycles/strudel/pull/1331
- better spacing in zen mode by @felixroos in https://github.com/tidalcycles/strudel/pull/1147
- Screenreader improvements by @yaxu in https://github.com/tidalcycles/strudel/pull/1158
- colorize console + tweak header by @felixroos in https://github.com/tidalcycles/strudel/pull/1203
- Menu Panel Improvements! by @daslyfe in https://github.com/tidalcycles/strudel/pull/1193
- Make panel hover behavior optional by @daslyfe in https://github.com/tidalcycles/strudel/pull/1199
- REPL: solo and sync configuration by @bthj in https://github.com/tidalcycles/strudel/pull/1214
- enhancement: make error messages easier to read by @daslyfe in https://github.com/tidalcycles/strudel/pull/1315
### mqtt
- MQTT support by @yaxu in https://github.com/tidalcycles/strudel/pull/1224
- MQTT - if password isn't provided, prompt for one by @yaxu in https://github.com/tidalcycles/strudel/pull/1249
- MQTT - support adding hap duration and cps metadata to JSON messages by @yaxu in https://github.com/tidalcycles/strudel/pull/1279
- make mqtt topic patternable by @yaxu in https://github.com/tidalcycles/strudel/pull/1280
- Bugfix: update mqtt connections dictionary by @yaxu in https://github.com/tidalcycles/strudel/pull/1281
- mqtt bugfix - connection check by @yaxu in https://github.com/tidalcycles/strudel/pull/1282
### new functions
- Add scramble and shuffle by @yaxu in https://github.com/tidalcycles/strudel/pull/1167
- polyJoin by @yaxu in https://github.com/tidalcycles/strudel/pull/1168
- Add seqPLoop from Tidal by @yaxu in https://github.com/tidalcycles/strudel/pull/1182
- add filter + filterWhen + within by @felixroos in https://github.com/tidalcycles/strudel/pull/1039
- Add bite function by @yaxu in https://github.com/tidalcycles/strudel/pull/1187
- markcss by @felixroos in https://github.com/tidalcycles/strudel/pull/1202
- "beat" function for "step sequencer" style rhythm notation by @daslyfe in https://github.com/tidalcycles/strudel/pull/1237
- Add s_zip for 'cat'-ing patterns together step-by-step, bugfix `steps` by @yaxu in https://github.com/tidalcycles/strudel/pull/1208
- "stretch" function (phase vocoder) by @daslyfe in https://github.com/tidalcycles/strudel/pull/1130
- add basic spectrum function by @felixroos in https://github.com/tidalcycles/strudel/pull/1213
- Add onKey function for custom key commands for patterns by @daslyfe in https://github.com/tidalcycles/strudel/pull/1235
- Add binary and binaryN by @heerman in https://github.com/tidalcycles/strudel/pull/1226
- midimaps by @felixroos in https://github.com/tidalcycles/strudel/pull/1274
- small feat: Add alias for segment and ribbon by @daslyfe in https://github.com/tidalcycles/strudel/pull/1314
- feat: Create scrub function for scrubbing an audio file by @daslyfe in https://github.com/tidalcycles/strudel/pull/1321
- feat: Improve gain curve by @daslyfe in https://github.com/tidalcycles/strudel/pull/1318
- Chop chop by @yaxu in https://github.com/tidalcycles/strudel/pull/1078
### more
- Make `all()` post-stack again, and add `each()` for pre-stack by @yaxu in https://github.com/tidalcycles/strudel/pull/1229
- Add stepBind, and some toplevel aliases for binds and withValue by @yaxu in https://github.com/tidalcycles/strudel/pull/1241
- Make cps patternable by @eefano in https://github.com/tidalcycles/strudel/pull/1001
- Allow wchooseCycles probabilities to be patterned by @yaxu in https://github.com/tidalcycles/strudel/pull/1292
- @strudel/sampler improvements by @felixroos in https://github.com/tidalcycles/strudel/pull/1288
### refactor
- expose comment commands by @felixroos in https://github.com/tidalcycles/strudel/pull/1136
- containerize/seperate out boolean checks for repl types/Repl logic into bespoke components. by @daslyfe in https://github.com/tidalcycles/strudel/pull/1163
- Improve + simplify neocyclist timing by @daslyfe in https://github.com/tidalcycles/strudel/pull/1164
- Make phaser control consistent with superdirt by @daslyfe in https://github.com/tidalcycles/strudel/pull/1178
- Revert "Make phaser control consistent with superdirt" by @daslyfe in https://github.com/tidalcycles/strudel/pull/1179
- make phaser control match superdirt by @daslyfe in https://github.com/tidalcycles/strudel/pull/1180
- refactor sampler by @felixroos in https://github.com/tidalcycles/strudel/pull/1101
- update lockfile + minor versions by @felixroos in https://github.com/tidalcycles/strudel/pull/1198
- Preserve tactus for 'degrade' and friends, and tidy up 'pick' and friends by @yaxu in https://github.com/tidalcycles/strudel/pull/1205
- Apply `all` function to individual patterns rather than final stack by @yaxu in https://github.com/tidalcycles/strudel/pull/1209
- Revert "Fix sometimes" by @yaxu in https://github.com/tidalcycles/strudel/pull/1267
- patchday by @felixroos in https://github.com/tidalcycles/strudel/pull/1264
- Rename repeat back to extend by @yaxu in https://github.com/tidalcycles/strudel/pull/1285
- Send delta in OSC message in seconds, to match tidal/superdirt by @yaxu in https://github.com/tidalcycles/strudel/pull/1323
### fixes
- Fix clock worker dependency path in module builds by @matthewkaney in https://github.com/tidalcycles/strudel/pull/1129
- Fix bug in Fraction.lcm by @yaxu in https://github.com/tidalcycles/strudel/pull/1133
- Fix tactus marking in mininotation by @yaxu in https://github.com/tidalcycles/strudel/pull/1144
- Fix loopAt tactus by @yaxu in https://github.com/tidalcycles/strudel/pull/1145
- Fix OSC clock jitter by @daslyfe in https://github.com/tidalcycles/strudel/pull/1157
- [CORS HOTFIX] by @daslyfe in https://github.com/tidalcycles/strudel/pull/1162
- Fixes fit so it works after a chop or slice by @yaxu in https://github.com/tidalcycles/strudel/pull/1171
- fix sample speed when using splice and fit with superdirt by @daslyfe in https://github.com/tidalcycles/strudel/pull/1172
- handle midin device not found error by @felixroos in https://github.com/tidalcycles/strudel/pull/1146
- Fix serial timing by @yaxu in https://github.com/tidalcycles/strudel/pull/1188
- Fix regression for d1, p1, p(n) by @yaxu in https://github.com/tidalcycles/strudel/pull/1227
- Fix sometimes by @yaxu in https://github.com/tidalcycles/strudel/pull/1243
- Fix sf2 timing by @felixroos in https://github.com/tidalcycles/strudel/pull/1272
- Fix "squeezejoin" and functions using it, including "bite" by @yaxu in https://github.com/tidalcycles/strudel/pull/1286
- Fixes inverted triangle wave by renaming it to "itri", making non-inverted "tri" by @yaxu in https://github.com/tidalcycles/strudel/pull/1283
- Hotfix: prevent undefined pattern code from crashing strudel on load by @daslyfe in https://github.com/tidalcycles/strudel/pull/1297
- Fix test error #1297 by @nkymut in https://github.com/tidalcycles/strudel/pull/1298
- bugfix zoom stepcount by @yaxu in https://github.com/tidalcycles/strudel/pull/1301
- bugfix: Allow single param to be used in the as function by @daslyfe in https://github.com/tidalcycles/strudel/pull/1312
- fix: replace empty spaces in registered sound keys by @daslyfe in https://github.com/tidalcycles/strudel/pull/1319
- FIX: Multichannel Audio by @daslyfe in https://github.com/tidalcycles/strudel/pull/1322
- fix: udels header by @daslyfe in https://github.com/tidalcycles/strudel/pull/1325
- fix: disable astro toolbar by default by @daslyfe in https://github.com/tidalcycles/strudel/pull/1324
- FIX: sound import order by @daslyfe in https://github.com/tidalcycles/strudel/pull/1333`
## New Contributors
- @EdwardBetts made their first contribution in https://github.com/tidalcycles/strudel/pull/1183
- @netux made their first contribution in https://github.com/tidalcycles/strudel/pull/1165
- @kdiab made their first contribution in https://github.com/tidalcycles/strudel/pull/1189
**Full Changelog**: https://github.com/tidalcycles/strudel/compare/v1.1.0...v1.1.1
## packages
- @strudel/codemirror@1.2.0
- @strudel/core@1.2.0
- @strudel/csound@1.2.0
- @strudel/draw@1.2.0
- @strudel/gamepad@1.2.0
- @strudel/hydra@1.2.0
- @strudel/midi@1.2.0
- @strudel/mini@1.2.0
- @strudel/motion@1.2.0
- @strudel/mqtt@1.2.0
- @strudel/osc@1.2.0
- @strudel/reference@1.2.0
- @strudel/repl@1.2.0
- @strudel/sampler@0.2.0
- @strudel/serial@1.2.0
- @strudel/soundfonts@1.2.0
- superdough@1.2.0
- @strudel/tonal@1.2.0
- @strudel/transpiler@1.2.0
- @strudel/web@1.2.0
- @strudel/webaudio@1.2.0
- @strudel/xen@1.2.0
+3 -3
View File
@@ -216,9 +216,9 @@ Here is a recording of the first session we organized over the discord server:
The midi integration has gotten a few new features:
- [clock out](https://github.com/tidalcycles/strudel/pull/710) to sync your midi devices / DAW to the strudel clock (better doc coming soon)
- [clock out](https://codeberg.org/uzu/strudel/pulls/710) to sync your midi devices / DAW to the strudel clock (better doc coming soon)
- [cc output](https://strudel.cc/learn/input-output/#ccn--ccv) to send cc values to your gear
- [cc input](https://github.com/tidalcycles/strudel/pull/699) to control strudel via MIDI (better doc coming soon)
- [cc input](https://codeberg.org/uzu/strudel/pulls/699) to control strudel via MIDI (better doc coming soon)
Here is a little demo of me fiddling with a midi controller, changing a piano pattern:
@@ -228,7 +228,7 @@ Here is a little demo of me fiddling with a midi controller, changing a piano pa
- You can now run [hydra inside strudel](https://strudel.cc/learn/hydra/) + you can even run strudel in [hydra](https://hydra.ojack.xyz), thanks to [Olivia Jack](https://ojack.xyz/) and [Ámbar Tenorio Fornés](https://atenor.io/)! Read more [here](https://alpaca.pubpub.org/pub/b7hwrjfk/release/2?readingCollection=1def0192)
- There is now a [VSCode Plugin](https://marketplace.visualstudio.com/items?itemName=roipoussiere.tidal-strudel) thanks to [roipoussiere](https://github.com/roipoussiere)! It allows you run patterns from a `.strudel` file inside VSCode.
- Strudel can now be downloaded as a desktop app, thanks to [vasilymilovidov](https://github.com/vasilymilovidov) who has wrapped the REPL with [tauri](https://tauri.app/). You can download it [on the releases page](https://github.com/tidalcycles/strudel/releases) (scroll down to Assets). The performance is not optimal on MacOS and Linux, which is why it is still considered experimental
- Strudel can now be downloaded as a desktop app, thanks to [vasilymilovidov](https://github.com/vasilymilovidov) who has wrapped the REPL with [tauri](https://tauri.app/). You can download it [on the releases page](https://codeberg.org/uzu/strudel/releases) (scroll down to Assets). The performance is not optimal on MacOS and Linux, which is why it is still considered experimental
## Stats
+1 -1
View File
@@ -1,6 +1,6 @@
/*
cx.js - <short description TODO>
Copyright (C) 2022 Strudel contributors - see <https://github.com/tidalcycles/strudel/blob/main/repl/src/cx.js>
Copyright (C) 2022 Strudel contributors - see <https://codeberg.org/uzu/strudel/src/branch/main/repl/src/cx.js>
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+2
View File
@@ -30,6 +30,7 @@ export function MiniRepl({
maxHeight,
autodraw,
drawTime,
mondo = false,
}) {
const code = tunes ? tunes[0] : tune;
const id = useMemo(() => s4(), []);
@@ -85,6 +86,7 @@ export function MiniRepl({
},
beforeStart: () => audioReady,
afterEval: ({ code }) => setVersionDefaultsFrom(code),
mondo,
});
// init settings
editor.setCode(code);
+38 -20
View File
@@ -95,7 +95,7 @@ Diese Kombinationen von Buchstaben stehen für verschiedene Teile eines Schlagze
- `mt` = **m**iddle tom
- `ht` = **h**igh tom
- `rd` = **r**i**d**e cymbal
- `rd` = **cr**ash cymbal
- `cr` = **cr**ash cymbal
Probier verschiedene Sounds aus!
@@ -168,9 +168,14 @@ Korrekt, der echte Vorteil dieser Schreibweise zeigt sich wenn du Elemente entfe
</Box>
**Tempo ändern mit `cpm`**
**Tempo ändern mit `setcpm`**
<MiniRepl client:visible tune={`sound("<bd hh rim hh>*8").cpm(90/4)`} punchcard />
<MiniRepl
client:visible
tune={`setcpm(90/4)
sound("<bd hh rim hh>*8")`}
punchcard
/>
<Box>
@@ -233,8 +238,9 @@ Bolero:
<MiniRepl
client:visible
tune={`sound("sd sd*3 sd sd*3 sd sd sd sd*3 sd sd*3 sd*3 sd*3")
.cpm(10)`}
tune={`
setcpm(10)
sound("sd sd*3 sd sd*3 sd sd sd sd*3 sd sd*3 sd*3 sd*3")`}
punchcard
/>
@@ -313,18 +319,23 @@ Das haben wir bisher gelernt:
Die mit Apostrophen umgebene Mini-Notation benutzt man normalerweise in einer sogenannten Funktion.
Die folgenden Funktionen haben wir bereits gesehen:
| Name | Description | Example |
| ----- | -------------------------------------- | ----------------------------------------------------------------------- |
| sound | Spielt den Sound mit dem Namen | <MiniRepl client:visible tune={`sound("bd sd")`} /> |
| bank | Wählt die Soundbank / Drum Machine | <MiniRepl client:visible tune={`sound("bd sd").bank("RolandTR909")`} /> |
| cpm | Tempo in **C**ycles **p**ro **M**inute | <MiniRepl client:visible tune={`sound("bd sd").cpm(90)`} /> |
| n | Sample Nummer | <MiniRepl client:visible tune={`n("0 1 4 2").sound("jazz")`} /> |
| Name | Description | Example |
| ------ | -------------------------------------- | ----------------------------------------------------------------------- |
| sound | Spielt den Sound mit dem Namen | <MiniRepl client:visible tune={`sound("bd sd")`} /> |
| bank | Wählt die Soundbank / Drum Machine | <MiniRepl client:visible tune={`sound("bd sd").bank("RolandTR909")`} /> |
| setcpm | Tempo in **C**ycles **p**ro **M**inute | <MiniRepl client:visible tune={`setcpm(90); sound("bd sd")`} /> |
| n | Sample Nummer | <MiniRepl client:visible tune={`n("0 1 4 2").sound("jazz")`} /> |
## Beispiele
**Einfacher Rock Beat**
<MiniRepl client:visible tune={`sound("bd sd, hh*4").bank("RolandTR505").cpm(100/2)`} punchcard />
<MiniRepl
client:visible
tune={`setcpm(100/2)
sound("bd sd, hh*4").bank("RolandTR505")`}
punchcard
/>
**Klassischer House**
@@ -339,7 +350,12 @@ Bestimmte Drum Patterns werden oft genreübergreifend wiederverwendet.
We Will Rock you
<MiniRepl client:visible tune={`sound("bd*2 cp").bank("RolandTR707").cpm(81/2)`} punchcard />
<MiniRepl
client:visible
tune={`setcpm(81/2)
sound("bd*2 cp").bank("RolandTR707")`}
punchcard
/>
**Yellow Magic Orchestra - Firecracker**
@@ -354,12 +370,13 @@ We Will Rock you
<MiniRepl
client:visible
tune={`sound(\`
tune={`setcpm(90/4)
sound(\`
[- - oh - ] [- - - - ] [- - - - ] [- - - - ],
[hh hh - - ] [hh - hh - ] [hh - hh - ] [hh - hh - ],
[- - - - ] [cp - - - ] [- - - - ] [cp - - - ],
[bd - - - ] [- - - bd] [- - bd - ] [- - - bd]
\`).cpm(90/4)`}
\`)`}
punchcard
/>
@@ -367,12 +384,13 @@ We Will Rock you
<MiniRepl
client:visible
tune={`sound(\`
tune={`setcpm(88/4)
sound(\`
[- - - - ] [- - - - ] [- - - - ] [- - oh:1 - ],
[hh hh hh hh] [hh hh hh hh] [hh hh hh hh] [hh hh - - ],
[- - - - ] [cp - - - ] [- - - - ] [- cp - - ],
[bd bd - - ] [- - bd - ] [bd bd - bd ] [- - - - ]
\`).bank("RolandTR808").cpm(88/4)`}
\`).bank("RolandTR808")`}
punchcard
/>
@@ -380,11 +398,11 @@ We Will Rock you
<MiniRepl
client:visible
tune={`s(\`jazz*2,
tune={`setcpm(100/2)
s(\`jazz*2,
insect [crow metal] - -,
- space:4 - space:1,
- wind\`)
.cpm(100/2)`}
- wind\`)`}
punchcard
/>
+10 -10
View File
@@ -56,13 +56,13 @@ Diese Seite ist eine Auflistung aller im Workshop vorgestellten Funktionen.
## Pattern-Effekte
| Name | Beschreibung | Beispiel |
| ---- | --------------------------------- | ----------------------------------------------------------------------------------- |
| cpm | Tempo in Cycles pro Minute | <MiniRepl client:visible tune={`sound("bd sd").cpm(90)`} /> |
| fast | schneller | <MiniRepl client:visible tune={`sound("bd sd").fast(2)`} /> |
| slow | langsamer | <MiniRepl client:visible tune={`sound("bd sd").slow(2)`} /> |
| rev | rückwärts | <MiniRepl client:visible tune={`n("0 2 4 6").scale("C:minor").rev()`} /> |
| jux | einen Stereo-Kanal modifizieren | <MiniRepl client:visible tune={`n("0 2 4 6").scale("C:minor").jux(rev)`} /> |
| add | addiert Zahlen oder Noten | <MiniRepl client:visible tune={`n("0 2 4 6".add("<0 1 2 1>")).scale("C:minor")`} /> |
| ply | jedes Element schneller machen | <MiniRepl client:visible tune={`s("bd sd").ply("<1 2 3>")`} /> |
| off | verzögert eine modifizierte Kopie | <MiniRepl client:visible tune={`s("bd sd, hh*4").off(1/8, x=>x.speed(2))`} /> |
| Name | Beschreibung | Beispiel |
| ------ | --------------------------------- | ----------------------------------------------------------------------------------- |
| setcpm | Tempo in Cycles pro Minute | <MiniRepl client:visible tune={`setcpm(90); sound("bd sd")`} /> |
| fast | schneller | <MiniRepl client:visible tune={`sound("bd sd").fast(2)`} /> |
| slow | langsamer | <MiniRepl client:visible tune={`sound("bd sd").slow(2)`} /> |
| rev | rückwärts | <MiniRepl client:visible tune={`n("0 2 4 6").scale("C:minor").rev()`} /> |
| jux | einen Stereo-Kanal modifizieren | <MiniRepl client:visible tune={`n("0 2 4 6").scale("C:minor").jux(rev)`} /> |
| add | addiert Zahlen oder Noten | <MiniRepl client:visible tune={`n("0 2 4 6".add("<0 1 2 1>")).scale("C:minor")`} /> |
| ply | jedes Element schneller machen | <MiniRepl client:visible tune={`s("bd sd").ply("<1 2 3>")`} /> |
| off | verzögert eine modifizierte Kopie | <MiniRepl client:visible tune={`s("bd sd, hh*4").off(1/8, x=>x.speed(2))`} /> |
+1 -1
View File
@@ -23,7 +23,7 @@ is equivalent to this Pattern without Mini Notation:
Similarly, there is an equivalent function for every aspect of the mini notation.
Which representation to use is a matter of context. As a rule of thumb, functions
are better suited in a larger context, while mini notation is more practical for individiual rhythms.
are better suited in a larger context, while mini notation is more practical for individual rhythms.
## Limits of Mini Notation
+1 -1
View File
@@ -44,7 +44,7 @@ xxx("foo").yyy("bar")
Generally, `xxx` and `yyy` are called [_functions_](<https://en.wikipedia.org/wiki/Function_(computer_programming)>), while `foo` and `bar` are called function [_arguments_ or _parameters_](<https://en.wikipedia.org/wiki/Parameter_(computer_programming)>).
So far, we've used the functions to declare which aspect of the sound we want to control, and their arguments for the actual data.
The `yyy` function is called a [_chained_ function](https://en.wikipedia.org/wiki/Method_chaining), because it is appended with a dot (`.`).
The `yyy` function is called a [_chained_ function](https://en.wikipedia.org/wiki/Method_chaining), because it is preceded with a dot (`.`).
Generally, the idea with chaining is that code such as `a("this").b("that").c("other")` allows `a`, `b` and `c` functions to happen in a specified order, without needing to write them as three separate lines of code.
You can think of this as being similar to chaining audio effects together using guitar pedals or digital audio effects.
@@ -34,11 +34,11 @@ import { JsDoc } from '../../docs/JsDoc';
## arp
<JsDoc client:idle name="Pattern#arp" h={0} />
<JsDoc client:idle name="arp" h={0} />
## arpWith 🧪
<JsDoc client:idle name="Pattern#arpWith" h={0} />
<JsDoc client:idle name="arpWith" h={0} />
## struct
@@ -58,7 +58,7 @@ import { JsDoc } from '../../docs/JsDoc';
## hush
<JsDoc client:idle name="hush" h={0} />
<JsDoc client:idle name="Pattern#hush" h={0} />
## invert
+1 -1
View File
@@ -5,6 +5,6 @@ layout: ../../layouts/MainLayout.astro
import { MiniRepl } from '../../docs/MiniRepl';
import { JsDoc } from '../../docs/JsDoc';
import DeviceMotion from '../../../../packages/motion/docs/devicemotion.mdx';
import DeviceMotion from '@strudel/motion/docs/devicemotion.mdx';
<DeviceMotion />
+165
View File
@@ -11,6 +11,129 @@ import { JsDoc } from '../../docs/JsDoc';
Whether you're using a synth or a sample, you can apply any of the following built-in audio effects.
As you might suspect, the effects can be chained together, and they accept a pattern string as their argument.
# Signal chain
<img src="/img/strudel-signal-flow.png"></img>
The signal chain in Strudel is as follows:
- An sound-generating event is triggered by a pattern
- This has a start time and a duration, which is usually
controlled by the note length and ADSR parameters
- If we exceed the max polyphony, old sounds begin to die off
- Muted sounds (one whose `s` value is `-`, `~`, or `_`) are skipped
- A sound is produced (through, say, a sample or an oscillator)
- This is where detune-based effects (like `detune`, `penv`, etc. occur)
- The following will occur _in order_ and only if they've been called in the pattern. Note that all of these are
single use effects, meaning that multiple occurrences of them in a pattern will simply override the values
(e.g. you can't do `s("bd").lpf(100).distort(2).lpf(800)` to lowpass, distort, and then lowpass
again)
- Phase vocoder (`stretch`)
- Gain is applied (`gain`)
- This is where the main (volume) ADSR happens
- A lowpass filter (`lpf`)
- A highpass filter (`hpf`)
- A bandpass filter (`bandpass`)
- A vowel filter (`vowel`)
- Sample rate reduction (`coarse`)
- Bit crushing (`crush`)
- Waveshape distortion (`shape`)
- Normal distortion (`distort`)
- Tremolo (`tremolo`)
- Compressor (`compressor`)
- Panning (`pan`)
- Phaser (`phaser`)
- Postgain (`post`)
- The sound is then split into multiple destinations
- Dry output (amount controlled by `dry` parameter)
- The sends
- Analyzers
- These are used for tooling like `scope` and `spectrum` and their setup usually happens behind the scenes
- Delay (amount controlled by `delay` parameter)
- Reverb (amount controlled by `room` parameter)
- The dry output, delay, and reverb are joined into what is called the "orbit" of the pattern (see more in the section below)
- The `duck` effect affects the volume of all signals in the orbit
- The orbit is then sent to the mixer
## Orbits
Orbits are the way in which outputs are handled in Strudel. They also prescribe which delay and reverb to associate with the dry signal.
By default, all orbits are mixed down to channels `1` and `2` in stereo, however with the "Multi Channel Orbits" setting
(under Settings at the right) you can use them as individual 2 channel stereo outs (orbit `i` will be mapped to
to channels `2i` and `2i + 1`). You can then use routers like Blackhole 16 to retrieve and record all of the channels in a DAW for later processing.
The default orbit is `1` and it is set with `orbit`. You may send a sound to multiple orbits via mininotation
<MiniRepl client:visible tune={`s("white").orbit("2,3,4").gain(0.2)`} />
but please be careful as this will create three copies of the sound behind the scenes, meaning that if they are mixed
down to a single output, they will triple the volume. We've reduced the gain here to save your ears.
⚠️ There is only one delay and reverb per orbit, so please be aware that if you attempt to change the parameters on two
patterns pointing to the same orbit, it can lead to unpredictable results. Compare, for example, this pretty pluck
with a large reverb:
<MiniRepl
client:visible
tune={`
$: s("triangle*4").decay(0.5).n(irand(12)).scale('C minor')
.room(1).roomsize(10)`}
/>
versus the same pluck with a muted kick drum coming in and overwriting the `roomsize` value:
<MiniRepl
client:visible
tune={`
$: s("triangle*4").decay(0.5).n(irand(12)).scale('C minor')
.room(1).roomsize(10)
$: s("bd\*4").room(0.01).roomsize(0.01).postgain(0)`}
/>
This is due to them sharing the same orbit: the default of `1`. It can be corrected simply by updating the orbits to be
distinct:
<MiniRepl
client:visible
tune={`
$: s("triangle*4").decay(0.5).n(irand(12)).scale('C minor')
.room(1).roomsize(10).orbit(2)
$: s("bd\*4").room(0.01).roomsize(0.01).postgain(0)`}
/>
## Continuous changes
As all of the above is triggered by a _sound occurring_, it is often the case that parameters may not be
modified continuously in time. For example,
<MiniRepl
client:visible
tune={`
s("supersaw").lpf(tri.range(100, 5000).slow(2))`}
/>
Will not produce a continually LFO'd low-pass filter due to the `tri` only being sampled every time the note hits
(in this case the default of once per cycle). You can fake it by introducing more sound-generating events, e.g.:
<MiniRepl
client:visible
tune={`
s("supersaw").seg(16).lpf(tri.range(100, 5000).slow(2))`}
/>
Some parameters _do_ induce continuous variations in time, though:
- The ADSR curve (governed by `attack`, `sustain`, `decay`, `release`)
- The pitch envelope curve (governed by `penv` and its associated ADSR)
- The FM curve (`fmenv`)
- The filter envelopes (`lpenv`, `hpenv`, `bpenv`)
- Tremolo (`tremolo`)
- Phaser (`phaser`)
- Vibrato (`vib`)
- Ducking (`duckorbit`)
# Filters
Filters are an essential building block of [subtractive synthesis](https://en.wikipedia.org/wiki/Subtractive_synthesis).
@@ -57,6 +180,34 @@ Each filter has 2 parameters:
<JsDoc client:idle name="vowel" h={0} />
# Amplitude Modulation
Amplitude modulation changes the amplitude (gain) periodically over time.
## am
<JsDoc client:idle name="am" h={0} />
## tremolosync
<JsDoc client:idle name="tremolosync" h={0} />
## tremolodepth
<JsDoc client:idle name="tremolodepth" h={0} />
## tremoloskew
<JsDoc client:idle name="tremoloskew" h={0} />
## tremolophase
<JsDoc client:idle name="tremolophase" h={0} />
## tremoloshape
<JsDoc client:idle name="tremoloshape" h={0} />
# Amplitude Envelope
The amplitude [envelope](<https://en.wikipedia.org/wiki/Envelope_(music)>) controls the dynamic contour of a sound.
@@ -311,4 +462,18 @@ global effects use the same chain for all events of the same orbit:
<JsDoc client:idle name="phasersweep" h={0} />
## Duck
### duckorbit
<JsDoc client:idle name="duckorbit" h={0} />
### duckattack
<JsDoc client:idle name="duckattack" h={0} />
### duckdepth
<JsDoc client:idle name="duckdepth" h={0} />
Next, we'll look at input / output via [MIDI, OSC and other methods](/learn/input-output).
+2 -2
View File
@@ -14,7 +14,7 @@ These pages will introduce you to [Strudel](https://strudel.cc/), a web-based [l
# What is Strudel?
[Strudel](https://strudel.cc/) is a version of [Tidal Cycles](https://tidalcycles.org) written in [JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript), initiated by [Alex McLean](https://slab.org) and [Felix Roos](https://github.com/felixroos) in 2022.
[Strudel](https://strudel.cc/) is a version of [Tidal Cycles](https://tidalcycles.org) written in [JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript), initiated by [Alex McLean](https://slab.org) and [Felix Roos](https://froos.cc/) in 2022.
Tidal Cycles, also known as Tidal, is a language for [algorithmic pattern](https://algorithmicpattern.org), and though it is most commonly used for [making music](https://tidalcycles.org/docs/showcase), it can be used for any kind of pattern making activity, including [weaving](https://www.youtube.com/watch?v=TfEmEsusXjU).
Tidal was first implemented as a library written in the [Haskell](https://www.haskell.org/) functional programming language, and by itself it does not make any sound.
@@ -81,7 +81,7 @@ s("bd,[~ <sd!3 sd(3,4,2)>],hh*8") // drums
Please note that this project is still in its experimental state.
In the future, parts of it might change significantly.
This tutorial is also far from complete.
You can contribute to it clicking 'Edit this page' in the top right, or by visiting the [Strudel GitHub page](https://github.com/tidalcycles/strudel/).
You can contribute to it clicking 'Edit this page' in the top right, or by visiting the [Strudel GitHub page](https://codeberg.org/uzu/strudel/).
# What's next?
+15
View File
@@ -0,0 +1,15 @@
---
title: Input Devices
layout: ../../layouts/MainLayout.astro
---
import { MiniRepl } from '../../docs/MiniRepl';
import { JsDoc } from '../../docs/JsDoc';
import Gamepad from '@strudel/gamepad/docs/gamepad.mdx';
# Input Devices
Strudel supports various input devices like Gamepads and MIDI controllers to manipulate patterns in real-time.
<Gamepad />
+137 -14
View File
@@ -8,7 +8,7 @@ import { JsDoc } from '../../docs/JsDoc';
# MIDI, OSC and MQTT
Normally, Strudel is used to pattern sound, using its own '[web audio](https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API)'-based synthesiser called [SuperDough](https://github.com/tidalcycles/strudel/tree/main/packages/superdough).
Normally, Strudel is used to pattern sound, using its own '[web audio](https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API)'-based synthesiser called [SuperDough](https://codeberg.org/uzu/strudel/src/branch/main/packages/superdough).
It is also possible to pattern other things with Strudel, such as software and hardware synthesisers with MIDI, other software using Open Sound Control/OSC (including the [SuperDirt](https://github.com/musikinformatik/SuperDirt/) synthesiser commonly used with Strudel's sibling [TidalCycles](https://tidalcycles.org/)), or the MQTT 'internet of things' protocol.
@@ -16,24 +16,97 @@ It is also possible to pattern other things with Strudel, such as software and h
Strudel supports MIDI without any additional software (thanks to [webmidi](https://npmjs.com/package/webmidi)), just by adding methods to your pattern:
## midi(outputName?)
## midiin(inputName?)
<JsDoc client:idle name="midin" h={0} />
## midi(outputName?,options?)
Either connect a midi device or use the IAC Driver (Mac) or Midi Through Port (Linux) for internal midi messages.
If no outputName is given, it uses the first midi output it finds.
<MiniRepl client:idle tune={`chord("<C^7 A7 Dm7 G7>").voicing().midi()`} />
<MiniRepl
client:idle
tune={`
$: chord("<C^7 A7 Dm7 G7>").voicing().midi('IAC Driver')
`}
/>
In the console, you will see a log of the available MIDI devices as soon as you run the code, e.g. `Midi connected! Using "Midi Through Port-0".`
In the console, you will see a log of the available MIDI devices as soon as you run the code,
e.g.
```
`Midi connected! Using "Midi Through Port-0".`
```
The `.midi()` function accepts an options object with the following properties:
<MiniRepl
client:idle
tune={`$: note("d e c a f").midi('IAC Driver', { isController: true, midimap: 'default'})
`}
/>
<details>
<summary>Available Options</summary>
| Option | Type | Default | Description |
| ------------ | ------------- | --------- | ---------------------------------------------------------------------- |
| isController | boolean | false | When true, disables sending note messages. Useful for MIDI controllers |
| latencyMs | number | 34 | Latency in milliseconds to align MIDI with audio engine |
| noteOffsetMs | number | 10 | Offset in milliseconds for note-off messages to prevent glitching |
| midichannel | number | 1 | Default MIDI channel (1-16) |
| velocity | number | 0.9 | Default note velocity (0-1) |
| gain | number | 1 | Default gain multiplier for velocity (0-1) |
| midimap | string | 'default' | Name of MIDI mapping to use for control changes |
| midiport | string/number | - | MIDI device name or index |
</details>
### midiport(outputName)
Selects the MIDI output device to use, pattern can be used to switch between devices.
```javascript
$: midiport('IAC Driver');
$: note('c a f e').midiport('<0 1 2 3>').midi();
```
<JsDoc client:idle name="midiport" h={0} />
## midichan(number)
Selects the MIDI channel to use. If not used, `.midi` will use channel 1 by default.
## ccn && ccv
## midicmd(command)
`midicmd` sends MIDI system real-time messages to control timing and transport on MIDI devices.
It supports the following commands:
- `clock`/`midiClock` - Sends MIDI timing clock messages
- `start` - Sends MIDI start message
- `stop` - Sends MIDI stop message
- `continue` - Sends MIDI continue message
// You can control the clock with a pattern and ensure it starts in sync when the repl begins.
// Note: It might act unexpectedly if MIDI isn't set up initially.
<MiniRepl
client:idle
tune={`$:stack(
midicmd("clock*48,<start stop>/2").midi('IAC Driver')
)`}
/>
## control, ccn && ccv
- `control` sends MIDI control change messages to your MIDI device.
- `ccn` sets the cc number. Depends on your synths midi mapping
- `ccv` sets the cc value. normalized from 0 to 1.
<MiniRepl client:idle tune={`note("c a f e").control([74, sine.slow(4)]).midi()`} />
<MiniRepl client:idle tune={`note("c a f e").ccn(74).ccv(sine.slow(4)).midi()`} />
In the above snippet, `ccn` is set to 74, which is the filter cutoff for many synths. `ccv` is controlled by a saw pattern.
@@ -56,6 +129,48 @@ Instead of setting `ccn` and `ccv` directly, you can also create mappings with `
<JsDoc client:idle name="defaultmidimap" h={0} />
## progNum (Program Change)
`progNum` sends MIDI program change messages to switch between different presets/patches on your MIDI device.
Program change values should be numbers between 0 and 127.
<MiniRepl client:idle tune={`// Switch between programs 0 and 1 every cycle
progNum("<0 1>").midi()
// Play notes while changing programs
note("c3 e3 g3").progNum("<0 1 2>").midi()`} />
Program change messages are useful for switching between different instrument sounds or presets during a performance.
The exact sound that each program number maps to depends on your MIDI device's configuration.
## sysex, sysexid && sysexdata (System Exclusive Message)
`sysex` sends MIDI System Exclusive (SysEx) messages to your MIDI device.
ysEx messages are device-specific commands that allow deeper control over synthesizer parameters.
The value should be an array of numbers between 0-255 representing the SysEx data bytes.
<MiniRepl
client:idle
tune={`// Send a simple SysEx message
let id = 0x43; //Yamaha
//let id = "0x00:0x20:0x32"; //Behringer ID can be an array of numbers
let data = "0x79:0x09:0x11:0x0A:0x00:0x00"; // Set NSX-39 voice to say "Aa"
$: note("c a f e").sysex(id, data).midi();
$: note("c a f e").sysexid(id).sysexdata(data).midi();`}
/>
The exact format of SysEx messages depends on your MIDI device's specification.
Consult your device's MIDI implementation guide for details on supported SysEx messages.
## midibend && miditouch
`midibend` sets MIDI pitch bend (-1 - 1)
`miditouch` sets MIDI key after touch (0-1)
<MiniRepl client:idle tune={`note("c a f e").midibend(sine.slow(4).range(-0.4,0.4)).midi()`} />
<MiniRepl client:idle tune={`note("c a f e").miditouch(sine.slow(4).range(0,1)).midi()`} />
# OSC/SuperDirt/StrudelDirt
In TidalCycles, sound is usually generated using [SuperDirt](https://github.com/musikinformatik/SuperDirt/), which runs inside SuperCollider. Strudel also supports using SuperDirt, although it requires installing some additional software.
@@ -69,7 +184,7 @@ To get SuperDirt to work with Strudel, you need to
1. install SuperCollider + sc3 plugins, see [Tidal Docs](https://tidalcycles.org/docs/) (Install Tidal) for more info.
2. install SuperDirt, or the [StrudelDirt](https://github.com/daslyfe/StrudelDirt) fork which is optimised for use with Strudel
3. install [node.js](https://nodejs.org/en/)
4. download [Strudel Repo](https://github.com/tidalcycles/strudel/) (or git clone, if you have git installed)
4. download [Strudel Repo](https://codeberg.org/uzu/strudel/) (or git clone, if you have git installed)
5. run `pnpm i` in the strudel directory
6. run `pnpm run osc` to start the osc server, which forwards OSC messages from Strudel REPL to SuperCollider
@@ -118,8 +233,8 @@ The following example shows how to send a pattern to an MQTT broker:
client:only="react"
tune={`"hello world"
.mqtt(undefined, // username (undefined for open/public servers)
undefined, // password
'/strudel-pattern', // mqtt 'topic'
undefined, // password
'/strudel-pattern', // mqtt 'topic'
'wss://mqtt.eclipseprojects.io:443/mqtt', // MQTT server address
'mystrudel', // MQTT client id - randomly generated if not supplied
0 // latency / delay before sending messages (0 = no delay)
@@ -130,12 +245,14 @@ The following example shows how to send a pattern to an MQTT broker:
Other software can then receive the messages. For example using the [mosquitto](https://mosquitto.org/) commandline client tools:
```
> mosquitto_sub -h mqtt.eclipseprojects.io -p 1883 -t "/strudel-pattern"
hello
world
hello
world
...
> mosquitto_sub -h mqtt.eclipseprojects.io -p 1883 -t "/strudel-pattern"
> hello
> world
> hello
> world
> ...
```
Control patterns will be encoded as JSON, for example:
@@ -155,11 +272,17 @@ Control patterns will be encoded as JSON, for example:
Will send messages like the following:
```
{"s":"sax","speed":2}
{"s":"sax","speed":2}
{"s":"sax","speed":3}
{"s":"sax","speed":2}
...
```
Libraries for receiving MQTT are available for many programming languages.
```
```
-2
View File
@@ -18,8 +18,6 @@ You can optionally add some music metadata in your Strudel code, by using tags i
Like other comments, those are ignored by Strudel, but it can be used by other tools to retrieve some information about the music.
It is for instance used by the [swatch tool](https://github.com/tidalcycles/strudel/tree/main/my-patterns) to display pattern titles in the [examples page](https://strudel.cc/examples/).
## Alternative syntax
You can also use comment blocks:
+16
View File
@@ -168,6 +168,20 @@ Using "!" we can repeat without speeding up:
<MiniRepl client:idle tune={`note("<[g3,b3,e4]!2 [a3,c3,e4] [b3,d3,f#4]>*2")`} punchcard />
## Randomness
Events with a "?" placed after them will have a 50% chance of being removed from the pattern:
<MiniRepl client:idle tune={`note("[g3,b3,e4]*8?")`} punchcard />
Adding a number between 0 and 1 after the "?" will affect the likelihood of the event being removed. For example, events with "?0.1" placed after them will have a 10% chance of being removed:
<MiniRepl client:idle tune={`note("[g3,b3,e4]*8?0.1")`} punchcard />
Events separated by a "|" will be chosen from at random:
<MiniRepl client:idle tune={`note("[g3,b3,e4] | [a3,c3,e4] | [b3,d3,f#4]")`} punchcard />
## Mini-notation review
To recap what we've learned so far, compare the following patterns:
@@ -179,6 +193,8 @@ To recap what we've learned so far, compare the following patterns:
<MiniRepl client:idle tune={`note("<[g3,b3,e4] _ [a3,c3,e4] [b3,d3,f#4]>*2")`} />
<MiniRepl client:idle tune={`note("<[g3,b3,e4]@2 [a3,c3,e4] [b3,d3,f#4]>*2")`} />
<MiniRepl client:idle tune={`note("<[g3,b3,e4]!2 [a3,c3,e4] [b3,d3,f#4]>*2")`} />
<MiniRepl client:idle tune={`note("<[g3,b3,e4]? [a3,c3,e4] [b3,d3,f#4]>*2")`} />
<MiniRepl client:idle tune={`note("<[g3|b3|e4] [a3,c3,e4] [b3,d3,f#4]>*2")`} />
## Euclidian rhythms
+191
View File
@@ -0,0 +1,191 @@
---
title: Mondo Notation
layout: ../../layouts/MainLayout.astro
---
import { MiniRepl } from '../../docs/MiniRepl';
import { JsDoc } from '../../docs/JsDoc';
# Mondo Notation
"Mondo Notation" is a new kind of notation that is similar to [Mini Notation](/learn/mini-notation/), but with enough abilities to make it work as a standalone pattern language.
Here's an example:
<MiniRepl
mondo
client:idle
tune={`$ note (c2 # euclid <3 6 3> <8 16>) # *2
# s "sine" # add (note [0 <12 24>]*2)
# dec(sine # range .2 2)
# room .5
# lpf (sine/3 # range 120 400)
# lpenv (rand # range .5 4)
# lpq (perlin # range 5 12 # * 2)
# dist 1 # fm 4 # fmh 5.01 # fmdecay <.1 .2>
# postgain .6 # delay .1 # clip 5
$ s [bd bd bd bd] # bank tr909 # clip .5
# ply <1 [1 [2 4]]>
$ s oh\*4 # press # bank tr909 # speed.8
# dec (<.02 .05>\*2 # add (saw/8 # range 0 1))
`}
/>
## Mondo in the REPL
For now, you can only use mondo in the repl like this:
<MiniRepl client:idle tune={'mondo`s hh*8`'} />
The rest of this site will only use the mondo notation itself.
In the future, the REPL might get a way to use mondo notation directly.
## Calling Functions
Compared to Mini Notation, the most notable feature of Mondo Notation is the ability to call functions using round brackets:
<MiniRepl mondo client:idle tune={`(s hh*8)`} />
The first element inside the brackets is the function name. In JS, this would look like:
<MiniRepl client:idle tune={`s("hh*8")`} />
The outermost parens are not needed, so we can drop them:
<MiniRepl mondo client:idle tune={`s hh*8`} />
## Mini Notation Features
Besides function calling with round parens, Mondo Notation has a lot in common with Mini Notation:
### Brackets
- `[]` for 1-cycle sequences
- `<>` for multi-cycle sequences
- `{}` for stepped sequences (more on that later)
### Infix Operators
- \* => [fast](/learn/time-modifiers/#fast)
- / => [slow](/learn/time-modifiers/#slow)
- ! => [extend](/learn/stepwise/#extend)
- @ => [expand](/learn/stepwise/#expand)
- % => [pace](/learn/stepwise/#pace)
- ? => [degradeBy](/learn/random-modifiers/#degradeby) (currently requires right operand)
- : => tail (creates a list)
- .. => range (between numbers)
- , => [stack](/learn/factories/#stack)
- | => [chooseIn](/learn/random-modifiers/#choose)
### Example
<MiniRepl
mondo
client:idle
tune={`note <
[e5 [b4 c5] d5 [c5 b4]]
[a4 [a4 c5] e5 [d5 c5]]
[b4 [~ c5] d5 e5]
[c5 a4 a4 ~]
[[~ d5] [~ f5] a5 [g5 f5]]
[e5 [~ c5] e5 [d5 c5]]
[b4 [b4 c5] d5 e5]
[c5 a4 a4 ~]
>`}
/>
## Chaining Functions
Similar to how "." works in javascript (JS), we can chain functions calls with the "#" operator:
<MiniRepl
mondo
client:idle
tune={`n <0 2 4 [3 1] -1>*4
# scale C4:minor
# jux rev
# dec .2
# delay .5`}
/>
Here's the same written in JS:
<MiniRepl
client:idle
tune={`n("<0 2 4 [3 1] -1>*4")
.scale("C4:minor")
.jux(rev)
.dec(.2)
.delay(.5)`}
/>
### Chaining Functions Locally
A function can be applied to a single element by wrapping it in round parens:
<MiniRepl mondo client:idle tune={`s [bd hh bd (cp # delay .6)] # bank tr909`} />
in this case, `delay .6` will only be applied to `cp`. compare this with the JS version:
<MiniRepl client:idle tune={`s(seq("bd", "hh", "bd", "cp".delay(.6))).bank('tr909')`} />
here we can see how much we can save when there's no boundary between mini notation and function calls!
### Chaining Infix Operators
Infix operators exist as regular functions, so they can be chained as well:
<MiniRepl client:idle mondo tune={`s [bd hh] # bank tr909 # *2`} />
In this case, the \*2 will be applied to the whole pattern.
### Lambda Functions
Some functions in strudel expect a function as input, for example:
<MiniRepl client:idle tune={`n("0 .. 7").scale("C:minor").sometimes(x=>x.dec(.1))`} />
in mondo, the `x=>x.` can be shortened to:
<MiniRepl client:idle mondo tune={`n 0..7 # scale C:minor # sometimes (# dec .1)`} />
chaining works as expected:
<MiniRepl client:idle mondo tune={`n 0..7 # scale C:minor # sometimes (# dec .1 # jux rev)`} />
## Strings
You can use "double quotes" and 'single quotes' to get a string:
<MiniRepl client:idle mondo tune={`n 0..7 # scale 'C minor'`} />
## Multiple Patterns
The `$` sign can be used to separate multiple patterns:
<MiniRepl
client:idle
mondo
tune={`$ s [bd rim [~ bd] rim] # bank tr707
$ chord <Dm9!3 Db7> # voicing
# struct[x ~ ~ x ~ x ~ ~] # delay .5`}
/>
The `$` sign is an alias for `,` so it will create a stack behind the scenes.
## variables
using the `def` keyword, you can define variables:
<MiniRepl
client:idle
mondo
tune={`
$ def melody [0 1 2 3]
$ n melody # scale C:minor
`}
/>
+52 -11
View File
@@ -59,14 +59,22 @@ Furthermore, strudel also loads instrument samples from [VCSL](https://github.co
To see which sample names are available, open the `sounds` tab in the [REPL](https://strudel.cc/).
You can also create custom aliases for existing sounds using the `soundAlias` function:
<MiniRepl
client:idle
tune={`soundAlias("RolandTR808_bd", "kick")
s("kick")`}
/>
Note that only the sample maps (mapping names to URLs) are loaded initially, while the audio samples themselves are not loaded until they are actually played.
This behaviour of loading things only when they are needed is also called `lazy loading`.
While it saves resources, it can also lead to sounds not being audible the first time they are triggered, because the sound is still loading.
[This might be fixed in the future](https://github.com/tidalcycles/strudel/issues/187)
[This might be fixed in the future](https://codeberg.org/uzu/strudel/issues/187)
# Sound Banks
If we open the `sounds` tab and then `drum machines`, we can see that the drum samples are all prefixed with drum machine names: `RolandTR808_bd`, `RolandTR808_sd`, `RolandTR808_hh` etc..
If we open the `sounds` tab and then `drum-machines`, we can see that the drum samples are all prefixed with drum machine names: `RolandTR808_bd`, `RolandTR808_sd`, `RolandTR808_hh` etc..
We _could_ use them like this:
@@ -163,6 +171,31 @@ The last section could be written as:
}
```
Please note that browsers will often cache `strudel.json` on first load, and keep using the cached
version even if the orginal has been updated. If this bites you (for example while developing a new
sample pack), you can force the browser to download a new copy by i.e. changing capitalization of one
character in the URL, or adding a URL attribute, such as:
```javascript
samples('https://raw.githubusercontent.com/tidalcycles/Dirt-Samples/master/strudel.json?version=2');
```
that gets ignored by GitHub (but changes the URL, forcing the browser to reload every time we increase
the version number).
It is also possible, of course, to just remove it from cache (deleting cache in browser Privacy settings,
or from the dev console if you're technically minded, or by using a cache deleting extension).
## Generating strudel.json
You can use [@strudel/sampler](https://www.npmjs.com/package/@strudel/sampler) to generate a strudel.json file for you, by running:
```sh
npx --yes @strudel/sampler --json > strudel.json
```
See other uses of strudel/sampler further below, under "From Disk via @strudel/sampler".
## Github Shortcut
Because loading samples from github is common, there is a shortcut:
@@ -180,11 +213,12 @@ It assumes a `strudel.json` file to be present at the root of the repository:
https://raw.githubusercontent.com/<user>/<repo>/<branch>/strudel.json
```
## From Disk via "Import Sounds"
## From Disk via "Import Sounds Folder"
If you don't want to upload your samples to the internet, you can also load them from your local disk.
Go to the `sounds` tab in the REPL and press "import sounds".
Then you can select a folder that contains audio files. The folder you select can also contain subfolders with audio files.
Go to the `sounds` tab in the REPL and open the `import-sounds` tab below the search bar.
Press the "import sounds folder" button and select a folder that contains audio files.
The folder you select can also contain subfolders with audio files.
Example:
```
@@ -200,12 +234,13 @@ Example:
```
In the above example the folder `samples` contains 2 subfolders `swoop` and `smash`, which contain audio files.
If you select that `samples` folder, the `user` tab (next to the import sounds button) will then contain 2 new sounds: `swoop(3) smash(3)`
If you select that `samples` folder, the `user` tab (next to the `import-sounds` tab) will then contain 2 new sounds: `swoop(3) smash(3)`
The individual samples can the be played normally like `s("swoop:0 swoop:1 smash:2")`.
The samples within each sound use zero-based indexing in alphabetical order.
## From Disk via @strudel/sampler
Instead of loading your samples into your browser with the "import sounds" button, you can also serve the samples from a local file server.
Instead of loading your samples into your browser with the "import sounds folder" button, you can also serve the samples from a local file server.
The easiest way to do this is using [@strudel/sampler](https://www.npmjs.com/package/@strudel/sampler):
```sh
@@ -245,15 +280,17 @@ We can also declare different samples for different regions of the keyboard:
<MiniRepl
client:idle
tune={`samples({
tune={`setcpm(60)
samples({
'moog': {
'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');
}}, 'github:tidalcycles/dirt-samples')
note("g2!2 <bb2 c3>!2, <c4@3 [<eb4 bb3> g4 f4]>")
.s('moog').clip(1)
.gain(.5).cpm(60)`}
.s('moog').clip(1)
.gain(.5)`}
/>
The sampler will always pick the closest matching sample for the current note!
@@ -342,6 +379,10 @@ Sampler effects are functions that can be used to change the behaviour of sample
<JsDoc client:idle name="splice" h={0} />
### scrub
<JsDoc client:idle name="Pattern.scrub" h={0} />{' '}
### speed
<JsDoc client:idle name="speed" h={0} />
+1 -5
View File
@@ -24,7 +24,7 @@ With the new stepwise `stepcat` function, the steps of the two patterns will be
By default, steps are counted according to the 'top level' in mini-notation. For example `"a [b c] d e"` has five events in it per cycle, but is counted as four steps, where `[b c]` is counted as a single step.
However, you can mark a different metrical level to count steps relative to, using a `^` at the start of a sub-pattern. If we do this to the subpattern in our example: `"a [^b c] d e"`, then the pattern is now counted as having _eight_ steps. This is because 'b' and 'c' are each counted as single steps, and the events in the pattenr are twice as long, and so counted as two steps each.
However, you can mark a different metrical level to count steps relative to, using a `^` at the start of a sub-pattern. If we do this to the subpattern in our example: `"a [^b c] d e"`, then the pattern is now counted as having _eight_ steps. This is because 'b' and 'c' are each counted as single steps, and the events in the pattern are twice as long, and so counted as two steps each.
## Pacing the steps
@@ -116,10 +116,6 @@ Earlier versions of many of these functions had `s_` prefixes, and the `pace` fu
<JsDoc client:idle name="polymeter" h={0} />
### polymeterSteps
<JsDoc client:idle name="polymeterSteps" h={0} />
### shrink
<JsDoc client:idle name="shrink" h={0} />
+4 -4
View File
@@ -79,7 +79,7 @@ Instead of `+` / `add`, you can use any of the available operators of the first
## Function Compatibility
[This issue](https://github.com/tidalcycles/strudel/issues/31) tracks which Tidal functions are implemented in Strudel.
[This issue](https://codeberg.org/uzu/strudel/issues/31) tracks which Tidal functions are implemented in Strudel.
The list might not be 100% up to date and probably also misses some functions completely..
Feel encouraged to search the source code for a function you're looking for.
If you find a function that's not on the list, please tell!
@@ -89,7 +89,7 @@ If you find a function that's not on the list, please tell!
As seen in the example, the `#` operator (shorthand for `|>`) is also just a function call in strudel.
So `note "c5" # s "gtr"` becomes `note("c5").s('gtr')`.
[This file](https://github.com/tidalcycles/strudel/blob/main/packages/core/controls.mjs) lists all available control params.
[This file](https://codeberg.org/uzu/strudel/src/branch/main/packages/core/controls.mjs) lists all available control params.
Note that not all of those work in the Webaudio Output of Strudel.
If you find a tidal control that's not on the list, please tell!
@@ -107,11 +107,11 @@ You can find a [list of available effects here](/learn/effects/).
### Sampler
Strudel's sampler supports [a subset](/learn/samples) of Superdirt's sampler.
Also, samples are always loaded from a URL rather than from the disk, although [that might be possible in the future](https://github.com/tidalcycles/strudel/issues/118).
Also, samples are always loaded from a URL rather than from the disk, although [that might be possible in the future](https://codeberg.org/uzu/strudel/issues/118).
## Evaluation
The Strudel REPL does not support [block based evaluation](https://github.com/tidalcycles/strudel/issues/34) yet.
The Strudel REPL does not support [block based evaluation](https://codeberg.org/uzu/strudel/issues/34) yet.
You can use labeled statements and `_` to mute:
<MiniRepl
+95
View File
@@ -0,0 +1,95 @@
---
title: Xen Harmonic Functions
layout: ../../layouts/MainLayout.astro
---
import { MiniRepl } from '../../docs/MiniRepl';
import { JsDoc } from '../../docs/JsDoc';
# Xen Harmonic Functions
These functions allow the use of scales other than your typical chromatic 12 based ones.
### tune(scale)
<JsDoc client:idle name="tune" h={0} />
Here's an example of how to configure a basic hexany scale:
<MiniRepl client:idle tune={`"0 1 2 3 4 5".tune("hexany15").mul("220").freq()`} />
Try other scales like `hexany1`, `iraq`, `gumbeng`, `gunkali`, or `tranh3`
For a full list of available scales from tunejs, see http://abbernie.github.io/tune/scales.html
You can set your root to be a particular note with `getFreq`
<MiniRepl
client:idle
tune={`"4 8 9 10 - - 5 7 9 11 - -".tune("tranh3")
.mul(getFreq('c3'))
.freq().clip(.5).room(1)`}
/>
Some tunings become more pronounced with a longer reverb decay:
<MiniRepl
client:idle
tune={`"<[5 6 8 10] - [5 7 9 12] -> -".tune("gumbeng")
.mul(getFreq('c3'))
.freq().clip(.8).room("3:10").rdim(10000).rfade(5)`}
/>
Additionally, you can combo this with `fmap` so that the base note changes:
<MiniRepl
client:idle
tune={`"9 11 12 10 - - -".tune("gunkali")
.mul("<c3 c3 a3 d#3>".fmap(getFreq))
.freq().legato("2 .7").room("1:15").rdim(8500).rlp(14000).rfade(8)`}
/>
Combining this with various polyrhythm tricks can become very evocative:
<MiniRepl
client:idle
tune={`"<[0 3 1 -] [-1 4 2 8]> ~ ~,<-4 -5>"
.transpose(4)
.tune("iraq")
.mul("<c3 d3 c#3>".fmap(getFreq))
.freq().clip(.5).room(1).rfade(9)`}
/>
Another helpful trick when exploring new tunings is to strum them.
Many have a much more enchanting sound that was chosen over many generations of musicians for being strummed.
Take the `sanza` tuning:
<MiniRepl
client:idle
tune={`"4 5 6 7 8 9".tune("sanza")
.mul(getFreq('c3'))
.freq()`}
/>
Notes 7 and 9 will clash quite a bit if you arp them normally. Many tunings will have this sort of sound, and it can feel distracting on its own.
See how close they are on the pitch wheel?
<MiniRepl client:idle tune={`"[7 9]!3".tune("sanza").mul(getFreq('c3')).freq()._pitchwheel()`} />
This quality is often due to how the tunings were formed with instruments that were played differently than a piano.
As such, some tunings are much better strummed, with the subtle clash of the detuned notes actually making the sound much more magical:
<MiniRepl
client:idle
tune={`"[0 1 2 3 4 5 6]@0.3 -"
.transpose("<2 5 8 1>")
.tune("sanza")
.mul(getFreq('c3')).freq()
.legato("3").room(1).rfade(5)`}
/>
Note the legato and reverb effects make sure the sound of the strumming gets to wash together. Alternating the direction of the strum can make the
tones sound even more alive, too.
The `tranh3` tuning has a similar set of notes, with two clashing. You might trying plugging that in above and see if you find a favorite strumming pattern.
+2 -2
View File
@@ -9,9 +9,9 @@ The docs page is built ontop of astro's [docs site](https://github.com/withastro
## Adding a new Docs Page
1. add a `.mdx` file in a path under `website/src/pages/`, e.g. [website/src/pages/learn/code.mdx](https://raw.githubusercontent.com/tidalcycles/strudel/main/website/src/pages/learn/code.mdx) will be available under https://strudel.cc/learn/code/ (or locally under `http://localhost:4321/learn/code/`)
1. add a `.mdx` file in a path under `website/src/pages/`, e.g. [website/src/pages/learn/code.mdx](https://codeberg.org/uzu/strudel/src/branch/main/website/src/pages/learn/code.mdx) will be available under https://strudel.cc/learn/code/ (or locally under `http://localhost:4321/learn/code/`)
2. make sure to copy the top part of another existing docs page. Adjust the title accordingly
3. To add a link to the sidebar, add a new entry to `SIDEBAR` to [`config.ts`](https://github.com/tidalcycles/strudel/blob/main/website/src/config.ts)
3. To add a link to the sidebar, add a new entry to `SIDEBAR` to [`config.ts`](https://codeberg.org/uzu/strudel/src/branch/main/website/src/config.ts)
## Using the Mini REPL
+15 -15
View File
@@ -7,7 +7,7 @@ import { MiniRepl } from '../../docs/MiniRepl';
# Strudel Packages
The [strudel repo](https://github.com/tidalcycles/strudel) is organized as a monorepo, containing multiple npm packages.
The [strudel repo](https://codeberg.org/uzu/strudel) is organized as a monorepo, containing multiple npm packages.
The purpose of the multiple packages is to
- organize the codebase into more modular, encapsulated pieces
@@ -23,8 +23,8 @@ Here is an overview of all the packages:
These packages give you a batteries-included point of getting started, and most likely the thing you'd want to use in your project:
- [repl](https://github.com/tidalcycles/strudel/tree/main/packages/repl): The Strudel REPL as a web component.
- [web](https://github.com/tidalcycles/strudel/tree/main/packages/web): Strudel library for the browser, without UI.
- [repl](https://codeberg.org/uzu/strudel/src/branch/main/packages/repl): The Strudel REPL as a web component.
- [web](https://codeberg.org/uzu/strudel/src/branch/main/packages/web): Strudel library for the browser, without UI.
To find out more about these two, read [Using Strudel in Your Project](/technical-manual/project-start)
@@ -32,31 +32,31 @@ To find out more about these two, read [Using Strudel in Your Project](/technica
These package are the most essential. You might want to use all of those if you're using strudel in your project:
- [core](https://github.com/tidalcycles/strudel/tree/main/packages/core#strudelcore): tidal pattern engine with core primitives
- [mini](https://github.com/tidalcycles/strudel/tree/main/packages/mini#strudelmini): mini notation parser + core bindings
- [transpiler](https://github.com/tidalcycles/strudel/tree/main/packages/transpiler#strudeltranspiler): user code transpiler. syntax sugar + highlighting
- [core](https://codeberg.org/uzu/strudel/src/branch/main/packages/core#strudelcore): tidal pattern engine with core primitives
- [mini](https://codeberg.org/uzu/strudel/src/branch/main/packages/mini#strudelmini): mini notation parser + core bindings
- [transpiler](https://codeberg.org/uzu/strudel/src/branch/main/packages/transpiler#strudeltranspiler): user code transpiler. syntax sugar + highlighting
### Language Extensions
These packages extend the pattern language by specific functions
- [tonal](https://github.com/tidalcycles/strudel/tree/main/packages/tonal): tonal functions for scales and chords
- [xen](https://github.com/tidalcycles/strudel/tree/main/packages/xen): microtonal / xenharmonic functions
- [tonal](https://codeberg.org/uzu/strudel/src/branch/main/packages/tonal): tonal functions for scales and chords
- [xen](https://codeberg.org/uzu/strudel/src/branch/main/packages/xen): microtonal / xenharmonic functions
### Outputs
These packages provide bindings for different ways to output strudel patterns:
- [webaudio](https://github.com/tidalcycles/strudel/tree/main/packages/webaudio#strudelwebaudio): the default webaudio output
- [osc](https://github.com/tidalcycles/strudel/tree/main/packages/osc#strudelosc): bindings to communicate via OSC
- [midi](https://github.com/tidalcycles/strudel/tree/main/packages/midi#strudelmidi): webmidi bindings
- [csound](https://github.com/tidalcycles/strudel/tree/main/packages/csound#strudelcsound): csound bindings
- [soundfonts](https://github.com/tidalcycles/strudel/tree/main/packages/serial#strudelsoundfonts): Soundfont support
- [serial](https://github.com/tidalcycles/strudel/tree/main/packages/serial#strudelserial): webserial bindings
- [webaudio](https://codeberg.org/uzu/strudel/src/branch/main/packages/webaudio#strudelwebaudio): the default webaudio output
- [osc](https://codeberg.org/uzu/strudel/src/branch/main/packages/osc#strudelosc): bindings to communicate via OSC
- [midi](https://codeberg.org/uzu/strudel/src/branch/main/packages/midi#strudelmidi): webmidi bindings
- [csound](https://codeberg.org/uzu/strudel/src/branch/main/packages/csound#strudelcsound): csound bindings
- [soundfonts](https://codeberg.org/uzu/strudel/src/branch/main/packages/serial#strudelsoundfonts): Soundfont support
- [serial](https://codeberg.org/uzu/strudel/src/branch/main/packages/serial#strudelserial): webserial bindings
### Others
- [embed](https://github.com/tidalcycles/strudel/tree/main/packages/embed#strudelembed): embeddable REPL web component
- [embed](https://codeberg.org/uzu/strudel/src/branch/main/packages/embed#strudelembed): embeddable REPL web component
### No Longer Maintained
@@ -61,7 +61,7 @@ n("<0 1 2 3 4>*8").scale('G4 minor')
This will load the strudel website in an iframe, using the code provided within the HTML comments `<!-- -->`.
The HTML comments are needed to make sure the browser won't interpret it as HTML.
For alternative ways to load this package, see the [@strudel/embed README](https://github.com/tidalcycles/strudel/tree/main/packages/embed#strudelembed).
For alternative ways to load this package, see the [@strudel/embed README](https://codeberg.org/uzu/strudel/src/branch/main/packages/embed#strudel-embed).
### @strudel/repl
@@ -99,7 +99,7 @@ The upside of using the repl without an iframe is that you can pin the strudel v
This will guarantee your pattern wont break due to changes to the strudel project in the future.
For more info on this package, see the [@strudel/repl README](https://github.com/tidalcycles/strudel/tree/main/packages/repl#strudelrepl).
For more info on this package, see the [@strudel/repl README](https://codeberg.org/uzu/strudel/src/branch/main/packages/repl#strudel-repl).
## With your own UI
@@ -118,7 +118,7 @@ If you'd rather use your own UI, you can use the `@strudel/web` package:
</script>
```
For more info on this package, see the [@strudel/web README](https://github.com/tidalcycles/strudel/tree/main/packages/web#strudelweb).
For more info on this package, see the [@strudel/web README]https://codeberg.org/uzu/strudel/src/branch/main/packages/web#strudel-web).
## Via npm
+5 -3
View File
@@ -9,7 +9,9 @@ import { MiniRepl } from '../../docs/MiniRepl';
{/* The [REPL](https://strudel.cc/) is the place where all packages come together to form a live coding system. It can also be seen as a reference implementation for users of the library. */}
While Strudel can be used as a library in any JavaScript codebase, its main, reference user interface is the Strudel REPL^[REPL stands for read, evaluate, print/play, loop. It is friendly jargon for an interactive programming interface from computing heritage, usually for a commandline interface but also applied to live coding editors.], which is a browser-based live coding environment. This live code editor is dedicated to manipulating Strudel patterns while they play. The REPL features built-in visual feedback, highlighting which elements in the patterned (mini-notation) sequences are influencing the event that is currently being played. This feedback is designed to support both learning and live use of Strudel.
While Strudel can be used as a library in any JavaScript codebase, its main, reference user interface is the Strudel REPL[^1], which is a browser-based live coding environment. This live code editor is dedicated to manipulating Strudel patterns while they play. The REPL features built-in visual feedback, highlighting which elements in the patterned (mini-notation) sequences are influencing the event that is currently being played. This feedback is designed to support both learning and live use of Strudel.
[^1]: REPL stands for read, evaluate, print/play, loop. It is friendly jargon for an interactive programming interface from computing heritage, usually for a commandline interface but also applied to live coding editors.
Besides a UI for playback control and meta information, the main part of the REPL interface is the code editor powered by CodeMirror. In it, the user can edit and evaluate pattern code live, using one of the available synthesis outputs to create music and/or sound art. The control flow of the REPL follows 3 basic steps:
@@ -17,7 +19,7 @@ Besides a UI for playback control and meta information, the main part of the REP
2. While the REPL is running, the `Scheduler` queries the active `Pattern` by a regular interval, generating `Events` (also known as `Haps` in Strudel) for the next time span.
3. For each scheduling tick, all generated `Events` are triggered by calling their `onTrigger` method, which is set by the output.
<img src="https://github.com/tidalcycles/strudel/blob/talk/talk/public/strudelflow.png?raw=true" width="600" />
<img src="https://codeberg.org/uzu/strudel/raw/branch/talk/talk/public/strudelflow.png" width="600" />
## User Code
@@ -75,7 +77,7 @@ The sum of both is passed to `withLoc` to tell each element its location, which
Another important part of the user code is the mini notation, which allows to express rhythms in a short manner.
- the mini notation is [implemented as a PEG grammar](https://github.com/tidalcycles/strudel/blob/main/packages/mini/krill.pegjs), living in the [mini package](https://github.com/tidalcycles/strudel/tree/main/packages/mini)
- the mini notation is [implemented as a PEG grammar](https://codeberg.org/uzu/strudel/src/branch/talk/packages/mini/krill.pegjs), living in the [mini package](https://codeberg.org/uzu/strudel/src/branch/main/packages/mini)
- it is based on [krill](https://github.com/Mdashdotdashn/krill) by Mdashdotdashn
- the peg grammar is used to generate a parser with [peggyjs](https://peggyjs.org/)
- the generated parser takes a mini notation string and outputs an AST
+10 -8
View File
@@ -1,12 +1,14 @@
---
import HeadCommon from '@components/HeadCommon.astro';
import { Udels } from '../../components/Udels/Udels.jsx';
const { BASE_URL } = import.meta.env;
const baseNoTrailing = BASE_URL.endsWith('/') ? BASE_URL.slice(0, -1) : BASE_URL;
---
<body class="m-0">
<Udels client:only="react" />
</body>
<html lang="en" class="m-0">
<head>
<HeadCommon />
<title>Strudel UDELS</title>
</head>
<body class="m-0">
<Udels client:only="react" />
</body>
</html>
+38 -13
View File
@@ -43,21 +43,35 @@ This is why the same CPS can produce different perceived tempos.
## Setting CPM
If you're familiar with BPM, you can use the `cpm` method to set the tempo in cycles per minute:
If you're familiar with BPM, you can use the `setcpm` method to set the global tempo in cycles per minute:
<MiniRepl client:visible tune={`s("bd hh").cpm(110)`} />
<MiniRepl
client:visible
tune={`setcpm(110)
s("bd hh")`}
/>
If you want to add more beats per cycle, you might want to divide the cpm:
<MiniRepl client:visible tune={`s("bd sd bd rim, hh*8").cpm(110/4)`} />
<MiniRepl
client:visible
tune={`setcpm(110/4)
s("bd sd bd rim, hh*8")`}
/>
Or using 2 beats per cycle:
<MiniRepl client:visible tune={`s("bd sd, hh*4").cpm(110/2)`} />
<MiniRepl
client:visible
tune={`setcpm(110/2)
s("bd sd, hh*4")`}
/>
You can use the `setcps` method to set the global tempo in cycles per second. `setcpm(x)` is the same as `setcps(x / 60)`.
<Box>
To set a specific bpm, use `.cpm(bpm/bpc)`
To set a specific bpm, use `setcpm(bpm/bpc)`
- bpm: the target beats per minute
- bpc: the number of perceived beats per cycle
@@ -74,22 +88,31 @@ Many music programs use it as a default.
Strudel does not a have concept of bars or measures, there are only cycles.
How you use them is up to you. Above, we've had this example:
<MiniRepl client:visible tune={`s("bd sd bd rim, hh*8").cpm(110/4)`} />
<MiniRepl
client:visible
tune={`setcpm(110/4)
s("bd sd bd rim, hh*8")`}
/>
This could be interpreted as 4/4 time with a tempo of 110bpm.
We could write out multiple bars like this:
<MiniRepl
client:visible
tune={`s(\`<
tune={`setcpm(110/4)
s(\`<
[bd sd bd rim, hh*8]
[bd sd bd rim*2, hh*8]
>\`).cpm(110/4)`}
>\`)`}
/>
Instead of writing out each bar separately, we could express this much shorter:
<MiniRepl client:visible tune={`s("bd <sd rim*<1 2>>,hh*4").cpm(110/2)`} />
<MiniRepl
client:visible
tune={`setcpm(110/2)
s("bd <sd rim*<1 2>>,hh*4")`}
/>
Here we can see that thinking in cycles rather than bars simplifies things a lot!
These types of simplifications work because of the repetitive nature of rhythm.
@@ -109,10 +132,11 @@ We could also write multiple bars with different time signatures:
<MiniRepl
client:visible
tune={`s(\`<
tune={`setcpm(110*2)
s(\`<
[bd hh rim]@3
[bd hh rim sd]@4
>\`).cpm(110*2)`}
>\`)`}
/>
Here we switch between 3/4 and 4/4, keeping the same tempo.
@@ -121,10 +145,11 @@ If we don't specify the length, we get what's called a metric modulation:
<MiniRepl
client:visible
tune={`s(\`<
tune={`setcpm(110/2)
s(\`<
[bd hh rim]
[bd hh rim sd]
>\`).cpm(110/2)`}
>\`)`}
/>
Now the 3 elements get the same time as the 4 elements, which is why the tempo changes.
+15 -7
View File
@@ -216,8 +216,9 @@ Finding the right notes can be difficult.. Scales are here to help:
<MiniRepl
client:visible
tune={`n("0 2 4 <[6,8] [7,9]>")
.scale("C:minor").sound("piano").cpm(60)`}
tune={`setcpm(60)
n("0 2 4 <[6,8] [7,9]>")
.scale("C:minor").sound("piano")`}
punchcard
/>
@@ -242,9 +243,10 @@ Just like anything, we can automate the scale with a pattern:
<MiniRepl
client:visible
tune={`n("<0 -3>, 2 4 <[6,8] [7,9]>")
tune={`setcpm(60)
n("<0 -3>, 2 4 <[6,8] [7,9]>")
.scale("<C:major D:mixolydian>/4")
.sound("piano").cpm(60)`}
.sound("piano")`}
punchcard
/>
@@ -275,9 +277,10 @@ Try changing that number!
<MiniRepl
client:visible
tune={`n("<[4@2 4] [5@2 5] [6@2 6] [5@2 5]>*2")
tune={`setcpm(60)
n("<[4@2 4] [5@2 5] [6@2 6] [5@2 5]>*2")
.scale("<C2:mixolydian F2:mixolydian>/4")
.sound("gm_acoustic_bass").cpm(60)`}
.sound("gm_acoustic_bass")`}
punchcard
/>
@@ -291,7 +294,12 @@ This is also sometimes called triplet swing. You'll often find it in blues and j
**Replicate**
<MiniRepl client:visible tune={`note("c!2 [eb,<g a bb a>]").sound("piano").cpm(60)`} punchcard />
<MiniRepl
client:visible
tune={`setcpm(60)
note("c!2 [eb,<g a bb a>]").sound("piano")`}
punchcard
/>
<Box>
+39 -25
View File
@@ -166,9 +166,14 @@ Try also changing the number at the end to change the tempo!
</Box>
**changing the tempo with cpm**
**changing the tempo with setcpm**
<MiniRepl client:visible tune={`sound("<bd hh rim hh>*8").cpm(90/4)`} punchcard />
<MiniRepl
client:visible
tune={`setcpm(90/4)
sound("<bd hh rim hh>*8")`}
punchcard
/>
<Box>
@@ -257,14 +262,14 @@ It is quite common that there are many ways to express the same idea.
**selecting sample numbers separately**
Instead of using ":", we can also use the `n` function to select sample numbers:
<MiniRepl client:visible tune={`n("0 1 [4 2] 3*2").sound("jazz")`} punchcard />
This is shorter and more readable than:
Instead of selecting sample numbers one by one:
<MiniRepl client:visible tune={`sound("jazz:0 jazz:1 [jazz:4 jazz:2] jazz:3*2")`} punchcard />
We can also use the `n` function to make it shorter and more readable:
<MiniRepl client:visible tune={`n("0 1 [4 2] 3*2").sound("jazz")`} punchcard />
## Recap
Now we've learned the basics of the so called Mini-Notation, the rhythm language of Tidal.
@@ -283,12 +288,12 @@ This is what we've learned so far:
The Mini-Notation is usually used inside some function. These are the functions we've seen so far:
| Name | Description | Example |
| ----- | ----------------------------------- | --------------------------------------------------------------------------------- |
| sound | plays the sound of the given name | <MiniRepl client:visible tune={`sound("bd sd [- bd] sd")`} /> |
| bank | selects the sound bank | <MiniRepl client:visible tune={`sound("bd sd [- bd] sd").bank("RolandTR909")`} /> |
| cpm | sets the tempo in cycles per minute | <MiniRepl client:visible tune={`sound("bd sd [- bd] sd").cpm(45)`} /> |
| n | select sample number | <MiniRepl client:visible tune={`n("0 1 4 2 0 6 3 2").sound("jazz")`} /> |
| Name | Description | Example |
| ------ | ----------------------------------- | --------------------------------------------------------------------------------- |
| sound | plays the sound of the given name | <MiniRepl client:visible tune={`sound("bd sd [- bd] sd")`} /> |
| bank | selects the sound bank | <MiniRepl client:visible tune={`sound("bd sd [- bd] sd").bank("RolandTR909")`} /> |
| setcpm | sets the tempo in cycles per minute | <MiniRepl client:visible tune={`setcpm(45); sound("bd sd [- bd] sd")`} /> |
| n | select sample number | <MiniRepl client:visible tune={`n("0 1 4 2 0 6 3 2").sound("jazz")`} /> |
## Examples
@@ -296,8 +301,8 @@ The Mini-Notation is usually used inside some function. These are the functions
<MiniRepl
client:visible
tune={`sound("[bd sd]*2, hh*8").bank("RolandTR505")
.cpm(100/4)`}
tune={`setcpm(100/4)
sound("[bd sd]*2, hh*8").bank("RolandTR505")`}
punchcard
/>
@@ -314,14 +319,20 @@ Certain drum patterns are reused across genres.
We Will Rock you
<MiniRepl client:visible tune={`sound("bd*2 cp").bank("RolandTR707").cpm(81/2)`} punchcard />
<MiniRepl
client:visible
tune={`setcpm(81/2)
sound("bd*2 cp").bank("RolandTR707")`}
punchcard
/>
**Yellow Magic Orchestra - Firecracker**
<MiniRepl
client:visible
tune={`sound("bd sd, - - - hh - hh - -, - perc - perc:1*2")
.bank("RolandCompurhythm1000").cpm(120/2)`}
tune={`setcpm(120/2)
sound("bd sd, - - - hh - hh - -, - perc - perc:1*2")
.bank("RolandCompurhythm1000")`}
punchcard
/>
@@ -329,12 +340,14 @@ We Will Rock you
<MiniRepl
client:visible
tune={`sound(\`
tune={`
setcpm(90/4)
sound(\`
[- - oh - ] [- - - - ] [- - - - ] [- - - - ],
[hh hh - - ] [hh - hh - ] [hh - hh - ] [hh - hh - ],
[- - - - ] [cp - - - ] [- - - - ] [cp - - - ],
[bd - - - ] [- - - bd] [- - bd - ] [- - - bd]
\`).cpm(90/4)`}
\`)`}
punchcard
/>
@@ -342,12 +355,13 @@ We Will Rock you
<MiniRepl
client:visible
tune={`sound(\`
tune={`setcpm(88/4)
sound(\`
[- - - - ] [- - - - ] [- - - - ] [- - oh:1 - ],
[hh hh hh hh] [hh hh hh hh] [hh hh hh hh] [hh hh - - ],
[- - - - ] [cp - - - ] [- - - - ] [~ cp - - ],
[bd bd - - ] [- - bd - ] [bd bd - bd ] [- - - - ]
\`).bank("RolandTR808").cpm(88/4)`}
\`).bank("RolandTR808")`}
punchcard
/>
@@ -355,11 +369,11 @@ We Will Rock you
<MiniRepl
client:visible
tune={`s(\`jazz*2,
tune={`setcpm(100/2)
s(\`jazz*2,
insect [crow metal] - -,
- space:4 - space:1,
- wind\`)
.cpm(100/2)`}
- wind\`)`}
punchcard
/>
@@ -68,9 +68,10 @@ Try commenting out one or more by adding `//` before a line
<MiniRepl
client:visible
tune={`note("c2 [eb3,g3] ".add("<0 <1 -1>>"))
tune={`setcpm(60)
note("c2 [eb3,g3] ".add("<0 <1 -1>>"))
.color("<cyan <magenta yellow>>").adsr("[.1 0]:.2:[1 0]")
.sound("gm_acoustic_bass").room(.5).cpm(60)`}
.sound("gm_acoustic_bass").room(.5)`}
punchcard
/>
@@ -84,9 +85,10 @@ We can add as often as we like:
<MiniRepl
client:visible
tune={`note("c2 [eb3,g3]".add("<0 <1 -1>>").add("0,7"))
tune={`setcpm(60)
note("c2 [eb3,g3]".add("<0 <1 -1>>").add("0,7"))
.color("<cyan <magenta yellow>>").adsr("[.1 0]:.2:[1 0]")
.sound("gm_acoustic_bass").room(.5).cpm(60)`}
.sound("gm_acoustic_bass").room(.5)`}
punchcard
/>
+10 -10
View File
@@ -56,13 +56,13 @@ This page is just a listing of all functions covered in the workshop!
## Pattern Effects
| name | description | example |
| ---- | ----------------------------------- | ----------------------------------------------------------------------------------- |
| cpm | sets the tempo in cycles per minute | <MiniRepl client:visible tune={`sound("bd sd [~ bd] sd").cpm(45)`} /> |
| fast | speed up | <MiniRepl client:visible tune={`sound("bd sd [~ bd] sd").fast(2)`} /> |
| slow | slow down | <MiniRepl client:visible tune={`sound("bd sd [~ bd] sd").slow(2)`} /> |
| rev | reverse | <MiniRepl client:visible tune={`n("0 2 4 6").scale("C:minor").rev()`} /> |
| jux | split left/right, modify right | <MiniRepl client:visible tune={`n("0 2 4 6").scale("C:minor").jux(rev)`} /> |
| add | add numbers / notes | <MiniRepl client:visible tune={`n("0 2 4 6".add("<0 1 2 1>")).scale("C:minor")`} /> |
| ply | speed up each event n times | <MiniRepl client:visible tune={`s("bd sd").ply("<1 2 3>")`} /> |
| off | copy, shift time & modify | <MiniRepl client:visible tune={`s("bd sd, hh*4").off(1/8, x=>x.speed(2))`} /> |
| name | description | example |
| ------ | ----------------------------------- | ----------------------------------------------------------------------------------- |
| setcpm | sets the tempo in cycles per minute | <MiniRepl client:visible tune={`setcpm(45); sound("bd sd [~ bd] sd")`} /> |
| fast | speed up | <MiniRepl client:visible tune={`sound("bd sd [~ bd] sd").fast(2)`} /> |
| slow | slow down | <MiniRepl client:visible tune={`sound("bd sd [~ bd] sd").slow(2)`} /> |
| rev | reverse | <MiniRepl client:visible tune={`n("0 2 4 6").scale("C:minor").rev()`} /> |
| jux | split left/right, modify right | <MiniRepl client:visible tune={`n("0 2 4 6").scale("C:minor").jux(rev)`} /> |
| add | add numbers / notes | <MiniRepl client:visible tune={`n("0 2 4 6".add("<0 1 2 1>")).scale("C:minor")`} /> |
| ply | speed up each event n times | <MiniRepl client:visible tune={`s("bd sd").ply("<1 2 3>")`} /> |
| off | copy, shift time & modify | <MiniRepl client:visible tune={`s("bd sd, hh*4").off(1/8, x=>x.speed(2))`} /> |
+147
View File
@@ -69,3 +69,150 @@
text-decoration: underline 0.18rem;
text-underline-offset: 0.22rem;
}
/* Override default styles from the codemirror inline css for autocomplete info tooltip*/
.cm-tooltip.cm-completionInfo {
padding: 0 !important;
border: 1px solid var(--foreground) !important;
border-radius: 4px !important;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3) !important;
max-width: 500px !important;
min-width: 300px !important;
max-height: 400px !important;
background-color: var(--lineHighlight) !important;
overflow: auto;
background: var(--background) !important;
}
/* Main tooltip container */
.autocomplete-info-container {
padding: 12px !important;
border-radius: 4px !important;
color: var(--foreground);
font-family: var(--font-family, 'SF Mono', 'Monaco', monospace);
font-size: var(--font-size, 13px);
line-height: 1.4;
max-width: 600px;
height: 100%;
min-width: 400px;
white-space: normal !important;
overflow-y: auto !important;
}
.autocomplete-info-tooltip {
overflow-y: auto !important;
}
.autocomplete-info-function-description {
white-space: pre-wrap !important;
}
.autocomplete-info-function-name {
font-size: 15px;
font-weight: 600;
color: var(--foreground);
margin: 0 0 8px 0;
}
.autocomplete-info-function-synonyms {
margin: 0 0 12px 0;
color: var(--foreground);
line-height: 1.5;
opacity: 0.8;
}
.autocomplete-info-function-description {
margin: 0 0 12px 0;
color: var(--foreground);
line-height: 1.5;
opacity: 0.8;
}
.autocomplete-info-section-title {
font-size: 12px;
font-weight: 600;
color: var(--foreground);
margin: 16px 0 6px 0;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.autocomplete-info-section-title:first-child {
margin-top: 0;
}
.autocomplete-info-params-section {
margin-top: 12px;
}
.autocomplete-info-params-list {
list-style: none;
margin: 0;
padding: 0;
}
.autocomplete-info-param-item {
margin-bottom: 8px;
padding: 8px;
background-color: var(--lineBackground);
border-radius: 3px;
border-left: 2px solid var(--foreground, #555);
}
.autocomplete-info-param-item:last-child {
margin-bottom: 0;
}
.autocomplete-info-param-name {
font-weight: 600;
color: var(--variable, var(--foreground));
margin-right: 8px;
}
.autocomplete-info-param-type {
color: var(--comment);
font-size: 12px;
background-color: var(--gutterForeground);
padding: 1px 4px;
border-radius: 2px;
}
.autocomplete-info-param-desc {
color: var(--foreground);
font-size: 10px;
margin-top: 4px;
line-height: 1.4;
opacity: 0.7;
}
.autocomplete-info-examples-section {
margin-top: 12px;
}
.autocomplete-info-example-code {
background: var(--lineBackground);
color: var(--foreground);
padding: 8px;
border-radius: 3px;
font-family: var(--font-family, 'SF Mono', 'Monaco', monospace);
font-size: 12px;
line-height: 1.5;
margin: 4px 0;
overflow-x: auto;
white-space: pre;
border: 1px solid var(--foreground, #3a3a3a);
}
.autocomplete-info-tooltip::-webkit-scrollbar {
width: 4px;
}
.autocomplete-info-tooltip::-webkit-scrollbar-track {
}
.autocomplete-info-tooltip::-webkit-scrollbar-thumb {
border-radius: 2px;
}
.autocomplete-info-tooltip::-webkit-scrollbar-thumb:hover {
}
+4 -2
View File
@@ -1,6 +1,6 @@
/*
Repl.jsx - <short description TODO>
Copyright (C) 2022 Strudel contributors - see <https://github.com/tidalcycles/strudel/blob/main/repl/src/App.js>
Copyright (C) 2022 Strudel contributors - see <https://codeberg.org/uzu/strudel/src/branch/main/repl/src/App.js>
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
@@ -9,10 +9,12 @@ import UdelsEditor from '@components/Udels/UdelsEditor';
import ReplEditor from './components/ReplEditor';
import EmbeddedReplEditor from './components/EmbeddedReplEditor';
import { useReplContext } from './useReplContext';
import { useSettings } from '@src/settings.mjs';
export function Repl({ embedded = false }) {
const isEmbedded = embedded || isIframe();
const Editor = isUdels() ? UdelsEditor : isEmbedded ? EmbeddedReplEditor : ReplEditor;
const context = useReplContext();
return <Editor context={context} />;
const { fontFamily } = useSettings();
return <Editor context={context} style={{ fontFamily }} />;
}
@@ -9,10 +9,10 @@ import { Header } from './Header';
// }
export default function EmbeddedReplEditor(Props) {
const { context } = Props;
const { context, ...editorProps } = Props;
const { pending, started, handleTogglePlay, containerRef, editorRef, error, init } = context;
return (
<div className="h-full flex flex-col relative">
<div className="h-full flex flex-col relative" {...editorProps}>
<Loader active={pending} />
<Header context={context} embedded={true} />
<BigPlayButton started={started} handleTogglePlay={handleTogglePlay} />
+5 -4
View File
@@ -11,7 +11,7 @@ export function Header({ context, embedded = false }) {
const { started, pending, isDirty, activeCode, handleTogglePlay, handleEvaluate, handleShuffle, handleShare } =
context;
const isEmbedded = typeof window !== 'undefined' && (embedded || window.location !== window.parent.location);
const { isZen, isButtonRowHidden, isCSSAnimationDisabled } = useSettings();
const { isZen, isButtonRowHidden, isCSSAnimationDisabled, fontFamily } = useSettings();
return (
<header
@@ -22,6 +22,7 @@ export function Header({ context, embedded = false }) {
isZen ? 'h-12 w-8 fixed top-0 left-0' : 'sticky top-0 w-full py-1 justify-between',
isEmbedded ? 'flex' : 'md:flex',
)}
style={{ fontFamily }}
>
<div className="px-4 flex space-x-2 md:pt-0 select-none">
<h1
@@ -46,7 +47,7 @@ export function Header({ context, embedded = false }) {
}
}}
>
<span className="block rotate-90"></span>
<span className="block text-foreground rotate-90"></span>
</div>
{!isZen && (
<div className="space-x-2">
@@ -92,7 +93,7 @@ export function Header({ context, embedded = false }) {
>
{!isEmbedded && <span>update</span>}
</button>
{!isEmbedded && (
{/* !isEmbedded && (
<button
title="shuffle"
className="hover:opacity-50 p-2 flex items-center space-x-1"
@@ -100,7 +101,7 @@ export function Header({ context, embedded = false }) {
>
<span> shuffle</span>
</button>
)}
) */}
{!isEmbedded && (
<button
title="share"
+2 -2
View File
@@ -10,13 +10,13 @@ import { useSettings } from '@src/settings.mjs';
// }
export default function ReplEditor(Props) {
const { context } = Props;
const { context, ...editorProps } = Props;
const { containerRef, editorRef, error, init, pending } = context;
const settings = useSettings();
const { panelPosition, isZen } = settings;
return (
<div className="h-full flex flex-col relative">
<div className="h-full flex flex-col relative" {...editorProps}>
<Loader active={pending} />
<Header context={context} />
<div className="grow flex relative overflow-hidden">
@@ -4,5 +4,9 @@ export default function UserFacingErrorMessage(Props) {
if (error == null) {
return;
}
return <div className="text-red-500 p-4 bg-lineHighlight animate-pulse">{error.message || 'Unknown Error :-/'}</div>;
return (
<div className="text-background px-2 py-1 bg-foreground w-full ml-auto">
Error: {error.message || 'Unknown Error :-/'}
</div>
);
}
@@ -0,0 +1,10 @@
import cx from '@src/cx.mjs';
export function ActionButton({ children, label, labelIsHidden, className, ...buttonProps }) {
return (
<button className={cx('hover:opacity-50 text-nowrap w-fit', className)} title={label} {...buttonProps}>
{labelIsHidden !== true && label}
{children}
</button>
);
}
@@ -6,7 +6,7 @@ function IncButton({ children, className, ...buttonProps }) {
<button
tabIndex={-1}
className={cx(
'border border-transparent p-1 text-center text-sm transition-all hover:bg-foreground active:bg-lineBackground disabled:pointer-events-none disabled:opacity-50 disabled:shadow-none',
'border border-transparent p-1 text-center hover:text-background text-sm transition-all hover:bg-foreground active:bg-lineBackground disabled:pointer-events-none disabled:opacity-50 disabled:shadow-none',
className,
)}
type="button"
@@ -1,6 +1,7 @@
import React, { useState } from 'react';
import { getAudioDevices, setAudioDevice } from '../../util.mjs';
import { SelectInput } from './SelectInput';
import { getAudioDevices } from '@strudel/webaudio';
const initdevices = new Map();
@@ -21,9 +22,7 @@ export function AudioDeviceSelector({ audioDeviceName, onChange, isDisabled }) {
if (!devicesInitialized) {
return;
}
const deviceID = devices.get(deviceName);
onChange(deviceName);
setAudioDevice(deviceID);
};
const options = new Map();
Array.from(devices.keys()).forEach((deviceName) => {
@@ -1,53 +1,32 @@
import { logger } from '@strudel/core';
import useEvent from '@src/useEvent.mjs';
import cx from '@src/cx.mjs';
import { nanoid } from 'nanoid';
import { useCallback, useState } from 'react';
import { useSettings } from '../../../settings.mjs';
import { useStore } from '@nanostores/react';
import { $strudel_log_history } from '../useLogger';
export function ConsoleTab() {
const [log, setLog] = useState([]);
const { fontFamily, fontSize } = useSettings();
useLogger(
useCallback((e) => {
const { message, type, data } = e.detail;
setLog((l) => {
const lastLog = l.length ? l[l.length - 1] : undefined;
const id = nanoid(12);
// if (type === 'loaded-sample' && lastLog.type === 'load-sample' && lastLog.url === data.url) {
if (type === 'loaded-sample') {
// const loadIndex = l.length - 1;
const loadIndex = l.findIndex(({ data: { url }, type }) => type === 'load-sample' && url === data.url);
l[loadIndex] = { message, type, id, data };
} else if (lastLog && lastLog.message === message) {
l = l.slice(0, -1).concat([{ message, type, count: (lastLog.count ?? 1) + 1, id, data }]);
} else {
l = l.concat([{ message, type, id, data }]);
}
return l.slice(-20);
});
}, []),
);
const log = useStore($strudel_log_history);
const { fontFamily } = useSettings();
return (
<div
id="console-tab"
className="break-all px-4 dark:text-white text-stone-900 text-sm py-2 space-y-1"
style={{ fontFamily, fontSize }}
>
{log.map((l, i) => {
const message = linkify(l.message);
const color = l.data?.hap?.value?.color;
return (
<div
key={l.id}
className={cx(l.type === 'error' && 'text-red-500', l.type === 'highlight' && 'underline')}
style={color ? { color } : {}}
>
<span dangerouslySetInnerHTML={{ __html: message }} />
{l.count ? ` (${l.count})` : ''}
</div>
);
})}
<div id="console-tab" className="break-all w-full first-line:text-sm p-2 h-full" style={{ fontFamily }}>
<div className="bg-background h-full w-full overflow-auto space-y-1 p-2 rounded-md">
{log.map((l, i) => {
const message = linkify(l.message);
const color = l.data?.hap?.value?.color;
return (
<div
key={l.id}
className={cx(
l.type === 'error' ? 'text-background bg-foreground' : 'text-foreground',
l.type === 'highlight' && 'underline',
)}
style={color ? { color } : {}}
>
<span dangerouslySetInnerHTML={{ __html: message }} />
{l.count ? ` (${l.count})` : ''}
</div>
);
})}
</div>
</div>
);
}
@@ -72,7 +51,3 @@ function linkify(inputText) {
return replacedText;
}
function useLogger(onTrigger) {
useEvent(logger.key, onTrigger);
}
@@ -20,25 +20,42 @@ export default function ImportSoundsButton({ onComplete }) {
});
return (
<label
style={{ alignItems: 'center' }}
className="flex bg-background ml-2 pl-2 pr-2 max-w-[300px] rounded-md hover:opacity-50 whitespace-nowrap cursor-pointer"
>
<input
disabled={isUploading}
ref={fileUploadRef}
id="audio_file"
style={{ display: 'none' }}
type="file"
directory=""
webkitdirectory=""
multiple
accept="audio/*, .wav, .mp3, .m4a, .flac, .aac, .ogg"
onChange={() => {
onChange();
}}
/>
{isUploading ? 'importing...' : 'import sounds'}
</label>
<div>
<label
style={{ alignItems: 'center', borderColor: 'red', border: 1 }}
className="flex bg-background p-4 w-fit rounded-xl hover:opacity-50 whitespace-nowrap cursor-pointer"
>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth={1.5}
stroke="currentColor"
className="size-6 mr-2"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M7.5 7.5h-.75A2.25 2.25 0 0 0 4.5 9.75v7.5a2.25 2.25 0 0 0 2.25 2.25h7.5a2.25 2.25 0 0 0 2.25-2.25v-7.5a2.25 2.25 0 0 0-2.25-2.25h-.75m0-3-3-3m0 0-3 3m3-3v11.25m6-2.25h.75a2.25 2.25 0 0 1 2.25 2.25v7.5a2.25 2.25 0 0 1-2.25 2.25h-7.5a2.25 2.25 0 0 1-2.25-2.25v-.75"
/>
</svg>
<input
disabled={isUploading}
ref={fileUploadRef}
id="audio_file"
style={{ display: 'none' }}
type="file"
directory=""
webkitdirectory=""
multiple
accept="audio/*, .wav, .mp3, .m4a, .flac, .aac, .ogg"
onChange={() => {
onChange();
}}
/>
{isUploading ? 'importing...' : 'import sounds folder'}
</label>
</div>
);
}
@@ -5,6 +5,7 @@ import { FilesTab } from './FilesTab';
import { Reference } from './Reference';
import { SettingsTab } from './SettingsTab';
import { SoundsTab } from './SoundsTab';
import { useLogger } from '../useLogger';
import { WelcomeTab } from './WelcomeTab';
import { PatternsTab } from './PatternsTab';
import { ChevronLeftIcon, XMarkIcon } from '@heroicons/react/16/solid';
@@ -115,6 +116,7 @@ function PanelNav({ children, className, settings, ...props }) {
}
function PanelContent({ context, tab }) {
useLogger();
switch (tab) {
case tabNames.patterns:
return <PatternsTab context={context} />;
@@ -12,8 +12,8 @@ import { useMemo } from 'react';
import { getMetadata } from '../../../metadata_parser.js';
import { useExamplePatterns } from '../../useExamplePatterns.jsx';
import { parseJSON, isUdels } from '../../util.mjs';
import { ButtonGroup } from './Forms.jsx';
import { settingsMap, useSettings } from '../../../settings.mjs';
import { useSettings } from '../../../settings.mjs';
import { ActionButton } from '../button/action-button.jsx';
import { Pagination } from '../pagination/Pagination.jsx';
import { useState } from 'react';
import { useDebounce } from '../usedebounce.jsx';
@@ -56,8 +56,8 @@ function PatternButtons({ patterns, activePattern, onClick, started }) {
const viewingPatternData = parseJSON(viewingPatternStore);
const viewingPatternID = viewingPatternData.id;
return (
<div className="font-mono text-sm">
{Object.values(patterns ?? {})
<div className="">
{Object.values(patterns)
.reverse()
.map((pattern) => {
const id = pattern.id;
@@ -75,15 +75,6 @@ function PatternButtons({ patterns, activePattern, onClick, started }) {
);
}
function ActionButton({ children, onClick, label, labelIsHidden }) {
return (
<button className="hover:opacity-50 text-nowrap" onClick={onClick} title={label}>
{labelIsHidden !== true && label}
{children}
</button>
);
}
const updateCodeWindow = (context, patternData, reset = false) => {
context.handleUpdate(patternData, reset);
};
@@ -125,7 +116,7 @@ function UserPatterns({ context }) {
style={{ display: 'none' }}
type="file"
multiple
accept="text/plain,application/json"
accept="text/plain,text/x-markdown,application/json"
onChange={(e) => importPatterns(e.target.files)}
/>
import
@@ -142,21 +133,21 @@ function UserPatterns({ context }) {
</div>
<div className="overflow-auto h-full bg-background p-2 rounded-md">
{patternFilter === patternFilterName.user && (
<PatternButtons
onClick={(id) =>
updateCodeWindow(
context,
{ ...userPatterns[id], collection: userPattern.collection },
autoResetPatternOnChange,
)
}
patterns={userPatterns}
started={context.started}
activePattern={activePattern}
viewingPatternID={viewingPatternID}
/>
)}
{/* {patternFilter === patternFilterName.user && ( */}
<PatternButtons
onClick={(id) =>
updateCodeWindow(
context,
{ ...userPatterns[id], collection: userPattern.collection },
autoResetPatternOnChange,
)
}
patterns={userPatterns}
started={context.started}
activePattern={activePattern}
viewingPatternID={viewingPatternID}
/>
{/* )} */}
</div>
</div>
);
@@ -250,6 +241,11 @@ export function PatternsTab({ context }) {
const { patternFilter } = useSettings();
return (
<div className="px-4 w-full text-foreground space-y-2 flex flex-col overflow-hidden max-h-full h-full">
<UserPatterns context={context} />
</div>
);
/* return (
<div className="px-4 w-full text-foreground space-y-2 flex flex-col overflow-hidden max-h-full h-full">
<ButtonGroup
value={patternFilter}
@@ -263,5 +259,5 @@ export function PatternsTab({ context }) {
<PublicPatterns context={context} />
)}
</div>
);
); */
}
@@ -2,9 +2,32 @@ import { useMemo, useState } from 'react';
import jsdocJson from '../../../../../doc.json';
import { Textbox } from '../textbox/Textbox';
const availableFunctions = jsdocJson.docs
.filter(({ name, description }) => name && !name.startsWith('_') && !!description)
.sort((a, b) => /* a.meta.filename.localeCompare(b.meta.filename) + */ a.name.localeCompare(b.name));
const isValid = ({ name, description }) => name && !name.startsWith('_') && !!description;
const availableFunctions = (() => {
const seen = new Set(); // avoid repetition
const functions = [];
for (const doc of jsdocJson.docs) {
if (!isValid(doc)) continue;
functions.push(doc);
const synonyms = doc.synonyms || [];
for (const s of synonyms) {
if (!s || seen.has(s)) continue;
seen.add(s);
// Swap `doc.name` in for `s` in the list of synonyms
const synonymsWithDoc = [doc.name, ...synonyms].filter((x) => x && x !== s);
functions.push({
...doc,
name: s, // update names for the synonym
longname: s,
synonyms: synonymsWithDoc,
synonyms_text: synonymsWithDoc.join(', '),
});
}
}
return functions.sort((a, b) => /* a.meta.filename.localeCompare(b.meta.filename) + */ a.name.localeCompare(b.name));
})();
const getInnerText = (html) => {
var div = document.createElement('div');
@@ -21,12 +44,16 @@ export function Reference() {
return true;
}
return entry.name.includes(search) || (entry.synonyms?.some((s) => s.includes(search)) ?? false);
const lowCaseSearch = search.toLowerCase();
return (
entry.name.toLowerCase().includes(lowCaseSearch) ||
(entry.synonyms?.some((s) => s.includes(lowCaseSearch)) ?? false)
);
});
}, [search]);
return (
<div className="flex h-full w-full p-2 text-foreground overflow-hidden">
<div className="flex h-full w-full p-2 overflow-hidden">
<div className="h-full flex flex-col gap-2 w-1/3 max-w-72 ">
<div class="w-full flex">
<Textbox className="w-full" placeholder="Search" value={search} onChange={setSearch} />
@@ -35,7 +62,7 @@ export function Reference() {
{visibleFunctions.map((entry, i) => (
<a
key={i}
className="cursor-pointer flex-none hover:bg-lineHighlight overflow-x-hidden px-1 text-ellipsis"
className="cursor-pointer text-foreground flex-none hover:bg-lineHighlight overflow-x-hidden px-1 text-ellipsis"
onClick={() => {
const el = document.getElementById(`doc-${i}`);
const container = document.getElementById('reference-container');
@@ -70,12 +97,14 @@ export function Reference() {
<ul>
{entry.params?.map(({ name, type, description }, i) => (
<li key={i}>
{name} : {type.names?.join(' | ')} {description ? <> - {getInnerText(description)}</> : ''}
{name} : {type?.names?.join(' | ')} {description ? <> - {getInnerText(description)}</> : ''}
</li>
))}
</ul>
{entry.examples?.map((example, j) => (
<pre key={j}>{example}</pre>
<pre className="bg-background" key={j}>
{example}
</pre>
))}
</section>
))}
@@ -5,7 +5,7 @@ export function SelectInput({ value, options, onChange, onClick, isDisabled }) {
<select
disabled={isDisabled}
onClick={onClick}
className="p-2 bg-background rounded-md text-foreground"
className="p-2 bg-background rounded-md text-foreground border-foreground"
value={value ?? ''}
onChange={(e) => onChange(e.target.value)}
>
@@ -1,10 +1,12 @@
import { defaultSettings, settingsMap, useSettings } from '../../../settings.mjs';
import { themes } from '@strudel/codemirror';
import { Textbox } from '../textbox/Textbox.jsx';
import { isUdels } from '../../util.mjs';
import { ButtonGroup } from './Forms.jsx';
import { AudioDeviceSelector } from './AudioDeviceSelector.jsx';
import { AudioEngineTargetSelector } from './AudioEngineTargetSelector.jsx';
import { confirmDialog } from '../../util.mjs';
import { DEFAULT_MAX_POLYPHONY, setMaxPolyphony, setMultiChannelOrbits } from '@strudel/webaudio';
function Checkbox({ label, value, onChange, disabled = false }) {
return (
@@ -18,7 +20,7 @@ function Checkbox({ label, value, onChange, disabled = false }) {
function SelectInput({ value, options, onChange }) {
return (
<select
className="p-2 bg-background rounded-md text-foreground"
className="p-2 bg-background rounded-md text-foreground border-foreground"
value={value}
onChange={(e) => onChange(e.target.value)}
>
@@ -53,7 +55,7 @@ function NumberSlider({ value, onChange, step = 1, ...rest }) {
);
}
function FormItem({ label, children }) {
function FormItem({ label, children, sublabel }) {
return (
<div className="grid gap-2">
<label>{label}</label>
@@ -66,11 +68,13 @@ const themeOptions = Object.fromEntries(Object.keys(themes).map((k) => [k, k]));
const fontFamilyOptions = {
monospace: 'monospace',
Courier: 'Courier',
CutiePi: 'CutiePi',
JetBrains: 'JetBrains',
Hack: 'Hack',
FiraCode: 'FiraCode',
'FiraCode-SemiBold': 'FiraCode SemiBold',
teletext: 'teletext',
tic80: 'tic80',
mode7: 'mode7',
BigBlueTerminal: 'BigBlueTerminal',
x3270: 'x3270',
@@ -104,11 +108,15 @@ export function SettingsTab({ started }) {
audioDeviceName,
audioEngineTarget,
togglePanelTrigger,
maxPolyphony,
multiChannelOrbits,
isTabIndentationEnabled,
isMultiCursorEnabled,
} = useSettings();
const shouldAlwaysSync = isUdels();
const canChangeAudioDevice = AudioContext.prototype.setSinkId != null;
return (
<div className="text-foreground p-4 space-y-4 w-full">
<div className="text-foreground p-4 space-y-4 w-full" style={{ fontFamily }}>
{canChangeAudioDevice && (
<FormItem label="Audio Output Device">
<AudioDeviceSelector
@@ -138,10 +146,46 @@ export function SettingsTab({ started }) {
}}
/>
</FormItem>
<FormItem label="Maximum Polyphony">
<Textbox
min={1}
max={Infinity}
onBlur={(e) => {
let v = parseInt(e.target.value);
v = isNaN(v) ? DEFAULT_MAX_POLYPHONY : v;
setMaxPolyphony(v);
settingsMap.setKey('maxPolyphony', v);
}}
onChange={(v) => {
v = Math.max(1, parseInt(v));
settingsMap.setKey('maxPolyphony', isNaN(v) ? undefined : v);
}}
type="number"
placeholder=""
value={maxPolyphony ?? ''}
/>
</FormItem>
<FormItem>
<Checkbox
label="Multi Channel Orbits"
onChange={(cbEvent) => {
const val = cbEvent.target.checked;
confirmDialog(RELOAD_MSG).then((r) => {
if (r == true) {
settingsMap.setKey('multiChannelOrbits', val);
setMultiChannelOrbits(val);
return window.location.reload();
}
});
}}
value={multiChannelOrbits}
/>
</FormItem>
<FormItem label="Theme">
<SelectInput options={themeOptions} value={theme} onChange={(theme) => settingsMap.setKey('theme', theme)} />
</FormItem>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 font-sans">
<FormItem label="Font Family">
<SelectInput
options={fontFamilyOptions}
@@ -178,25 +222,7 @@ export function SettingsTab({ started }) {
value={togglePanelTrigger}
onChange={(value) => settingsMap.setKey('togglePanelTrigger', value)}
items={{ click: 'Click', hover: 'Hover' }}
></ButtonGroup>
{/* <Checkbox
label="Click"
onChange={(cbEvent) => {
if (cbEvent.target.checked) {
settingsMap.setKey('togglePanelTrigger', 'click');
}
}}
value={togglePanelTrigger != 'hover'}
/>
<Checkbox
label="Hover"
onChange={(cbEvent) => {
if (cbEvent.target.checked) {
settingsMap.setKey('togglePanelTrigger', 'hover');
}
}}
value={togglePanelTrigger == 'hover'}
/> */}
</FormItem>
<FormItem label="More Settings">
<Checkbox
@@ -239,6 +265,16 @@ export function SettingsTab({ started }) {
onChange={(cbEvent) => settingsMap.setKey('isLineWrappingEnabled', cbEvent.target.checked)}
value={isLineWrappingEnabled}
/>
<Checkbox
label="Enable Tab indentation"
onChange={(cbEvent) => settingsMap.setKey('isTabIndentationEnabled', cbEvent.target.checked)}
value={isTabIndentationEnabled}
/>
<Checkbox
label="Enable Multi-Cursor (Cmd/Ctrl+Click)"
onChange={(cbEvent) => settingsMap.setKey('isMultiCursorEnabled', cbEvent.target.checked)}
value={isMultiCursorEnabled}
/>
<Checkbox
label="Enable flashing on evaluation"
onChange={(cbEvent) => settingsMap.setKey('isFlashEnabled', cbEvent.target.checked)}
@@ -276,7 +312,8 @@ export function SettingsTab({ started }) {
onClick={() => {
confirmDialog('Sure?').then((r) => {
if (r) {
settingsMap.set(defaultSettings);
const { userPatterns } = settingsMap.get(); // keep current patterns
settingsMap.set({ ...defaultSettings, userPatterns });
}
});
}}
+96 -11
View File
@@ -2,18 +2,25 @@ import useEvent from '@src/useEvent.mjs';
import { useStore } from '@nanostores/react';
import { getAudioContext, soundMap, connectToDestination } from '@strudel/webaudio';
import { useMemo, useRef, useState } from 'react';
import { settingsMap, useSettings } from '../../../settings.mjs';
import { settingsMap, soundFilterType, useSettings } from '../../../settings.mjs';
import { ButtonGroup } from './Forms.jsx';
import ImportSoundsButton from './ImportSoundsButton.jsx';
import { Textbox } from '../textbox/Textbox.jsx';
import { ActionButton } from '../button/action-button.jsx';
import { confirmDialog } from '@src/repl/util.mjs';
import { clearIDB, userSamplesDBConfig } from '@src/repl/idbutils.mjs';
import { prebake } from '@src/repl/prebake.mjs';
const getSamples = (samples) =>
Array.isArray(samples) ? samples.length : typeof samples === 'object' ? Object.values(samples).length : 1;
export function SoundsTab() {
const sounds = useStore(soundMap);
const { soundsFilter } = useSettings();
const [search, setSearch] = useState('');
const { BASE_URL } = import.meta.env;
const baseNoTrailing = BASE_URL.endsWith('/') ? BASE_URL.slice(0, -1) : BASE_URL;
const soundEntries = useMemo(() => {
if (!sounds) {
@@ -25,24 +32,34 @@ export function SoundsTab() {
.sort((a, b) => a[0].localeCompare(b[0]))
.filter(([name]) => name.toLowerCase().includes(search.toLowerCase()));
if (soundsFilter === 'user') {
if (soundsFilter === soundFilterType.USER) {
return filtered.filter(([_, { data }]) => !data.prebake);
}
if (soundsFilter === 'drums') {
if (soundsFilter === soundFilterType.DRUMS) {
return filtered.filter(([_, { data }]) => data.type === 'sample' && data.tag === 'drum-machines');
}
if (soundsFilter === 'samples') {
if (soundsFilter === soundFilterType.SAMPLES) {
return filtered.filter(([_, { data }]) => data.type === 'sample' && data.tag !== 'drum-machines');
}
if (soundsFilter === 'synths') {
if (soundsFilter === soundFilterType.SYNTHS) {
return filtered.filter(([_, { data }]) => ['synth', 'soundfont'].includes(data.type));
}
if (soundsFilter === soundFilterType.WAVETABLES) {
return filtered.filter(([_, { data }]) => data.type === 'wavetable');
}
//TODO: tidy this up, it does not need to be saved in settings
if (soundsFilter === 'importSounds') {
return [];
}
return filtered;
}, [sounds, soundsFilter, search]);
// holds mutable ref to current triggered sound
const trigRef = useRef();
// Used to cycle through sound previews on banks with multiple sounds
let soundPreviewIdx = 0;
// stop current sound on mouseup
useEvent('mouseup', () => {
const t = trigRef.current;
@@ -51,12 +68,11 @@ export function SoundsTab() {
ref?.stop(getAudioContext().currentTime + 0.01);
});
});
return (
<div id="sounds-tab" className="px-4 flex flex-col w-full h-full dark:text-white text-stone-900">
<div id="sounds-tab" className="px-4 flex gap-2 flex-col w-full h-full text-foreground">
<Textbox placeholder="Search" value={search} onChange={(v) => setSearch(v)} />
<div className="pb-2 flex shrink-0 flex-wrap">
<div className=" flex shrink-0 flex-wrap">
<ButtonGroup
value={soundsFilter}
onChange={(value) => settingsMap.setKey('soundsFilter', value)}
@@ -64,13 +80,33 @@ export function SoundsTab() {
samples: 'samples',
drums: 'drum-machines',
synths: 'Synths',
wavetables: 'Wavetables',
user: 'User',
importSounds: 'import-sounds',
}}
></ButtonGroup>
<ImportSoundsButton onComplete={() => settingsMap.setKey('soundsFilter', 'user')} />
</div>
<div className="min-h-0 max-h-full grow overflow-auto font-mono text-sm break-normal pb-2">
{soundsFilter === soundFilterType.USER && soundEntries.length > 0 && (
<ActionButton
className="pl-2"
label="delete-all"
onClick={async () => {
try {
const confirmed = await confirmDialog('Delete all imported user samples?');
if (confirmed) {
clearIDB(userSamplesDBConfig.dbName);
soundMap.set({});
await prebake();
}
} catch (e) {
console.error(e);
}
}}
/>
)}
<div className="min-h-0 max-h-full grow overflow-auto text-sm break-normal bg-background p-2 rounded-md">
{soundEntries.map(([name, { data, onTrigger }]) => {
return (
<span
@@ -81,11 +117,13 @@ export function SoundsTab() {
const params = {
note: ['synth', 'soundfont'].includes(data.type) ? 'a3' : undefined,
s: name,
n: soundPreviewIdx,
clip: 1,
release: 0.5,
sustain: 1,
duration: 0.5,
};
soundPreviewIdx++;
const time = ctx.currentTime + 0.05;
const onended = () => trigRef.current?.node?.disconnect();
trigRef.current = Promise.resolve(onTrigger(time, params, onended));
@@ -97,11 +135,58 @@ export function SoundsTab() {
{' '}
{name}
{data?.type === 'sample' ? `(${getSamples(data.samples)})` : ''}
{data?.type === 'wavetable' ? `(${getSamples(data.tables)})` : ''}
{data?.type === 'soundfont' ? `(${data.fonts.length})` : ''}
</span>
);
})}
{!soundEntries.length ? 'No custom sounds loaded in this pattern (yet).' : ''}
{!soundEntries.length && soundsFilter === 'importSounds' ? (
<div className="prose dark:prose-invert min-w-full pt-2 pb-8 px-4">
<ImportSoundsButton onComplete={() => settingsMap.setKey('soundsFilter', 'user')} />
<p>
To import sounds into strudel, they must be contained{' '}
<a href={`${baseNoTrailing}/learn/samples/#from-disk-via-import-sounds-folder`} target="_blank">
within a folder or subfolder
</a>
. The best way to do this is to upload a samples folder containing subfolders of individual sounds or
soundbanks (see diagram below).{' '}
</p>
<pre className="bg-background" key={'sample-diagram'}>
{`└─ samples <-- import this folder
├─ swoop
│ ├─ swoopshort.wav
│ ├─ swooplong.wav
│ └─ swooptight.wav
└─ smash
├─ smashhigh.wav
├─ smashlow.wav
└─ smashmiddle.wav`}
</pre>
<p>
The name of a subfolder corresponds to the sound name under the user tab. Multiple samples within a
subfolder are all labelled with the same name, but can be accessed using .n( ) - remember sounds are
zero-indexed and in alphabetical order!
</p>
<p>
For more information, and other ways to use your own sounds in strudel,{' '}
<a href={`${baseNoTrailing}/learn/samples/#from-disk-via-import-sounds-folder`} target="_blank">
check out the docs
</a>
!
</p>
<h3>Preview Sounds</h3>
<pre className="bg-background" key={'sample-preview'}>
n("0 1 2 3 4 5").s("sample-name")
</pre>
<p>
Paste the line above into the main editor to hear the uploaded folder. Remember to use the name of your
sample as it appears under the "user" tab.
</p>
</div>
) : (
''
)}
{!soundEntries.length && soundsFilter !== 'importSounds' ? 'No sounds loaded' : ''}
</div>
</div>
);
@@ -1,11 +1,12 @@
import cx from '@src/cx.mjs';
import { useSettings } from '@src/settings.mjs';
const { BASE_URL } = import.meta.env;
const baseNoTrailing = BASE_URL.endsWith('/') ? BASE_URL.slice(0, -1) : BASE_URL;
export function WelcomeTab({ context }) {
const { fontFamily } = useSettings();
return (
<div className="prose dark:prose-invert min-w-full pt-2 font-sans pb-8 px-4 ">
<div className="prose dark:prose-invert min-w-full pt-2 font-sans pb-8 px-4 " style={{ fontFamily }}>
<h3> welcome</h3>
<p>
You have found <span className="underline">strudel</span>, a new live coding platform to write dynamic music
@@ -14,17 +15,18 @@ export function WelcomeTab({ context }) {
<br />
<span className="underline">1. hit play</span> - <span className="underline">2. change something</span> -{' '}
<span className="underline">3. hit update</span>
<br />
If you don't like what you hear, try <span className="underline">shuffle</span>!
{/* <br />
If you don't like what you hear, try <span className="underline">shuffle</span>! */}
</p>
<p>
To learn more about what this all means, check out the{' '}
{/* To learn more about what this all means, check out the{' '} */}
To get started, check out the{' '}
<a href={`${baseNoTrailing}/workshop/getting-started/`} target="_blank">
interactive tutorial
</a>
. Also feel free to join the{' '}
<a href="https://discord.com/invite/HGEdXmRkzT" target="_blank">
tidalcycles discord channel
discord channel
</a>{' '}
to ask any questions, give feedback or just say hello.
</p>
@@ -36,12 +38,12 @@ export function WelcomeTab({ context }) {
</a>
, which is a popular live coding language for music, written in Haskell. Strudel is free/open source software:
you can redistribute and/or modify it under the terms of the{' '}
<a href="https://github.com/tidalcycles/strudel/blob/main/LICENSE" target="_blank">
<a href="https://codeberg.org/uzu/strudel/src/branch/main/LICENSE" target="_blank">
GNU Affero General Public License
</a>
. You can find the source code at{' '}
<a href="https://github.com/tidalcycles/strudel" target="_blank">
github
<a href="https://codeberg.org/uzu/strudel" target="_blank">
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{' '}
@@ -3,7 +3,10 @@ import cx from '@src/cx.mjs';
export function Textbox({ onChange, className, ...inputProps }) {
return (
<input
className={cx('p-1 bg-background rounded-md my-2 border-foreground', className)}
className={cx(
'p-2 bg-background rounded-md border-foreground text-foreground placeholder-foreground',
className,
)}
onChange={(e) => onChange(e.target.value)}
{...inputProps}
/>
+33
View File
@@ -0,0 +1,33 @@
import useEvent from '@src/useEvent.mjs';
import { logger } from '@strudel/core';
import { nanoid } from 'nanoid';
import { atom } from 'nanostores';
export const $strudel_log_history = atom([]);
function useLoggerEvent(onTrigger) {
useEvent(logger.key, onTrigger);
}
function getUpdatedLog(log, event) {
const { message, type, data } = event.detail;
const lastLog = log.length ? log[log.length - 1] : undefined;
const id = nanoid(12);
if (type === 'loaded-sample') {
const loadIndex = log.findIndex(({ data: { url }, type }) => type === 'load-sample' && url === data.url);
log[loadIndex] = { message, type, id, data };
} else if (lastLog && lastLog.message === message) {
log = log.slice(0, -1).concat([{ message, type, count: (lastLog.count ?? 1) + 1, id, data }]);
} else {
log = log.concat([{ message, type, id, data }]);
}
return log.slice(-20);
}
export function useLogger() {
useLoggerEvent((event) => {
const log = $strudel_log_history.get();
const newLog = getUpdatedLog(log, event);
$strudel_log_history.set(newLog);
});
}
+19 -23
View File
@@ -1,4 +1,4 @@
import { registerSound, onTriggerSample } from '@strudel/webaudio';
import { registerSampleSource } from '@strudel/webaudio';
import { isAudioFile } from './files.mjs';
import { logger } from '@strudel/core';
@@ -12,17 +12,21 @@ export const userSamplesDBConfig = {
};
// deletes all of the databases, useful for debugging
function clearIDB() {
function clearAllIDB() {
window.indexedDB
.databases()
.then((r) => {
for (var i = 0; i < r.length; i++) window.indexedDB.deleteDatabase(r[i].name);
for (var i = 0; i < r.length; i++) clearIDB(r[i].name);
})
.then(() => {
alert('All data cleared.');
});
}
export function clearIDB(dbName) {
return window.indexedDB.deleteDatabase(dbName);
}
// queries the DB, and registers the sounds so they can be played
export function registerSamplesFromDB(config = userSamplesDBConfig, onComplete = () => {}) {
openDB(config, (objectStore) => {
@@ -54,33 +58,25 @@ export function registerSamplesFromDB(config = userSamplesDBConfig, onComplete =
splitRelativePath[splitRelativePath.length - 2] ?? soundFile.id.split(/\W+/)[0] ?? 'user';
const blob = soundFile.blob;
// Files used to be uploaded as base64 strings, After Jan 1 2025 this check can be safely deleted
if (typeof blob === 'string') {
const soundPaths = sounds.get(parentDirectory) ?? new Set();
soundPaths.add(blob);
sounds.set(parentDirectory, soundPaths);
return;
}
return blobToDataUrl(blob).then((soundPath) => {
const soundPaths = sounds.get(parentDirectory) ?? new Set();
soundPaths.add(soundPath);
sounds.set(parentDirectory, soundPaths);
const titlePathMap = sounds.get(parentDirectory) ?? new Map();
titlePathMap.set(title, soundPath);
sounds.set(parentDirectory, titlePathMap);
return;
});
}),
)
.then(() => {
sounds.forEach((soundPaths, key) => {
const value = Array.from(soundPaths);
sounds.forEach((titlePathMap, key) => {
const value = Array.from(titlePathMap.keys())
.sort((a, b) => {
return a.localeCompare(b);
})
.map((title) => titlePathMap.get(title));
registerSound(key, (t, hapValue, onended) => onTriggerSample(t, hapValue, onended, value), {
type: 'sample',
samples: value,
baseUrl: undefined,
prebake: false,
tag: undefined,
});
registerSampleSource(key, value, { prebake: false });
});
logger('imported sounds registered!', 'success');
+30 -1
View File
@@ -28,7 +28,13 @@ export async function prebake() {
prebake: true,
tag: 'drum-machines',
}),
samples(`${baseNoTrailing}/EmuSP12.json`, undefined, { prebake: true, tag: 'drum-machines' }),
samples(`${baseNoTrailing}/uzu-drumkit.json`, undefined, {
prebake: true,
tag: 'drum-machines',
}),
samples(`${baseNoTrailing}/uzu-wavetables.json`, undefined, {
prebake: true,
}),
samples(`${baseNoTrailing}/mridangam.json`, undefined, { prebake: true, tag: 'drum-machines' }),
samples(
{
@@ -115,6 +121,29 @@ export async function prebake() {
'numbers/7.wav',
'numbers/8.wav',
],
num: [
'num/00.wav',
'num/01.wav',
'num/02.wav',
'num/03.wav',
'num/04.wav',
'num/05.wav',
'num/06.wav',
'num/07.wav',
'num/08.wav',
'num/09.wav',
'num/10.wav',
'num/11.wav',
'num/12.wav',
'num/13.wav',
'num/14.wav',
'num/15.wav',
'num/16.wav',
'num/17.wav',
'num/18.wav',
'num/19.wav',
'num/20.wav',
],
},
'github:tidalcycles/dirt-samples',
{
+7 -27
View File
@@ -1,6 +1,6 @@
/*
tunes.mjs - <short description TODO>
Copyright (C) 2022 Strudel contributors - see <https://github.com/tidalcycles/strudel/blob/main/repl/src/tunes.mjs>
Copyright (C) 2022 Strudel contributors - see <https://codeberg.org/uzu/strudel/src/branch/main/repl/src/tunes.mjs>
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
@@ -69,32 +69,32 @@ stack(
export const giantSteps = `// John Coltrane - Giant Steps
let melody = note(
let melody = seq(
"[F#5 D5] [B4 G4] Bb4 [B4 A4]",
"[D5 Bb4] [G4 Eb4] F#4 [G4 F4]",
"Bb4 [B4 A4] D5 [D#5 C#5]",
"F#5 [G5 F5] Bb5 [F#5 F#5]",
)
).note()
stack(
// melody
melody.color('#F8E71C'),
// chords
chord(
seq(
"[B^7 D7] [G^7 Bb7] Eb^7 [Am7 D7]",
"[G^7 Bb7] [Eb^7 F#7] B^7 [Fm7 Bb7]",
"Eb^7 [Am7 D7] G^7 [C#m7 F#7]",
"B^7 [Fm7 Bb7] Eb^7 [C#m7 F#7]"
).dict('lefthand')
).chord().dict('lefthand')
.anchor(melody).mode('duck')
.voicing().color('#7ED321'),
// bass
note(
seq(
"[B2 D2] [G2 Bb2] [Eb2 Bb3] [A2 D2]",
"[G2 Bb2] [Eb2 F#2] [B2 F#2] [F2 Bb2]",
"[Eb2 Bb2] [A2 D2] [G2 D2] [C#2 F#2]",
"[B2 F#2] [F2 Bb2] [Eb2 Bb3] [C#2 F#2]"
).color('#00B8D4')
).note().color('#00B8D4')
).slow(20)
.pianoroll({fold:1})`;
@@ -313,26 +313,6 @@ stack(
)
.fast(2/3)
.pianoroll()`;
/*
export const bridgeIsOver = `// "Bridge is over"
// @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
// @by Felix Roos, bassline by BDP - The Bridge Is Over
samples({mad:'https://freesound.org/data/previews/22/22274_109943-lq.mp3'})
stack(
stack(
note("c3*2 [[c3@1.4 bb2] ab2] gb2*2 <[[gb2@1.4 ab2] bb2] gb2>")
.gain(.8).clip("[.5 1]*2"),
n("<0 1 2 3 4 3 2 1>")
.clip(.5)
.echoWith(8, 1/32, (x,i)=>x.add(n(i)).velocity(Math.pow(.7,i)))
.scale('c4 whole tone')
.echo(3, 1/8, .5)
).piano(),
s("mad").slow(2)
).cpm(78).slow(4)
.pianoroll()
`; */
export const goodTimes = `// "Good times"
// @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
+19 -24
View File
@@ -1,6 +1,6 @@
/*
Repl.jsx - <short description TODO>
Copyright (C) 2022 Strudel contributors - see <https://github.com/tidalcycles/strudel/blob/main/repl/src/App.js>
Copyright (C) 2022 Strudel contributors - see <https://codeberg.org/uzu/strudel/src/branch/main/repl/src/App.js>
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
@@ -13,12 +13,13 @@ import {
resetGlobalEffects,
resetLoadedSounds,
initAudioOnFirstClick,
resetDefaults,
} from '@strudel/webaudio';
import { getAudioDevices, setAudioDevice, setVersionDefaultsFrom } from './util.mjs';
import { setVersionDefaultsFrom } from './util.mjs';
import { StrudelMirror, defaultSettings } from '@strudel/codemirror';
import { clearHydra } from '@strudel/hydra';
import { useCallback, useEffect, useRef, useState } from 'react';
import { settingsMap, useSettings } from '../settings.mjs';
import { parseBoolean, settingsMap, useSettings } from '../settings.mjs';
import {
setActivePattern,
setLatestCode,
@@ -28,7 +29,7 @@ import {
setViewingPatternData,
} from '../user_pattern_utils.mjs';
import { superdirtOutput } from '@strudel/osc/superdirtoutput';
import { audioEngineTargets, defaultAudioDeviceName } from '../settings.mjs';
import { audioEngineTargets } from '../settings.mjs';
import { useStore } from '@nanostores/react';
import { prebake } from './prebake.mjs';
import { getRandomTune, initCode, loadModules, shareCode } from './util.mjs';
@@ -36,11 +37,15 @@ import './Repl.css';
import { setInterval, clearInterval } from 'worker-timers';
import { getMetadata } from '../metadata_parser';
const { latestCode } = settingsMap.get();
const { latestCode, maxPolyphony, audioDeviceName, multiChannelOrbits } = settingsMap.get();
let modulesLoading, presets, drawContext, clearCanvas, audioReady;
if (typeof window !== 'undefined') {
audioReady = initAudioOnFirstClick();
audioReady = initAudioOnFirstClick({
maxPolyphony,
audioDeviceName,
multiChannelOrbits: parseBoolean(multiChannelOrbits),
});
modulesLoading = loadModules();
presets = prebake();
drawContext = getDrawContext();
@@ -55,6 +60,8 @@ async function getModule(name) {
return modules.find((m) => m.packageName === name);
}
const initialCode = `// LOADING`;
export function useReplContext() {
const { isSyncEnabled, audioEngineTarget } = useSettings();
const shouldUseWebaudio = audioEngineTarget !== audioEngineTargets.osc;
@@ -73,7 +80,7 @@ export function useReplContext() {
transpiler,
autodraw: false,
root: containerRef.current,
initialCode: '// LOADING',
initialCode,
pattern: silence,
drawTime,
drawContext,
@@ -129,9 +136,10 @@ export function useReplContext() {
code = latestCode;
msg = `Your last session has been loaded!`;
} else {
const { code: randomTune, name } = await getRandomTune();
code = randomTune;
msg = `A random code snippet named "${name}" has been loaded!`;
/* const { code: randomTune, name } = await getRandomTune();
code = randomTune; */
code = '$: s("[bd <hh oh>]*2").bank("tr909").dec(.4)';
msg = `Default code has been loaded`;
}
editor.setCode(code);
setDocumentTitle(code);
@@ -159,20 +167,6 @@ export function useReplContext() {
editorRef.current?.updateSettings(editorSettings);
}, [_settings]);
// on first load, set stored audio device if possible
useEffect(() => {
const { audioDeviceName } = _settings;
if (audioDeviceName !== defaultAudioDeviceName) {
getAudioDevices().then((devices) => {
const deviceID = devices.get(audioDeviceName);
if (deviceID == null) {
return;
}
setAudioDevice(deviceID);
});
}
}, []);
//
// UI Actions
//
@@ -188,6 +182,7 @@ export function useReplContext() {
const resetEditor = async () => {
(await getModule('@strudel/tonal'))?.resetVoicings();
resetDefaults();
resetGlobalEffects();
clearCanvas();
clearHydra();
+54 -66
View File
@@ -1,13 +1,13 @@
import { evalScope, hash2code, logger } from '@strudel/core';
import { settingPatterns, defaultAudioDeviceName } from '../settings.mjs';
import { getAudioContext, initializeAudioOutput, setDefaultAudioContext, setVersionDefaults } from '@strudel/webaudio';
import { settingPatterns } from '../settings.mjs';
import { setVersionDefaults } from '@strudel/webaudio';
import { getMetadata } from '../metadata_parser';
import { isTauri } from '../tauri.mjs';
import './Repl.css';
import { createClient } from '@supabase/supabase-js';
import { nanoid } from 'nanoid';
import { writeText } from '@tauri-apps/plugin-clipboard-manager';
import { $featuredPatterns, loadDBPatterns } from '@src/user_pattern_utils.mjs';
import { $featuredPatterns /* , loadDBPatterns */ } from '@src/user_pattern_utils.mjs';
// Create a single supabase client for interacting with your database
export const supabase = createClient(
@@ -16,9 +16,9 @@ export const supabase = createClient(
);
let dbLoaded;
if (typeof window !== 'undefined') {
/* if (typeof window !== 'undefined') {
dbLoaded = loadDBPatterns();
}
} */
export async function initCode() {
// load code from url hash (either short hash from database or decode long hash)
@@ -81,8 +81,10 @@ export function loadModules() {
import('@strudel/soundfonts'),
import('@strudel/csound'),
import('@strudel/tidal'),
import('@strudel/gamepad'),
import('@strudel/motion'),
import('@strudel/mqtt'),
import('@strudel/mondo'),
];
if (isTauri()) {
modules = modules.concat([
@@ -108,38 +110,56 @@ export function confirmDialog(msg) {
}
let lastShared;
export async function shareCode(codeToShare) {
// const codeToShare = activeCode || code;
if (lastShared === codeToShare) {
logger(`Link already generated!`, 'error');
return;
}
confirmDialog(
'Do you want your pattern to be public? If no, press cancel and you will get just a private link.',
).then(async (isPublic) => {
const hash = nanoid(12);
const shareUrl = window.location.origin + window.location.pathname + '?' + hash;
const { error } = await supabase.from('code_v1').insert([{ code: codeToShare, hash, ['public']: isPublic }]);
if (!error) {
lastShared = codeToShare;
// copy shareUrl to clipboard
if (isTauri()) {
await writeText(shareUrl);
} else {
await navigator.clipboard.writeText(shareUrl);
}
const message = `Link copied to clipboard: ${shareUrl}`;
alert(message);
// alert(message);
logger(message, 'highlight');
//RIP due to SPAM
// export async function shareCode(codeToShare) {
// // const codeToShare = activeCode || code;
// if (lastShared === codeToShare) {
// logger(`Link already generated!`, 'error');
// return;
// }
// confirmDialog(
// 'Do you want your pattern to be public? If no, press cancel and you will get just a private link.',
// ).then(async (isPublic) => {
// const hash = nanoid(12);
// const shareUrl = window.location.origin + window.location.pathname + '?' + hash;
// const { error } = await supabase.from('code_v1').insert([{ code: codeToShare, hash, ['public']: isPublic }]);
// if (!error) {
// lastShared = codeToShare;
// // copy shareUrl to clipboard
// if (isTauri()) {
// await writeText(shareUrl);
// } else {
// await navigator.clipboard.writeText(shareUrl);
// }
// const message = `Link copied to clipboard: ${shareUrl}`;
// alert(message);
// // alert(message);
// logger(message, 'highlight');
// } else {
// console.log('error', error);
// const message = `Error: ${error.message}`;
// // alert(message);
// logger(message);
// }
// });
// }
export async function shareCode() {
try {
const shareUrl = window.location.href;
if (isTauri()) {
await writeText(shareUrl);
} else {
console.log('error', error);
const message = `Error: ${error.message}`;
// alert(message);
logger(message);
await navigator.clipboard.writeText(shareUrl);
}
});
const message = `Link copied to clipboard!`;
alert(message);
logger(message, 'highlight');
} catch (e) {
console.error(e);
}
}
export const isIframe = () => window.location !== window.parent.location;
@@ -158,38 +178,6 @@ export const isUdels = () => {
return window.top?.location?.pathname.includes('udels');
};
export const getAudioDevices = async () => {
await navigator.mediaDevices.getUserMedia({ audio: true });
let mediaDevices = await navigator.mediaDevices.enumerateDevices();
mediaDevices = mediaDevices.filter((device) => device.kind === 'audiooutput' && device.deviceId !== 'default');
const devicesMap = new Map();
devicesMap.set(defaultAudioDeviceName, '');
mediaDevices.forEach((device) => {
devicesMap.set(device.label, device.deviceId);
});
return devicesMap;
};
export const setAudioDevice = async (id) => {
let audioCtx = getAudioContext();
if (audioCtx.sinkId === id) {
return;
}
await audioCtx.suspend();
await audioCtx.close();
audioCtx = setDefaultAudioContext();
await audioCtx.resume();
const isValidID = (id ?? '').length > 0;
if (isValidID) {
try {
await audioCtx.setSinkId(id);
} catch {
logger('failed to set audio interface', 'warning');
}
}
initializeAudioOutput();
};
export function setVersionDefaultsFrom(code) {
try {
const metadata = getMetadata(code);
+18 -5
View File
@@ -3,13 +3,20 @@ import { useStore } from '@nanostores/react';
import { register } from '@strudel/core';
import { isUdels } from './repl/util.mjs';
export const defaultAudioDeviceName = 'System Standard';
export const audioEngineTargets = {
webaudio: 'webaudio',
osc: 'osc',
};
export const soundFilterType = {
USER: 'user',
DRUMS: 'drums',
SAMPLES: 'samples',
SYNTHS: 'synths',
WAVETABLES: 'wavetables',
ALL: 'all',
};
export const defaultSettings = {
activeFooter: 'intro',
keybindings: 'codemirror',
@@ -23,12 +30,14 @@ export const defaultSettings = {
isSyncEnabled: false,
isLineWrappingEnabled: false,
isPatternHighlightingEnabled: true,
isTabIndentationEnabled: false,
isMultiCursorEnabled: false,
theme: 'strudelTheme',
fontFamily: 'monospace',
fontSize: 18,
latestCode: '',
isZen: false,
soundsFilter: 'all',
soundsFilter: soundFilterType.ALL,
patternFilter: 'community',
// panelPosition: window.innerWidth > 1000 ? 'right' : 'bottom', //FIX: does not work on astro
panelPosition: 'right',
@@ -36,10 +45,11 @@ export const defaultSettings = {
isPanelOpen: true,
togglePanelTrigger: 'click', //click | hover
userPatterns: '{}',
audioDeviceName: defaultAudioDeviceName,
audioEngineTarget: audioEngineTargets.webaudio,
isButtonRowHidden: false,
isCSSAnimationDisabled: false,
maxPolyphony: 128,
multiChannelOrbits: false,
};
let search = null;
@@ -52,7 +62,7 @@ const settings_key = `strudel-settings${instance > 0 ? instance : ''}`;
export const settingsMap = persistentMap(settings_key, defaultSettings);
const parseBoolean = (booleanlike) => ([true, 'true'].includes(booleanlike) ? true : false);
export const parseBoolean = (booleanlike) => ([true, 'true'].includes(booleanlike) ? true : false);
export function useSettings() {
const state = useStore(settingsMap);
@@ -78,11 +88,14 @@ export function useSettings() {
isLineWrappingEnabled: parseBoolean(state.isLineWrappingEnabled),
isFlashEnabled: parseBoolean(state.isFlashEnabled),
isSyncEnabled: isUdels() ? true : parseBoolean(state.isSyncEnabled),
isTabIndentationEnabled: parseBoolean(state.isTabIndentationEnabled),
isMultiCursorEnabled: parseBoolean(state.isMultiCursorEnabled),
fontSize: Number(state.fontSize),
panelPosition: state.activeFooter !== '' && !isUdels() ? state.panelPosition : 'bottom', // <-- keep this 'bottom' where it is!
isPanelPinned: parseBoolean(state.isPanelPinned),
isPanelOpen: parseBoolean(state.isPanelOpen),
userPatterns: userPatterns,
multiChannelOrbits: parseBoolean(state.multiChannelOrbits),
};
}
+14
View File
@@ -1,6 +1,7 @@
@font-face {
font-family: 'PressStart';
src: url('/fonts/PressStart2P/PressStart2P-Regular.ttf');
size-adjust: 65%;
}
@font-face {
font-family: 'BigBlueTerminal';
@@ -14,6 +15,11 @@
font-family: 'galactico';
src: url('/fonts/galactico/Galactico-Basic.otf');
}
@font-face {
font-family: 'CutiePi';
src: url('/fonts/CutiePi/Cute_Aurora_demo.ttf');
size-adjust: 120%;
}
@font-face {
font-family: 'JetBrains';
src: url('/fonts/JetBrains/JetBrainsMono.woff2');
@@ -21,6 +27,7 @@
@font-face {
font-family: 'Monocraft';
src: url('/fonts/Monocraft/Monocraft.ttf');
size-adjust: 90%;
}
@font-face {
font-family: 'Hack';
@@ -41,10 +48,17 @@
@font-face {
font-family: 'teletext';
src: url('/fonts/teletext/EuropeanTeletext.ttf');
size-adjust: 90%;
}
@font-face {
font-family: 'tic80';
src: url('/fonts/tic80/tic-80-wide-font.otf');
size-adjust: 60%;
}
@font-face {
font-family: 'mode7';
src: url('/fonts/mode7/MODE7GX3.TTF');
size-adjust: 82%;
}
.prose > h1:not(:first-child) {
+2 -2
View File
@@ -96,7 +96,7 @@ export async function loadDBPatterns() {
}
}
// reason: https://github.com/tidalcycles/strudel/issues/857
// reason: https://codeberg.org/uzu/strudel/issues/857
const $activePattern = sessionAtom('activePattern', '');
export function setActivePattern(key) {
@@ -197,7 +197,7 @@ export async function importPatterns(fileList) {
if (file.type === 'application/json') {
const userPatterns = userPattern.getAll();
setUserPatterns({ ...userPatterns, ...parseJSON(content) });
} else if (file.type === 'text/plain') {
} else if (['text/x-markdown', 'text/plain'].includes(file.type)) {
const id = file.name.replace(/\.[^/.]+$/, '');
userPattern.update(id, { code: content });
}