audio-channel-queue 1.7.0 → 1.8.0

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/dist/index.d.ts CHANGED
@@ -5,9 +5,10 @@
5
5
  */
6
6
  export { queueAudio, queueAudioPriority, stopCurrentAudioInChannel, stopAllAudioInChannel, stopAllAudio, playAudioQueue } from './core';
7
7
  export { getErrorRecovery, getRetryConfig, offAudioError, onAudioError, retryFailedAudio, setErrorRecovery, setRetryConfig, } from './errors';
8
- export { getAllChannelsPauseState, isChannelPaused, pauseAllChannels, pauseChannel, resumeAllChannels, resumeChannel, togglePauseAllChannels, togglePauseChannel, } from './pause';
9
- export { clearVolumeDucking, getAllChannelsVolume, getChannelVolume, setAllChannelsVolume, setChannelVolume, setVolumeDucking, } from './volume';
8
+ export { getAllChannelsPauseState, isChannelPaused, pauseAllChannels, pauseAllWithFade, pauseChannel, pauseWithFade, resumeAllChannels, resumeAllWithFade, resumeChannel, resumeWithFade, togglePauseAllChannels, togglePauseAllWithFade, togglePauseChannel, togglePauseWithFade, } from './pause';
9
+ export { clearVolumeDucking, fadeVolume, getAllChannelsVolume, getChannelVolume, getFadeConfig, setAllChannelsVolume, setChannelVolume, setVolumeDucking, transitionVolume, } from './volume';
10
10
  export { getAllChannelsInfo, getCurrentAudioInfo, getQueueSnapshot, offAudioPause, offAudioProgress, offAudioResume, offQueueChange, onAudioComplete, onAudioPause, onAudioProgress, onAudioResume, onAudioStart, onQueueChange, } from './info';
11
11
  export { audioChannels } from './info';
12
12
  export { cleanWebpackFilename, createQueueSnapshot, extractFileName, getAudioInfoFromElement } from './utils';
13
- export type { AudioCompleteCallback, AudioCompleteInfo, AudioErrorCallback, AudioErrorInfo, AudioInfo, AudioPauseCallback, AudioQueueOptions, AudioResumeCallback, AudioStartCallback, AudioStartInfo, ErrorRecoveryOptions, ExtendedAudioQueueChannel, ProgressCallback, QueueChangeCallback, QueueItem, QueueSnapshot, RetryConfig, VolumeConfig } from './types';
13
+ export type { AudioCompleteCallback, AudioCompleteInfo, AudioErrorCallback, AudioErrorInfo, AudioInfo, AudioPauseCallback, AudioQueueOptions, AudioResumeCallback, AudioStartCallback, AudioStartInfo, ChannelFadeState, ErrorRecoveryOptions, ExtendedAudioQueueChannel, FadeConfig, ProgressCallback, QueueChangeCallback, QueueItem, QueueSnapshot, RetryConfig, VolumeConfig } from './types';
14
+ export { EasingType, FadeType } from './types';
package/dist/index.js CHANGED
@@ -5,7 +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.getAudioInfoFromElement = exports.extractFileName = exports.createQueueSnapshot = exports.cleanWebpackFilename = exports.audioChannels = exports.onQueueChange = exports.onAudioStart = exports.onAudioResume = exports.onAudioProgress = exports.onAudioPause = exports.onAudioComplete = exports.offQueueChange = exports.offAudioResume = exports.offAudioProgress = exports.offAudioPause = exports.getQueueSnapshot = exports.getCurrentAudioInfo = exports.getAllChannelsInfo = exports.setVolumeDucking = exports.setChannelVolume = exports.setAllChannelsVolume = exports.getChannelVolume = exports.getAllChannelsVolume = exports.clearVolumeDucking = exports.togglePauseChannel = exports.togglePauseAllChannels = exports.resumeChannel = exports.resumeAllChannels = exports.pauseChannel = exports.pauseAllChannels = exports.isChannelPaused = exports.getAllChannelsPauseState = exports.setRetryConfig = exports.setErrorRecovery = exports.retryFailedAudio = exports.onAudioError = exports.offAudioError = exports.getRetryConfig = exports.getErrorRecovery = exports.playAudioQueue = exports.stopAllAudio = exports.stopAllAudioInChannel = exports.stopCurrentAudioInChannel = exports.queueAudioPriority = exports.queueAudio = void 0;
8
+ exports.audioChannels = exports.onQueueChange = exports.onAudioStart = exports.onAudioResume = exports.onAudioProgress = exports.onAudioPause = exports.onAudioComplete = exports.offQueueChange = exports.offAudioResume = exports.offAudioProgress = exports.offAudioPause = exports.getQueueSnapshot = exports.getCurrentAudioInfo = exports.getAllChannelsInfo = exports.transitionVolume = exports.setVolumeDucking = exports.setChannelVolume = exports.setAllChannelsVolume = exports.getFadeConfig = exports.getChannelVolume = exports.getAllChannelsVolume = exports.fadeVolume = exports.clearVolumeDucking = 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.playAudioQueue = exports.stopAllAudio = exports.stopAllAudioInChannel = exports.stopCurrentAudioInChannel = exports.queueAudioPriority = exports.queueAudio = void 0;
9
+ exports.FadeType = exports.EasingType = exports.getAudioInfoFromElement = exports.extractFileName = exports.createQueueSnapshot = exports.cleanWebpackFilename = void 0;
9
10
  // Core queue management functions
10
11
  var core_1 = require("./core");
11
12
  Object.defineProperty(exports, "queueAudio", { enumerable: true, get: function () { return core_1.queueAudio; } });
@@ -28,19 +29,28 @@ var pause_1 = require("./pause");
28
29
  Object.defineProperty(exports, "getAllChannelsPauseState", { enumerable: true, get: function () { return pause_1.getAllChannelsPauseState; } });
29
30
  Object.defineProperty(exports, "isChannelPaused", { enumerable: true, get: function () { return pause_1.isChannelPaused; } });
30
31
  Object.defineProperty(exports, "pauseAllChannels", { enumerable: true, get: function () { return pause_1.pauseAllChannels; } });
32
+ Object.defineProperty(exports, "pauseAllWithFade", { enumerable: true, get: function () { return pause_1.pauseAllWithFade; } });
31
33
  Object.defineProperty(exports, "pauseChannel", { enumerable: true, get: function () { return pause_1.pauseChannel; } });
34
+ Object.defineProperty(exports, "pauseWithFade", { enumerable: true, get: function () { return pause_1.pauseWithFade; } });
32
35
  Object.defineProperty(exports, "resumeAllChannels", { enumerable: true, get: function () { return pause_1.resumeAllChannels; } });
36
+ Object.defineProperty(exports, "resumeAllWithFade", { enumerable: true, get: function () { return pause_1.resumeAllWithFade; } });
33
37
  Object.defineProperty(exports, "resumeChannel", { enumerable: true, get: function () { return pause_1.resumeChannel; } });
38
+ Object.defineProperty(exports, "resumeWithFade", { enumerable: true, get: function () { return pause_1.resumeWithFade; } });
34
39
  Object.defineProperty(exports, "togglePauseAllChannels", { enumerable: true, get: function () { return pause_1.togglePauseAllChannels; } });
40
+ Object.defineProperty(exports, "togglePauseAllWithFade", { enumerable: true, get: function () { return pause_1.togglePauseAllWithFade; } });
35
41
  Object.defineProperty(exports, "togglePauseChannel", { enumerable: true, get: function () { return pause_1.togglePauseChannel; } });
42
+ Object.defineProperty(exports, "togglePauseWithFade", { enumerable: true, get: function () { return pause_1.togglePauseWithFade; } });
36
43
  // Volume control and ducking functions
37
44
  var volume_1 = require("./volume");
38
45
  Object.defineProperty(exports, "clearVolumeDucking", { enumerable: true, get: function () { return volume_1.clearVolumeDucking; } });
46
+ Object.defineProperty(exports, "fadeVolume", { enumerable: true, get: function () { return volume_1.fadeVolume; } });
39
47
  Object.defineProperty(exports, "getAllChannelsVolume", { enumerable: true, get: function () { return volume_1.getAllChannelsVolume; } });
40
48
  Object.defineProperty(exports, "getChannelVolume", { enumerable: true, get: function () { return volume_1.getChannelVolume; } });
49
+ Object.defineProperty(exports, "getFadeConfig", { enumerable: true, get: function () { return volume_1.getFadeConfig; } });
41
50
  Object.defineProperty(exports, "setAllChannelsVolume", { enumerable: true, get: function () { return volume_1.setAllChannelsVolume; } });
42
51
  Object.defineProperty(exports, "setChannelVolume", { enumerable: true, get: function () { return volume_1.setChannelVolume; } });
43
52
  Object.defineProperty(exports, "setVolumeDucking", { enumerable: true, get: function () { return volume_1.setVolumeDucking; } });
53
+ Object.defineProperty(exports, "transitionVolume", { enumerable: true, get: function () { return volume_1.transitionVolume; } });
44
54
  // Audio information and progress tracking functions
45
55
  var info_1 = require("./info");
46
56
  Object.defineProperty(exports, "getAllChannelsInfo", { enumerable: true, get: function () { return info_1.getAllChannelsInfo; } });
@@ -65,3 +75,7 @@ Object.defineProperty(exports, "cleanWebpackFilename", { enumerable: true, get:
65
75
  Object.defineProperty(exports, "createQueueSnapshot", { enumerable: true, get: function () { return utils_1.createQueueSnapshot; } });
66
76
  Object.defineProperty(exports, "extractFileName", { enumerable: true, get: function () { return utils_1.extractFileName; } });
67
77
  Object.defineProperty(exports, "getAudioInfoFromElement", { enumerable: true, get: function () { return utils_1.getAudioInfoFromElement; } });
78
+ // Enums
79
+ var types_1 = require("./types");
80
+ Object.defineProperty(exports, "EasingType", { enumerable: true, get: function () { return types_1.EasingType; } });
81
+ Object.defineProperty(exports, "FadeType", { enumerable: true, get: function () { return types_1.FadeType; } });
package/dist/pause.d.ts CHANGED
@@ -1,6 +1,77 @@
1
1
  /**
2
2
  * @fileoverview Pause and resume management functions for the audio-channel-queue package
3
3
  */
4
+ import { FadeType } from './types';
5
+ /**
6
+ * Pauses the currently playing audio in a specific channel with smooth volume fade
7
+ * @param fadeType - Type of fade transition to apply
8
+ * @param channelNumber - The channel number to pause (defaults to 0)
9
+ * @returns Promise that resolves when the pause and fade are complete
10
+ * @example
11
+ * ```typescript
12
+ * await pauseWithFade(FadeType.Gentle, 0); // Pause with gentle fade out over 800ms
13
+ * await pauseWithFade(FadeType.Dramatic, 1); // Pause with dramatic fade out over 800ms
14
+ * await pauseWithFade(FadeType.Linear, 2); // Linear pause with 800ms fade
15
+ * ```
16
+ */
17
+ export declare const pauseWithFade: (fadeType?: FadeType, channelNumber?: number) => Promise<void>;
18
+ /**
19
+ * Resumes the currently paused audio in a specific channel with smooth volume fade
20
+ * Uses the complementary fade curve automatically based on the pause fade type, or allows override
21
+ * @param fadeType - Optional fade type to override the stored fade type from pause
22
+ * @param channelNumber - The channel number to resume (defaults to 0)
23
+ * @returns Promise that resolves when the resume and fade are complete
24
+ * @example
25
+ * ```typescript
26
+ * await resumeWithFade(); // Resume with automatically paired fade curve from pause
27
+ * await resumeWithFade(FadeType.Dramatic, 0); // Override with dramatic fade
28
+ * await resumeWithFade(FadeType.Linear); // Override with linear fade on default channel
29
+ * ```
30
+ */
31
+ export declare const resumeWithFade: (fadeType?: FadeType, channelNumber?: number) => Promise<void>;
32
+ /**
33
+ * Toggles pause/resume state for a specific channel with integrated fade
34
+ * @param fadeType - Type of fade transition to apply when pausing
35
+ * @param channelNumber - The channel number to toggle (defaults to 0)
36
+ * @returns Promise that resolves when the toggle and fade are complete
37
+ * @example
38
+ * ```typescript
39
+ * await togglePauseWithFade(FadeType.Gentle, 0); // Toggle with gentle fade
40
+ * ```
41
+ */
42
+ export declare const togglePauseWithFade: (fadeType?: FadeType, channelNumber?: number) => Promise<void>;
43
+ /**
44
+ * Pauses all currently playing audio across all channels with smooth volume fade
45
+ * @param fadeType - Type of fade transition to apply to all channels
46
+ * @returns Promise that resolves when all channels are paused and faded
47
+ * @example
48
+ * ```typescript
49
+ * await pauseAllWithFade('dramatic'); // Pause everything with dramatic fade
50
+ * ```
51
+ */
52
+ export declare const pauseAllWithFade: (fadeType?: FadeType) => Promise<void>;
53
+ /**
54
+ * Resumes all currently paused audio across all channels with smooth volume fade
55
+ * Uses automatically paired fade curves based on each channel's pause fade type
56
+ * @returns Promise that resolves when all channels are resumed and faded
57
+ * @example
58
+ * ```typescript
59
+ * await resumeAllWithFade(); // Resume everything with paired fade curves
60
+ * ```
61
+ */
62
+ export declare const resumeAllWithFade: () => Promise<void>;
63
+ /**
64
+ * Toggles pause/resume state for all channels with integrated fade
65
+ * If any channels are playing, all will be paused with fade
66
+ * If all channels are paused, all will be resumed with fade
67
+ * @param fadeType - Type of fade transition to apply when pausing
68
+ * @returns Promise that resolves when all toggles and fades are complete
69
+ * @example
70
+ * ```typescript
71
+ * await togglePauseAllWithFade('gentle'); // Global toggle with gentle fade
72
+ * ```
73
+ */
74
+ export declare const togglePauseAllWithFade: (fadeType?: FadeType) => Promise<void>;
4
75
  /**
5
76
  * Pauses the currently playing audio in a specific channel
6
77
  * @param channelNumber - The channel number to pause (defaults to 0)
package/dist/pause.js CHANGED
@@ -12,10 +12,213 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
12
12
  });
13
13
  };
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.togglePauseAllChannels = exports.getAllChannelsPauseState = exports.isChannelPaused = exports.resumeAllChannels = exports.pauseAllChannels = exports.togglePauseChannel = exports.resumeChannel = exports.pauseChannel = void 0;
15
+ exports.togglePauseAllChannels = exports.getAllChannelsPauseState = exports.isChannelPaused = exports.resumeAllChannels = exports.pauseAllChannels = exports.togglePauseChannel = exports.resumeChannel = exports.pauseChannel = exports.togglePauseAllWithFade = exports.resumeAllWithFade = exports.pauseAllWithFade = exports.togglePauseWithFade = exports.resumeWithFade = exports.pauseWithFade = void 0;
16
+ const types_1 = require("./types");
16
17
  const info_1 = require("./info");
17
18
  const utils_1 = require("./utils");
18
19
  const events_1 = require("./events");
20
+ const volume_1 = require("./volume");
21
+ /**
22
+ * Predefined fade configurations for different transition types
23
+ */
24
+ const FADE_CONFIGS = {
25
+ [types_1.FadeType.Linear]: { duration: 800, pauseCurve: types_1.EasingType.Linear, resumeCurve: types_1.EasingType.Linear },
26
+ [types_1.FadeType.Gentle]: { duration: 800, pauseCurve: types_1.EasingType.EaseOut, resumeCurve: types_1.EasingType.EaseIn },
27
+ [types_1.FadeType.Dramatic]: { duration: 800, pauseCurve: types_1.EasingType.EaseIn, resumeCurve: types_1.EasingType.EaseOut }
28
+ };
29
+ /**
30
+ * Gets the current volume for a channel, accounting for synchronous state
31
+ * @param channelNumber - The channel number
32
+ * @returns Current volume level (0-1)
33
+ */
34
+ const getChannelVolumeSync = (channelNumber) => {
35
+ const channel = info_1.audioChannels[channelNumber];
36
+ return (channel === null || channel === void 0 ? void 0 : channel.volume) || 1.0;
37
+ };
38
+ /**
39
+ * Sets the channel volume synchronously in internal state
40
+ * @param channelNumber - The channel number
41
+ * @param volume - Volume level (0-1)
42
+ */
43
+ const setChannelVolumeSync = (channelNumber, volume) => {
44
+ const channel = info_1.audioChannels[channelNumber];
45
+ if (channel) {
46
+ channel.volume = volume;
47
+ if (channel.queue.length > 0) {
48
+ channel.queue[0].volume = volume;
49
+ }
50
+ }
51
+ };
52
+ /**
53
+ * Pauses the currently playing audio in a specific channel with smooth volume fade
54
+ * @param fadeType - Type of fade transition to apply
55
+ * @param channelNumber - The channel number to pause (defaults to 0)
56
+ * @returns Promise that resolves when the pause and fade are complete
57
+ * @example
58
+ * ```typescript
59
+ * await pauseWithFade(FadeType.Gentle, 0); // Pause with gentle fade out over 800ms
60
+ * await pauseWithFade(FadeType.Dramatic, 1); // Pause with dramatic fade out over 800ms
61
+ * await pauseWithFade(FadeType.Linear, 2); // Linear pause with 800ms fade
62
+ * ```
63
+ */
64
+ const pauseWithFade = (...args_1) => __awaiter(void 0, [...args_1], void 0, function* (fadeType = types_1.FadeType.Gentle, channelNumber = 0) {
65
+ const channel = info_1.audioChannels[channelNumber];
66
+ if (!channel || channel.queue.length === 0)
67
+ return;
68
+ const currentAudio = channel.queue[0];
69
+ // Don't pause if already paused or ended
70
+ if (currentAudio.paused || currentAudio.ended)
71
+ return;
72
+ const config = FADE_CONFIGS[fadeType];
73
+ const originalVolume = getChannelVolumeSync(channelNumber);
74
+ // Store fade state for resumeWithFade to use
75
+ channel.fadeState = {
76
+ originalVolume,
77
+ fadeType,
78
+ isPaused: true
79
+ };
80
+ if (config.duration === 0) {
81
+ // Instant pause
82
+ yield (0, exports.pauseChannel)(channelNumber);
83
+ return;
84
+ }
85
+ // Fade to 0 with pause curve, then pause
86
+ yield (0, volume_1.transitionVolume)(channelNumber, 0, config.duration, config.pauseCurve);
87
+ yield (0, exports.pauseChannel)(channelNumber);
88
+ // Reset volume to original for resume (synchronously to avoid state issues)
89
+ setChannelVolumeSync(channelNumber, originalVolume);
90
+ });
91
+ exports.pauseWithFade = pauseWithFade;
92
+ /**
93
+ * Resumes the currently paused audio in a specific channel with smooth volume fade
94
+ * Uses the complementary fade curve automatically based on the pause fade type, or allows override
95
+ * @param fadeType - Optional fade type to override the stored fade type from pause
96
+ * @param channelNumber - The channel number to resume (defaults to 0)
97
+ * @returns Promise that resolves when the resume and fade are complete
98
+ * @example
99
+ * ```typescript
100
+ * await resumeWithFade(); // Resume with automatically paired fade curve from pause
101
+ * await resumeWithFade(FadeType.Dramatic, 0); // Override with dramatic fade
102
+ * await resumeWithFade(FadeType.Linear); // Override with linear fade on default channel
103
+ * ```
104
+ */
105
+ const resumeWithFade = (fadeType_1, ...args_1) => __awaiter(void 0, [fadeType_1, ...args_1], void 0, function* (fadeType, channelNumber = 0) {
106
+ const channel = info_1.audioChannels[channelNumber];
107
+ if (!channel || channel.queue.length === 0)
108
+ return;
109
+ const fadeState = channel.fadeState;
110
+ if (!fadeState || !fadeState.isPaused) {
111
+ // Fall back to regular resume if no fade state
112
+ yield (0, exports.resumeChannel)(channelNumber);
113
+ return;
114
+ }
115
+ // Use provided fadeType or fall back to stored fadeType from pause
116
+ const effectiveFadeType = fadeType || fadeState.fadeType;
117
+ const config = FADE_CONFIGS[effectiveFadeType];
118
+ if (config.duration === 0) {
119
+ // Instant resume
120
+ yield (0, exports.resumeChannel)(channelNumber);
121
+ fadeState.isPaused = false;
122
+ return;
123
+ }
124
+ // Set volume to 0, resume, then fade to original with resume curve
125
+ setChannelVolumeSync(channelNumber, 0);
126
+ yield (0, exports.resumeChannel)(channelNumber);
127
+ yield (0, volume_1.transitionVolume)(channelNumber, fadeState.originalVolume, config.duration, config.resumeCurve);
128
+ fadeState.isPaused = false;
129
+ });
130
+ exports.resumeWithFade = resumeWithFade;
131
+ /**
132
+ * Toggles pause/resume state for a specific channel with integrated fade
133
+ * @param fadeType - Type of fade transition to apply when pausing
134
+ * @param channelNumber - The channel number to toggle (defaults to 0)
135
+ * @returns Promise that resolves when the toggle and fade are complete
136
+ * @example
137
+ * ```typescript
138
+ * await togglePauseWithFade(FadeType.Gentle, 0); // Toggle with gentle fade
139
+ * ```
140
+ */
141
+ const togglePauseWithFade = (...args_1) => __awaiter(void 0, [...args_1], void 0, function* (fadeType = types_1.FadeType.Gentle, channelNumber = 0) {
142
+ const channel = info_1.audioChannels[channelNumber];
143
+ if (!channel || channel.queue.length === 0)
144
+ return;
145
+ const currentAudio = channel.queue[0];
146
+ if (currentAudio.paused) {
147
+ yield (0, exports.resumeWithFade)(undefined, channelNumber);
148
+ }
149
+ else {
150
+ yield (0, exports.pauseWithFade)(fadeType, channelNumber);
151
+ }
152
+ });
153
+ exports.togglePauseWithFade = togglePauseWithFade;
154
+ /**
155
+ * Pauses all currently playing audio across all channels with smooth volume fade
156
+ * @param fadeType - Type of fade transition to apply to all channels
157
+ * @returns Promise that resolves when all channels are paused and faded
158
+ * @example
159
+ * ```typescript
160
+ * await pauseAllWithFade('dramatic'); // Pause everything with dramatic fade
161
+ * ```
162
+ */
163
+ const pauseAllWithFade = (...args_1) => __awaiter(void 0, [...args_1], void 0, function* (fadeType = types_1.FadeType.Gentle) {
164
+ const pausePromises = [];
165
+ info_1.audioChannels.forEach((_channel, index) => {
166
+ pausePromises.push((0, exports.pauseWithFade)(fadeType, index));
167
+ });
168
+ yield Promise.all(pausePromises);
169
+ });
170
+ exports.pauseAllWithFade = pauseAllWithFade;
171
+ /**
172
+ * Resumes all currently paused audio across all channels with smooth volume fade
173
+ * Uses automatically paired fade curves based on each channel's pause fade type
174
+ * @returns Promise that resolves when all channels are resumed and faded
175
+ * @example
176
+ * ```typescript
177
+ * await resumeAllWithFade(); // Resume everything with paired fade curves
178
+ * ```
179
+ */
180
+ const resumeAllWithFade = () => __awaiter(void 0, void 0, void 0, function* () {
181
+ const resumePromises = [];
182
+ info_1.audioChannels.forEach((_channel, index) => {
183
+ resumePromises.push((0, exports.resumeWithFade)(undefined, index));
184
+ });
185
+ yield Promise.all(resumePromises);
186
+ });
187
+ exports.resumeAllWithFade = resumeAllWithFade;
188
+ /**
189
+ * Toggles pause/resume state for all channels with integrated fade
190
+ * If any channels are playing, all will be paused with fade
191
+ * If all channels are paused, all will be resumed with fade
192
+ * @param fadeType - Type of fade transition to apply when pausing
193
+ * @returns Promise that resolves when all toggles and fades are complete
194
+ * @example
195
+ * ```typescript
196
+ * await togglePauseAllWithFade('gentle'); // Global toggle with gentle fade
197
+ * ```
198
+ */
199
+ const togglePauseAllWithFade = (...args_1) => __awaiter(void 0, [...args_1], void 0, function* (fadeType = types_1.FadeType.Gentle) {
200
+ let hasPlayingChannel = false;
201
+ // Check if any channel is currently playing
202
+ for (let i = 0; i < info_1.audioChannels.length; i++) {
203
+ const channel = info_1.audioChannels[i];
204
+ if (channel && channel.queue.length > 0) {
205
+ const currentAudio = channel.queue[0];
206
+ if (!currentAudio.paused && !currentAudio.ended) {
207
+ hasPlayingChannel = true;
208
+ break;
209
+ }
210
+ }
211
+ }
212
+ // If any channel is playing, pause all with fade
213
+ // If no channels are playing, resume all with fade
214
+ if (hasPlayingChannel) {
215
+ yield (0, exports.pauseAllWithFade)(fadeType);
216
+ }
217
+ else {
218
+ yield (0, exports.resumeAllWithFade)();
219
+ }
220
+ });
221
+ exports.togglePauseAllWithFade = togglePauseAllWithFade;
19
222
  /**
20
223
  * Pauses the currently playing audio in a specific channel
21
224
  * @param channelNumber - The channel number to pause (defaults to 0)
package/dist/types.d.ts CHANGED
@@ -26,7 +26,7 @@ export interface VolumeConfig {
26
26
  /** Duration in milliseconds for volume restore transition (defaults to 500ms) */
27
27
  restoreTransitionDuration?: number;
28
28
  /** Easing function for volume transitions (defaults to 'ease-out') */
29
- transitionEasing?: 'linear' | 'ease-in' | 'ease-out' | 'ease-in-out';
29
+ transitionEasing?: EasingType;
30
30
  }
31
31
  /**
32
32
  * Audio file configuration for queueing
@@ -206,6 +206,7 @@ export interface ExtendedAudioQueueChannel {
206
206
  audioPauseCallbacks: Set<AudioPauseCallback>;
207
207
  audioResumeCallbacks: Set<AudioResumeCallback>;
208
208
  audioStartCallbacks: Set<AudioStartCallback>;
209
+ fadeState?: ChannelFadeState;
209
210
  isPaused?: boolean;
210
211
  progressCallbacks: Map<HTMLAudioElement | null, Set<ProgressCallback>>;
211
212
  queue: HTMLAudioElement[];
@@ -214,3 +215,42 @@ export interface ExtendedAudioQueueChannel {
214
215
  volume?: number;
215
216
  volumeConfig?: VolumeConfig;
216
217
  }
218
+ /**
219
+ * Easing function types for volume transitions
220
+ */
221
+ export declare enum EasingType {
222
+ Linear = "linear",
223
+ EaseIn = "ease-in",
224
+ EaseOut = "ease-out",
225
+ EaseInOut = "ease-in-out"
226
+ }
227
+ /**
228
+ * Fade type for pause/resume operations with integrated volume transitions
229
+ */
230
+ export declare enum FadeType {
231
+ Linear = "linear",
232
+ Gentle = "gentle",
233
+ Dramatic = "dramatic"
234
+ }
235
+ /**
236
+ * Configuration for fade transitions
237
+ */
238
+ export interface FadeConfig {
239
+ /** Duration in milliseconds for the fade transition */
240
+ duration: number;
241
+ /** Easing curve to use when pausing (fading out) */
242
+ pauseCurve: EasingType;
243
+ /** Easing curve to use when resuming (fading in) */
244
+ resumeCurve: EasingType;
245
+ }
246
+ /**
247
+ * Internal fade state tracking for pause/resume with fade functionality
248
+ */
249
+ export interface ChannelFadeState {
250
+ /** The original volume level before fading began */
251
+ originalVolume: number;
252
+ /** The type of fade being used */
253
+ fadeType: FadeType;
254
+ /** Whether the channel is currently paused due to fade */
255
+ isPaused: boolean;
256
+ }
package/dist/types.js CHANGED
@@ -3,3 +3,23 @@
3
3
  * @fileoverview Type definitions for the audio-channel-queue package
4
4
  */
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.FadeType = exports.EasingType = void 0;
7
+ /**
8
+ * Easing function types for volume transitions
9
+ */
10
+ var EasingType;
11
+ (function (EasingType) {
12
+ EasingType["Linear"] = "linear";
13
+ EasingType["EaseIn"] = "ease-in";
14
+ EasingType["EaseOut"] = "ease-out";
15
+ EasingType["EaseInOut"] = "ease-in-out";
16
+ })(EasingType || (exports.EasingType = EasingType = {}));
17
+ /**
18
+ * Fade type for pause/resume operations with integrated volume transitions
19
+ */
20
+ var FadeType;
21
+ (function (FadeType) {
22
+ FadeType["Linear"] = "linear";
23
+ FadeType["Gentle"] = "gentle";
24
+ FadeType["Dramatic"] = "dramatic";
25
+ })(FadeType || (exports.FadeType = FadeType = {}));
package/dist/volume.d.ts CHANGED
@@ -1,7 +1,18 @@
1
1
  /**
2
2
  * @fileoverview Volume management functions for the audio-channel-queue package
3
3
  */
4
- import { VolumeConfig } from './types';
4
+ import { VolumeConfig, FadeType, FadeConfig, EasingType } from './types';
5
+ /**
6
+ * Gets the fade configuration for a specific fade type
7
+ * @param fadeType - The fade type to get configuration for
8
+ * @returns Fade configuration object
9
+ * @example
10
+ * ```typescript
11
+ * const config = getFadeConfig('gentle');
12
+ * console.log(`Gentle fade duration: ${config.duration}ms`);
13
+ * ```
14
+ */
15
+ export declare const getFadeConfig: (fadeType: FadeType) => FadeConfig;
5
16
  /**
6
17
  * Smoothly transitions volume for a specific channel over time
7
18
  * @param channelNumber - The channel number to transition
@@ -14,7 +25,7 @@ import { VolumeConfig } from './types';
14
25
  * await transitionVolume(0, 0.2, 500, 'ease-out'); // Duck to 20% over 500ms
15
26
  * ```
16
27
  */
17
- export declare const transitionVolume: (channelNumber: number, targetVolume: number, duration?: number, easing?: "linear" | "ease-in" | "ease-out" | "ease-in-out") => Promise<void>;
28
+ export declare const transitionVolume: (channelNumber: number, targetVolume: number, duration?: number, easing?: EasingType) => Promise<void>;
18
29
  /**
19
30
  * Sets the volume for a specific channel with optional smooth transition
20
31
  * @param channelNumber - The channel number to set volume for
@@ -27,7 +38,7 @@ export declare const transitionVolume: (channelNumber: number, targetVolume: num
27
38
  * setChannelVolume(0, 0.5, 300, 'ease-out'); // Smooth transition over 300ms
28
39
  * ```
29
40
  */
30
- export declare const setChannelVolume: (channelNumber: number, volume: number, transitionDuration?: number, easing?: "linear" | "ease-in" | "ease-out" | "ease-in-out") => Promise<void>;
41
+ export declare const setChannelVolume: (channelNumber: number, volume: number, transitionDuration?: number, easing?: EasingType) => Promise<void>;
31
42
  /**
32
43
  * Gets the current volume for a specific channel
33
44
  * @param channelNumber - The channel number to get volume for (defaults to 0)
@@ -90,6 +101,20 @@ export declare const clearVolumeDucking: () => void;
90
101
  * @internal
91
102
  */
92
103
  export declare const applyVolumeDucking: (activeChannelNumber: number) => Promise<void>;
104
+ /**
105
+ * Fades the volume for a specific channel over time (alias for transitionVolume with improved naming)
106
+ * @param channelNumber - The channel number to fade
107
+ * @param targetVolume - Target volume level (0-1)
108
+ * @param duration - Fade duration in milliseconds (defaults to 250)
109
+ * @param easing - Easing function type (defaults to 'ease-out')
110
+ * @returns Promise that resolves when fade completes
111
+ * @example
112
+ * ```typescript
113
+ * await fadeVolume(0, 0, 800, 'ease-in'); // Fade out over 800ms
114
+ * await fadeVolume(0, 1, 600, 'ease-out'); // Fade in over 600ms
115
+ * ```
116
+ */
117
+ export declare const fadeVolume: (channelNumber: number, targetVolume: number, duration?: number, easing?: EasingType) => Promise<void>;
93
118
  /**
94
119
  * Restores normal volume levels when priority channel stops with smooth transitions
95
120
  * @param stoppedChannelNumber - The channel that just stopped playing
package/dist/volume.js CHANGED
@@ -12,18 +12,41 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
12
12
  });
13
13
  };
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.restoreVolumeLevels = exports.applyVolumeDucking = exports.clearVolumeDucking = exports.setVolumeDucking = exports.setAllChannelsVolume = exports.getAllChannelsVolume = exports.getChannelVolume = exports.setChannelVolume = exports.transitionVolume = void 0;
15
+ exports.restoreVolumeLevels = exports.fadeVolume = exports.applyVolumeDucking = exports.clearVolumeDucking = exports.setVolumeDucking = exports.setAllChannelsVolume = exports.getAllChannelsVolume = exports.getChannelVolume = exports.setChannelVolume = exports.transitionVolume = exports.getFadeConfig = void 0;
16
+ const types_1 = require("./types");
16
17
  const info_1 = require("./info");
17
18
  // Store active volume transitions to handle interruptions
18
19
  const activeTransitions = new Map();
20
+ /**
21
+ * Predefined fade configurations for different transition types
22
+ */
23
+ const FADE_CONFIGS = {
24
+ [types_1.FadeType.Dramatic]: { duration: 800, pauseCurve: types_1.EasingType.EaseIn, resumeCurve: types_1.EasingType.EaseOut },
25
+ [types_1.FadeType.Gentle]: { duration: 800, pauseCurve: types_1.EasingType.EaseOut, resumeCurve: types_1.EasingType.EaseIn },
26
+ [types_1.FadeType.Linear]: { duration: 800, pauseCurve: types_1.EasingType.Linear, resumeCurve: types_1.EasingType.Linear }
27
+ };
28
+ /**
29
+ * Gets the fade configuration for a specific fade type
30
+ * @param fadeType - The fade type to get configuration for
31
+ * @returns Fade configuration object
32
+ * @example
33
+ * ```typescript
34
+ * const config = getFadeConfig('gentle');
35
+ * console.log(`Gentle fade duration: ${config.duration}ms`);
36
+ * ```
37
+ */
38
+ const getFadeConfig = (fadeType) => {
39
+ return Object.assign({}, FADE_CONFIGS[fadeType]);
40
+ };
41
+ exports.getFadeConfig = getFadeConfig;
19
42
  /**
20
43
  * Easing functions for smooth volume transitions
21
44
  */
22
45
  const easingFunctions = {
23
- linear: (t) => t,
24
- 'ease-in': (t) => t * t,
25
- 'ease-out': (t) => t * (2 - t),
26
- 'ease-in-out': (t) => t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t
46
+ [types_1.EasingType.Linear]: (t) => t,
47
+ [types_1.EasingType.EaseIn]: (t) => t * t,
48
+ [types_1.EasingType.EaseOut]: (t) => t * (2 - t),
49
+ [types_1.EasingType.EaseInOut]: (t) => t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t
27
50
  };
28
51
  /**
29
52
  * Smoothly transitions volume for a specific channel over time
@@ -37,7 +60,7 @@ const easingFunctions = {
37
60
  * await transitionVolume(0, 0.2, 500, 'ease-out'); // Duck to 20% over 500ms
38
61
  * ```
39
62
  */
40
- const transitionVolume = (channelNumber_1, targetVolume_1, ...args_1) => __awaiter(void 0, [channelNumber_1, targetVolume_1, ...args_1], void 0, function* (channelNumber, targetVolume, duration = 250, easing = 'ease-out') {
63
+ const transitionVolume = (channelNumber_1, targetVolume_1, ...args_1) => __awaiter(void 0, [channelNumber_1, targetVolume_1, ...args_1], void 0, function* (channelNumber, targetVolume, duration = 250, easing = types_1.EasingType.EaseOut) {
41
64
  const channel = info_1.audioChannels[channelNumber];
42
65
  if (!channel || channel.queue.length === 0)
43
66
  return;
@@ -266,7 +289,7 @@ const applyVolumeDucking = (activeChannelNumber) => __awaiter(void 0, void 0, vo
266
289
  const config = channel.volumeConfig;
267
290
  if (activeChannelNumber === config.priorityChannel) {
268
291
  const duration = config.duckTransitionDuration || 250;
269
- const easing = config.transitionEasing || 'ease-out';
292
+ const easing = config.transitionEasing || types_1.EasingType.EaseOut;
270
293
  // Priority channel is active, duck other channels
271
294
  if (channelNumber === config.priorityChannel) {
272
295
  transitionPromises.push((0, exports.transitionVolume)(channelNumber, config.priorityVolume, duration, easing));
@@ -281,6 +304,23 @@ const applyVolumeDucking = (activeChannelNumber) => __awaiter(void 0, void 0, vo
281
304
  yield Promise.all(transitionPromises);
282
305
  });
283
306
  exports.applyVolumeDucking = applyVolumeDucking;
307
+ /**
308
+ * Fades the volume for a specific channel over time (alias for transitionVolume with improved naming)
309
+ * @param channelNumber - The channel number to fade
310
+ * @param targetVolume - Target volume level (0-1)
311
+ * @param duration - Fade duration in milliseconds (defaults to 250)
312
+ * @param easing - Easing function type (defaults to 'ease-out')
313
+ * @returns Promise that resolves when fade completes
314
+ * @example
315
+ * ```typescript
316
+ * await fadeVolume(0, 0, 800, 'ease-in'); // Fade out over 800ms
317
+ * await fadeVolume(0, 1, 600, 'ease-out'); // Fade in over 600ms
318
+ * ```
319
+ */
320
+ const fadeVolume = (channelNumber_1, targetVolume_1, ...args_1) => __awaiter(void 0, [channelNumber_1, targetVolume_1, ...args_1], void 0, function* (channelNumber, targetVolume, duration = 250, easing = types_1.EasingType.EaseOut) {
321
+ return (0, exports.transitionVolume)(channelNumber, targetVolume, duration, easing);
322
+ });
323
+ exports.fadeVolume = fadeVolume;
284
324
  /**
285
325
  * Restores normal volume levels when priority channel stops with smooth transitions
286
326
  * @param stoppedChannelNumber - The channel that just stopped playing
@@ -293,7 +333,7 @@ const restoreVolumeLevels = (stoppedChannelNumber) => __awaiter(void 0, void 0,
293
333
  const config = channel.volumeConfig;
294
334
  if (stoppedChannelNumber === config.priorityChannel) {
295
335
  const duration = config.restoreTransitionDuration || 500;
296
- const easing = config.transitionEasing || 'ease-out';
336
+ const easing = config.transitionEasing || types_1.EasingType.EaseOut;
297
337
  // Priority channel stopped, restore normal volumes
298
338
  transitionPromises.push((0, exports.transitionVolume)(channelNumber, channel.volume || 1.0, duration, easing));
299
339
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "audio-channel-queue",
3
- "version": "1.7.0",
3
+ "version": "1.8.0",
4
4
  "description": "Allows you to queue audio files to different playback channels.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
package/src/index.ts CHANGED
@@ -23,21 +23,30 @@ export {
23
23
  getAllChannelsPauseState,
24
24
  isChannelPaused,
25
25
  pauseAllChannels,
26
+ pauseAllWithFade,
26
27
  pauseChannel,
28
+ pauseWithFade,
27
29
  resumeAllChannels,
30
+ resumeAllWithFade,
28
31
  resumeChannel,
32
+ resumeWithFade,
29
33
  togglePauseAllChannels,
30
- togglePauseChannel,
34
+ togglePauseAllWithFade,
35
+ togglePauseChannel,
36
+ togglePauseWithFade,
31
37
  } from './pause';
32
38
 
33
39
  // Volume control and ducking functions
34
40
  export {
35
41
  clearVolumeDucking,
42
+ fadeVolume,
36
43
  getAllChannelsVolume,
37
44
  getChannelVolume,
45
+ getFadeConfig,
38
46
  setAllChannelsVolume,
39
47
  setChannelVolume,
40
- setVolumeDucking,
48
+ setVolumeDucking,
49
+ transitionVolume,
41
50
  } from './volume';
42
51
 
43
52
  // Audio information and progress tracking functions
@@ -80,12 +89,20 @@ export type {
80
89
  AudioResumeCallback,
81
90
  AudioStartCallback,
82
91
  AudioStartInfo,
92
+ ChannelFadeState,
83
93
  ErrorRecoveryOptions,
84
94
  ExtendedAudioQueueChannel,
95
+ FadeConfig,
85
96
  ProgressCallback,
86
97
  QueueChangeCallback,
87
98
  QueueItem,
88
99
  QueueSnapshot,
89
100
  RetryConfig,
90
101
  VolumeConfig
102
+ } from './types';
103
+
104
+ // Enums
105
+ export {
106
+ EasingType,
107
+ FadeType
91
108
  } from './types';
package/src/pause.ts CHANGED
@@ -2,10 +2,232 @@
2
2
  * @fileoverview Pause and resume management functions for the audio-channel-queue package
3
3
  */
4
4
 
5
- import { ExtendedAudioQueueChannel, AudioInfo } from './types';
5
+ import { ExtendedAudioQueueChannel, AudioInfo, FadeType, FadeConfig, ChannelFadeState, EasingType } from './types';
6
6
  import { audioChannels } from './info';
7
7
  import { getAudioInfoFromElement } from './utils';
8
8
  import { emitAudioPause, emitAudioResume } from './events';
9
+ import { transitionVolume } from './volume';
10
+
11
+ /**
12
+ * Predefined fade configurations for different transition types
13
+ */
14
+ const FADE_CONFIGS: Record<FadeType, FadeConfig> = {
15
+ [FadeType.Linear]: { duration: 800, pauseCurve: EasingType.Linear, resumeCurve: EasingType.Linear },
16
+ [FadeType.Gentle]: { duration: 800, pauseCurve: EasingType.EaseOut, resumeCurve: EasingType.EaseIn },
17
+ [FadeType.Dramatic]: { duration: 800, pauseCurve: EasingType.EaseIn, resumeCurve: EasingType.EaseOut }
18
+ };
19
+
20
+ /**
21
+ * Gets the current volume for a channel, accounting for synchronous state
22
+ * @param channelNumber - The channel number
23
+ * @returns Current volume level (0-1)
24
+ */
25
+ const getChannelVolumeSync = (channelNumber: number): number => {
26
+ const channel: ExtendedAudioQueueChannel = audioChannels[channelNumber];
27
+ return channel?.volume || 1.0;
28
+ };
29
+
30
+ /**
31
+ * Sets the channel volume synchronously in internal state
32
+ * @param channelNumber - The channel number
33
+ * @param volume - Volume level (0-1)
34
+ */
35
+ const setChannelVolumeSync = (channelNumber: number, volume: number): void => {
36
+ const channel: ExtendedAudioQueueChannel = audioChannels[channelNumber];
37
+ if (channel) {
38
+ channel.volume = volume;
39
+ if (channel.queue.length > 0) {
40
+ channel.queue[0].volume = volume;
41
+ }
42
+ }
43
+ };
44
+
45
+ /**
46
+ * Pauses the currently playing audio in a specific channel with smooth volume fade
47
+ * @param fadeType - Type of fade transition to apply
48
+ * @param channelNumber - The channel number to pause (defaults to 0)
49
+ * @returns Promise that resolves when the pause and fade are complete
50
+ * @example
51
+ * ```typescript
52
+ * await pauseWithFade(FadeType.Gentle, 0); // Pause with gentle fade out over 800ms
53
+ * await pauseWithFade(FadeType.Dramatic, 1); // Pause with dramatic fade out over 800ms
54
+ * await pauseWithFade(FadeType.Linear, 2); // Linear pause with 800ms fade
55
+ * ```
56
+ */
57
+ export const pauseWithFade = async (fadeType: FadeType = FadeType.Gentle, channelNumber: number = 0): Promise<void> => {
58
+ const channel: ExtendedAudioQueueChannel = audioChannels[channelNumber];
59
+
60
+ if (!channel || channel.queue.length === 0) return;
61
+
62
+ const currentAudio: HTMLAudioElement = channel.queue[0];
63
+
64
+ // Don't pause if already paused or ended
65
+ if (currentAudio.paused || currentAudio.ended) return;
66
+
67
+ const config: FadeConfig = FADE_CONFIGS[fadeType];
68
+ const originalVolume: number = getChannelVolumeSync(channelNumber);
69
+
70
+ // Store fade state for resumeWithFade to use
71
+ channel.fadeState = {
72
+ originalVolume,
73
+ fadeType,
74
+ isPaused: true
75
+ };
76
+
77
+ if (config.duration === 0) {
78
+ // Instant pause
79
+ await pauseChannel(channelNumber);
80
+ return;
81
+ }
82
+
83
+ // Fade to 0 with pause curve, then pause
84
+ await transitionVolume(channelNumber, 0, config.duration, config.pauseCurve);
85
+ await pauseChannel(channelNumber);
86
+
87
+ // Reset volume to original for resume (synchronously to avoid state issues)
88
+ setChannelVolumeSync(channelNumber, originalVolume);
89
+ };
90
+
91
+ /**
92
+ * Resumes the currently paused audio in a specific channel with smooth volume fade
93
+ * Uses the complementary fade curve automatically based on the pause fade type, or allows override
94
+ * @param fadeType - Optional fade type to override the stored fade type from pause
95
+ * @param channelNumber - The channel number to resume (defaults to 0)
96
+ * @returns Promise that resolves when the resume and fade are complete
97
+ * @example
98
+ * ```typescript
99
+ * await resumeWithFade(); // Resume with automatically paired fade curve from pause
100
+ * await resumeWithFade(FadeType.Dramatic, 0); // Override with dramatic fade
101
+ * await resumeWithFade(FadeType.Linear); // Override with linear fade on default channel
102
+ * ```
103
+ */
104
+ export const resumeWithFade = async (fadeType?: FadeType, channelNumber: number = 0): Promise<void> => {
105
+ const channel: ExtendedAudioQueueChannel = audioChannels[channelNumber];
106
+
107
+ if (!channel || channel.queue.length === 0) return;
108
+
109
+ const fadeState: ChannelFadeState | undefined = channel.fadeState;
110
+ if (!fadeState || !fadeState.isPaused) {
111
+ // Fall back to regular resume if no fade state
112
+ await resumeChannel(channelNumber);
113
+ return;
114
+ }
115
+
116
+ // Use provided fadeType or fall back to stored fadeType from pause
117
+ const effectiveFadeType: FadeType = fadeType || fadeState.fadeType;
118
+ const config: FadeConfig = FADE_CONFIGS[effectiveFadeType];
119
+
120
+ if (config.duration === 0) {
121
+ // Instant resume
122
+ await resumeChannel(channelNumber);
123
+ fadeState.isPaused = false;
124
+ return;
125
+ }
126
+
127
+ // Set volume to 0, resume, then fade to original with resume curve
128
+ setChannelVolumeSync(channelNumber, 0);
129
+ await resumeChannel(channelNumber);
130
+ await transitionVolume(channelNumber, fadeState.originalVolume, config.duration, config.resumeCurve);
131
+
132
+ fadeState.isPaused = false;
133
+ };
134
+
135
+ /**
136
+ * Toggles pause/resume state for a specific channel with integrated fade
137
+ * @param fadeType - Type of fade transition to apply when pausing
138
+ * @param channelNumber - The channel number to toggle (defaults to 0)
139
+ * @returns Promise that resolves when the toggle and fade are complete
140
+ * @example
141
+ * ```typescript
142
+ * await togglePauseWithFade(FadeType.Gentle, 0); // Toggle with gentle fade
143
+ * ```
144
+ */
145
+ export const togglePauseWithFade = async (fadeType: FadeType = FadeType.Gentle, channelNumber: number = 0): Promise<void> => {
146
+ const channel: ExtendedAudioQueueChannel = audioChannels[channelNumber];
147
+
148
+ if (!channel || channel.queue.length === 0) return;
149
+
150
+ const currentAudio: HTMLAudioElement = channel.queue[0];
151
+
152
+ if (currentAudio.paused) {
153
+ await resumeWithFade(undefined, channelNumber);
154
+ } else {
155
+ await pauseWithFade(fadeType, channelNumber);
156
+ }
157
+ };
158
+
159
+ /**
160
+ * Pauses all currently playing audio across all channels with smooth volume fade
161
+ * @param fadeType - Type of fade transition to apply to all channels
162
+ * @returns Promise that resolves when all channels are paused and faded
163
+ * @example
164
+ * ```typescript
165
+ * await pauseAllWithFade('dramatic'); // Pause everything with dramatic fade
166
+ * ```
167
+ */
168
+ export const pauseAllWithFade = async (fadeType: FadeType = FadeType.Gentle): Promise<void> => {
169
+ const pausePromises: Promise<void>[] = [];
170
+
171
+ audioChannels.forEach((_channel: ExtendedAudioQueueChannel, index: number) => {
172
+ pausePromises.push(pauseWithFade(fadeType, index));
173
+ });
174
+
175
+ await Promise.all(pausePromises);
176
+ };
177
+
178
+ /**
179
+ * Resumes all currently paused audio across all channels with smooth volume fade
180
+ * Uses automatically paired fade curves based on each channel's pause fade type
181
+ * @returns Promise that resolves when all channels are resumed and faded
182
+ * @example
183
+ * ```typescript
184
+ * await resumeAllWithFade(); // Resume everything with paired fade curves
185
+ * ```
186
+ */
187
+ export const resumeAllWithFade = async (): Promise<void> => {
188
+ const resumePromises: Promise<void>[] = [];
189
+
190
+ audioChannels.forEach((_channel: ExtendedAudioQueueChannel, index: number) => {
191
+ resumePromises.push(resumeWithFade(undefined, index));
192
+ });
193
+
194
+ await Promise.all(resumePromises);
195
+ };
196
+
197
+ /**
198
+ * Toggles pause/resume state for all channels with integrated fade
199
+ * If any channels are playing, all will be paused with fade
200
+ * If all channels are paused, all will be resumed with fade
201
+ * @param fadeType - Type of fade transition to apply when pausing
202
+ * @returns Promise that resolves when all toggles and fades are complete
203
+ * @example
204
+ * ```typescript
205
+ * await togglePauseAllWithFade('gentle'); // Global toggle with gentle fade
206
+ * ```
207
+ */
208
+ export const togglePauseAllWithFade = async (fadeType: FadeType = FadeType.Gentle): Promise<void> => {
209
+ let hasPlayingChannel: boolean = false;
210
+
211
+ // Check if any channel is currently playing
212
+ for (let i = 0; i < audioChannels.length; i++) {
213
+ const channel: ExtendedAudioQueueChannel = audioChannels[i];
214
+ if (channel && channel.queue.length > 0) {
215
+ const currentAudio: HTMLAudioElement = channel.queue[0];
216
+ if (!currentAudio.paused && !currentAudio.ended) {
217
+ hasPlayingChannel = true;
218
+ break;
219
+ }
220
+ }
221
+ }
222
+
223
+ // If any channel is playing, pause all with fade
224
+ // If no channels are playing, resume all with fade
225
+ if (hasPlayingChannel) {
226
+ await pauseAllWithFade(fadeType);
227
+ } else {
228
+ await resumeAllWithFade();
229
+ }
230
+ };
9
231
 
10
232
  /**
11
233
  * Pauses the currently playing audio in a specific channel
package/src/types.ts CHANGED
@@ -29,7 +29,7 @@ export interface VolumeConfig {
29
29
  /** Duration in milliseconds for volume restore transition (defaults to 500ms) */
30
30
  restoreTransitionDuration?: number;
31
31
  /** Easing function for volume transitions (defaults to 'ease-out') */
32
- transitionEasing?: 'linear' | 'ease-in' | 'ease-out' | 'ease-in-out';
32
+ transitionEasing?: EasingType;
33
33
  }
34
34
 
35
35
  /**
@@ -226,6 +226,7 @@ export interface ExtendedAudioQueueChannel {
226
226
  audioPauseCallbacks: Set<AudioPauseCallback>;
227
227
  audioResumeCallbacks: Set<AudioResumeCallback>;
228
228
  audioStartCallbacks: Set<AudioStartCallback>;
229
+ fadeState?: ChannelFadeState;
229
230
  isPaused?: boolean;
230
231
  progressCallbacks: Map<HTMLAudioElement | null, Set<ProgressCallback>>;
231
232
  queue: HTMLAudioElement[];
@@ -233,4 +234,47 @@ export interface ExtendedAudioQueueChannel {
233
234
  retryConfig?: RetryConfig;
234
235
  volume?: number;
235
236
  volumeConfig?: VolumeConfig;
237
+ }
238
+
239
+ /**
240
+ * Easing function types for volume transitions
241
+ */
242
+ export enum EasingType {
243
+ Linear = 'linear',
244
+ EaseIn = 'ease-in',
245
+ EaseOut = 'ease-out',
246
+ EaseInOut = 'ease-in-out'
247
+ }
248
+
249
+ /**
250
+ * Fade type for pause/resume operations with integrated volume transitions
251
+ */
252
+ export enum FadeType {
253
+ Linear = 'linear',
254
+ Gentle = 'gentle',
255
+ Dramatic = 'dramatic'
256
+ }
257
+
258
+ /**
259
+ * Configuration for fade transitions
260
+ */
261
+ export interface FadeConfig {
262
+ /** Duration in milliseconds for the fade transition */
263
+ duration: number;
264
+ /** Easing curve to use when pausing (fading out) */
265
+ pauseCurve: EasingType;
266
+ /** Easing curve to use when resuming (fading in) */
267
+ resumeCurve: EasingType;
268
+ }
269
+
270
+ /**
271
+ * Internal fade state tracking for pause/resume with fade functionality
272
+ */
273
+ export interface ChannelFadeState {
274
+ /** The original volume level before fading began */
275
+ originalVolume: number;
276
+ /** The type of fade being used */
277
+ fadeType: FadeType;
278
+ /** Whether the channel is currently paused due to fade */
279
+ isPaused: boolean;
236
280
  }
package/src/volume.ts CHANGED
@@ -2,20 +2,43 @@
2
2
  * @fileoverview Volume management functions for the audio-channel-queue package
3
3
  */
4
4
 
5
- import { ExtendedAudioQueueChannel, VolumeConfig } from './types';
5
+ import { ExtendedAudioQueueChannel, VolumeConfig, FadeType, FadeConfig, EasingType } from './types';
6
6
  import { audioChannels } from './info';
7
7
 
8
8
  // Store active volume transitions to handle interruptions
9
9
  const activeTransitions = new Map<number, number>();
10
10
 
11
+ /**
12
+ * Predefined fade configurations for different transition types
13
+ */
14
+ const FADE_CONFIGS: Record<FadeType, FadeConfig> = {
15
+ [FadeType.Dramatic]: { duration: 800, pauseCurve: EasingType.EaseIn, resumeCurve: EasingType.EaseOut },
16
+ [FadeType.Gentle]: { duration: 800, pauseCurve: EasingType.EaseOut, resumeCurve: EasingType.EaseIn },
17
+ [FadeType.Linear]: { duration: 800, pauseCurve: EasingType.Linear, resumeCurve: EasingType.Linear }
18
+ };
19
+
20
+ /**
21
+ * Gets the fade configuration for a specific fade type
22
+ * @param fadeType - The fade type to get configuration for
23
+ * @returns Fade configuration object
24
+ * @example
25
+ * ```typescript
26
+ * const config = getFadeConfig('gentle');
27
+ * console.log(`Gentle fade duration: ${config.duration}ms`);
28
+ * ```
29
+ */
30
+ export const getFadeConfig = (fadeType: FadeType): FadeConfig => {
31
+ return { ...FADE_CONFIGS[fadeType] };
32
+ };
33
+
11
34
  /**
12
35
  * Easing functions for smooth volume transitions
13
36
  */
14
- const easingFunctions = {
15
- linear: (t: number): number => t,
16
- 'ease-in': (t: number): number => t * t,
17
- 'ease-out': (t: number): number => t * (2 - t),
18
- 'ease-in-out': (t: number): number => t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t
37
+ const easingFunctions: Record<EasingType, (t: number) => number> = {
38
+ [EasingType.Linear]: (t: number): number => t,
39
+ [EasingType.EaseIn]: (t: number): number => t * t,
40
+ [EasingType.EaseOut]: (t: number): number => t * (2 - t),
41
+ [EasingType.EaseInOut]: (t: number): number => t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t
19
42
  };
20
43
 
21
44
  /**
@@ -34,7 +57,7 @@ export const transitionVolume = async (
34
57
  channelNumber: number,
35
58
  targetVolume: number,
36
59
  duration: number = 250,
37
- easing: 'linear' | 'ease-in' | 'ease-out' | 'ease-in-out' = 'ease-out'
60
+ easing: EasingType = EasingType.EaseOut
38
61
  ): Promise<void> => {
39
62
  const channel: ExtendedAudioQueueChannel = audioChannels[channelNumber];
40
63
  if (!channel || channel.queue.length === 0) return;
@@ -119,7 +142,7 @@ export const setChannelVolume = async (
119
142
  channelNumber: number,
120
143
  volume: number,
121
144
  transitionDuration?: number,
122
- easing?: 'linear' | 'ease-in' | 'ease-out' | 'ease-in-out'
145
+ easing?: EasingType
123
146
  ): Promise<void> => {
124
147
  const clampedVolume: number = Math.max(0, Math.min(1, volume));
125
148
 
@@ -282,7 +305,7 @@ export const applyVolumeDucking = async (activeChannelNumber: number): Promise<v
282
305
 
283
306
  if (activeChannelNumber === config.priorityChannel) {
284
307
  const duration = config.duckTransitionDuration || 250;
285
- const easing = config.transitionEasing || 'ease-out';
308
+ const easing = config.transitionEasing || EasingType.EaseOut;
286
309
 
287
310
  // Priority channel is active, duck other channels
288
311
  if (channelNumber === config.priorityChannel) {
@@ -298,10 +321,32 @@ export const applyVolumeDucking = async (activeChannelNumber: number): Promise<v
298
321
  }
299
322
  });
300
323
 
301
- // Wait for all transitions to complete
324
+ // Wait for all transitions to complete
302
325
  await Promise.all(transitionPromises);
303
326
  };
304
327
 
328
+ /**
329
+ * Fades the volume for a specific channel over time (alias for transitionVolume with improved naming)
330
+ * @param channelNumber - The channel number to fade
331
+ * @param targetVolume - Target volume level (0-1)
332
+ * @param duration - Fade duration in milliseconds (defaults to 250)
333
+ * @param easing - Easing function type (defaults to 'ease-out')
334
+ * @returns Promise that resolves when fade completes
335
+ * @example
336
+ * ```typescript
337
+ * await fadeVolume(0, 0, 800, 'ease-in'); // Fade out over 800ms
338
+ * await fadeVolume(0, 1, 600, 'ease-out'); // Fade in over 600ms
339
+ * ```
340
+ */
341
+ export const fadeVolume = async (
342
+ channelNumber: number,
343
+ targetVolume: number,
344
+ duration: number = 250,
345
+ easing: EasingType = EasingType.EaseOut
346
+ ): Promise<void> => {
347
+ return transitionVolume(channelNumber, targetVolume, duration, easing);
348
+ };
349
+
305
350
  /**
306
351
  * Restores normal volume levels when priority channel stops with smooth transitions
307
352
  * @param stoppedChannelNumber - The channel that just stopped playing
@@ -316,7 +361,7 @@ export const restoreVolumeLevels = async (stoppedChannelNumber: number): Promise
316
361
 
317
362
  if (stoppedChannelNumber === config.priorityChannel) {
318
363
  const duration = config.restoreTransitionDuration || 500;
319
- const easing = config.transitionEasing || 'ease-out';
364
+ const easing = config.transitionEasing || EasingType.EaseOut;
320
365
 
321
366
  // Priority channel stopped, restore normal volumes
322
367
  transitionPromises.push(