super-productivity/src/app/util/audio-context.ts
Johannes Millan b69dded9f1 chore(deps): update minor/patch dependencies
- prettier: 3.5.1 → 3.7.4
- pretty-quick: 4.1.1 → 4.2.2
- stylelint: 16.18.0 → 16.26.1
- @playwright/test: 1.56.1 → 1.57.0
- jasmine-core: 5.10.0 → 5.13.0
- eslint-plugin-prettier: 5.2.1 → 5.5.4
- chrono-node: 2.8.3 → 2.9.0
- ical.js: 2.1.0 → 2.2.1
- electron-builder: 26.3.3 → 26.4.0
- core-js: 3.39.0 → 3.47.0
- And other minor updates

Applied prettier formatting changes from v3.7.4.
2026-01-10 16:16:47 +01:00

66 lines
1.9 KiB
TypeScript

/**
* Singleton AudioContext manager to avoid creating multiple AudioContext instances.
* This prevents memory leaks and browser resource exhaustion when playing sounds frequently.
*/
let audioContext: AudioContext | null = null;
const audioBufferCache = new Map<string, AudioBuffer>();
/**
* Returns the singleton AudioContext instance, creating it if necessary.
* Handles the AudioContext suspended state that can occur due to browser autoplay policies.
*/
export const getAudioContext = (): AudioContext => {
if (!audioContext) {
audioContext = new (
(window as any).AudioContext || (window as any).webkitAudioContext
)();
}
// Resume if suspended (can happen due to browser autoplay policies)
// Intentionally fire-and-forget - audio playback is async anyway
if (audioContext && audioContext.state === 'suspended') {
audioContext.resume();
}
return audioContext!;
};
/**
* Retrieves a cached audio buffer or fetches and decodes it if not cached.
* @param filePath - Path to the audio file
* @returns Promise resolving to the decoded AudioBuffer
*/
export const getAudioBuffer = async (filePath: string): Promise<AudioBuffer> => {
const cached = audioBufferCache.get(filePath);
if (cached) {
return cached;
}
const ctx = getAudioContext();
const response = await fetch(filePath);
const arrayBuffer = await response.arrayBuffer();
const audioBuffer = await ctx.decodeAudioData(arrayBuffer);
audioBufferCache.set(filePath, audioBuffer);
return audioBuffer;
};
/**
* Clears the audio buffer cache. Useful for testing or memory management.
*/
export const clearAudioBufferCache = (): void => {
audioBufferCache.clear();
};
/**
* Closes the AudioContext and clears all caches.
* Should only be called when audio is no longer needed (e.g., app shutdown).
*/
export const closeAudioContext = (): void => {
if (audioContext) {
audioContext.close();
audioContext = null;
}
audioBufferCache.clear();
};