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:
Martín (Netux) Rodríguez
2024-08-18 02:14:03 -03:00
parent 3945abd7e9
commit c6e1f758be
5 changed files with 40 additions and 6 deletions
+8
View File
@@ -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>
+8 -3
View File
@@ -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);
}, []);
//
+8 -1
View File
@@ -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);
+1
View File
@@ -28,6 +28,7 @@ export const defaultSettings = {
panelPosition: 'right',
userPatterns: '{}',
audioDeviceName: defaultAudioDeviceName,
audioVolume: 50
};
let search = null;