mirror of
https://codeberg.org/uzu/strudel
synced 2026-07-23 13:42:56 -04:00
Add Audio Volume setting to REPL
Allows for adjusting the global volume/gain of the REPL. Set default global value to 50%. Acts similarily to `gain()`, but without modifying the code, so passerbys who don't know how to use the tool can adjust the volume too). The volume slider uses a logarithmic scale, so it adjusts better to human sound perception.
This commit is contained in:
@@ -143,6 +143,14 @@ export function initializeAudioOutput() {
|
||||
destinationGain.connect(audioContext.destination);
|
||||
}
|
||||
|
||||
export function setGlobalGain(gain) {
|
||||
if (destinationGain == null) {
|
||||
initializeAudioOutput();
|
||||
}
|
||||
|
||||
destinationGain.gain.value = gain;
|
||||
}
|
||||
|
||||
// input: AudioNode, channels: ?Array<int>
|
||||
export const connectToDestination = (input, channels = [0, 1]) => {
|
||||
const ctx = getAudioContext();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { defaultSettings, settingsMap, useSettings } from '../../../settings.mjs';
|
||||
import { themes } from '@strudel/codemirror';
|
||||
import { isUdels } from '../../util.mjs';
|
||||
import { isUdels, setGlobalAudioVolume } from '../../util.mjs';
|
||||
import { ButtonGroup } from './Forms.jsx';
|
||||
import { AudioDeviceSelector } from './AudioDeviceSelector.jsx';
|
||||
|
||||
@@ -42,7 +42,7 @@ function NumberSlider({ value, onChange, step = 1, ...rest }) {
|
||||
/>
|
||||
<input
|
||||
type="number"
|
||||
value={value}
|
||||
value={Math.floor(value)}
|
||||
step={step}
|
||||
className="w-16 bg-background rounded-md"
|
||||
onChange={(e) => onChange(Number(e.target.value))}
|
||||
@@ -96,6 +96,7 @@ export function SettingsTab({ started }) {
|
||||
fontFamily,
|
||||
panelPosition,
|
||||
audioDeviceName,
|
||||
audioVolume,
|
||||
} = useSettings();
|
||||
const shouldAlwaysSync = isUdels();
|
||||
return (
|
||||
@@ -109,6 +110,18 @@ export function SettingsTab({ started }) {
|
||||
/>
|
||||
</FormItem>
|
||||
)}
|
||||
<FormItem label="Audio Volume">
|
||||
<NumberSlider
|
||||
value={audioVolume}
|
||||
onChange={(audioVolume) => {
|
||||
settingsMap.setKey('audioVolume', audioVolume);
|
||||
setGlobalAudioVolume(audioVolume);
|
||||
}}
|
||||
min={0}
|
||||
max={100}
|
||||
step={.1}
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem label="Theme">
|
||||
<SelectInput options={themeOptions} value={theme} onChange={(theme) => settingsMap.setKey('theme', theme)} />
|
||||
</FormItem>
|
||||
|
||||
@@ -15,7 +15,7 @@ import {
|
||||
initAudioOnFirstClick,
|
||||
} from '@strudel/webaudio';
|
||||
import { defaultAudioDeviceName } from '../settings.mjs';
|
||||
import { getAudioDevices, setAudioDevice, setVersionDefaultsFrom } from './util.mjs';
|
||||
import { getAudioDevices, setAudioDevice, setGlobalAudioVolume, setVersionDefaultsFrom } from './util.mjs';
|
||||
import { StrudelMirror, defaultSettings } from '@strudel/codemirror';
|
||||
import { clearHydra } from '@strudel/hydra';
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
@@ -154,9 +154,11 @@ export function useReplContext() {
|
||||
editorRef.current?.updateSettings(editorSettings);
|
||||
}, [_settings]);
|
||||
|
||||
// on first load, set stored audio device if possible
|
||||
// on first load...
|
||||
useEffect(() => {
|
||||
const { audioDeviceName } = _settings;
|
||||
const { audioDeviceName, audioVolume } = _settings;
|
||||
|
||||
// set stored audio device if possible
|
||||
if (audioDeviceName !== defaultAudioDeviceName) {
|
||||
getAudioDevices().then((devices) => {
|
||||
const deviceID = devices.get(audioDeviceName);
|
||||
@@ -166,6 +168,9 @@ export function useReplContext() {
|
||||
setAudioDevice(deviceID);
|
||||
});
|
||||
}
|
||||
|
||||
// set stored audio volume
|
||||
setGlobalAudioVolume(audioVolume);
|
||||
}, []);
|
||||
|
||||
//
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { evalScope, hash2code, logger } from '@strudel/core';
|
||||
import { settingPatterns, defaultAudioDeviceName } from '../settings.mjs';
|
||||
import { getAudioContext, initializeAudioOutput, setDefaultAudioContext, setVersionDefaults } from '@strudel/webaudio';
|
||||
import { getAudioContext, initializeAudioOutput, setDefaultAudioContext, setGlobalGain, setVersionDefaults } from '@strudel/webaudio';
|
||||
import { getMetadata } from '../metadata_parser';
|
||||
|
||||
import { isTauri } from '../tauri.mjs';
|
||||
@@ -180,6 +180,13 @@ export const setAudioDevice = async (id) => {
|
||||
initializeAudioOutput();
|
||||
};
|
||||
|
||||
export const setGlobalAudioVolume = (volume) => {
|
||||
// Adjust user visible volume to a gain value in the range [0, 1]
|
||||
// Pow is used to also adjust the volume to a logarithmic scale (as perceived by us humans)
|
||||
const gain = Math.pow(volume / 100, 2);
|
||||
setGlobalGain(gain);
|
||||
}
|
||||
|
||||
export function setVersionDefaultsFrom(code) {
|
||||
try {
|
||||
const metadata = getMetadata(code);
|
||||
|
||||
@@ -28,6 +28,7 @@ export const defaultSettings = {
|
||||
panelPosition: 'right',
|
||||
userPatterns: '{}',
|
||||
audioDeviceName: defaultAudioDeviceName,
|
||||
audioVolume: 50
|
||||
};
|
||||
|
||||
let search = null;
|
||||
|
||||
Reference in New Issue
Block a user