From 1170ff58ee0b91de8e2578bd00f52f45345c0f74 Mon Sep 17 00:00:00 2001 From: gogins Date: Thu, 10 Aug 2023 20:26:37 -0400 Subject: [PATCH 01/16] Fix for #1. --- packages/csound/index.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/csound/index.mjs b/packages/csound/index.mjs index 31ffa83a..3063febc 100644 --- a/packages/csound/index.mjs +++ b/packages/csound/index.mjs @@ -137,7 +137,7 @@ export async function loadOrc(url) { export const csoundm = register('csoundm', (instrument, pat) => { let p1 = instrument; if (typeof instrument === 'string') { - p1 = `"{instrument}"`; + p1 = `"${instrument}"`; } init(); // not async to support csound inside other patterns + to be able to call pattern methods after it return pat.onTrigger((tidal_time, hap) => { From 08aab9d4d80099d4330549ee732c0ba9ec701297 Mon Sep 17 00:00:00 2001 From: Raphael Forment Date: Wed, 20 Sep 2023 19:44:32 +0200 Subject: [PATCH 02/16] Adding vibrato to Superdough sampler Modulating the `playbackRate` to simulate a vibrato! --- packages/superdough/sampler.mjs | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/packages/superdough/sampler.mjs b/packages/superdough/sampler.mjs index 76b6a542..365d397c 100644 --- a/packages/superdough/sampler.mjs +++ b/packages/superdough/sampler.mjs @@ -22,7 +22,7 @@ function humanFileSize(bytes, si) { return bytes.toFixed(1) + ' ' + units[u]; } -export const getSampleBufferSource = async (s, n, note, speed, freq, bank, resolveUrl) => { +export const getSampleBufferSource = async (s, n, note, speed, freq, vib, vibmod, bank, resolveUrl) => { let transpose = 0; if (freq !== undefined && note !== undefined) { logger('[sampler] hap has note and freq. ignoring note', 'warning'); @@ -57,8 +57,20 @@ export const getSampleBufferSource = async (s, n, note, speed, freq, bank, resol const bufferSource = ac.createBufferSource(); bufferSource.buffer = buffer; const playbackRate = 1.0 * Math.pow(2, transpose / 12); - // bufferSource.playbackRate.value = Math.pow(2, transpose / 12); - bufferSource.playbackRate.value = playbackRate; + if (vib > 0) { + let vibrato_oscillator = getAudioContext().createOscillator(); + vibrato_oscillator.frequency.value = vib; + const gain = getAudioContext().createGain(); + // Vibmod is the amount of vibrato, in semitones + bufferSource.playbackRate.value = Math.pow(2, transpose / 12); + gain.gain.value = vibmod / 4; + vibrato_oscillator.connect(gain); + gain.connect(bufferSource.playbackRate); + vibrato_oscillator.start(0); + } else { + bufferSource.playbackRate.value = Math.pow(2, transpose / 12); + bufferSource.playbackRate.value = playbackRate; + } return bufferSource; }; @@ -211,6 +223,8 @@ export async function onTriggerSample(t, value, onended, bank, resolveUrl) { begin = 0, loopEnd = 1, end = 1, + vib, + vibmod = 0.5, } = value; // load sample if (speed === 0) { @@ -224,7 +238,7 @@ export async function onTriggerSample(t, value, onended, bank, resolveUrl) { //const soundfont = getSoundfontKey(s); const time = t + nudge; - const bufferSource = await getSampleBufferSource(s, n, note, speed, freq, bank, resolveUrl); + const bufferSource = await getSampleBufferSource(s, n, note, speed, freq, vib, vibmod, bank, resolveUrl); // asny stuff above took too long? if (ac.currentTime > t) { @@ -255,7 +269,7 @@ export async function onTriggerSample(t, value, onended, bank, resolveUrl) { bufferSource.connect(envelope); const out = ac.createGain(); // we need a separate gain for the cutgroups because firefox... envelope.connect(out); - bufferSource.onended = function () { + bufferSource.onended = function() { bufferSource.disconnect(); envelope.disconnect(); out.disconnect(); From 624e540cb4a6b85cc3f8464bc96dcb1b40ae8ba1 Mon Sep 17 00:00:00 2001 From: "Alexandre G.-Raymond" Date: Sun, 5 Nov 2023 16:23:00 +0100 Subject: [PATCH 03/16] Add pianoroll function documentation --- packages/core/pianoroll.mjs | 34 +++++++++++++++++++++++ test/__snapshots__/examples.test.mjs.snap | 33 ++++++++++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/packages/core/pianoroll.mjs b/packages/core/pianoroll.mjs index f3d2c38a..2ea5727b 100644 --- a/packages/core/pianoroll.mjs +++ b/packages/core/pianoroll.mjs @@ -56,6 +56,40 @@ Pattern.prototype.pianoroll = function (options = {}) { // this function allows drawing a pianoroll without ties to Pattern.prototype // it will probably replace the above in the future + +/** + * Displays a midi-style piano roll + * + * @name pianoroll + * @param {Object} options Object containing all the optional following parameters as key value pairs: + * @param {integer} cycles defaults to 4 - number of cycles to be displayed at the same time + * @param {number} playhead 0 to 1, defaults to 0.5 - location of the active notes on the time axis + * @param {integer} vertical 0 (default) or 1 - displays the roll vertically + * @param {boolean} labels false (default) or true - displays labels on individual notes (see the label function) + * @param {integer} flipTime 0 (default) or 1 - reverse the direction of the roll + * @param {integer} flipValues 0 (default) or 1 - reverse the relative location of notes on the value axis + * @param {number} overscan 1 (default) - lookup X cycles outside of the cycles window to display notes in advance + * @param {boolean} hideNegative false (default) or true - hide notes with negative time (before starting playing the pattern) + * @param {integer} smear 0 (default) or 1 - notes leave a solid trace + * @param {integer} fold 0 (default) or 1 - notes takes the full value axis width + * @param {string} active hexadecimal or CSS color (defaults to #FFCA28) - color of the active notes + * @param {string} inactive hexadecimal or CSS color (defaults to #7491D2) - color of the inactive notes + * @param {string} background hexadecimal or CSS color (defaults to transparent) - color of the background + * @param {string} playheadColor hexadecimal or CSS color (defaults to transparent) - color of the line representing the play head + * @param {integer} fill 1 (default) or 0 - notes are filled with color (otherwise only the label is displayed) + * @param {boolean} fillActive: false (default) or true - active notes are filled with color + * @param {integer} stroke 0 (default) or 1 - notes are shown with colored borders + * @param {boolean} strokeActive: false (default) or true - active notes are shown with colored borders + * @param {integer} hideInactive 0 (default) or 1 - only active notes are shown + * @param {integer} colorizeInactive 1 (default) or 0 - use note color for inactive notes + * @param {string} fontFamily: defaults to 'monospace' - define the font used by notes labels + * @param {integer} minMidi integer, defaults to 10 - minimum note value to display on the value axis + * @param {integer} maxMidi integer, defaults to 90 - maximum note value to display on the value axis + * @param {integer} autorange 0 (default) or 1 - automatically calculate the minMidi and maxMidi parameters + * + * @example + * note("C2 A2 G2").euclid(5,8).s('piano').clip(1).color('salmon').pianoroll({vertical:1, labels:1}) + */ export function pianoroll({ time, haps, diff --git a/test/__snapshots__/examples.test.mjs.snap b/test/__snapshots__/examples.test.mjs.snap index 0963638f..5d485210 100644 --- a/test/__snapshots__/examples.test.mjs.snap +++ b/test/__snapshots__/examples.test.mjs.snap @@ -3297,6 +3297,39 @@ exports[`runs examples > example "perlin" example index 0 1`] = ` ] `; +exports[`runs examples > example "pianoroll" example index 0 1`] = ` +[ + "[ 0/1 → 1/8 | note:C2 s:piano clip:1 ]", + "[ (1/4 → 1/3) ⇝ 3/8 | note:C2 s:piano clip:1 ]", + "[ 1/4 ⇜ (1/3 → 3/8) | note:A2 s:piano clip:1 ]", + "[ 3/8 → 1/2 | note:A2 s:piano clip:1 ]", + "[ (5/8 → 2/3) ⇝ 3/4 | note:A2 s:piano clip:1 ]", + "[ 5/8 ⇜ (2/3 → 3/4) | note:G2 s:piano clip:1 ]", + "[ 3/4 → 7/8 | note:G2 s:piano clip:1 ]", + "[ 1/1 → 9/8 | note:C2 s:piano clip:1 ]", + "[ (5/4 → 4/3) ⇝ 11/8 | note:C2 s:piano clip:1 ]", + "[ 5/4 ⇜ (4/3 → 11/8) | note:A2 s:piano clip:1 ]", + "[ 11/8 → 3/2 | note:A2 s:piano clip:1 ]", + "[ (13/8 → 5/3) ⇝ 7/4 | note:A2 s:piano clip:1 ]", + "[ 13/8 ⇜ (5/3 → 7/4) | note:G2 s:piano clip:1 ]", + "[ 7/4 → 15/8 | note:G2 s:piano clip:1 ]", + "[ 2/1 → 17/8 | note:C2 s:piano clip:1 ]", + "[ (9/4 → 7/3) ⇝ 19/8 | note:C2 s:piano clip:1 ]", + "[ 9/4 ⇜ (7/3 → 19/8) | note:A2 s:piano clip:1 ]", + "[ 19/8 → 5/2 | note:A2 s:piano clip:1 ]", + "[ (21/8 → 8/3) ⇝ 11/4 | note:A2 s:piano clip:1 ]", + "[ 21/8 ⇜ (8/3 → 11/4) | note:G2 s:piano clip:1 ]", + "[ 11/4 → 23/8 | note:G2 s:piano clip:1 ]", + "[ 3/1 → 25/8 | note:C2 s:piano clip:1 ]", + "[ (13/4 → 10/3) ⇝ 27/8 | note:C2 s:piano clip:1 ]", + "[ 13/4 ⇜ (10/3 → 27/8) | note:A2 s:piano clip:1 ]", + "[ 27/8 → 7/2 | note:A2 s:piano clip:1 ]", + "[ (29/8 → 11/3) ⇝ 15/4 | note:A2 s:piano clip:1 ]", + "[ 29/8 ⇜ (11/3 → 15/4) | note:G2 s:piano clip:1 ]", + "[ 15/4 → 31/8 | note:G2 s:piano clip:1 ]", +] +`; + exports[`runs examples > example "pick" example index 0 1`] = ` [ "[ 0/1 → 1/2 | note:g ]", From 0d06840a1bc496b9c50c280ec88340193854d73c Mon Sep 17 00:00:00 2001 From: "Alexandre G.-Raymond" Date: Sun, 5 Nov 2023 16:23:21 +0100 Subject: [PATCH 04/16] Add label function documentation --- packages/core/controls.mjs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/core/controls.mjs b/packages/core/controls.mjs index 1ca49bb6..866be4fb 100644 --- a/packages/core/controls.mjs +++ b/packages/core/controls.mjs @@ -867,7 +867,12 @@ const generic_params = [ * */ ['lsize'], - // label for pianoroll + /** + * Sets the displayed text for an event on the pianoroll + * + * @name label + * @param {string} label text to display + */ ['activeLabel'], [['label', 'activeLabel']], // ['lfo'], From f045fb44de8dfc3b0e23d131d3fe33f69ef35114 Mon Sep 17 00:00:00 2001 From: "Alexandre G.-Raymond" Date: Sun, 5 Nov 2023 16:23:36 +0100 Subject: [PATCH 05/16] Add color function documentation --- packages/core/pattern.mjs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/core/pattern.mjs b/packages/core/pattern.mjs index dcf5da1b..f09b89b9 100644 --- a/packages/core/pattern.mjs +++ b/packages/core/pattern.mjs @@ -2191,6 +2191,9 @@ export const duration = register('duration', function (value, pat) { /** * Sets the color of the hap in visualizations like pianoroll or highlighting. + * @name color + * @synonyms colour + * @param {string} color Hexadecimal or CSS color name */ // TODO: move this to controls https://github.com/tidalcycles/strudel/issues/288 export const { color, colour } = register(['color', 'colour'], function (color, pat) { From 8fa7bf795a6760a23defb33ee69c3fd824807298 Mon Sep 17 00:00:00 2001 From: "Alexandre G.-Raymond" Date: Sun, 5 Nov 2023 16:25:10 +0100 Subject: [PATCH 06/16] Fix pianoroll documentation --- packages/core/pianoroll.mjs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/core/pianoroll.mjs b/packages/core/pianoroll.mjs index 2ea5727b..60cab07c 100644 --- a/packages/core/pianoroll.mjs +++ b/packages/core/pianoroll.mjs @@ -77,12 +77,12 @@ Pattern.prototype.pianoroll = function (options = {}) { * @param {string} background hexadecimal or CSS color (defaults to transparent) - color of the background * @param {string} playheadColor hexadecimal or CSS color (defaults to transparent) - color of the line representing the play head * @param {integer} fill 1 (default) or 0 - notes are filled with color (otherwise only the label is displayed) - * @param {boolean} fillActive: false (default) or true - active notes are filled with color + * @param {boolean} fillActive false (default) or true - active notes are filled with color * @param {integer} stroke 0 (default) or 1 - notes are shown with colored borders - * @param {boolean} strokeActive: false (default) or true - active notes are shown with colored borders + * @param {boolean} strokeActive false (default) or true - active notes are shown with colored borders * @param {integer} hideInactive 0 (default) or 1 - only active notes are shown * @param {integer} colorizeInactive 1 (default) or 0 - use note color for inactive notes - * @param {string} fontFamily: defaults to 'monospace' - define the font used by notes labels + * @param {string} fontFamily defaults to 'monospace' - define the font used by notes labels * @param {integer} minMidi integer, defaults to 10 - minimum note value to display on the value axis * @param {integer} maxMidi integer, defaults to 90 - maximum note value to display on the value axis * @param {integer} autorange 0 (default) or 1 - automatically calculate the minMidi and maxMidi parameters From 8fe4dca4c21a7c8544a979a87807531a9b77d30f Mon Sep 17 00:00:00 2001 From: "Alexandre G.-Raymond" Date: Sun, 5 Nov 2023 18:07:42 +0100 Subject: [PATCH 07/16] Update pianoroll documentation --- packages/core/pianoroll.mjs | 48 ++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/packages/core/pianoroll.mjs b/packages/core/pianoroll.mjs index 60cab07c..c10460a4 100644 --- a/packages/core/pianoroll.mjs +++ b/packages/core/pianoroll.mjs @@ -62,30 +62,30 @@ Pattern.prototype.pianoroll = function (options = {}) { * * @name pianoroll * @param {Object} options Object containing all the optional following parameters as key value pairs: - * @param {integer} cycles defaults to 4 - number of cycles to be displayed at the same time - * @param {number} playhead 0 to 1, defaults to 0.5 - location of the active notes on the time axis - * @param {integer} vertical 0 (default) or 1 - displays the roll vertically - * @param {boolean} labels false (default) or true - displays labels on individual notes (see the label function) - * @param {integer} flipTime 0 (default) or 1 - reverse the direction of the roll - * @param {integer} flipValues 0 (default) or 1 - reverse the relative location of notes on the value axis - * @param {number} overscan 1 (default) - lookup X cycles outside of the cycles window to display notes in advance - * @param {boolean} hideNegative false (default) or true - hide notes with negative time (before starting playing the pattern) - * @param {integer} smear 0 (default) or 1 - notes leave a solid trace - * @param {integer} fold 0 (default) or 1 - notes takes the full value axis width - * @param {string} active hexadecimal or CSS color (defaults to #FFCA28) - color of the active notes - * @param {string} inactive hexadecimal or CSS color (defaults to #7491D2) - color of the inactive notes - * @param {string} background hexadecimal or CSS color (defaults to transparent) - color of the background - * @param {string} playheadColor hexadecimal or CSS color (defaults to transparent) - color of the line representing the play head - * @param {integer} fill 1 (default) or 0 - notes are filled with color (otherwise only the label is displayed) - * @param {boolean} fillActive false (default) or true - active notes are filled with color - * @param {integer} stroke 0 (default) or 1 - notes are shown with colored borders - * @param {boolean} strokeActive false (default) or true - active notes are shown with colored borders - * @param {integer} hideInactive 0 (default) or 1 - only active notes are shown - * @param {integer} colorizeInactive 1 (default) or 0 - use note color for inactive notes - * @param {string} fontFamily defaults to 'monospace' - define the font used by notes labels - * @param {integer} minMidi integer, defaults to 10 - minimum note value to display on the value axis - * @param {integer} maxMidi integer, defaults to 90 - maximum note value to display on the value axis - * @param {integer} autorange 0 (default) or 1 - automatically calculate the minMidi and maxMidi parameters + * @param {integer} cycles number of cycles to be displayed at the same time - defaults to 4 + * @param {number} playhead location of the active notes on the time axis - 0 to 1, defaults to 0.5 + * @param {boolean} vertical displays the roll vertically - 0 by default + * @param {boolean} labels displays labels on individual notes (see the label function) - 0 by default + * @param {boolean} flipTime reverse the direction of the roll - 0 by default + * @param {boolean} flipValues reverse the relative location of notes on the value axis - 0 by default + * @param {number} overscan lookup X cycles outside of the cycles window to display notes in advance - 1 by default + * @param {boolean} hideNegative hide notes with negative time (before starting playing the pattern) - 0 by default + * @param {boolean} smear notes leave a solid trace - 0 by default + * @param {boolean} fold notes takes the full value axis width - 0 by default + * @param {string} active hexadecimal or CSS color of the active notes - defaults to #FFCA28 + * @param {string} inactive hexadecimal or CSS color of the inactive notes - defaults to #7491D2 + * @param {string} background hexadecimal or CSS color of the background - defaults to transparent + * @param {string} playheadColor hexadecimal or CSS color of the line representing the play head - defaults to white + * @param {boolean} fill notes are filled with color (otherwise only the label is displayed) - 0 by default + * @param {boolean} fillActive active notes are filled with color - 0 by default + * @param {boolean} stroke notes are shown with colored borders - 0 by default + * @param {boolean} strokeActive active notes are shown with colored borders - 0 by default + * @param {boolean} hideInactive only active notes are shown - 0 by default + * @param {boolean} colorizeInactive use note color for inactive notes - 1 by default + * @param {string} fontFamily define the font used by notes labels - defaults to 'monospace' + * @param {integer} minMidi minimum note value to display on the value axis - defaults to 10 + * @param {integer} maxMidi maximum note value to display on the value axis - defaults to 90 + * @param {boolean} autorange automatically calculate the minMidi and maxMidi parameters - 0 by default * * @example * note("C2 A2 G2").euclid(5,8).s('piano').clip(1).color('salmon').pianoroll({vertical:1, labels:1}) From eed2c304e483f4f920163565b90b7b7cc123fcba Mon Sep 17 00:00:00 2001 From: Bernhard Wagner Date: Tue, 7 Nov 2023 15:57:31 +0100 Subject: [PATCH 08/16] Update first-effects.mdx grammatical amendments --- .../src/pages/de/workshop/first-effects.mdx | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/website/src/pages/de/workshop/first-effects.mdx b/website/src/pages/de/workshop/first-effects.mdx index 7719249a..b408a343 100644 --- a/website/src/pages/de/workshop/first-effects.mdx +++ b/website/src/pages/de/workshop/first-effects.mdx @@ -25,7 +25,7 @@ import Box from '@components/Box.astro'; lpf = **l**ow **p**ass **f**ilter -- Ändere `lpf` in 200. Hörst du wie der Bass dumpfer klingt? Es klingt so ähnlich als würde die Musik hinter einer geschlossenen Tür laufen 🚪 +- Ändere `lpf` in 200. Hörst du, wie der Bass dumpfer klingt? Es klingt so, als würde die Musik hinter einer geschlossenen Tür spielen 🚪 - Lass uns nun die Tür öffnen: Ändere `lpf` in 5000. Der Klang wird dadurch viel heller und schärfer ✨🪩 @@ -42,9 +42,9 @@ lpf = **l**ow **p**ass **f**ilter - Füg noch mehr `lpf` Werte hinzu -- Das pattern in `lpf` ändert nicht den Rhythmus der Bassline +- Das Pattern in `lpf` ändert nicht den Rhythmus der Basslinie -Später sehen wir wie man mit Wellenformen Dinge automatisieren kann. +Später sehen wir, wie man mit Wellenformen Dinge automatisieren kann. @@ -73,7 +73,7 @@ Später sehen wir wie man mit Wellenformen Dinge automatisieren kann. Bei Rhythmen ist die Dynamik (= Veränderungen der Lautstärke) sehr wichtig. -- Entferne `.gain(...)` und achte darauf wie es viel flacher klingt. +- Entferne `.gain(...)` und achte darauf, wie es viel flacher klingt. - Mach es rückgängig (strg+z dann strg+enter) @@ -99,13 +99,13 @@ Lass uns die obigen Beispiele kombinieren: -Versuche die einzelnen Teile innerhalb `stack` zu erkennen, schau dir an wie die Kommas gesetzt sind. +Versuche die einzelnen Teile innerhalb von `stack` zu erkennen. Schau dir an wie die Kommas gesetzt sind. -Die 3 Teile (Drums, Bass, Akkorde) sind genau wie vorher, nur in einem `stack`, getrennt durch Kommas +Die 3 Teile (Drums, Bass, Akkorde) sind genau wie vorher, nur in einem `stack`, getrennt durch Kommas. -**Den Sound formen mit ADSR Hüllkurve** +**Den Sound formen mit ADSR-Hüllkurve** -Versuche herauszufinden was die Zahlen machen. Probier folgendes: +Versuche herauszufinden, was die Zahlen machen. Probier folgendes: - attack: `.5` vs `0` - decay: `.5` vs `0` - sustain: `1` vs `.25` vs `0` - release: `0` vs `.5` vs `1` -Kannst du erraten was die einzelnen Werte machen? +Kannst du erraten, was die einzelnen Werte machen? @@ -142,7 +142,7 @@ Kannst du erraten was die einzelnen Werte machen? -**adsr Kurznotation** +**adsr-Kurznotation** @@ -181,7 +181,7 @@ Was passiert wenn du `.delay(".8:.06:.8")` schreibst? Kannst du erraten was die - a: Lautstärke des Delays - b: Verzögerungszeit -- c: Feedback (je kleiner desto schneller verschwindet das Delay) +- c: Feedback (je kleiner, desto schneller verschwindet das Delay) @@ -203,7 +203,7 @@ Füg auch ein Delay hinzu! -**kleiner dub tune** +**kleiner Dub-Tune** -Füg `.hush()` ans ende eines Patterns im stack... +Füg `.hush()` ans Ende eines Patterns im stack... @@ -258,25 +258,25 @@ Füg `.hush()` ans ende eines Patterns im stack... **fast and slow = schnell und langsam** -Mit `fast` und `slow` kann man das tempo eines patterns außerhalb der Mini-Notation ändern: +Mit `fast` und `slow` kann man das Tempo eines Patterns außerhalb der Mini-Notation ändern: -Ändere den `slow` Wert. Tausche `slow` durch `fast`. +Ändere den `slow`-Wert. Ersetze `slow` durch `fast`. -Was passiert wenn du den Wert automatisierst? z.b. `.fast("<1 [2 4]>")` ? +Was passiert, wenn du den Wert automatisierst? z.b. `.fast("<1 [2 4]>")` ? -Übrigens, innerhalb der Mini-Notation, `fast` ist `*` und `slow` ist `/`. +Übrigens, innerhalb der Mini-Notation: `fast` ist `*` und `slow` ist `/`. ")`} /> ## Automation mit Signalen -Anstatt Werte schrittweise zu automatisieren können wir auch sogenannte Signale benutzen: +Anstatt Werte schrittweise zu automatisieren, können wir auch sogenannte Signale benutzen: @@ -296,7 +296,7 @@ Signale bewegen sich standardmäßig zwischen 0 und 1. Wir können das mit `rang -`range` ist nützlich wenn wir Funktionen mit einem anderen Wertebereich als 0 und 1 automatisieren wollen (z.b. lpf) +`range` ist nützlich wenn wir Funktionen mit einem anderen Wertebereich als 0 und 1 automatisieren wollen (z.b. `lpf`) @@ -322,7 +322,7 @@ Die ganze Automation braucht nun 8 cycle bis sie sich wiederholt. ## Rückblick -| name | example | +| Name | Beispiel | | ----- | -------------------------------------------------------------------------------------------------- | | lpf | ")`} /> | | vowel | ")`} /> | @@ -333,4 +333,4 @@ Die ganze Automation braucht nun 8 cycle bis sie sich wiederholt. | speed | ")`} /> | | range | | -Lass uns nun die für Tidal typischen [Pattern Effekte anschauen](/de/workshop/pattern-effects). +Lass uns nun die für Tidal typischen [Pattern-Effekte anschauen](/de/workshop/pattern-effects). From df277d6b7b66147563a64d4fe561d93a099328ba Mon Sep 17 00:00:00 2001 From: Bernhard Wagner Date: Tue, 7 Nov 2023 16:10:57 +0100 Subject: [PATCH 09/16] Update pattern-effects.mdx grammatical amendments --- .../src/pages/de/workshop/pattern-effects.mdx | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/website/src/pages/de/workshop/pattern-effects.mdx b/website/src/pages/de/workshop/pattern-effects.mdx index b701958a..6603db06 100644 --- a/website/src/pages/de/workshop/pattern-effects.mdx +++ b/website/src/pages/de/workshop/pattern-effects.mdx @@ -1,5 +1,5 @@ --- -title: Pattern Effekte +title: Pattern-Effekte layout: ../../../layouts/MainLayout.astro --- @@ -7,11 +7,11 @@ import { MiniRepl } from '@src/docs/MiniRepl'; import Box from '@components/Box.astro'; import QA from '@components/QA'; -# Pattern Effekte +# Pattern-Effekte -Bis jetzt sind die meisten Funktionen die wir kennengelernt haben ähnlich wie Funktionen in anderen Musik Programmen: Sequencing von Sounds, Noten und Effekten. +Bis jetzt sind die meisten Funktionen, die wir kennengelernt haben, ähnlich wie Funktionen in anderen Musik Programmen: Sequencing von Sounds, Noten und Effekten. -In diesem Kapitel beschäftigen wir uns mit Funktionen die weniger herkömmlich oder auch enzigartig sind. +In diesem Kapitel beschäftigen wir uns mit Funktionen die weniger herkömmlich oder auch einzigartig sind. **rev = rückwärts abspielen** @@ -21,7 +21,7 @@ In diesem Kapitel beschäftigen wir uns mit Funktionen die weniger herkömmlich -So würde man das ohne jux schreiben: +So würde man das ohne `jux` schreiben: -Lass uns visualisieren was hier passiert: +Lass uns visualisieren, was hier passiert: -Das hat den gleichen Effekt wie: +Das hat den gleichen Effekt, wie: "` -In der notation `x=>x.`, das `x` ist das Pattern das wir bearbeiten. +In der Notation `x=>x.`, ist `x` das Pattern, das wir bearbeiten. -`off` ist auch nützlich für sounds: +`off` ist auch nützlich für Sounds: x.`, das `x` ist das Pattern das wir bearbeiten. .off(1/8, x=>x.speed(1.5).gain(.25))`} /> -| name | description | example | -| ---- | --------------------------------- | ---------------------------------------------------------------------------------------------- | -| rev | rückwärts | | -| jux | ein stereo-kanal modifizieren | | -| add | addiert zahlen oder noten | ")).scale("C:minor")`} /> | -| ply | multipliziert jedes element x mal | ")`} /> | -| off | verzögert eine modifizierte kopie | x.speed(2))`} /> | +| Name | Beschreibung | Beispiel | +| ---- | ----------------------------------- | ---------------------------------------------------------------------------------------------- | +| rev | rückwärts | | +| jux | einen Stereo-Kanal modifizieren | | +| add | addiert Zahlen oder Noten | ")).scale("C:minor")`} /> | +| ply | multipliziert jedes Element x mal | ")`} /> | +| off | verzögert eine modifizierte Kopie | x.speed(2))`} /> | From 23dd9d4c01e52c42f02fd494df290e1efe431700 Mon Sep 17 00:00:00 2001 From: Bernhard Wagner Date: Tue, 7 Nov 2023 16:16:46 +0100 Subject: [PATCH 10/16] Update recap.mdx Adds a few missing translations --- website/src/pages/de/workshop/recap.mdx | 50 ++++++++++++------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/website/src/pages/de/workshop/recap.mdx b/website/src/pages/de/workshop/recap.mdx index db392b8b..c0d577d1 100644 --- a/website/src/pages/de/workshop/recap.mdx +++ b/website/src/pages/de/workshop/recap.mdx @@ -7,19 +7,19 @@ import { MiniRepl } from '../../../docs/MiniRepl'; # Workshop Rückblick -Diese Seite ist eine Auflistung aller im Workshop enthaltenen Funktionen. +Diese Seite ist eine Auflistung aller im Workshop vorgestellten Funktionen. ## Mini Notation -| Concept | Syntax | Example | +| Konzept | Syntax | Beispiel | | --------------------- | -------- | -------------------------------------------------------------------------------- | -| Sequence | space | | -| Sample Nummer | :x | | +| Sequenz | space | | +| Sample-Nummer | :x | | | Pausen | ~ | | -| Unter-Sequences | \[\] | | -| Unter-Unter-Sequences | \[\[\]\] | | +| Unter-Sequenzen | \[\] | | +| Unter-Unter-Sequenzen | \[\[\]\] | | | Schneller | \* | | -| Slow down | \/ | | +| Verlangsamen | \/ | | | Parallel | , | | | Alternieren | \<\> | ")`} /> | | Verlängern | @ | | @@ -27,23 +27,23 @@ Diese Seite ist eine Auflistung aller im Workshop enthaltenen Funktionen. ## Sounds -| Name | Description | Example | +| Name | Beschreibung | Beispiel | | ----- | -------------------------- | ---------------------------------------------------------------------------------- | -| sound | spielt den sound mit namen | | -| bank | wählt die soundbank | | -| n | wählt sample mit nummer | | +| sound | spielt den Sound mit Namen | | +| bank | wählt die Soundbank | | +| n | wählt Sample mit Nummer | | -## Notes +## Noten -| Name | Description | Example | +| Name | Beschreibung | Beispiel | | --------- | ---------------------------------- | -------------------------------------------------------------------------------------------- | -| note | wählt note per zahl oder buchstabe | | -| n + scale | wählt note n in skala | | -| stack | spielt mehrere patterns parallel | | +| note | wählt Note per Zahl oder Buchstabe | | +| n + scale | wählt Note n in Skala | | +| stack | spielt mehrere Patterns parallel | | -## Audio Effekte +## Audio-Effekte -| name | example | +| Name | Beispiele | | ----- | -------------------------------------------------------------------------------------------------- | | lpf | ")`} /> | | vowel | ")`} /> | @@ -54,15 +54,15 @@ Diese Seite ist eine Auflistung aller im Workshop enthaltenen Funktionen. | speed | ")`} /> | | range | | -## Pattern Effects +## Pattern-Effekte -| name | description | example | +| Name | Beschreibung | Beispiel | | ---- | --------------------------------- | ---------------------------------------------------------------------------------------------- | -| cpm | tempo in cycles pro minute | | +| cpm | Tempo in Cycles pro Minute | | | fast | schneller | | | slow | langsamer | | | rev | rückwärts | | -| jux | ein stereo-kanal modifizieren | | -| add | addiert zahlen oder noten | ")).scale("C:minor")`} /> | -| ply | jedes element schneller machen | ")`} /> | -| off | verzögert eine modifizierte kopie | x.speed(2))`} /> | +| jux | einen Stereo-Kanal modifizieren | | +| add | addiert Zahlen oder Noten | ")).scale("C:minor")`} /> | +| ply | jedes Element schneller machen | ")`} /> | +| off | verzögert eine modifizierte Kopie | x.speed(2))`} /> | From 4a16cd891f771165ee4f2f3fd4cc0126fe8e5d2e Mon Sep 17 00:00:00 2001 From: Bernhard Wagner Date: Tue, 7 Nov 2023 18:55:35 +0100 Subject: [PATCH 11/16] FIXES: table --- website/src/pages/de/workshop/pattern-effects.mdx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/website/src/pages/de/workshop/pattern-effects.mdx b/website/src/pages/de/workshop/pattern-effects.mdx index 6603db06..70335881 100644 --- a/website/src/pages/de/workshop/pattern-effects.mdx +++ b/website/src/pages/de/workshop/pattern-effects.mdx @@ -174,10 +174,10 @@ In der Notation `x=>x.`, ist `x` das Pattern, das wir bearbeiten. .off(1/8, x=>x.speed(1.5).gain(.25))`} /> -| Name | Beschreibung | Beispiel | -| ---- | ----------------------------------- | ---------------------------------------------------------------------------------------------- | -| rev | rückwärts | | -| jux | einen Stereo-Kanal modifizieren | | -| add | addiert Zahlen oder Noten | ")).scale("C:minor")`} /> | -| ply | multipliziert jedes Element x mal | ")`} /> | -| off | verzögert eine modifizierte Kopie | x.speed(2))`} /> | +| Name | Beschreibung | Beispiel | +| ---- | --------------------------------- | ---------------------------------------------------------------------------------------------- | +| rev | rückwärts | | +| jux | einen Stereo-Kanal modifizieren | | +| add | addiert Zahlen oder Noten | ")).scale("C:minor")`} /> | +| ply | multipliziert jedes Element x mal | ")`} /> | +| off | verzögert eine modifizierte Kopie | x.speed(2))`} /> | From 85835087ba0c55ac6e028de6c76812c20bb26018 Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Thu, 9 Nov 2023 08:48:23 +0100 Subject: [PATCH 12/16] format --- packages/superdough/sampler.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/superdough/sampler.mjs b/packages/superdough/sampler.mjs index ed73eeb8..d278913a 100644 --- a/packages/superdough/sampler.mjs +++ b/packages/superdough/sampler.mjs @@ -298,7 +298,7 @@ export async function onTriggerSample(t, value, onended, bank, resolveUrl) { bufferSource.connect(envelope); const out = ac.createGain(); // we need a separate gain for the cutgroups because firefox... envelope.connect(out); - bufferSource.onended = function() { + bufferSource.onended = function () { bufferSource.disconnect(); envelope.disconnect(); out.disconnect(); From 7c8a8b8b7044b8a3e422717bd6a928486940dbb3 Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Thu, 9 Nov 2023 08:59:23 +0100 Subject: [PATCH 13/16] simplify --- packages/superdough/sampler.mjs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/superdough/sampler.mjs b/packages/superdough/sampler.mjs index d278913a..7127d891 100644 --- a/packages/superdough/sampler.mjs +++ b/packages/superdough/sampler.mjs @@ -57,19 +57,16 @@ export const getSampleBufferSource = async (s, n, note, speed, freq, vib, vibmod const bufferSource = ac.createBufferSource(); bufferSource.buffer = buffer; const playbackRate = 1.0 * Math.pow(2, transpose / 12); + bufferSource.playbackRate.value = playbackRate; if (vib > 0) { let vibrato_oscillator = getAudioContext().createOscillator(); vibrato_oscillator.frequency.value = vib; const gain = getAudioContext().createGain(); // Vibmod is the amount of vibrato, in semitones - bufferSource.playbackRate.value = Math.pow(2, transpose / 12); gain.gain.value = vibmod / 4; vibrato_oscillator.connect(gain); gain.connect(bufferSource.playbackRate); vibrato_oscillator.start(0); - } else { - bufferSource.playbackRate.value = Math.pow(2, transpose / 12); - bufferSource.playbackRate.value = playbackRate; } return bufferSource; }; From 0052d349d925275e5f14d89bf49e01c4629b952f Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Thu, 9 Nov 2023 09:06:50 +0100 Subject: [PATCH 14/16] refactor: move vibrato up + cleanup oscillator --- packages/superdough/sampler.mjs | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/packages/superdough/sampler.mjs b/packages/superdough/sampler.mjs index 7127d891..6da8b1d1 100644 --- a/packages/superdough/sampler.mjs +++ b/packages/superdough/sampler.mjs @@ -22,7 +22,7 @@ function humanFileSize(bytes, si) { return bytes.toFixed(1) + ' ' + units[u]; } -export const getSampleBufferSource = async (s, n, note, speed, freq, vib, vibmod, bank, resolveUrl) => { +export const getSampleBufferSource = async (s, n, note, speed, freq, bank, resolveUrl) => { let transpose = 0; if (freq !== undefined && note !== undefined) { logger('[sampler] hap has note and freq. ignoring note', 'warning'); @@ -58,16 +58,6 @@ export const getSampleBufferSource = async (s, n, note, speed, freq, vib, vibmod bufferSource.buffer = buffer; const playbackRate = 1.0 * Math.pow(2, transpose / 12); bufferSource.playbackRate.value = playbackRate; - if (vib > 0) { - let vibrato_oscillator = getAudioContext().createOscillator(); - vibrato_oscillator.frequency.value = vib; - const gain = getAudioContext().createGain(); - // Vibmod is the amount of vibrato, in semitones - gain.gain.value = vibmod / 4; - vibrato_oscillator.connect(gain); - gain.connect(bufferSource.playbackRate); - vibrato_oscillator.start(0); - } return bufferSource; }; @@ -264,7 +254,20 @@ export async function onTriggerSample(t, value, onended, bank, resolveUrl) { //const soundfont = getSoundfontKey(s); const time = t + nudge; - const bufferSource = await getSampleBufferSource(s, n, note, speed, freq, vib, vibmod, bank, resolveUrl); + const bufferSource = await getSampleBufferSource(s, n, note, speed, freq, bank, resolveUrl); + + // vibrato + let vibratoOscillator; + if (vib > 0) { + vibratoOscillator = getAudioContext().createOscillator(); + vibratoOscillator.frequency.value = vib; + const gain = getAudioContext().createGain(); + // Vibmod is the amount of vibrato, in semitones + gain.gain.value = vibmod * 100; + vibratoOscillator.connect(gain); + gain.connect(bufferSource.detune); + vibratoOscillator.start(0); + } // asny stuff above took too long? if (ac.currentTime > t) { @@ -297,6 +300,7 @@ export async function onTriggerSample(t, value, onended, bank, resolveUrl) { envelope.connect(out); bufferSource.onended = function () { bufferSource.disconnect(); + vibratoOscillator.stop(); envelope.disconnect(); out.disconnect(); onended(); From 2a09f9ef0b51a8006efd745275eb48ac128516ba Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Thu, 9 Nov 2023 09:21:40 +0100 Subject: [PATCH 15/16] fix: sampler broke without vibrato --- packages/superdough/sampler.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/superdough/sampler.mjs b/packages/superdough/sampler.mjs index 6da8b1d1..b8f10d5d 100644 --- a/packages/superdough/sampler.mjs +++ b/packages/superdough/sampler.mjs @@ -300,7 +300,7 @@ export async function onTriggerSample(t, value, onended, bank, resolveUrl) { envelope.connect(out); bufferSource.onended = function () { bufferSource.disconnect(); - vibratoOscillator.stop(); + vibratoOscillator?.stop(); envelope.disconnect(); out.disconnect(); onended(); From d25851ac1761064d646188dacc1ef65ad9301772 Mon Sep 17 00:00:00 2001 From: Alex McLean Date: Fri, 10 Nov 2023 11:17:35 +0000 Subject: [PATCH 16/16] support multiple named serial connections, change default baudrate to 115200 (#551) --- packages/serial/serial.mjs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/serial/serial.mjs b/packages/serial/serial.mjs index c4e52d4d..652b6054 100644 --- a/packages/serial/serial.mjs +++ b/packages/serial/serial.mjs @@ -6,23 +6,23 @@ This program is free software: you can redistribute it and/or modify it under th import { Pattern, isPattern } from '@strudel.cycles/core'; -var writeMessage; +var writeMessagers = {}; var choosing = false; -export async function getWriter(br = 38400) { +export async function getWriter(name, br) { if (choosing) { return; } choosing = true; - if (writeMessage) { - return writeMessage; + if (name in writeMessagers) { + return writeMessagers[name]; } if ('serial' in navigator) { const port = await navigator.serial.requestPort(); await port.open({ baudRate: br }); const encoder = new TextEncoder(); const writer = port.writable.getWriter(); - writeMessage = function (message, chk) { + writeMessagers[name] = function (message, chk) { const encoded = encoder.encode(message); if (!chk) { writer.write(encoded); @@ -63,10 +63,10 @@ function crc16(data) { return crc & 0xffff; } -Pattern.prototype.serial = function (br = 38400, sendcrc = false, singlecharids = false) { +Pattern.prototype.serial = function (br = 115200, sendcrc = false, singlecharids = false, name = 'default') { return this.withHap((hap) => { - if (!writeMessage) { - getWriter(br); + if (!(name in writeMessagers)) { + getWriter(name, br); } const onTrigger = (time, hap, currentTime) => { var message = ''; @@ -108,7 +108,7 @@ Pattern.prototype.serial = function (br = 38400, sendcrc = false, singlecharids const offset = (time - currentTime + latency) * 1000; window.setTimeout(function () { - writeMessage(message, chk); + writeMessagers[name](message, chk); }, offset); }; return hap.setContext({ ...hap.context, onTrigger, dominantTrigger: true });