Fix: notification sound preview - base-path prefix + longer default beep
The sound picker's preview always played the default beep, even for the other choices, on a subpath deployment. playFile() used a raw '/notification/x.mp3' path, which 404s under a deployment base path (e.g. /webmail); audio.play() then rejected and fell back to the beep for every non-default choice. Prefix the file with withBasePath(). The default beep was a 150 ms tone with no envelope - easy to miss on Bluetooth outputs, whose audio path can take 100-200 ms to wake up and route. Lengthen it to ~0.45 s with a fade in/out (also removes click artifacts).
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
import { debug } from '@/lib/debug';
|
import { debug } from '@/lib/debug';
|
||||||
|
import { withBasePath } from '@/lib/browser-navigation';
|
||||||
|
|
||||||
export type NotificationSoundChoice = 'default' | 'cheerful' | 'involved' | 'swift' | 'relax';
|
export type NotificationSoundChoice = 'default' | 'cheerful' | 'involved' | 'swift' | 'relax';
|
||||||
|
|
||||||
@@ -20,15 +21,29 @@ function playBeep() {
|
|||||||
|
|
||||||
oscillator.frequency.value = 800;
|
oscillator.frequency.value = 800;
|
||||||
oscillator.type = 'sine';
|
oscillator.type = 'sine';
|
||||||
gainNode.gain.value = 0.1;
|
|
||||||
|
|
||||||
oscillator.start();
|
// Longer, enveloped tone. A 150 ms blip was easy to miss on Bluetooth
|
||||||
oscillator.stop(audioContext.currentTime + 0.15);
|
// outputs, whose audio path can take 100-200 ms to wake up and route - by
|
||||||
|
// the time sound reached the headphones the blip was already over. The
|
||||||
|
// fade in/out also avoids click artifacts.
|
||||||
|
const now = audioContext.currentTime;
|
||||||
|
const duration = 0.45;
|
||||||
|
const peak = 0.12;
|
||||||
|
gainNode.gain.setValueAtTime(0.0001, now);
|
||||||
|
gainNode.gain.exponentialRampToValueAtTime(peak, now + 0.04);
|
||||||
|
gainNode.gain.setValueAtTime(peak, now + duration - 0.08);
|
||||||
|
gainNode.gain.exponentialRampToValueAtTime(0.0001, now + duration);
|
||||||
|
|
||||||
|
oscillator.start(now);
|
||||||
|
oscillator.stop(now + duration + 0.02);
|
||||||
oscillator.onended = () => audioContext.close();
|
oscillator.onended = () => audioContext.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
function playFile(file: string) {
|
function playFile(file: string) {
|
||||||
const audio = new Audio(file);
|
// Prefix with the deployment base path (e.g. /webmail); a raw "/notification/
|
||||||
|
// x.mp3" 404s under a subpath, which made playFile fall back to the beep for
|
||||||
|
// every choice.
|
||||||
|
const audio = new Audio(withBasePath(file));
|
||||||
audio.volume = 0.3;
|
audio.volume = 0.3;
|
||||||
audio.play().catch((e) => {
|
audio.play().catch((e) => {
|
||||||
debug.log('push', 'Could not play audio file, falling back to beep:', e);
|
debug.log('push', 'Could not play audio file, falling back to beep:', e);
|
||||||
|
|||||||
Reference in New Issue
Block a user