audio-channel-queue 1.12.0 → 1.12.1-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -5,20 +5,20 @@ The purpose of this package is to help manage the playback of audio files.
5
5
 
6
6
  📚 [Docs](https://tonycarpenter21.github.io/audio-queue-docs/)
7
7
 
8
- ## 🌟 Key Features
8
+ ## Key Features
9
9
 
10
- - **Multi-channel queue management** - Independent audio queues for concurrent playback
11
- - **Pause/Resume functionality** - Full playback control for individual channels or all channels
12
- - **Volume control with ducking** - Dynamic volume management and automatic background audio reduction
13
- - **Loop support** - Seamless audio looping for background music and ambient sounds
14
- - **Priority queueing** - Add urgent audio to the front of any queue
15
- - **Real-time progress tracking** - Comprehensive playback monitoring and metadata
16
- - **Event-driven architecture** - Extensive callback system for UI integration
17
- - **TypeScript support** - Full type definitions and IntelliSense support
18
- - **Zero dependencies** - Lightweight and self-contained
19
- - **Backward compatible** - All existing APIs continue to work
10
+ - **Multi-channel queue management** - Independent audio queues for concurrent playback
11
+ - **Pause/Resume functionality** - Full playback control for individual channels or all channels
12
+ - **Volume control with ducking** - Dynamic volume management, global volume control, and automatic background audio reduction
13
+ - **Loop support** - Seamless audio looping for background music and ambient sounds
14
+ - **Priority queueing** - Add urgent audio to the front of any queue
15
+ - **Real-time progress tracking** - Comprehensive playback monitoring and metadata
16
+ - **Event-driven architecture** - Extensive callback system for UI integration
17
+ - **TypeScript support** - Full type definitions and IntelliSense support
18
+ - **Zero dependencies** - Lightweight and self-contained
19
+ - **Backward compatible** - All existing APIs continue to work
20
20
 
21
- This package offers TypeScript support 📘, boasts zero dependencies 🚫, and is released under the MIT license 📜. As an added bonus, it's NON-GMO 🌱 and 100% Free Range Organic 🐓.
21
+ This package offers TypeScript support, has zero dependencies, and is released under the MIT license.
22
22
 
23
23
  To preview this package and see how it works with visualized code examples, check out the demo that can be found here: [Audio Channel Queue Demo](https://tonycarpenter21.github.io/audio-queue-demo/). (A link to the demo repo can be found here: [Audio Channel Queue Demo Repo](https://github.com/tonycarpenter21/audio-queue-demo).)
24
24
 
@@ -32,18 +32,18 @@ Documentation can be found [here](https://tonycarpenter21.github.io/audio-queue-
32
32
 
33
33
  This package is designed for **browser environments** and uses the Web Audio API (`HTMLAudioElement`). It is **not** intended for Node.js server-side use.
34
34
 
35
- ### **Supported Browsers:**
35
+ ### **Supported Browsers:**
36
36
  - **Chrome 51+** (June 2016)
37
37
  - **Firefox 54+** (June 2017)
38
38
  - **Safari 10+** (September 2016)
39
39
  - **Edge 15+** (April 2017)
40
40
  - **Mobile browsers** with HTML5 audio support
41
41
 
42
- ### 🛠️ **Development Requirements:**
42
+ ### **Development Requirements:**
43
43
  - **Node.js 14+** (for building and testing only)
44
44
  - **TypeScript 4.5+** (included in devDependencies)
45
45
 
46
- ### ⚠️ **Not Supported:**
46
+ ### **Not Supported:**
47
47
  - Node.js server environments (no HTMLAudioElement)
48
48
  - Internet Explorer (lacks ES6 support)
49
49
  - Web Workers (no DOM access)
@@ -197,6 +197,47 @@ await setAllChannelsVolume(0.6); // Set all channels to 60% volume
197
197
  await setAllChannelsVolume(0.0); // Mute all channels
198
198
  ```
199
199
 
200
+ ### Global Volume Control
201
+ ```typescript
202
+ // Set a global volume multiplier that affects all channels while preserving their relative levels.
203
+ setGlobalVolume(volume);
204
+ await setGlobalVolume(0.5); // Set global volume to 50%
205
+ ```
206
+
207
+ ```typescript
208
+ // Get the current global volume level.
209
+ getGlobalVolume();
210
+ const globalVol = getGlobalVolume(); // Returns current global volume (0-1)
211
+ console.log(`Global volume: ${(getGlobalVolume() * 100).toFixed(0)}%`);
212
+ ```
213
+
214
+ **How Global Volume Works:**
215
+ The global volume acts as a **global volume multiplier** - it scales all channel volumes proportionally while preserving their individual settings. This is perfect for implementing a global volume slider in your UI.
216
+
217
+ ```typescript
218
+ // Example: Setting up different audio types with a global volume control
219
+ await setChannelVolume(0, 0.3); // SFX channel at 30%
220
+ await setChannelVolume(1, 0.7); // Music channel at 70%
221
+ await setChannelVolume(2, 0.5); // Voice channel at 50%
222
+
223
+ // User adjusts global volume slider to 50%
224
+ await setGlobalVolume(0.5);
225
+
226
+ // Actual playback volumes become:
227
+ // - SFX: 30% × 50% = 15%
228
+ // - Music: 70% × 50% = 35%
229
+ // - Voice: 50% × 50% = 25%
230
+
231
+ // Channel volumes remain at their original settings (0.3, 0.7, 0.5)
232
+ // So when global volume is increased, ratios are preserved
233
+ await setGlobalVolume(1.0); // Back to full volume
234
+ // - SFX: 30% × 100% = 30%
235
+ // - Music: 70% × 100% = 70%
236
+ // - Voice: 50% × 100% = 50%
237
+ ```
238
+
239
+ **Note:** `setAllChannelsVolume()` sets all channels to the **same** volume, while `setGlobalVolume()` **multiplies** all channels by the same amount, preserving their relative differences.
240
+
200
241
  ### Volume Ducking (Background Audio Reduction)
201
242
  ```typescript
202
243
  // Automatically reduce other channels' volume when priority audio plays.
package/dist/core.js CHANGED
@@ -244,6 +244,8 @@ const queueAudio = (audioUrl_1, ...args_1) => __awaiter(void 0, [audioUrl_1, ...
244
244
  (0, errors_1.setupAudioErrorHandling)(audio, channelNumber, validatedUrl, (error) => __awaiter(void 0, void 0, void 0, function* () {
245
245
  yield (0, errors_1.handleAudioError)(audio, channelNumber, validatedUrl, error);
246
246
  }));
247
+ // Initialize Web Audio API support if needed
248
+ yield (0, volume_1.initializeWebAudioForAudio)(audio, channelNumber);
247
249
  // Apply options if provided
248
250
  if (options) {
249
251
  if (typeof options.loop === 'boolean') {
@@ -378,6 +380,7 @@ const playAudioQueue = (channelNumber) => __awaiter(void 0, void 0, void 0, func
378
380
  // For non-looping audio, remove from queue and play next
379
381
  currentAudio.pause();
380
382
  (0, events_1.cleanupProgressTracking)(currentAudio, channelNumber, info_1.audioChannels);
383
+ (0, volume_1.cleanupWebAudioForAudio)(currentAudio, channelNumber);
381
384
  channel.queue.shift();
382
385
  channel.isPaused = false; // Reset pause state
383
386
  // Restore volume levels AFTER removing audio from queue
package/dist/errors.js CHANGED
@@ -56,7 +56,6 @@ let globalErrorRecovery = {
56
56
  showUserFeedback: false
57
57
  };
58
58
  const retryAttempts = new WeakMap();
59
- const loadTimeouts = new WeakMap();
60
59
  /**
61
60
  * Subscribes to audio error events for a specific channel
62
61
  * @param channelNumber - The channel number to listen to (defaults to 0)
@@ -306,37 +305,9 @@ const setupAudioErrorHandling = (audio, channelNumber, originalUrl, onError) =>
306
305
  const channel = info_1.audioChannels[channelNumber];
307
306
  if (!channel)
308
307
  return;
309
- // Set up loading timeout with test environment compatibility
310
- let timeoutId;
311
- if (typeof setTimeout !== 'undefined') {
312
- timeoutId = setTimeout(() => {
313
- if (audio.networkState === HTMLMediaElement.NETWORK_LOADING) {
314
- const timeoutError = new Error(`Audio loading timeout after ${globalRetryConfig.timeoutMs}ms`);
315
- (0, exports.handleAudioError)(audio, channelNumber, originalUrl, timeoutError);
316
- }
317
- }, globalRetryConfig.timeoutMs);
318
- loadTimeouts.set(audio, timeoutId);
319
- }
320
- // Clear timeout when metadata loads successfully
321
- const handleLoadSuccess = () => {
322
- if (typeof setTimeout !== 'undefined') {
323
- const timeoutId = loadTimeouts.get(audio);
324
- if (timeoutId) {
325
- clearTimeout(timeoutId);
326
- loadTimeouts.delete(audio);
327
- }
328
- }
329
- };
330
308
  // Handle various error events
331
309
  const handleError = (_event) => {
332
310
  var _a;
333
- if (typeof setTimeout !== 'undefined') {
334
- const timeoutId = loadTimeouts.get(audio);
335
- if (timeoutId) {
336
- clearTimeout(timeoutId);
337
- loadTimeouts.delete(audio);
338
- }
339
- }
340
311
  const error = new Error(`Audio loading failed: ${((_a = audio.error) === null || _a === void 0 ? void 0 : _a.message) || 'Unknown error'}`);
341
312
  (0, exports.handleAudioError)(audio, channelNumber, originalUrl, error);
342
313
  };
@@ -352,8 +323,6 @@ const setupAudioErrorHandling = (audio, channelNumber, originalUrl, onError) =>
352
323
  audio.addEventListener('error', handleError);
353
324
  audio.addEventListener('abort', handleAbort);
354
325
  audio.addEventListener('stalled', handleStall);
355
- audio.addEventListener('loadedmetadata', handleLoadSuccess);
356
- audio.addEventListener('canplay', handleLoadSuccess);
357
326
  // Custom play error handling
358
327
  if (onError) {
359
328
  const originalPlay = audio.play.bind(audio);
@@ -451,19 +420,10 @@ exports.handleAudioError = handleAudioError;
451
420
  const createProtectedAudioElement = (url, channelNumber) => __awaiter(void 0, void 0, void 0, function* () {
452
421
  const audio = new Audio();
453
422
  return new Promise((resolve, reject) => {
454
- const cleanup = () => {
455
- const timeoutId = loadTimeouts.get(audio);
456
- if (timeoutId) {
457
- clearTimeout(timeoutId);
458
- loadTimeouts.delete(audio);
459
- }
460
- };
461
423
  const handleSuccess = () => {
462
- cleanup();
463
424
  resolve(audio);
464
425
  };
465
426
  const handleError = (error) => {
466
- cleanup();
467
427
  reject(error);
468
428
  };
469
429
  // Set up error handling
package/dist/index.d.ts CHANGED
@@ -7,9 +7,10 @@ export { queueAudio, queueAudioPriority, stopCurrentAudioInChannel, stopAllAudio
7
7
  export { clearQueueAfterCurrent, getQueueItemInfo, getQueueLength, removeQueuedItem, reorderQueue, swapQueueItems } from './queue-manipulation';
8
8
  export { getErrorRecovery, getRetryConfig, offAudioError, onAudioError, retryFailedAudio, setErrorRecovery, setRetryConfig } from './errors';
9
9
  export { getAllChannelsPauseState, isChannelPaused, pauseAllChannels, pauseAllWithFade, pauseChannel, pauseWithFade, resumeAllChannels, resumeAllWithFade, resumeChannel, resumeWithFade, togglePauseAllChannels, togglePauseAllWithFade, togglePauseChannel, togglePauseWithFade } from './pause';
10
- export { cancelAllVolumeTransitions, cancelVolumeTransition, clearVolumeDucking, getAllChannelsVolume, getChannelVolume, getFadeConfig, setAllChannelsVolume, setChannelVolume, setVolumeDucking, transitionVolume } from './volume';
10
+ export { cancelAllVolumeTransitions, cancelVolumeTransition, clearVolumeDucking, getAllChannelsVolume, getChannelVolume, getFadeConfig, getGlobalVolume, setAllChannelsVolume, setChannelVolume, setGlobalVolume, setVolumeDucking, transitionVolume } from './volume';
11
+ export { cleanupWebAudioNodes, createWebAudioNodes, getAudioContext, getWebAudioConfig, getWebAudioSupport, getWebAudioVolume, isIOSDevice, isWebAudioSupported, resumeAudioContext, setWebAudioConfig, setWebAudioVolume, shouldUseWebAudio } from './web-audio';
11
12
  export { getAllChannelsInfo, getCurrentAudioInfo, getQueueSnapshot, offAudioComplete, offAudioPause, offAudioProgress, offAudioResume, offAudioStart, offQueueChange, onAudioComplete, onAudioPause, onAudioProgress, onAudioResume, onAudioStart, onQueueChange } from './info';
12
13
  export { audioChannels } from './info';
13
14
  export { cleanWebpackFilename, createQueueSnapshot, extractFileName, getAudioInfoFromElement, sanitizeForDisplay, validateAudioUrl } from './utils';
14
- export type { AudioCompleteCallback, AudioCompleteInfo, AudioErrorCallback, AudioErrorInfo, AudioInfo, AudioPauseCallback, AudioQueueOptions, AudioResumeCallback, AudioStartCallback, AudioStartInfo, ChannelFadeState, ErrorRecoveryOptions, ExtendedAudioQueueChannel, FadeConfig, ProgressCallback, QueueChangeCallback, QueueItem, QueueManipulationResult, QueueSnapshot, RetryConfig, VolumeConfig, QueueConfig } from './types';
15
+ export type { AudioCompleteCallback, AudioCompleteInfo, AudioErrorCallback, AudioErrorInfo, AudioInfo, AudioPauseCallback, AudioQueueOptions, AudioResumeCallback, AudioStartCallback, AudioStartInfo, ChannelFadeState, ErrorRecoveryOptions, ExtendedAudioQueueChannel, FadeConfig, ProgressCallback, QueueChangeCallback, QueueConfig, QueueItem, QueueManipulationResult, QueueSnapshot, RetryConfig, VolumeConfig, WebAudioConfig, WebAudioNodeSet, WebAudioSupport } from './types';
15
16
  export { AudioErrorType, EasingType, FadeType, MAX_CHANNELS, TimerType, GLOBAL_PROGRESS_KEY } from './types';
package/dist/index.js CHANGED
@@ -5,8 +5,8 @@
5
5
  * volume management with ducking, progress tracking, and comprehensive event system
6
6
  */
7
7
  Object.defineProperty(exports, "__esModule", { value: true });
8
- exports.getCurrentAudioInfo = exports.getAllChannelsInfo = exports.transitionVolume = exports.setVolumeDucking = exports.setChannelVolume = exports.setAllChannelsVolume = exports.getFadeConfig = exports.getChannelVolume = exports.getAllChannelsVolume = exports.clearVolumeDucking = exports.cancelVolumeTransition = exports.cancelAllVolumeTransitions = exports.togglePauseWithFade = exports.togglePauseChannel = exports.togglePauseAllWithFade = exports.togglePauseAllChannels = exports.resumeWithFade = exports.resumeChannel = exports.resumeAllWithFade = exports.resumeAllChannels = exports.pauseWithFade = exports.pauseChannel = exports.pauseAllWithFade = exports.pauseAllChannels = exports.isChannelPaused = exports.getAllChannelsPauseState = exports.setRetryConfig = exports.setErrorRecovery = exports.retryFailedAudio = exports.onAudioError = exports.offAudioError = exports.getRetryConfig = exports.getErrorRecovery = exports.swapQueueItems = exports.reorderQueue = exports.removeQueuedItem = exports.getQueueLength = exports.getQueueItemInfo = exports.clearQueueAfterCurrent = exports.setChannelQueueLimit = exports.getQueueConfig = exports.setQueueConfig = exports.destroyAllChannels = exports.destroyChannel = exports.playAudioQueue = exports.stopAllAudio = exports.stopAllAudioInChannel = exports.stopCurrentAudioInChannel = exports.queueAudioPriority = exports.queueAudio = void 0;
9
- exports.GLOBAL_PROGRESS_KEY = exports.TimerType = exports.MAX_CHANNELS = exports.FadeType = exports.EasingType = exports.AudioErrorType = exports.validateAudioUrl = exports.sanitizeForDisplay = exports.getAudioInfoFromElement = exports.extractFileName = exports.createQueueSnapshot = exports.cleanWebpackFilename = exports.audioChannels = exports.onQueueChange = exports.onAudioStart = exports.onAudioResume = exports.onAudioProgress = exports.onAudioPause = exports.onAudioComplete = exports.offQueueChange = exports.offAudioStart = exports.offAudioResume = exports.offAudioProgress = exports.offAudioPause = exports.offAudioComplete = exports.getQueueSnapshot = void 0;
8
+ exports.transitionVolume = exports.setVolumeDucking = exports.setGlobalVolume = exports.setChannelVolume = exports.setAllChannelsVolume = exports.getGlobalVolume = exports.getFadeConfig = exports.getChannelVolume = exports.getAllChannelsVolume = exports.clearVolumeDucking = exports.cancelVolumeTransition = exports.cancelAllVolumeTransitions = exports.togglePauseWithFade = exports.togglePauseChannel = exports.togglePauseAllWithFade = exports.togglePauseAllChannels = exports.resumeWithFade = exports.resumeChannel = exports.resumeAllWithFade = exports.resumeAllChannels = exports.pauseWithFade = exports.pauseChannel = exports.pauseAllWithFade = exports.pauseAllChannels = exports.isChannelPaused = exports.getAllChannelsPauseState = exports.setRetryConfig = exports.setErrorRecovery = exports.retryFailedAudio = exports.onAudioError = exports.offAudioError = exports.getRetryConfig = exports.getErrorRecovery = exports.swapQueueItems = exports.reorderQueue = exports.removeQueuedItem = exports.getQueueLength = exports.getQueueItemInfo = exports.clearQueueAfterCurrent = exports.setChannelQueueLimit = exports.getQueueConfig = exports.setQueueConfig = exports.destroyAllChannels = exports.destroyChannel = exports.playAudioQueue = exports.stopAllAudio = exports.stopAllAudioInChannel = exports.stopCurrentAudioInChannel = exports.queueAudioPriority = exports.queueAudio = void 0;
9
+ exports.GLOBAL_PROGRESS_KEY = exports.TimerType = exports.MAX_CHANNELS = exports.FadeType = exports.EasingType = exports.AudioErrorType = exports.validateAudioUrl = exports.sanitizeForDisplay = exports.getAudioInfoFromElement = exports.extractFileName = exports.createQueueSnapshot = exports.cleanWebpackFilename = exports.audioChannels = exports.onQueueChange = exports.onAudioStart = exports.onAudioResume = exports.onAudioProgress = exports.onAudioPause = exports.onAudioComplete = exports.offQueueChange = exports.offAudioStart = exports.offAudioResume = exports.offAudioProgress = exports.offAudioPause = exports.offAudioComplete = exports.getQueueSnapshot = exports.getCurrentAudioInfo = exports.getAllChannelsInfo = exports.shouldUseWebAudio = exports.setWebAudioVolume = exports.setWebAudioConfig = exports.resumeAudioContext = exports.isWebAudioSupported = exports.isIOSDevice = exports.getWebAudioVolume = exports.getWebAudioSupport = exports.getWebAudioConfig = exports.getAudioContext = exports.createWebAudioNodes = exports.cleanupWebAudioNodes = void 0;
10
10
  // Core queue management functions
11
11
  var core_1 = require("./core");
12
12
  Object.defineProperty(exports, "queueAudio", { enumerable: true, get: function () { return core_1.queueAudio; } });
@@ -61,10 +61,26 @@ Object.defineProperty(exports, "clearVolumeDucking", { enumerable: true, get: fu
61
61
  Object.defineProperty(exports, "getAllChannelsVolume", { enumerable: true, get: function () { return volume_1.getAllChannelsVolume; } });
62
62
  Object.defineProperty(exports, "getChannelVolume", { enumerable: true, get: function () { return volume_1.getChannelVolume; } });
63
63
  Object.defineProperty(exports, "getFadeConfig", { enumerable: true, get: function () { return volume_1.getFadeConfig; } });
64
+ Object.defineProperty(exports, "getGlobalVolume", { enumerable: true, get: function () { return volume_1.getGlobalVolume; } });
64
65
  Object.defineProperty(exports, "setAllChannelsVolume", { enumerable: true, get: function () { return volume_1.setAllChannelsVolume; } });
65
66
  Object.defineProperty(exports, "setChannelVolume", { enumerable: true, get: function () { return volume_1.setChannelVolume; } });
67
+ Object.defineProperty(exports, "setGlobalVolume", { enumerable: true, get: function () { return volume_1.setGlobalVolume; } });
66
68
  Object.defineProperty(exports, "setVolumeDucking", { enumerable: true, get: function () { return volume_1.setVolumeDucking; } });
67
69
  Object.defineProperty(exports, "transitionVolume", { enumerable: true, get: function () { return volume_1.transitionVolume; } });
70
+ // Web Audio API support functions
71
+ var web_audio_1 = require("./web-audio");
72
+ Object.defineProperty(exports, "cleanupWebAudioNodes", { enumerable: true, get: function () { return web_audio_1.cleanupWebAudioNodes; } });
73
+ Object.defineProperty(exports, "createWebAudioNodes", { enumerable: true, get: function () { return web_audio_1.createWebAudioNodes; } });
74
+ Object.defineProperty(exports, "getAudioContext", { enumerable: true, get: function () { return web_audio_1.getAudioContext; } });
75
+ Object.defineProperty(exports, "getWebAudioConfig", { enumerable: true, get: function () { return web_audio_1.getWebAudioConfig; } });
76
+ Object.defineProperty(exports, "getWebAudioSupport", { enumerable: true, get: function () { return web_audio_1.getWebAudioSupport; } });
77
+ Object.defineProperty(exports, "getWebAudioVolume", { enumerable: true, get: function () { return web_audio_1.getWebAudioVolume; } });
78
+ Object.defineProperty(exports, "isIOSDevice", { enumerable: true, get: function () { return web_audio_1.isIOSDevice; } });
79
+ Object.defineProperty(exports, "isWebAudioSupported", { enumerable: true, get: function () { return web_audio_1.isWebAudioSupported; } });
80
+ Object.defineProperty(exports, "resumeAudioContext", { enumerable: true, get: function () { return web_audio_1.resumeAudioContext; } });
81
+ Object.defineProperty(exports, "setWebAudioConfig", { enumerable: true, get: function () { return web_audio_1.setWebAudioConfig; } });
82
+ Object.defineProperty(exports, "setWebAudioVolume", { enumerable: true, get: function () { return web_audio_1.setWebAudioVolume; } });
83
+ Object.defineProperty(exports, "shouldUseWebAudio", { enumerable: true, get: function () { return web_audio_1.shouldUseWebAudio; } });
68
84
  // Audio information and progress tracking functions
69
85
  var info_1 = require("./info");
70
86
  Object.defineProperty(exports, "getAllChannelsInfo", { enumerable: true, get: function () { return info_1.getAllChannelsInfo; } });
package/dist/types.d.ts CHANGED
@@ -260,6 +260,39 @@ export interface ErrorRecoveryOptions {
260
260
  * Callback function type for audio error events
261
261
  */
262
262
  export type AudioErrorCallback = (errorInfo: AudioErrorInfo) => void;
263
+ /**
264
+ * Web Audio API configuration options
265
+ */
266
+ export interface WebAudioConfig {
267
+ /** Whether to automatically use Web Audio API on iOS devices */
268
+ autoDetectIOS: boolean;
269
+ /** Whether Web Audio API support is enabled */
270
+ enabled: boolean;
271
+ /** Whether to force Web Audio API usage on all devices */
272
+ forceWebAudio: boolean;
273
+ }
274
+ /**
275
+ * Web Audio API support information
276
+ */
277
+ export interface WebAudioSupport {
278
+ /** Whether Web Audio API is available in the current environment */
279
+ available: boolean;
280
+ /** Whether the current device is iOS */
281
+ isIOS: boolean;
282
+ /** Whether Web Audio API is currently being used */
283
+ usingWebAudio: boolean;
284
+ /** Reason for current Web Audio API usage state */
285
+ reason: string;
286
+ }
287
+ /**
288
+ * Web Audio API node set for audio element control
289
+ */
290
+ export interface WebAudioNodeSet {
291
+ /** Gain node for volume control */
292
+ gainNode: GainNode;
293
+ /** Media element source node */
294
+ sourceNode: MediaElementAudioSourceNode;
295
+ }
263
296
  /**
264
297
  * Extended audio channel with comprehensive queue management, callback support, and state tracking
265
298
  */
@@ -292,6 +325,10 @@ export interface ExtendedAudioQueueChannel {
292
325
  retryConfig?: RetryConfig;
293
326
  /** Current volume level for the channel (0-1) */
294
327
  volume: number;
328
+ /** Web Audio API context for this channel */
329
+ webAudioContext?: AudioContext;
330
+ /** Map of Web Audio API nodes for each audio element */
331
+ webAudioNodes?: Map<HTMLAudioElement, WebAudioNodeSet>;
295
332
  }
296
333
  /**
297
334
  * Easing function types for smooth volume transitions and animations
package/dist/volume.d.ts CHANGED
@@ -28,6 +28,7 @@ export declare const getFadeConfig: (fadeType: FadeType) => FadeConfig;
28
28
  export declare const transitionVolume: (channelNumber: number, targetVolume: number, duration?: number, easing?: EasingType) => Promise<void>;
29
29
  /**
30
30
  * Sets the volume for a specific channel with optional smooth transition
31
+ * Automatically uses Web Audio API on iOS devices for enhanced volume control
31
32
  * @param channelNumber - The channel number to set volume for
32
33
  * @param volume - Volume level (0-1)
33
34
  * @param transitionDuration - Optional transition duration in milliseconds
@@ -73,6 +74,31 @@ export declare const getAllChannelsVolume: () => number[];
73
74
  * ```
74
75
  */
75
76
  export declare const setAllChannelsVolume: (volume: number) => Promise<void>;
77
+ /**
78
+ * Sets the global volume multiplier that affects all channels
79
+ * This acts as a global volume control - individual channel volumes are multiplied by this value
80
+ * @param volume - Global volume level (0-1, will be clamped to this range)
81
+ * @example
82
+ * ```typescript
83
+ * // Set channel-specific volumes
84
+ * await setChannelVolume(0, 0.8); // SFX at 80%
85
+ * await setChannelVolume(1, 0.6); // Music at 60%
86
+ *
87
+ * // Apply global volume of 50% - all channels play at half their set volume
88
+ * await setGlobalVolume(0.5); // SFX now plays at 40%, music at 30%
89
+ * ```
90
+ */
91
+ export declare const setGlobalVolume: (volume: number) => Promise<void>;
92
+ /**
93
+ * Gets the current global volume multiplier
94
+ * @returns Current global volume level (0-1), defaults to 1.0
95
+ * @example
96
+ * ```typescript
97
+ * const globalVol = getGlobalVolume();
98
+ * console.log(`Global volume is ${globalVol * 100}%`);
99
+ * ```
100
+ */
101
+ export declare const getGlobalVolume: () => number;
76
102
  /**
77
103
  * Configures volume ducking for channels. When the priority channel plays audio,
78
104
  * all other channels will be automatically reduced to the ducking volume level
@@ -120,3 +146,17 @@ export declare const cancelVolumeTransition: (channelNumber: number) => void;
120
146
  * @internal
121
147
  */
122
148
  export declare const cancelAllVolumeTransitions: () => void;
149
+ /**
150
+ * Initializes Web Audio API nodes for a new audio element
151
+ * @param audio - The audio element to initialize nodes for
152
+ * @param channelNumber - The channel number this audio belongs to
153
+ * @internal
154
+ */
155
+ export declare const initializeWebAudioForAudio: (audio: HTMLAudioElement, channelNumber: number) => Promise<void>;
156
+ /**
157
+ * Cleans up Web Audio API nodes for an audio element
158
+ * @param audio - The audio element to clean up nodes for
159
+ * @param channelNumber - The channel number this audio belongs to
160
+ * @internal
161
+ */
162
+ export declare const cleanupWebAudioForAudio: (audio: HTMLAudioElement, channelNumber: number) => void;