add: global cat volumes
This commit is contained in:
@@ -3,6 +3,12 @@ import { logger } from "@/utils/core/logger";
|
|||||||
export type AudioCategory = "music" | "sfx" | "dialogue";
|
export type AudioCategory = "music" | "sfx" | "dialogue";
|
||||||
export type OneShotAudioCategory = Exclude<AudioCategory, "music">;
|
export type OneShotAudioCategory = Exclude<AudioCategory, "music">;
|
||||||
|
|
||||||
|
const DEFAULT_CATEGORY_VOLUMES: Record<AudioCategory, number> = {
|
||||||
|
music: 1,
|
||||||
|
sfx: 1,
|
||||||
|
dialogue: 1,
|
||||||
|
};
|
||||||
|
|
||||||
interface PlaySoundOptions {
|
interface PlaySoundOptions {
|
||||||
category?: OneShotAudioCategory;
|
category?: OneShotAudioCategory;
|
||||||
playbackRate?: number;
|
playbackRate?: number;
|
||||||
@@ -11,8 +17,12 @@ interface PlaySoundOptions {
|
|||||||
export class AudioManager {
|
export class AudioManager {
|
||||||
private static _instance: AudioManager | null = null;
|
private static _instance: AudioManager | null = null;
|
||||||
private readonly _audioPools = new Map<string, HTMLAudioElement[]>();
|
private readonly _audioPools = new Map<string, HTMLAudioElement[]>();
|
||||||
|
private readonly _categoryVolumes: Record<AudioCategory, number> = {
|
||||||
|
...DEFAULT_CATEGORY_VOLUMES,
|
||||||
|
};
|
||||||
private _music: HTMLAudioElement | null = null;
|
private _music: HTMLAudioElement | null = null;
|
||||||
private _musicPath: string | null = null;
|
private _musicPath: string | null = null;
|
||||||
|
private _musicVolume = 1;
|
||||||
private _musicUnlockHandler: (() => void) | null = null;
|
private _musicUnlockHandler: (() => void) | null = null;
|
||||||
|
|
||||||
private static readonly MAX_POOL_SIZE_PER_SOUND = 6;
|
private static readonly MAX_POOL_SIZE_PER_SOUND = 6;
|
||||||
@@ -32,10 +42,22 @@ export class AudioManager {
|
|||||||
|
|
||||||
private constructor() {}
|
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 {
|
playSound(path: string, volume = 1, options: PlaySoundOptions = {}): void {
|
||||||
const audio = this._acquireAudio(path);
|
const audio = this._acquireAudio(path);
|
||||||
const category = options.category ?? AudioManager.DEFAULT_SOUND_CATEGORY;
|
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.playbackRate = options.playbackRate ?? 1;
|
||||||
audio.currentTime = 0;
|
audio.currentTime = 0;
|
||||||
|
|
||||||
@@ -56,8 +78,10 @@ export class AudioManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
playMusic(path: string, volume = 1): void {
|
playMusic(path: string, volume = 1): void {
|
||||||
|
this._musicVolume = AudioManager._clampVolume(volume);
|
||||||
|
|
||||||
if (this._musicPath === path && this._music) {
|
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;
|
if (!this._music.paused) return;
|
||||||
} else {
|
} else {
|
||||||
this.stopMusic();
|
this.stopMusic();
|
||||||
@@ -66,7 +90,7 @@ export class AudioManager {
|
|||||||
this._musicPath = path;
|
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) => {
|
void this._music.play().catch((error: unknown) => {
|
||||||
if (
|
if (
|
||||||
@@ -151,6 +175,14 @@ export class AudioManager {
|
|||||||
this._musicUnlockHandler = null;
|
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 {
|
private static _toLogValue(error: unknown): Error | DOMException | string {
|
||||||
if (error instanceof Error || error instanceof DOMException) {
|
if (error instanceof Error || error instanceof DOMException) {
|
||||||
return error;
|
return error;
|
||||||
|
|||||||
Reference in New Issue
Block a user