mirror of
https://github.com/eliasstepanik/strudel-docker.git
synced 2026-01-24 03:58:53 +00:00
use nanostore for soundmap
+ rename tab samples to sounds + listed sounds are now reactive
This commit is contained in:
parent
6059c69995
commit
b08a0b8102
@ -34,7 +34,8 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/tidalcycles/strudel#readme",
|
"homepage": "https://github.com/tidalcycles/strudel#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@strudel.cycles/core": "workspace:*"
|
"@strudel.cycles/core": "workspace:*",
|
||||||
|
"nanostores": "^0.7.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"vite": "^3.2.2"
|
"vite": "^3.2.2"
|
||||||
|
|||||||
@ -179,11 +179,6 @@ export async function onTriggerSample(options, bank) {
|
|||||||
// no playback
|
// no playback
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!s) {
|
|
||||||
// is this check really needed?
|
|
||||||
console.warn('no sample specified');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
//const soundfont = getSoundfontKey(s);
|
//const soundfont = getSoundfontKey(s);
|
||||||
let bufferSource;
|
let bufferSource;
|
||||||
|
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import { fromMidi, toMidi } from '@strudel.cycles/core';
|
|||||||
import { setSound } from './webaudio.mjs';
|
import { setSound } from './webaudio.mjs';
|
||||||
import { getOscillator, gainNode, getADSR } from './helpers.mjs';
|
import { getOscillator, gainNode, getADSR } from './helpers.mjs';
|
||||||
|
|
||||||
export function loadSynthSounds() {
|
export function registerSynthSounds() {
|
||||||
['sine', 'square', 'triangle', 'sawtooth'].forEach((wave) => {
|
['sine', 'square', 'triangle', 'sawtooth'].forEach((wave) => {
|
||||||
setSound(wave, ({ hap, duration, t }) => {
|
setSound(wave, ({ hap, duration, t }) => {
|
||||||
// destructure adsr here, because the default should be different for synths and samples
|
// destructure adsr here, because the default should be different for synths and samples
|
||||||
|
|||||||
@ -11,15 +11,14 @@ const { Pattern } = strudel;
|
|||||||
import './vowel.mjs';
|
import './vowel.mjs';
|
||||||
import workletsUrl from './worklets.mjs?url';
|
import workletsUrl from './worklets.mjs?url';
|
||||||
import { getFilter, gainNode } from './helpers.mjs';
|
import { getFilter, gainNode } from './helpers.mjs';
|
||||||
|
import { map } from 'nanostores';
|
||||||
|
|
||||||
// export const getAudioContext = () => Tone.getContext().rawContext;
|
export const soundMap = map();
|
||||||
|
|
||||||
export const soundMap = new Map();
|
|
||||||
// onTrigger = ({ hap: Hap, t: number, deadline: number, duration: number, cps: number }) => AudioNode
|
// onTrigger = ({ hap: Hap, t: number, deadline: number, duration: number, cps: number }) => AudioNode
|
||||||
export function setSound(key, onTrigger) {
|
export function setSound(key, onTrigger) {
|
||||||
soundMap.set(key, onTrigger);
|
soundMap.setKey(key, onTrigger);
|
||||||
}
|
}
|
||||||
export const resetLoadedSounds = () => soundMap.clear();
|
export const resetLoadedSounds = () => soundMap.set({});
|
||||||
|
|
||||||
let audioContext;
|
let audioContext;
|
||||||
export const getAudioContext = () => {
|
export const getAudioContext = () => {
|
||||||
@ -161,14 +160,17 @@ export const webaudioOutput = async (hap, deadline, hapDuration, cps) => {
|
|||||||
if (bank && s) {
|
if (bank && s) {
|
||||||
s = `${bank}_${s}`;
|
s = `${bank}_${s}`;
|
||||||
}
|
}
|
||||||
if (soundMap.has(s)) {
|
// get source AudioNode
|
||||||
const node = await soundMap.get(s)({ hap, t, deadline, duration: hapDuration, cps });
|
let node;
|
||||||
chain.push(node);
|
const options = { hap, t, deadline, duration: hapDuration, cps };
|
||||||
} else if (source) {
|
if (source) {
|
||||||
chain.push(source({ hap, t, deadline, duration: hapDuration, cps }));
|
node = source(options);
|
||||||
|
} else if (soundMap.get()[s]) {
|
||||||
|
node = await soundMap.get()[s](options);
|
||||||
} else {
|
} else {
|
||||||
throw new Error(`sound ${s} not found! Is it loaded?`);
|
throw new Error(`sound ${s} not found! Is it loaded?`);
|
||||||
}
|
}
|
||||||
|
chain.push(node);
|
||||||
|
|
||||||
// gain stage
|
// gain stage
|
||||||
chain.push(gainNode(gain));
|
chain.push(gainNode(gain));
|
||||||
|
|||||||
2
pnpm-lock.yaml
generated
2
pnpm-lock.yaml
generated
@ -321,9 +321,11 @@ importers:
|
|||||||
packages/webaudio:
|
packages/webaudio:
|
||||||
specifiers:
|
specifiers:
|
||||||
'@strudel.cycles/core': workspace:*
|
'@strudel.cycles/core': workspace:*
|
||||||
|
nanostores: ^0.7.4
|
||||||
vite: ^3.2.2
|
vite: ^3.2.2
|
||||||
dependencies:
|
dependencies:
|
||||||
'@strudel.cycles/core': link:../core
|
'@strudel.cycles/core': link:../core
|
||||||
|
nanostores: 0.7.4
|
||||||
devDependencies:
|
devDependencies:
|
||||||
vite: 3.2.5
|
vite: 3.2.5
|
||||||
|
|
||||||
|
|||||||
@ -7,6 +7,8 @@ import React, { useCallback, useLayoutEffect, useRef, useState } from 'react';
|
|||||||
import { Reference } from './Reference';
|
import { Reference } from './Reference';
|
||||||
import { themes } from './themes.mjs';
|
import { themes } from './themes.mjs';
|
||||||
import { useSettings, settingsMap, setActiveFooter, defaultSettings } from '../settings.mjs';
|
import { useSettings, settingsMap, setActiveFooter, defaultSettings } from '../settings.mjs';
|
||||||
|
import { soundMap } from '@strudel.cycles/webaudio';
|
||||||
|
import { useStore } from '@nanostores/react';
|
||||||
|
|
||||||
export function Footer({ context }) {
|
export function Footer({ context }) {
|
||||||
const footerContent = useRef();
|
const footerContent = useRef();
|
||||||
@ -71,7 +73,7 @@ export function Footer({ context }) {
|
|||||||
<div className="flex justify-between px-2">
|
<div className="flex justify-between px-2">
|
||||||
<div className={cx('flex select-none max-w-full overflow-auto', activeFooter && 'pb-2')}>
|
<div className={cx('flex select-none max-w-full overflow-auto', activeFooter && 'pb-2')}>
|
||||||
<FooterTab name="intro" label="welcome" />
|
<FooterTab name="intro" label="welcome" />
|
||||||
<FooterTab name="samples" />
|
<FooterTab name="sounds" />
|
||||||
<FooterTab name="console" />
|
<FooterTab name="console" />
|
||||||
<FooterTab name="reference" />
|
<FooterTab name="reference" />
|
||||||
<FooterTab name="settings" />
|
<FooterTab name="settings" />
|
||||||
@ -89,7 +91,7 @@ export function Footer({ context }) {
|
|||||||
>
|
>
|
||||||
{activeFooter === 'intro' && <WelcomeTab />}
|
{activeFooter === 'intro' && <WelcomeTab />}
|
||||||
{activeFooter === 'console' && <ConsoleTab log={log} />}
|
{activeFooter === 'console' && <ConsoleTab log={log} />}
|
||||||
{activeFooter === 'samples' && <SamplesTab />}
|
{activeFooter === 'sounds' && <SoundsTab />}
|
||||||
{activeFooter === 'reference' && <Reference />}
|
{activeFooter === 'reference' && <Reference />}
|
||||||
{activeFooter === 'settings' && <SettingsTab scheduler={context.scheduler} />}
|
{activeFooter === 'settings' && <SettingsTab scheduler={context.scheduler} />}
|
||||||
</div>
|
</div>
|
||||||
@ -192,18 +194,19 @@ function ConsoleTab({ log }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function SamplesTab() {
|
function SoundsTab() {
|
||||||
|
const sounds = useStore(soundMap);
|
||||||
return (
|
return (
|
||||||
<div id="samples-tab" className="break-normal w-full px-4 dark:text-white text-stone-900">
|
<div id="sounds-tab" className="break-normal w-full px-4 dark:text-white text-stone-900">
|
||||||
TODO: use nanostore with sampleMap
|
{/* <span>{loadedSamples.length} banks loaded:</span> */}
|
||||||
{/* <span>{loadedSamples.length} banks loaded:</span>
|
{Object.entries(sounds).map(([name, samples]) => (
|
||||||
{loadedSamples.map(([name, samples]) => (
|
|
||||||
<span key={name} className="cursor-pointer hover:opacity-50" onClick={() => {}}>
|
<span key={name} className="cursor-pointer hover:opacity-50" onClick={() => {}}>
|
||||||
{' '}
|
{' '}
|
||||||
{name}(
|
{name}
|
||||||
{Array.isArray(samples) ? samples.length : typeof samples === 'object' ? Object.values(samples).length : 1}){' '}
|
{/* (
|
||||||
|
{Array.isArray(samples) ? samples.length : typeof samples === 'object' ? Object.values(samples).length : 1}) */}
|
||||||
</span>
|
</span>
|
||||||
))} */}
|
))}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,11 +1,10 @@
|
|||||||
import { Pattern, toMidi, valueToMidi } from '@strudel.cycles/core';
|
import { Pattern, toMidi, valueToMidi } from '@strudel.cycles/core';
|
||||||
import { loadSynthSounds, samples } from '@strudel.cycles/webaudio';
|
import { registerSynthSounds, samples } from '@strudel.cycles/webaudio';
|
||||||
|
|
||||||
export async function prebake() {
|
export async function prebake() {
|
||||||
// https://archive.org/details/SalamanderGrandPianoV3
|
// https://archive.org/details/SalamanderGrandPianoV3
|
||||||
// License: CC-by http://creativecommons.org/licenses/by/3.0/ Author: Alexander Holm
|
// License: CC-by http://creativecommons.org/licenses/by/3.0/ Author: Alexander Holm
|
||||||
loadSynthSounds();
|
await Promise.all([
|
||||||
return await Promise.all([
|
|
||||||
samples(`./piano.json`, `./piano/`),
|
samples(`./piano.json`, `./piano/`),
|
||||||
// https://github.com/sgossner/VCSL/
|
// https://github.com/sgossner/VCSL/
|
||||||
// https://api.github.com/repositories/126427031/contents/
|
// https://api.github.com/repositories/126427031/contents/
|
||||||
@ -15,6 +14,7 @@ export async function prebake() {
|
|||||||
samples(`./EmuSP12.json`, `./EmuSP12/`),
|
samples(`./EmuSP12.json`, `./EmuSP12/`),
|
||||||
// samples('github:tidalcycles/Dirt-Samples/master'),
|
// samples('github:tidalcycles/Dirt-Samples/master'),
|
||||||
]);
|
]);
|
||||||
|
registerSynthSounds();
|
||||||
}
|
}
|
||||||
|
|
||||||
const maxPan = toMidi('C8');
|
const maxPan = toMidi('C8');
|
||||||
|
|||||||
@ -23,6 +23,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
#console-tab,
|
#console-tab,
|
||||||
#samples-tab {
|
#sounds-tab {
|
||||||
font-family: BigBlueTerminal, monospace;
|
font-family: BigBlueTerminal, monospace;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user