Compare commits

..

17 Commits

Author SHA1 Message Date
Felix Roos bda95fb6f6 Merge branch 'main' into eefano-brotli 2025-12-20 23:15:33 +01:00
froos 5a51b4ec71 Merge pull request 'Document "-" in mini-notation' (#1818) from Wuzzy/strudel:dashtilde into main
Reviewed-on: https://codeberg.org/uzu/strudel/pulls/1818
2025-12-20 22:27:50 +01:00
froos 3922defab9 Merge pull request 'simplify envValAtTime and remove asymmetric behavior (fix #1653)' (#1815) from pulu/strudel:remove-env-asymmetry into main
Reviewed-on: https://codeberg.org/uzu/strudel/pulls/1815
2025-12-20 22:20:26 +01:00
froos 0a2f2eaa3d Merge pull request 'fix: visual block selection mode for vim bindings' (#1839) from Dsm0/strudel:visual-block-mode-fix into main
Reviewed-on: https://codeberg.org/uzu/strudel/pulls/1839
2025-12-19 08:11:49 +01:00
Dsm0 0de212c12f fix visual block mode 2025-12-18 22:55:44 -08:00
eefano db4bb4ada9 formatted 2025-12-09 20:12:16 +01:00
eefano 3311c2f2c9 Merge branch 'main' into brotli 2025-12-09 19:51:13 +01:00
Alex McLean 31bcd9886f Merge branch 'main' into brotli 2025-12-08 13:37:49 +01:00
Wuzzy 53c101005c Document "-" in mini-notation 2025-12-07 00:12:40 +01:00
miranda 173e359a65 simplify envValAtTime and remove asymmetric behavior (fix #1653) 2025-12-06 17:46:16 +02:00
froos 451dd126fc Merge branch 'main' into brotli 2025-10-28 23:39:36 +01:00
s.maini 0e58dc3df0 replaced brotli in favor of Compression Streams API 2025-10-21 15:33:30 +02:00
eefano 6e7c18b15f Merge branch 'main' into brotli 2025-10-21 13:49:23 +02:00
eefano 625d9ecfe8 Merge branch 'main' into brotli 2025-09-13 13:17:11 +02:00
eefano ae3ae2df02 with _ retrieves raw script from external URIencoded link 2025-07-05 18:25:09 +02:00
eefano c32538afed switched to brotli-compress coz of building problems 2025-07-05 15:19:16 +02:00
eefano 9107d0bd3e uses brotli and base64url for link sharing 2025-07-03 22:49:32 +02:00
9 changed files with 84 additions and 13 deletions
@@ -1,5 +1,4 @@
<script src="https://unpkg.com/@strudel/repl@1.2.7"></script>
<!-- <script src="../../packages/repl/dist/index.js"></script> -->
<script src="https://unpkg.com/@strudel/repl@1.0.2"></script>
<strudel-editor>
<!--
// @date 23-08-15
+6 -2
View File
@@ -1,5 +1,5 @@
import { defaultKeymap } from '@codemirror/commands';
import { Prec } from '@codemirror/state';
import { Prec, EditorState } from '@codemirror/state';
import { keymap, ViewPlugin } from '@codemirror/view';
// import { searchKeymap } from '@codemirror/search';
import { emacs } from '@replit/codemirror-emacs';
@@ -133,5 +133,9 @@ const keymaps = {
export function keybindings(name) {
const active = keymaps[name];
return [active ? Prec.high(active()) : []];
const extensions = active ? [Prec.high(active())] : [];
if (name === 'vim') {
extensions.push(EditorState.allowMultipleSelections.of(true));
}
return extensions;
}
+1 -2
View File
@@ -1,12 +1,11 @@
import { silence } from '@strudel/core';
import { getDrawContext } from '@strudel/draw';
import { transpiler } from '@strudel/transpiler';
import { getAudioContext, webaudioOutput, initAudioOnFirstClick } from '@strudel/webaudio';
import { getAudioContext, webaudioOutput } from '@strudel/webaudio';
import { StrudelMirror, codemirrorSettings } from '@strudel/codemirror';
import { prebake } from './prebake.mjs';
if (typeof HTMLElement !== 'undefined') {
initAudioOnFirstClick();
class StrudelRepl extends HTMLElement {
static observedAttributes = ['code'];
settings = codemirrorSettings.get();
+3 -4
View File
@@ -42,6 +42,7 @@ export const getParamADSR = (
decay,
sustain,
release,
// min = value at start of attack, max = value at end of attack; it is possible that max < min
min,
max,
begin,
@@ -59,17 +60,15 @@ export const getParamADSR = (
max = max === 0 ? 0.001 : max;
}
const range = max - min;
const peak = max;
const sustainVal = min + sustain * range;
const duration = end - begin;
const envValAtTime = (time) => {
let val;
if (attack > time) {
let slope = getSlope(min, peak, 0, attack);
val = time * slope + (min > peak ? min : 0);
val = time * getSlope(min, max, 0, attack) + min;
} else {
val = (time - attack) * getSlope(peak, sustainVal, 0, decay) + peak;
val = (time - attack) * getSlope(max, sustainVal, 0, decay) + max;
}
if (curve === 'exponential') {
val = val || 0.001;
+18 -1
View File
@@ -804,6 +804,9 @@ importers:
astro:
specifier: ^5.1.9
version: 5.1.9(@types/node@22.10.10)(jiti@2.4.2)(lightningcss@1.29.1)(rollup@2.79.2)(terser@5.37.0)(typescript@5.7.3)(yaml@2.7.0)
base64url-universal:
specifier: ^2.0.0
version: 2.0.0
claviature:
specifier: ^0.1.0
version: 0.1.0
@@ -3297,6 +3300,14 @@ packages:
base64-js@1.5.1:
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
base64url-universal@2.0.0:
resolution: {integrity: sha512-6Hpg7EBf3t148C3+fMzjf+CHnADVDafWzlJUXAqqqbm4MKNXbsoPdOkWeRTjNlkYG7TpyjIpRO1Gk0SnsFD1rw==}
engines: {node: '>=14'}
base64url@3.0.1:
resolution: {integrity: sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==}
engines: {node: '>=6.0.0'}
before-after-hook@2.2.3:
resolution: {integrity: sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==}
@@ -11008,6 +11019,12 @@ snapshots:
base64-js@1.5.1: {}
base64url-universal@2.0.0:
dependencies:
base64url: 3.0.1
base64url@3.0.1: {}
before-after-hook@2.2.3: {}
bin-links@4.0.4:
@@ -12978,7 +12995,7 @@ snapshots:
jake@10.9.2:
dependencies:
async: 3.2.6
chalk: 4.1.0
chalk: 4.1.2
filelist: 1.0.4
minimatch: 3.1.2
+1
View File
@@ -53,6 +53,7 @@
"@types/react": "^19.0.8",
"@types/react-dom": "^19.0.3",
"astro": "^5.1.9",
"base64url-universal": "^2.0.0",
"claviature": "^0.1.0",
"date-fns": "^4.1.0",
"hs2js": "0.1.0",
@@ -142,6 +142,8 @@ The "~" represents a rest, and will create silence between other events:
<MiniRepl client:idle tune={`note("[b4 [~ c5] d5 e5]")`} punchcard />
Alternatively, "-" can be used instead of "~". It means the same thing.
## Parallel / polyphony
Using commas, we can play chords.
+19 -2
View File
@@ -38,6 +38,7 @@ import { getRandomTune, initCode, loadModules, shareCode } from './util.mjs';
import './Repl.css';
import { setInterval, clearInterval } from 'worker-timers';
import { getMetadata } from '../metadata_parser';
import { encode as base64urlencode } from 'base64url-universal';
import { debugAudiograph } from './audiograph';
const { latestCode, maxPolyphony, audioDeviceName, multiChannelOrbits } = settingsMap.get();
@@ -101,13 +102,29 @@ export function useReplContext() {
}
},
beforeEval: () => audioReady,
afterEval: (all) => {
afterEval: async (all) => {
const { code } = all;
//post to iframe parent (like Udels) if it exists...
window.parent?.postMessage(code);
setLatestCode(code);
window.location.hash = '#' + code2hash(code);
//window.location.hash = '#' + code2hash(code);
// Compress the script and encode it with base64url
const encoded = new TextEncoder().encode(code);
//console.log('encoded',encoded);
const cs = new CompressionStream('deflate');
const writer = cs.writable.getWriter();
writer.write(encoded);
writer.close();
const compressed = new Uint8Array(await new Response(cs.readable).arrayBuffer());
//console.log('compressed',compressed);
const baseurled = base64urlencode(compressed);
//console.log('baseurled',baseurled);
window.location.hash = '#~' + baseurled;
setDocumentTitle(code);
const viewingPatternData = getViewingPatternData();
setVersionDefaultsFrom(code);
+33
View File
@@ -7,6 +7,7 @@ import './Repl.css';
import { createClient } from '@supabase/supabase-js';
import { writeText } from '@tauri-apps/plugin-clipboard-manager';
import { $featuredPatterns /* , loadDBPatterns */ } from '@src/user_pattern_utils.mjs';
import { decode as base64urldecode } from 'base64url-universal';
// Create a single supabase client for interacting with your database
export const supabase = createClient(
@@ -26,6 +27,38 @@ export async function initCode() {
const hash = initialUrl.split('?')[1]?.split('#')?.[0]?.split('&')[0];
const codeParam = window.location.href.split('#')[1] || '';
if (codeParam) {
if (codeParam[0] === '~') {
// Encoded using base64url and compressed
const baseurled = codeParam.substring(1);
//console.log('baseurled', baseurled);
const compressed = base64urldecode(baseurled);
//console.log('compressed', compressed);
const cs = new DecompressionStream('deflate');
const writer = cs.writable.getWriter();
writer.write(compressed);
writer.close();
const encoded = await new Response(cs.readable).arrayBuffer();
//console.log('encoded', encoded);
const decoded = new TextDecoder().decode(encoded);
//console.log('decoded', decoded);
return decoded;
}
if (codeParam[0] === '_') {
const url = decodeURIComponent(codeParam.substring(1));
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`Response status: ${response.status}`);
}
console.log('Response', response);
return await response.text();
} catch (error) {
return `/* ERROR LOADING SCRIPT. ${error.message} */`;
}
}
// looking like https://strudel.cc/#ImMzIGUzIg%3D%3D (hash length depends on code length)
return hash2code(codeParam);
} else if (hash) {