mirror of
https://github.com/eliasstepanik/strudel.git
synced 2026-01-11 05:38:35 +00:00
settings panel
This commit is contained in:
parent
6f9bcc53dc
commit
d8e4055c6e
@ -14,9 +14,10 @@ import { map } from 'nanostores';
|
||||
import { logger } from './logger.mjs';
|
||||
import { loadBuffer } from './sampler.mjs';
|
||||
|
||||
let maxPolyphony = 128;
|
||||
export const DEFAULT_MAX_POLYPHONY = 128;
|
||||
let maxPolyphony = DEFAULT_MAX_POLYPHONY;
|
||||
export function setMaxPolyphony(polyphony) {
|
||||
maxPolyphony = polyphony;
|
||||
maxPolyphony = parseInt(polyphony) ?? DEFAULT_MAX_POLYPHONY;
|
||||
}
|
||||
export const soundMap = map();
|
||||
|
||||
@ -166,8 +167,8 @@ function loadWorklets() {
|
||||
|
||||
// this function should be called on first user interaction (to avoid console warning)
|
||||
export async function initAudio(options = {}) {
|
||||
const { disableWorklets = false, polyphony = maxPolyphony } = options;
|
||||
setMaxPolyphony(polyphony);
|
||||
const { disableWorklets = false, maxPolyphony } = options;
|
||||
setMaxPolyphony(maxPolyphony);
|
||||
if (typeof window === 'undefined') {
|
||||
return;
|
||||
}
|
||||
@ -487,7 +488,7 @@ export const superdough = async (value, t, hapDuration) => {
|
||||
const ch = activeSoundSources.entries().next();
|
||||
const source = ch.value[1];
|
||||
const chainID = ch.value[0];
|
||||
const endTime = t + .25;
|
||||
const endTime = t + 0.25;
|
||||
source?.node?.gain?.linearRampToValueAtTime(0, endTime);
|
||||
source?.stop?.(endTime);
|
||||
activeSoundSources.delete(chainID);
|
||||
|
||||
@ -25,6 +25,10 @@ const getFrequencyFromValue = (value) => {
|
||||
|
||||
return Number(freq);
|
||||
};
|
||||
function destroyAudioWorkletNode(node) {
|
||||
node.disconnect();
|
||||
node.parameters.get('end')?.setValueAtTime(0, 0);
|
||||
}
|
||||
|
||||
const waveforms = ['triangle', 'square', 'sawtooth', 'sine'];
|
||||
const noises = ['pink', 'white', 'brown', 'crackle'];
|
||||
@ -117,7 +121,7 @@ export function registerSynthSounds() {
|
||||
let timeoutNode = webAudioTimeout(
|
||||
ac,
|
||||
() => {
|
||||
o.disconnect();
|
||||
destroyAudioWorkletNode(o);
|
||||
envGain.disconnect();
|
||||
onended();
|
||||
fm?.stop();
|
||||
@ -173,13 +177,12 @@ export function registerSynthSounds() {
|
||||
let envGain = gainNode(1);
|
||||
envGain = o.connect(envGain);
|
||||
|
||||
|
||||
getParamADSR(envGain.gain, attack, decay, sustain, release, 0, 1, begin, holdend, 'linear');
|
||||
|
||||
let timeoutNode = webAudioTimeout(
|
||||
ac,
|
||||
() => {
|
||||
o.disconnect();
|
||||
destroyAudioWorkletNode(o);
|
||||
envGain.disconnect();
|
||||
onended();
|
||||
fm?.stop();
|
||||
@ -237,7 +240,7 @@ export function registerSynthSounds() {
|
||||
return {
|
||||
node,
|
||||
stop: (endTime) => {
|
||||
stop(endTime)
|
||||
stop(endTime);
|
||||
},
|
||||
};
|
||||
},
|
||||
@ -308,7 +311,6 @@ export function getOscillator(s, t, value) {
|
||||
return {
|
||||
node: noiseMix?.node || o,
|
||||
stop: (time) => {
|
||||
// console.info(time)
|
||||
fmModulator.stop(time);
|
||||
vibratoOscillator?.stop(time);
|
||||
noiseMix?.stop(time);
|
||||
|
||||
@ -663,9 +663,6 @@ registerProcessor('phase-vocoder-processor', PhaseVocoderProcessor);
|
||||
class PulseOscillatorProcessor extends AudioWorkletProcessor {
|
||||
constructor() {
|
||||
super();
|
||||
// this.port.onmessage = (event) => {
|
||||
// console.info(event)
|
||||
// };
|
||||
this.pi = _PI;
|
||||
this.phi = -this.pi; // phase
|
||||
this.Y0 = 0; // feedback memories
|
||||
@ -713,6 +710,9 @@ class PulseOscillatorProcessor extends AudioWorkletProcessor {
|
||||
}
|
||||
|
||||
process(inputs, outputs, params) {
|
||||
if (this.disconnected) {
|
||||
return false;
|
||||
}
|
||||
if (currentTime <= params.begin[0]) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1,10 +1,12 @@
|
||||
import { defaultSettings, settingsMap, useSettings } from '../../../settings.mjs';
|
||||
import { themes } from '@strudel/codemirror';
|
||||
import { Textbox } from '../textbox/Textbox.jsx';
|
||||
import { isUdels } from '../../util.mjs';
|
||||
import { ButtonGroup } from './Forms.jsx';
|
||||
import { AudioDeviceSelector } from './AudioDeviceSelector.jsx';
|
||||
import { AudioEngineTargetSelector } from './AudioEngineTargetSelector.jsx';
|
||||
import { confirmDialog } from '../../util.mjs';
|
||||
import { DEFAULT_MAX_POLYPHONY, setMaxPolyphony } from '@strudel/webaudio';
|
||||
|
||||
function Checkbox({ label, value, onChange, disabled = false }) {
|
||||
return (
|
||||
@ -53,7 +55,7 @@ function NumberSlider({ value, onChange, step = 1, ...rest }) {
|
||||
);
|
||||
}
|
||||
|
||||
function FormItem({ label, children }) {
|
||||
function FormItem({ label, children, sublabel }) {
|
||||
return (
|
||||
<div className="grid gap-2">
|
||||
<label>{label}</label>
|
||||
@ -105,6 +107,7 @@ export function SettingsTab({ started }) {
|
||||
audioDeviceName,
|
||||
audioEngineTarget,
|
||||
togglePanelTrigger,
|
||||
maxPolyphony,
|
||||
} = useSettings();
|
||||
const shouldAlwaysSync = isUdels();
|
||||
const canChangeAudioDevice = AudioContext.prototype.setSinkId != null;
|
||||
@ -139,6 +142,26 @@ export function SettingsTab({ started }) {
|
||||
}}
|
||||
/>
|
||||
</FormItem>
|
||||
|
||||
<FormItem label="Maximum Polyphony">
|
||||
<Textbox
|
||||
min={1}
|
||||
max={Infinity}
|
||||
onBlur={(e) => {
|
||||
let v = parseInt(e.target.value);
|
||||
v = isNaN(v) ? DEFAULT_MAX_POLYPHONY : v;
|
||||
setMaxPolyphony(v);
|
||||
settingsMap.setKey('maxPolyphony', v);
|
||||
}}
|
||||
onChange={(v) => {
|
||||
v = Math.max(1, parseInt(v));
|
||||
settingsMap.setKey('maxPolyphony', isNaN(v) ? undefined : v);
|
||||
}}
|
||||
type="number"
|
||||
placeholder=""
|
||||
value={maxPolyphony ?? ''}
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem label="Theme">
|
||||
<SelectInput options={themeOptions} value={theme} onChange={(theme) => settingsMap.setKey('theme', theme)} />
|
||||
</FormItem>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user