commit
087423c754
6 changed files with 338 additions and 241 deletions
|
|
@ -76,6 +76,7 @@ export const SIDEBAR: Sidebar = {
|
|||
{ text: 'REPL', link: 'technical-manual/repl' },
|
||||
{ text: 'Docs', link: 'technical-manual/docs' },
|
||||
{ text: 'Testing', link: 'technical-manual/testing' },
|
||||
{ text: 'Packages', link: 'technical-manual/packages' },
|
||||
// { text: 'Internals', link: 'technical-manual/internals' },
|
||||
],
|
||||
},
|
||||
|
|
|
|||
|
|
@ -12,13 +12,98 @@ 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.
|
||||
|
||||
## bandf
|
||||
# Filters
|
||||
|
||||
<JsDoc client:idle name="bandf" h={0} />
|
||||
Filters are an essential building block of [subtractive synthesis](https://en.wikipedia.org/wiki/Subtractive_synthesis).
|
||||
Strudel comes with 3 types of filters:
|
||||
|
||||
## bandq
|
||||
- low-pass filter: low frequencies may _pass_, high frequencies are cut off
|
||||
- high-pass filter: high frequencies may _pass_, low frequencies are cut off
|
||||
- band-pass filters: only a frequency band may _pass_, low and high frequencies around are cut off
|
||||
|
||||
<JsDoc client:idle name="bandq" h={0} />
|
||||
Each filter has 2 parameters:
|
||||
|
||||
- cutoff: the frequency at which the filter starts to work. e.g. a low-pass filter with a cutoff of 1000Hz allows frequencies below 1000Hz to pass.
|
||||
- q-value: Controls the resonance of the filter. Higher values sound more aggressive. Also see [Q-Factor](https://en.wikipedia.org/wiki/Q_factor)
|
||||
|
||||
## lpf
|
||||
|
||||
<JsDoc client:idle name="lpf" h={0} />
|
||||
|
||||
## lpq
|
||||
|
||||
<JsDoc client:idle name="lpq" h={0} />
|
||||
|
||||
## hpf
|
||||
|
||||
<JsDoc client:idle name="hpf" h={0} />
|
||||
|
||||
## hpq
|
||||
|
||||
<JsDoc client:idle name="hpq" h={0} />
|
||||
|
||||
## bpf
|
||||
|
||||
<JsDoc client:idle name="bpf" h={0} />
|
||||
|
||||
## bpq
|
||||
|
||||
<JsDoc client:idle name="bpq" h={0} />
|
||||
|
||||
## vowel
|
||||
|
||||
<JsDoc client:idle name="vowel" h={0} />
|
||||
|
||||
# Amplitude Envelope
|
||||
|
||||
The amplitude [envelope](<https://en.wikipedia.org/wiki/Envelope_(music)>) controls the dynamic contour of a sound.
|
||||
Strudel uses ADSR envelopes, which are probably the most common way to describe an envelope:
|
||||
|
||||

|
||||
|
||||
[image link](https://commons.wikimedia.org/wiki/File:ADSR_parameter.svg)
|
||||
|
||||
## attack
|
||||
|
||||
<JsDoc client:idle name="attack" h={0} />
|
||||
|
||||
## decay
|
||||
|
||||
<JsDoc client:idle name="decay" h={0} />
|
||||
|
||||
## sustain
|
||||
|
||||
<JsDoc client:idle name="sustain" h={0} />
|
||||
|
||||
## release
|
||||
|
||||
<JsDoc client:idle name="release" h={0} />
|
||||
|
||||
# Dynamics
|
||||
|
||||
## gain
|
||||
|
||||
<JsDoc client:idle name="gain" h={0} />
|
||||
|
||||
## velocity
|
||||
|
||||
<JsDoc client:idle name="velocity" h={0} />
|
||||
|
||||
# Panning
|
||||
|
||||
## jux
|
||||
|
||||
<JsDoc client:idle name="jux" h={0} />
|
||||
|
||||
## juxBy
|
||||
|
||||
<JsDoc client:idle name="juxBy" h={0} />
|
||||
|
||||
## pan
|
||||
|
||||
<JsDoc client:idle name="pan" h={0} />
|
||||
|
||||
# Waveshaping
|
||||
|
||||
## coarse
|
||||
|
||||
|
|
@ -28,50 +113,10 @@ As you might suspect, the effects can be chained together, and they accept a pat
|
|||
|
||||
<JsDoc client:idle name="crush" h={0} />
|
||||
|
||||
## cutoff
|
||||
|
||||
<JsDoc client:idle name="cutoff" h={0} />
|
||||
|
||||
## gain
|
||||
|
||||
<JsDoc client:idle name="gain" h={0} />
|
||||
|
||||
## hcutoff
|
||||
|
||||
<JsDoc client:idle name="hcutoff" h={0} />
|
||||
|
||||
## hresonance
|
||||
|
||||
<JsDoc client:idle name="hresonance" h={0} />
|
||||
|
||||
## pan
|
||||
|
||||
<JsDoc client:idle name="pan" h={0} />
|
||||
|
||||
## resonance
|
||||
|
||||
<JsDoc client:idle name="resonance" h={0} />
|
||||
|
||||
## shape
|
||||
|
||||
<JsDoc client:idle name="shape" h={0} />
|
||||
|
||||
## velocity
|
||||
|
||||
<JsDoc client:idle name="velocity" h={0} />
|
||||
|
||||
## vowel
|
||||
|
||||
<JsDoc client:idle name="vowel" h={0} />
|
||||
|
||||
## jux
|
||||
|
||||
<JsDoc client:idle name="jux" h={0} />
|
||||
|
||||
## juxBy
|
||||
|
||||
<JsDoc client:idle name="juxBy" h={0} />
|
||||
|
||||
# Global Effects
|
||||
|
||||
## Local vs Global Effects
|
||||
|
|
|
|||
|
|
@ -28,15 +28,3 @@ The power of patterns allows us to sequence any _param_ independently:
|
|||
|
||||
Now we not only pattern the notes, but the sound as well!
|
||||
`sawtooth` `square` and `triangle` are the basic waveforms available in `s`.
|
||||
|
||||
## Ampltude Envelope
|
||||
|
||||
You can control the envelope of a synth using the `attack`, `decay`, `sustain` and `release` functions:
|
||||
|
||||
<MiniRepl
|
||||
client:idle
|
||||
tune={`note("c2 <eb2 <g2 g1>>").s('sawtooth')
|
||||
.attack(.1).decay(.1).sustain(.2).release(.1)`}
|
||||
/>
|
||||
|
||||
<br />
|
||||
|
|
|
|||
|
|
@ -1,10 +1,79 @@
|
|||
---
|
||||
title: Strudel Packages
|
||||
layout: ../../layouts/MainLayout.astro
|
||||
---
|
||||
|
||||
import { MiniRepl } from '../../docs/MiniRepl';
|
||||
|
||||
## Strudel Packages
|
||||
|
||||
The [strudel repo](github.com/tidalcycles/strudel) is organized into packages, using [npm workspaces](https://docs.npmjs.com/cli/v7/using-npm/workspaces).
|
||||
Publishing packages is done with [lerna](https://lerna.js.org/).
|
||||
|
||||
There are different packages for different purposes. They..
|
||||
|
||||
- split up the code into smaller chunks
|
||||
- can be selectively used to implement some sort of time based system
|
||||
|
||||
Please refer to the individual README files in the [packages folder](https://github.com/tidalcycles/strudel/tree/main/packages)
|
||||
[See the latest published packages on npm](https://www.npmjs.com/search?q=%40strudel.cycles).
|
||||
|
||||
TODO
|
||||
### Important bits
|
||||
|
||||
- The [root package.json](https://github.com/tidalcycles/strudel/blob/main/package.json) specifies `packages/*` as `workspaces`
|
||||
- Each folder in `packages` comes with its own `package.json`, defining a package name of the format `@strudel.cycles/<name>`
|
||||
- Running `npm i` from the root folder will symlink all packages to the `node_modules` folder, e.g. `node_modules/@strudel.cycles/core` symlinks `packages/core`
|
||||
- These symlinks allow importing the packages with their package name, instead of a relative path, e.g. `import { seq } from '@strudel.cycles/core'`, instead of `import { seq } from '../core/`.
|
||||
This works because the [bare module import](https://vitejs.dev/guide/features.html#npm-dependency-resolving-and-pre-bundling) `@strudel.cycles/core` is resolved to `node_modules/@strudel.cycles/core`.
|
||||
In a project that installs the published packages from npm, these imports will still work, whereas relative ones might not.
|
||||
- When a strudel package is importing from another strudel package, the package that is imported from should be listed in the `dependencies` field of the `package.json`.
|
||||
For example, [@strudel.cycles/mini lists `@strudel.cycles/core` as a dependency](https://github.com/tidalcycles/strudel/blob/main/packages/mini/package.json).
|
||||
- In development, files in any package can be changed and saved to instantly update the dev server via [hot module replacement](https://vitejs.dev/guide/features.html#hot-module-replacement)
|
||||
- To publish packages, `npx lerna publish` will check which packages were changed since the last publish and publish only those.
|
||||
The version numbers in the dependencies of each packages will be updated automatically to the latest version.
|
||||
|
||||
### Building & Publishing
|
||||
|
||||
Currently, all packages are only published as ESM with vite flavour.
|
||||
To build standardized ESM and CJS files, a `vite.config.js` like that is needed:
|
||||
|
||||
```js
|
||||
import { defineConfig } from 'vite';
|
||||
import { dependencies } from './package.json';
|
||||
import { resolve } from 'path';
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [],
|
||||
build: {
|
||||
lib: {
|
||||
entry: resolve(__dirname, 'index.mjs'),
|
||||
formats: ['es', 'cjs'],
|
||||
fileName: (ext) => ({ es: 'index.mjs', cjs: 'index.js' }[ext]),
|
||||
},
|
||||
rollupOptions: {
|
||||
external: [...Object.keys(dependencies)],
|
||||
},
|
||||
target: 'esnext',
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
This will build `index.mjs` (ESM) and `index.js` (CJS) to the dist folder.
|
||||
|
||||
### What's the main file?
|
||||
|
||||
Currently, each package uses the unbundled `index.mjs` as its main file, which must change for the published version.
|
||||
There are 2 ways to handle this:
|
||||
|
||||
1. `main` = `dist/index.js`, `module` = `dist/index.mjs`. The built files are used. This means that changing a source file won't take effect in the dev server without a rebuild.
|
||||
2. Use different `package.json` files for dev vs publish. So the unbuilt `index.mjs` could be used in dev, while the built files can be used when publishing.
|
||||
|
||||
Option 1 could be done with [workspace watching](https://lerna.js.org/docs/features/workspace-watching), although it might make the dev server less snappy..
|
||||
Option 2 can be done by [publishing just the dist folder and copying over the `package.json` file](https://stackoverflow.com/questions/37862712/how-to-publish-contents-only-of-a-specific-folder).
|
||||
Sadly, [this does not fit into how lerna works](https://github.com/lerna/lerna/issues/91).
|
||||
|
||||
https://github.com/changesets/changesets
|
||||
|
||||
https://turbo.build/repo/docs/handbook/publishing-packages/versioning-and-publishing
|
||||
|
||||
https://pnpm.io/workspaces
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue