add: global cat volumes

This commit is contained in:
Tom Boullay
2026-05-09 23:37:07 +01:00
parent e0adb84eca
commit 41cb61ae2d
+35 -3
View File
@@ -3,6 +3,12 @@ import { logger } from "@/utils/core/logger";
export type AudioCategory = "music" | "sfx" | "dialogue";
export type OneShotAudioCategory = Exclude<AudioCategory, "music">;
const DEFAULT_CATEGORY_VOLUMES: Record<AudioCategory, number> = {
music: 1,
sfx: 1,
dialogue: 1,
};
interface PlaySoundOptions {
category?: OneShotAudioCategory;
playbackRate?: number;
@@ -11,8 +17,12 @@ interface PlaySoundOptions {
export class AudioManager {
private static _instance: AudioManager | null = null;
private readonly _audioPools = new Map<string, HTMLAudioElement[]>();
private readonly _categoryVolumes: Record<AudioCategory, number> = {
...DEFAULT_CATEGORY_VOLUMES,
};
private _music: HTMLAudioElement | null = null;
private _musicPath: string | null = null;
private _musicVolume = 1;
private _musicUnlockHandler: (() => void) | null = null;
private static readonly MAX_POOL_SIZE_PER_SOUND = 6;
@@ -32,10 +42,22 @@ export class AudioManager {
private constructor() {}
setCategoryVolume(category: AudioCategory, volume: number): void {
this._categoryVolumes[category] = AudioManager._clampVolume(volume);
if (category === "music" && this._music) {
this._music.volume = this._getEffectiveVolume("music", this._musicVolume);
}
}
getCategoryVolume(category: AudioCategory): number {
return this._categoryVolumes[category];
}
playSound(path: string, volume = 1, options: PlaySoundOptions = {}): void {
const audio = this._acquireAudio(path);
const category = options.category ?? AudioManager.DEFAULT_SOUND_CATEGORY;
audio.volume = Math.max(0, Math.min(1, volume));
audio.volume = this._getEffectiveVolume(category, volume);
audio.playbackRate = options.playbackRate ?? 1;
audio.currentTime = 0;
@@ -56,8 +78,10 @@ export class AudioManager {
}
playMusic(path: string, volume = 1): void {
this._musicVolume = AudioManager._clampVolume(volume);
if (this._musicPath === path && this._music) {
this._music.volume = Math.max(0, Math.min(1, volume));
this._music.volume = this._getEffectiveVolume("music", this._musicVolume);
if (!this._music.paused) return;
} else {
this.stopMusic();
@@ -66,7 +90,7 @@ export class AudioManager {
this._musicPath = path;
}
this._music.volume = Math.max(0, Math.min(1, volume));
this._music.volume = this._getEffectiveVolume("music", this._musicVolume);
void this._music.play().catch((error: unknown) => {
if (
@@ -151,6 +175,14 @@ export class AudioManager {
this._musicUnlockHandler = null;
}
private _getEffectiveVolume(category: AudioCategory, volume: number): number {
return AudioManager._clampVolume(volume) * this._categoryVolumes[category];
}
private static _clampVolume(volume: number): number {
return Math.max(0, Math.min(1, volume));
}
private static _toLogValue(error: unknown): Error | DOMException | string {
if (error instanceof Error || error instanceof DOMException) {
return error;