Compare commits

..

4 Commits

Author SHA1 Message Date
Jade (Rose) Rowland ecbd7c77a5 almost working 2025-07-29 18:58:28 -04:00
Jade (Rose) Rowland ec920a1551 i made a mess 2025-07-29 18:44:12 -04:00
Jade (Rose) Rowland d6045c943b working 2025-07-29 18:20:13 -04:00
Jade (Rose) Rowland 30c80119e9 works 2025-07-28 01:20:42 -04:00
17 changed files with 284 additions and 363 deletions
+13 -23
View File
@@ -551,28 +551,6 @@ export const { tremoloshape } = registerControl('tremoloshape', 'tremshape');
export const { drive } = registerControl('drive');
/**
* waveshaping distortion with selectable algorithms
*
* @name shape
* @param {number | Pattern} amount
* @example
* $: s("909bd").beat("0,4,8,11,14",16).shape("<2 4 1>").shapetype("<0 1 2>*2")
*
*/
export const { shape } = registerControl(['shape', 'shapevol', 'shapetype']);
/**
* filter overdrive for supported filter types
*
* @name shapetype
* @param {number | Pattern} type
* @example
* $: s("909bd").beat("0,4,8,11,14",16).shape("2").shapetype("<0 1 2>")
*
*/
export const { shapeType } = registerControl('shapetype');
/**
* Create byte beats with custom expressions
*
@@ -1532,7 +1510,19 @@ export const { roomsize, size, sz, rsize } = registerControl('roomsize', 'size',
// ['sclap'],
// ['sclaves'],
// ['scrash'],
/**
* (Deprecated) Wave shaping distortion. WARNING: can suddenly get unpredictably loud.
* Please use distort instead, which has a more predictable response curve
* second option in optional array syntax (ex: ".9:.5") applies a postgain to the output
*
*
* @name shape
* @param {number | Pattern} distortion between 0 and 1
* @example
* s("bd sd [~ bd] sd,hh*8").shape("<0 .2 .4 .6 .8>")
*
*/
export const { shape } = registerControl(['shape', 'shapevol']);
/**
* Wave shaping distortion. CAUTION: it can get loud.
* Second option in optional array syntax (ex: ".9:.5") applies a postgain to the output.
@@ -1,9 +1,12 @@
import { registerSound, onTriggerSample } from '@strudel/webaudio';
import { isAudioFile } from './files.mjs';
import { logger } from '@strudel/core';
//utilites for writing and reading to the indexdb
export const isAudioFile = (filename) =>
['wav', 'mp3', 'flac', 'ogg', 'm4a', 'aac'].includes(filename.split('.').slice(-1)[0]);
export const userSamplesDBConfig = {
dbName: 'samples',
table: 'usersamples',
+2
View File
@@ -25,6 +25,8 @@ export * from './cyclist.mjs';
export * from './logger.mjs';
export * from './time.mjs';
export * from './ui.mjs';
export * from './ui.mjs';
export * from './idbutils.mjs'
export { default as drawLine } from './drawLine.mjs';
// below won't work with runtime.mjs (json import fails)
/* import * as p from './package.json';
+1
View File
@@ -1,2 +1,3 @@
export * from './repl-component.mjs';
export * from './prebake.mjs';
+4 -2
View File
@@ -1,5 +1,5 @@
import { noteToMidi, valueToMidi, Pattern, evalScope } from '@strudel/core';
import { aliasBank, registerSynthSounds, registerZZFXSounds, samples } from '@strudel/webaudio';
import { noteToMidi, valueToMidi, Pattern, evalScope,registerSamplesFromDB } from '@strudel/core';
import { aliasBank, registerSynthSounds, registerZZFXSounds, samples, } from '@strudel/webaudio';
import * as core from '@strudel/core';
export async function prebake() {
@@ -28,6 +28,7 @@ export async function prebake() {
modulesLoading,
registerSynthSounds(),
registerZZFXSounds(),
registerSamplesFromDB(),
//registerSoundfonts(),
// need dynamic import here, because importing @strudel/soundfonts fails on server:
// => getting "window is not defined", as soon as "@strudel/soundfonts" is imported statically
@@ -39,6 +40,7 @@ export async function prebake() {
samples(`https://raw.githubusercontent.com/tidalcycles/uzu-drumkit/main/strudel.json`),
samples(`${ds}/vcsl.json`),
samples(`${ds}/mridangam.json`),
registerSamplesFromDB(),
]);
aliasBank(`${ts}/tidal-drum-machines-alias.json`);
-15
View File
@@ -277,18 +277,3 @@ export function applyFM(param, value, begin) {
}
return { stop };
}
export const saturationAlgos = [
(x, k) => ((1 + k) * x) / (1 + k * Math.abs(x)), //S Curve sourced from: https://www.nickwritesablog.com/sound-design-in-web-audio-neurofunk-bass-part-1/
(x, k) => Math.tanh(x * k),
];
export function makeSaturationCurve(amount, n_samples, algo = 0) {
const k = typeof amount === 'number' ? amount : 50;
const curve = new Float32Array(n_samples);
for (let i = 0; i < n_samples; i++) {
const x = (i * 2) / n_samples - 1;
curve[i] = saturationAlgos[algo % saturationAlgos.length]?.(x, amount);
}
return curve;
}
+54 -41
View File
@@ -216,50 +216,63 @@ function getSamplesPrefixHandler(url) {
*/
export const samples = async (sampleMap, baseUrl = sampleMap._base || '', options = {}) => {
if (typeof sampleMap === 'string') {
// check if custom prefix handler
const handler = getSamplesPrefixHandler(sampleMap);
if (handler) {
return handler(sampleMap);
}
sampleMap = resolveSpecialPaths(sampleMap);
if (sampleMap.startsWith('github:')) {
sampleMap = githubPath(sampleMap, 'strudel.json');
}
if (sampleMap.startsWith('local:')) {
sampleMap = `http://localhost:5432`;
}
if (sampleMap.startsWith('shabda:')) {
let [_, path] = sampleMap.split('shabda:');
sampleMap = `https://shabda.ndre.gr/${path}.json?strudel=1`;
}
if (sampleMap.startsWith('shabda/speech')) {
let [_, path] = sampleMap.split('shabda/speech');
path = path.startsWith('/') ? path.substring(1) : path;
let [params, words] = path.split(':');
let gender = 'f';
let language = 'en-GB';
if (params) {
[language, gender] = params.split('/');
}
sampleMap = `https://shabda.ndre.gr/speech/${words}.json?gender=${gender}&language=${language}&strudel=1'`;
}
if (typeof fetch !== 'function') {
// not a browser
return;
}
const base = sampleMap.split('/').slice(0, -1).join('/');
if (typeof fetch === 'undefined') {
// skip fetch when in node / testing
return;
const savedJSON = localStorage.getItem(sampleMap)
if (savedJSON) {
const json = JSON.parse(savedJSON)
samples(json, baseUrl || json._base || base, options)
} else {
// check if custom prefix handler
const handler = getSamplesPrefixHandler(sampleMap);
if (handler) {
return handler(sampleMap);
}
sampleMap = resolveSpecialPaths(sampleMap);
if (sampleMap.startsWith('github:')) {
sampleMap = githubPath(sampleMap, 'strudel.json');
}
if (sampleMap.startsWith('local:')) {
sampleMap = `http://localhost:5432`;
}
if (sampleMap.startsWith('shabda:')) {
let [_, path] = sampleMap.split('shabda:');
sampleMap = `https://shabda.ndre.gr/${path}.json?strudel=1`;
}
if (sampleMap.startsWith('shabda/speech')) {
let [_, path] = sampleMap.split('shabda/speech');
path = path.startsWith('/') ? path.substring(1) : path;
let [params, words] = path.split(':');
let gender = 'f';
let language = 'en-GB';
if (params) {
[language, gender] = params.split('/');
}
sampleMap = `https://shabda.ndre.gr/speech/${words}.json?gender=${gender}&language=${language}&strudel=1'`;
}
if (typeof fetch !== 'function') {
// not a browser
return;
}
if (typeof fetch === 'undefined') {
// skip fetch when in node / testing
return;
}
return fetch(sampleMap)
.then((res) => res.json())
.then((json) => {
localStorage.setItem(sampleMap, JSON.stringify(json))
samples(json, baseUrl || json._base || base, options)
})
.catch((error) => {
console.error(error);
throw new Error(`error loading "${sampleMap}"`);
});
}
return fetch(sampleMap)
.then((res) => res.json())
.then((json) => samples(json, baseUrl || json._base || base, options))
.catch((error) => {
console.error(error);
throw new Error(`error loading "${sampleMap}"`);
});
}
const { prebake, tag } = options;
processSampleMap(
+2 -11
View File
@@ -9,7 +9,7 @@ import './reverb.mjs';
import './vowel.mjs';
import { clamp, nanFallback, _mod, cycleToSeconds, secondsToCycle } from './util.mjs';
import workletsUrl from './worklets.mjs?audioworklet';
import { createFilter, gainNode, getCompressor, getWorklet, makeSaturationCurve } from './helpers.mjs';
import { createFilter, gainNode, getCompressor, getWorklet } from './helpers.mjs';
import { map } from 'nanostores';
import { logger } from './logger.mjs';
import { loadBuffer } from './sampler.mjs';
@@ -147,7 +147,6 @@ let defaultDefaultValues = {
phaserdepth: 0.75,
shapevol: 1,
distortvol: 1,
saturatevol: 1,
delay: 0,
byteBeatExpression: '0',
delayfeedback: 0.5,
@@ -574,7 +573,6 @@ export const superdough = async (value, t, hapDuration, cps = 0.5, cycle = 0.5)
crush,
shape,
shapevol = getDefaultValue('shapevol'),
shapetype,
distort,
distortvol = getDefaultValue('distortvol'),
pan,
@@ -678,14 +676,6 @@ export const superdough = async (value, t, hapDuration, cps = 0.5, cycle = 0.5)
// gain stage
chain.push(gainNode(gain));
if (shape != null) {
const shaper = new WaveShaperNode(ac);
shaper.curve = makeSaturationCurve(shape, ac.sampleRate, shapetype);
const shapeGain = new GainNode(ac, { gain: shapevol });
chain.push(shaper);
chain.push(shapeGain);
}
//filter
const ftype = getFilterType(value.ftype);
if (cutoff !== undefined) {
@@ -751,6 +741,7 @@ export const superdough = async (value, t, hapDuration, cps = 0.5, cycle = 0.5)
// effects
coarse !== undefined && chain.push(getWorklet(ac, 'coarse-processor', { coarse }));
crush !== undefined && chain.push(getWorklet(ac, 'crush-processor', { crush }));
shape !== undefined && chain.push(getWorklet(ac, 'shape-processor', { shape, postgain: shapevol }));
distort !== undefined && chain.push(getWorklet(ac, 'distort-processor', { distort, postgain: distortvol }));
if (tremolosync != null) {
+2 -72
View File
@@ -9,13 +9,12 @@ import {
getVibratoOscillator,
webAudioTimeout,
getWorklet,
makeSaturationCurve,
} from './helpers.mjs';
import { getNoiseMix, getNoiseOscillator } from './noise.mjs';
const getFrequencyFromValue = (value, defaultNote = 36) => {
const getFrequencyFromValue = (value) => {
let { note, freq } = value;
note = note || defaultNote;
note = note || 36;
if (typeof note === 'string') {
note = noteToMidi(note); // e.g. c3 => 48
}
@@ -85,75 +84,6 @@ export function registerSynthSounds() {
{ type: 'synth', prebake: true },
);
});
registerSound(
'909bd',
(t, value, onended) => {
const { duration, decay = 0.5, pdecay = 0.5, penv = 36, clip } = value;
const ctx = getAudioContext();
const attackhold = 0.02;
const noiselvl = 1.2;
const noisedecay = 0.025;
const mixGain = 1;
const o = ctx.createOscillator();
o.type = 'triangle';
o.frequency.value = getFrequencyFromValue(value, 29);
o.detune.setValueAtTime(penv * 100, 0);
o.detune.setValueAtTime(penv * 100, t);
o.detune.exponentialRampToValueAtTime(0.001, t + pdecay);
const g = gainNode(1);
g.gain.setValueAtTime(1, t + attackhold);
g.gain.exponentialRampToValueAtTime(0.001, t + attackhold + decay);
o.start(t);
const noise = getNoiseOscillator('brown', t, 2);
const noiseGain = gainNode(1);
noiseGain.gain.setValueAtTime(noiselvl, t);
noiseGain.gain.exponentialRampToValueAtTime(0.001, t + noisedecay);
const sat = new WaveShaperNode(ctx);
// tri to sine diode shaper emulation
sat.curve = makeSaturationCurve(2, ctx.sampleRate, 1);
const mix = gainNode(mixGain);
o.onended = () => {
o.disconnect();
g.disconnect();
sat.disconnect();
noise.node.disconnect();
noiseGain.disconnect();
mix.disconnect();
onended();
};
const node = o.connect(sat).connect(g).connect(mix);
noise.node.connect(noiseGain).connect(mix);
const holdEnd = t + decay;
let end = holdEnd + 0.01;
if (clip != null) {
end = Math.min(t + clip * duration, end);
}
// prevent clicking
mix.gain.setValueAtTime(mixGain, end - 0.01);
mix.gain.linearRampToValueAtTime(0, end);
o.stop(end);
noise.stop(end);
return {
node,
stop: (endTime) => {
o.stop(endTime);
},
};
},
{ type: 'synth', prebake: true },
);
registerSound(
'supersaw',
(begin, value, onended) => {
+48 -45
View File
@@ -8612,51 +8612,54 @@ exports[`runs examples > example "setcpm" example index 0 1`] = `
exports[`runs examples > example "shape" example index 0 1`] = `
[
"[ 0/1 → 1/16 | s:909bd shape:2 shapetype:0 ]",
"[ 1/4 → 5/16 | s:909bd shape:2 shapetype:0 ]",
"[ 1/29/16 | s:909bd shape:2 shapetype:1 ]",
"[ 11/16 → 3/4 | s:909bd shape:2 shapetype:1 ]",
"[ 7/8 → 15/16 | s:909bd shape:2 shapetype:1 ]",
"[ 1/1 → 17/16 | s:909bd shape:4 shapetype:2 ]",
"[ 5/4 → 21/16 | s:909bd shape:4 shapetype:2 ]",
"[ 3/2 → 25/16 | s:909bd shape:4 shapetype:0 ]",
"[ 27/167/4 | s:909bd shape:4 shapetype:0 ]",
"[ 15/8 → 31/16 | s:909bd shape:4 shapetype:0 ]",
"[ 2/133/16 | s:909bd shape:1 shapetype:1 ]",
"[ 9/437/16 | s:909bd shape:1 shapetype:1 ]",
"[ 5/2 → 41/16 | s:909bd shape:1 shapetype:2 ]",
"[ 43/1611/4 | s:909bd shape:1 shapetype:2 ]",
"[ 23/8 → 47/16 | s:909bd shape:1 shapetype:2 ]",
"[ 3/1 → 49/16 | s:909bd shape:2 shapetype:0 ]",
"[ 13/4 → 53/16 | s:909bd shape:2 shapetype:0 ]",
"[ 7/2 → 57/16 | s:909bd shape:2 shapetype:1 ]",
"[ 59/16 → 15/4 | s:909bd shape:2 shapetype:1 ]",
"[ 31/8 → 63/16 | s:909bd shape:2 shapetype:1 ]",
]
`;
exports[`runs examples > example "shapetype" example index 0 1`] = `
[
"[ 0/1 → 1/16 | s:909bd shape:2 shapetype:0 ]",
"[ 1/4 → 5/16 | s:909bd shape:2 shapetype:0 ]",
"[ 1/2 → 9/16 | s:909bd shape:2 shapetype:0 ]",
"[ 11/16 → 3/4 | s:909bd shape:2 shapetype:0 ]",
"[ 7/8 → 15/16 | s:909bd shape:2 shapetype:0 ]",
"[ 1/1 → 17/16 | s:909bd shape:2 shapetype:1 ]",
"[ 5/421/16 | s:909bd shape:2 shapetype:1 ]",
"[ 3/2 → 25/16 | s:909bd shape:2 shapetype:1 ]",
"[ 27/16 → 7/4 | s:909bd shape:2 shapetype:1 ]",
"[ 15/8 → 31/16 | s:909bd shape:2 shapetype:1 ]",
"[ 2/133/16 | s:909bd shape:2 shapetype:2 ]",
"[ 9/4 → 37/16 | s:909bd shape:2 shapetype:2 ]",
"[ 5/2 → 41/16 | s:909bd shape:2 shapetype:2 ]",
"[ 43/16 → 11/4 | s:909bd shape:2 shapetype:2 ]",
"[ 23/847/16 | s:909bd shape:2 shapetype:2 ]",
"[ 3/149/16 | s:909bd shape:2 shapetype:0 ]",
"[ 13/4 → 53/16 | s:909bd shape:2 shapetype:0 ]",
"[ 7/2 → 57/16 | s:909bd shape:2 shapetype:0 ]",
"[ 59/16 → 15/4 | s:909bd shape:2 shapetype:0 ]",
"[ 31/8 → 63/16 | s:909bd shape:2 shapetype:0 ]",
"[ 0/1 → 1/8 | s:hh shape:0 ]",
"[ 0/1 → 1/4 | s:bd shape:0 ]",
"[ 1/81/4 | s:hh shape:0 ]",
"[ 1/4 → 3/8 | s:hh shape:0 ]",
"[ 1/4 → 1/2 | s:sd shape:0 ]",
"[ 3/8 → 1/2 | s:hh shape:0 ]",
"[ 1/2 → 5/8 | s:hh shape:0 ]",
"[ 5/8 → 3/4 | s:bd shape:0 ]",
"[ 5/83/4 | s:hh shape:0 ]",
"[ 3/4 → 7/8 | s:hh shape:0 ]",
"[ 3/41/1 | s:sd shape:0 ]",
"[ 7/81/1 | s:hh shape:0 ]",
"[ 1/1 → 9/8 | s:hh shape:0.2 ]",
"[ 1/1 → 5/4 | s:bd shape:0.2 ]",
"[ 9/8 → 5/4 | s:hh shape:0.2 ]",
"[ 5/4 → 11/8 | s:hh shape:0.2 ]",
"[ 5/4 → 3/2 | s:sd shape:0.2 ]",
"[ 11/8 → 3/2 | s:hh shape:0.2 ]",
"[ 3/2 → 13/8 | s:hh shape:0.2 ]",
"[ 13/8 → 7/4 | s:bd shape:0.2 ]",
"[ 13/8 → 7/4 | s:hh shape:0.2 ]",
"[ 7/4 → 15/8 | s:hh shape:0.2 ]",
"[ 7/4 → 2/1 | s:sd shape:0.2 ]",
"[ 15/8 → 2/1 | s:hh shape:0.2 ]",
"[ 2/1 → 17/8 | s:hh shape:0.4 ]",
"[ 2/1 → 9/4 | s:bd shape:0.4 ]",
"[ 17/8 → 9/4 | s:hh shape:0.4 ]",
"[ 9/419/8 | s:hh shape:0.4 ]",
"[ 9/4 → 5/2 | s:sd shape:0.4 ]",
"[ 19/8 → 5/2 | s:hh shape:0.4 ]",
"[ 5/2 → 21/8 | s:hh shape:0.4 ]",
"[ 21/811/4 | s:bd shape:0.4 ]",
"[ 21/8 → 11/4 | s:hh shape:0.4 ]",
"[ 11/4 → 23/8 | s:hh shape:0.4 ]",
"[ 11/4 → 3/1 | s:sd shape:0.4 ]",
"[ 23/8 → 3/1 | s:hh shape:0.4 ]",
"[ 3/1 → 25/8 | s:hh shape:0.6 ]",
"[ 3/1 → 13/4 | s:bd shape:0.6 ]",
"[ 25/8 → 13/4 | s:hh shape:0.6 ]",
"[ 13/427/8 | s:hh shape:0.6 ]",
"[ 13/47/2 | s:sd shape:0.6 ]",
"[ 27/8 → 7/2 | s:hh shape:0.6 ]",
"[ 7/2 → 29/8 | s:hh shape:0.6 ]",
"[ 29/8 → 15/4 | s:bd shape:0.6 ]",
"[ 29/8 → 15/4 | s:hh shape:0.6 ]",
"[ 15/4 → 31/8 | s:hh shape:0.6 ]",
"[ 15/4 → 4/1 | s:sd shape:0.6 ]",
"[ 31/8 → 4/1 | s:hh shape:0.6 ]",
]
`;
@@ -1,7 +1,7 @@
import { Fragment, useEffect } from 'react';
import React, { useMemo, useState } from 'react';
import { isAudioFile, readDir, dir, playFile } from '../../files.mjs';
import { useMemo, useState } from 'react';
import { readDir, dir, playFile } from '../../files.mjs';
import { isAudioFile } from '@strudel/core';
export function FilesTab() {
const [path, setPath] = useState([]);
useEffect(() => {
@@ -1,5 +1,5 @@
import React, { useCallback, useState } from 'react';
import { registerSamplesFromDB, uploadSamplesToDB, userSamplesDBConfig } from '../../idbutils.mjs';
import { registerSamplesFromDB, uploadSamplesToDB, userSamplesDBConfig } from '@strudel/core';
//choose a directory to locally import samples
export default function ImportSoundsButton({ onComplete }) {
@@ -125,7 +125,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
+1 -2
View File
@@ -75,8 +75,7 @@ export const walkFileTree = (node, fn) => {
}
};
export const isAudioFile = (filename) =>
['wav', 'mp3', 'flac', 'ogg', 'm4a', 'aac'].includes(filename.split('.').slice(-1)[0]);
function uint8ArrayToDataURL(uint8Array) {
const blob = new Blob([uint8Array], { type: 'audio/*' });
+146 -144
View File
@@ -1,156 +1,158 @@
import { Pattern, noteToMidi, valueToMidi } from '@strudel/core';
import { aliasBank, registerSynthSounds, registerZZFXSounds, samples } from '@strudel/webaudio';
import { registerSamplesFromDB } from './idbutils.mjs';
import { registerSamplesFromDB } from '@strudel/core'
import './piano.mjs';
import './files.mjs';
const { BASE_URL } = import.meta.env;
const baseNoTrailing = BASE_URL.endsWith('/') ? BASE_URL.slice(0, -1) : BASE_URL;
export async function prebake() {
// https://archive.org/details/SalamanderGrandPianoV3
// License: CC-by http://creativecommons.org/licenses/by/3.0/ Author: Alexander Holm
await Promise.all([
registerSynthSounds(),
registerZZFXSounds(),
registerSamplesFromDB(),
//registerSoundfonts(),
// need dynamic import here, because importing @strudel/soundfonts fails on server:
// => getting "window is not defined", as soon as "@strudel/soundfonts" is imported statically
// seems to be a problem with soundfont2
import('@strudel/soundfonts').then(({ registerSoundfonts }) => registerSoundfonts()),
samples(`${baseNoTrailing}/piano.json`, undefined, { prebake: true }),
// https://github.com/sgossner/VCSL/
// https://api.github.com/repositories/126427031/contents/
// LICENSE: CC0 general-purpose
samples(`${baseNoTrailing}/vcsl.json`, 'github:sgossner/VCSL/master/', { prebake: true }),
samples(`${baseNoTrailing}/tidal-drum-machines.json`, 'github:ritchse/tidal-drum-machines/main/machines/', {
prebake: true,
tag: 'drum-machines',
}),
samples(`https://raw.githubusercontent.com/tidalcycles/uzu-drumkit/main/strudel.json`, undefined, {
prebake: true,
tag: 'drum-machines',
}),
samples(`${baseNoTrailing}/mridangam.json`, undefined, { prebake: true, tag: 'drum-machines' }),
samples(
{
casio: ['casio/high.wav', 'casio/low.wav', 'casio/noise.wav'],
crow: ['crow/000_crow.wav', 'crow/001_crow2.wav', 'crow/002_crow3.wav', 'crow/003_crow4.wav'],
insect: [
'insect/000_everglades_conehead.wav',
'insect/001_robust_shieldback.wav',
'insect/002_seashore_meadow_katydid.wav',
],
wind: [
'wind/000_wind1.wav',
'wind/001_wind10.wav',
'wind/002_wind2.wav',
'wind/003_wind3.wav',
'wind/004_wind4.wav',
'wind/005_wind5.wav',
'wind/006_wind6.wav',
'wind/007_wind7.wav',
'wind/008_wind8.wav',
'wind/009_wind9.wav',
],
jazz: [
'jazz/000_BD.wav',
'jazz/001_CB.wav',
'jazz/002_FX.wav',
'jazz/003_HH.wav',
'jazz/004_OH.wav',
'jazz/005_P1.wav',
'jazz/006_P2.wav',
'jazz/007_SN.wav',
],
metal: [
'metal/000_0.wav',
'metal/001_1.wav',
'metal/002_2.wav',
'metal/003_3.wav',
'metal/004_4.wav',
'metal/005_5.wav',
'metal/006_6.wav',
'metal/007_7.wav',
'metal/008_8.wav',
'metal/009_9.wav',
],
east: [
'east/000_nipon_wood_block.wav',
'east/001_ohkawa_mute.wav',
'east/002_ohkawa_open.wav',
'east/003_shime_hi.wav',
'east/004_shime_hi_2.wav',
'east/005_shime_mute.wav',
'east/006_taiko_1.wav',
'east/007_taiko_2.wav',
'east/008_taiko_3.wav',
],
space: [
'space/000_0.wav',
'space/001_1.wav',
'space/002_11.wav',
'space/003_12.wav',
'space/004_13.wav',
'space/005_14.wav',
'space/006_15.wav',
'space/007_16.wav',
'space/008_17.wav',
'space/009_18.wav',
'space/010_2.wav',
'space/011_3.wav',
'space/012_4.wav',
'space/013_5.wav',
'space/014_6.wav',
'space/015_7.wav',
'space/016_8.wav',
'space/017_9.wav',
],
numbers: [
'numbers/0.wav',
'numbers/1.wav',
'numbers/2.wav',
'numbers/3.wav',
'numbers/4.wav',
'numbers/5.wav',
'numbers/6.wav',
'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',
{
prebake: true,
},
),
]);
// export async function prebake() {
// // https://archive.org/details/SalamanderGrandPianoV3
// // License: CC-by http://creativecommons.org/licenses/by/3.0/ Author: Alexander Holm
// await Promise.all([
// registerSynthSounds(),
// registerZZFXSounds(),
// registerSamplesFromDB(),
// //registerSoundfonts(),
// // need dynamic import here, because importing @strudel/soundfonts fails on server:
// // => getting "window is not defined", as soon as "@strudel/soundfonts" is imported statically
// // seems to be a problem with soundfont2
// import('@strudel/soundfonts').then(({ registerSoundfonts }) => registerSoundfonts()),
// samples(`${baseNoTrailing}/piano.json`, undefined, { prebake: true }),
// // https://github.com/sgossner/VCSL/
// // https://api.github.com/repositories/126427031/contents/
// // LICENSE: CC0 general-purpose
// samples(`${baseNoTrailing}/vcsl.json`, 'github:sgossner/VCSL/master/', { prebake: true }),
// samples(`${baseNoTrailing}/tidal-drum-machines.json`, 'github:ritchse/tidal-drum-machines/main/machines/', {
// prebake: true,
// tag: 'drum-machines',
// }),
// samples(`https://raw.githubusercontent.com/tidalcycles/uzu-drumkit/main/strudel.json`, undefined, {
// prebake: true,
// tag: 'drum-machines',
// }),
// samples(`${baseNoTrailing}/mridangam.json`, undefined, { prebake: true, tag: 'drum-machines' }),
// samples(
// {
// casio: ['casio/high.wav', 'casio/low.wav', 'casio/noise.wav'],
// crow: ['crow/000_crow.wav', 'crow/001_crow2.wav', 'crow/002_crow3.wav', 'crow/003_crow4.wav'],
// insect: [
// 'insect/000_everglades_conehead.wav',
// 'insect/001_robust_shieldback.wav',
// 'insect/002_seashore_meadow_katydid.wav',
// ],
// wind: [
// 'wind/000_wind1.wav',
// 'wind/001_wind10.wav',
// 'wind/002_wind2.wav',
// 'wind/003_wind3.wav',
// 'wind/004_wind4.wav',
// 'wind/005_wind5.wav',
// 'wind/006_wind6.wav',
// 'wind/007_wind7.wav',
// 'wind/008_wind8.wav',
// 'wind/009_wind9.wav',
// ],
// jazz: [
// 'jazz/000_BD.wav',
// 'jazz/001_CB.wav',
// 'jazz/002_FX.wav',
// 'jazz/003_HH.wav',
// 'jazz/004_OH.wav',
// 'jazz/005_P1.wav',
// 'jazz/006_P2.wav',
// 'jazz/007_SN.wav',
// ],
// metal: [
// 'metal/000_0.wav',
// 'metal/001_1.wav',
// 'metal/002_2.wav',
// 'metal/003_3.wav',
// 'metal/004_4.wav',
// 'metal/005_5.wav',
// 'metal/006_6.wav',
// 'metal/007_7.wav',
// 'metal/008_8.wav',
// 'metal/009_9.wav',
// ],
// east: [
// 'east/000_nipon_wood_block.wav',
// 'east/001_ohkawa_mute.wav',
// 'east/002_ohkawa_open.wav',
// 'east/003_shime_hi.wav',
// 'east/004_shime_hi_2.wav',
// 'east/005_shime_mute.wav',
// 'east/006_taiko_1.wav',
// 'east/007_taiko_2.wav',
// 'east/008_taiko_3.wav',
// ],
// space: [
// 'space/000_0.wav',
// 'space/001_1.wav',
// 'space/002_11.wav',
// 'space/003_12.wav',
// 'space/004_13.wav',
// 'space/005_14.wav',
// 'space/006_15.wav',
// 'space/007_16.wav',
// 'space/008_17.wav',
// 'space/009_18.wav',
// 'space/010_2.wav',
// 'space/011_3.wav',
// 'space/012_4.wav',
// 'space/013_5.wav',
// 'space/014_6.wav',
// 'space/015_7.wav',
// 'space/016_8.wav',
// 'space/017_9.wav',
// ],
// numbers: [
// 'numbers/0.wav',
// 'numbers/1.wav',
// 'numbers/2.wav',
// 'numbers/3.wav',
// 'numbers/4.wav',
// 'numbers/5.wav',
// 'numbers/6.wav',
// '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',
// {
// prebake: true,
// },
// ),
// ]);
aliasBank(`${baseNoTrailing}/tidal-drum-machines-alias.json`);
}
// aliasBank(`${baseNoTrailing}/tidal-drum-machines-alias.json`);
// }
const maxPan = noteToMidi('C8');
const panwidth = (pan, width) => pan * width + (1 - width) / 2;
+1 -1
View File
@@ -31,7 +31,7 @@ import {
import { superdirtOutput } from '@strudel/osc/superdirtoutput';
import { audioEngineTargets } from '../settings.mjs';
import { useStore } from '@nanostores/react';
import { prebake } from './prebake.mjs';
import { prebake } from '../../../packages/repl/prebake.mjs'
import { getRandomTune, initCode, loadModules, shareCode } from './util.mjs';
import './Repl.css';
import { setInterval, clearInterval } from 'worker-timers';
+1 -1
View File
@@ -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 });
}