Volume Control
Control audio levels across individual channels or all channels simultaneously.
setChannelVolume​
Sets the volume for a specific audio channel.
Syntax​
setChannelVolume(channelNumber: number, volume: number): void
Parameters​
channelNumber
(number): The channel number (0-based index)volume
(number): Volume level between 0.0 (muted) and 1.0 (full volume)
Examples​
import { setChannelVolume } from 'audio-channel-queue';
// Set channel 0 to half volume
setChannelVolume(0, 0.5);
// Mute channel 1
setChannelVolume(1, 0);
// Set channel 2 to full volume
setChannelVolume(2, 1.0);
Real-world Usage​
class GameAudioManager {
private musicVolume: number = 0.7;
private sfxVolume: number = 0.8;
updateMusicVolume(volume: number): void {
this.musicVolume = volume;
setChannelVolume(0, volume); // Music channel
}
updateSFXVolume(volume: number): void {
this.sfxVolume = volume;
setChannelVolume(1, volume); // SFX channel
}
muteAllAudio(): void {
setChannelVolume(0, 0); // Mute music
setChannelVolume(1, 0); // Mute SFX
}
restoreVolumes(): void {
setChannelVolume(0, this.musicVolume);
setChannelVolume(1, this.sfxVolume);
}
}
getChannelVolume​
Retrieves the current volume level for a specific channel.
Syntax​
getChannelVolume(channelNumber: number): number
Parameters​
channelNumber
(number): The channel number to query
Returns​
number
: Current volume level (0.0 to 1.0)
Examples​
import { getChannelVolume, setChannelVolume } from 'audio-channel-queue';
// Set and then get volume
setChannelVolume(0, 0.75);
const currentVolume = getChannelVolume(0);
console.log(currentVolume); // 0.75
// Check if channel is muted
if (getChannelVolume(1) === 0) {
console.log('Channel 1 is muted');
}
setAllChannelsVolume​
Sets the same volume level for all audio channels.
Syntax​
setAllChannelsVolume(volume: number): void
Parameters​
volume
(number): Volume level between 0.0 and 1.0 to apply to all channels
Examples​
import { setAllChannelsVolume } from 'audio-channel-queue';
// Set all channels to half volume
setAllChannelsVolume(0.5);
// Mute all channels
setAllChannelsVolume(0);
// Master volume control
function setMasterVolume(volume: number): void {
// Clamp volume between 0 and 1
const clampedVolume = Math.max(0, Math.min(1, volume));
setAllChannelsVolume(clampedVolume);
}
setVolumeDucking​
Temporarily reduces volume on specified channels (ducking effect).
Syntax​
setVolumeDucking(channelNumbers: number[], duckVolume: number): void
Parameters​
channelNumbers
(number[]): Array of channel numbers to duckduckVolume
(number): Reduced volume level (0.0 to 1.0)
Examples​
import { setVolumeDucking, clearVolumeDucking } from 'audio-channel-queue';
// Duck background music when dialog plays
function playDialog(): void {
// Reduce music (channel 0) and ambient sounds (channel 2) to 20%
setVolumeDucking([0, 2], 0.2);
// Play dialog on channel 1
queueAudio('/audio/dialog/important-message.mp3', 1);
}
// Restore original volumes when dialog ends
onAudioComplete(1, () => {
clearVolumeDucking([0, 2]);
});
Real-world Usage​
class PodcastPlayer {
private readonly MUSIC_CHANNEL = 0;
private readonly VOICE_CHANNEL = 1;
private readonly ADS_CHANNEL = 2;
playIntroMusic(): void {
queueAudio('/audio/intro-music.mp3', this.MUSIC_CHANNEL);
}
startPodcast(): void {
// Duck intro music when podcast starts
setVolumeDucking([this.MUSIC_CHANNEL], 0.1);
queueAudio('/audio/podcast-episode.mp3', this.VOICE_CHANNEL);
}
playAd(): void {
// Duck both music and podcast for ad
setVolumeDucking([this.MUSIC_CHANNEL, this.VOICE_CHANNEL], 0.05);
queueAudio('/audio/advertisement.mp3', this.ADS_CHANNEL);
}
restoreNormalVolumes(): void {
clearVolumeDucking([this.MUSIC_CHANNEL, this.VOICE_CHANNEL]);
}
}
clearVolumeDucking​
Restores original volume levels for channels that were ducked.
Syntax​
clearVolumeDucking(channelNumbers: number[]): void
Parameters​
channelNumbers
(number[]): Array of channel numbers to restore
Examples​
import { setVolumeDucking, clearVolumeDucking } from 'audio-channel-queue';
// Temporary volume reduction for notification
function playNotification(): void {
setVolumeDucking([0, 1], 0.3); // Duck channels 0 and 1
setTimeout(() => {
clearVolumeDucking([0, 1]); // Restore after 2 seconds
}, 2000);
}
Volume Best Practices​
1. Volume Curves​
Use logarithmic scaling for more natural volume perception:
function linearToLogarithmic(linear: number): number {
return Math.pow(linear, 2);
}
function setNaturalVolume(channel: number, linearVolume: number): void {
const logVolume = linearToLogarithmic(linearVolume);
setChannelVolume(channel, logVolume);
}
🎵 Smooth Volume Transitions & Easing Functions​
The audio-channel-queue
package includes built-in easing functions for creating smooth, natural-sounding volume transitions. These mathematical functions control how volume changes over time, making audio transitions feel more professional and pleasant to listen to.
Available Easing Functions​
Linear Easing​
// Constant rate of change - mechanical feeling
linear: (t: number): number => t
- Use case: Technical applications, precise timing
- Feel: Mechanical, robotic
- Best for: UI sound effects, technical demos
Ease-In​
// Starts slow, accelerates - builds anticipation
'ease-in': (t: number): number => t * t
- Use case: Fade-ins, building tension
- Feel: Gradual buildup, anticipation
- Best for: Background music fade-in, dramatic reveals
Ease-Out​
// Starts fast, decelerates - natural ending
'ease-out': (t: number): number => t * (2 - t)
- Use case: Fade-outs, natural endings
- Feel: Smooth deceleration, gentle conclusion
- Best for: Ending music, pause transitions
Ease-In-Out​
// Slow start and end, fast middle - most natural
'ease-in-out': (t: number): number => t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t
- Use case: General-purpose smooth transitions
- Feel: Most natural to human perception
- Best for: Volume ducking, crossfades, general transitions
Custom Volume Fade Implementation​
You can implement smooth volume transitions using the existing volume controls and easing functions:
async function fadeVolume(
channelNumber: number,
targetVolume: number,
duration: number = 1000,
easing: 'linear' | 'ease-in' | 'ease-out' | 'ease-in-out' = 'ease-in-out'
): Promise<void> {
const currentVolume = getChannelVolume(channelNumber);
const steps = 20;
const stepDuration = duration / steps;
// Easing function implementations
const easingFunctions = {
linear: (t: number): number => t,
'ease-in': (t: number): number => t * t,
'ease-out': (t: number): number => t * (2 - t),
'ease-in-out': (t: number): number => t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t
};
const easingFunc = easingFunctions[easing];
return new Promise((resolve) => {
let currentStep = 0;
const interval = setInterval(() => {
currentStep++;
const progress = currentStep / steps;
const easedProgress = easingFunc(progress);
const newVolume = currentVolume + (targetVolume - currentVolume) * easedProgress;
setChannelVolume(channelNumber, newVolume);
if (currentStep >= steps) {
clearInterval(interval);
setChannelVolume(channelNumber, targetVolume); // Ensure exact final value
resolve();
}
}, stepDuration);
});
}
// Usage examples
await fadeVolume(0, 0, 2000, 'ease-out'); // Fade out over 2 seconds
await fadeVolume(1, 1, 1000, 'ease-in'); // Fade in over 1 second
await fadeVolume(0, 0.3, 500, 'ease-in-out'); // Duck to 30% volume
Real-World Easing Examples​
Gaming Audio Manager​
class GameAudioManager {
async startLevel(): Promise<void> {
// Start background music with fade-in
await queueAudio('./music/level-bg.mp3', 0, { loop: true, volume: 0 });
await fadeVolume(0, 0.6, 2000, 'ease-in');
}
async playDialogue(audioFile: string): Promise<void> {
// Duck background music for dialogue
await fadeVolume(0, 0.1, 500, 'ease-in-out');
await queueAudio(audioFile, 1);
// Restore background music when dialogue ends
onAudioComplete(1, async () => {
await fadeVolume(0, 0.6, 500, 'ease-in-out');
});
}
async endLevel(): Promise<void> {
// Fade out all audio
await Promise.all([
fadeVolume(0, 0, 3000, 'ease-out'),
fadeVolume(1, 0, 1000, 'ease-out')
]);
}
}
Podcast Player​
class PodcastPlayer {
async insertAd(): Promise<void> {
// Fade out podcast, play ad, fade back in
await fadeVolume(0, 0.1, 800, 'ease-in-out');
await queueAudioPriority('./ads/sponsor.mp3', 1);
onAudioComplete(1, async () => {
await fadeVolume(0, 1.0, 800, 'ease-in-out');
});
}
async pauseWithFade(): Promise<void> {
await fadeVolume(0, 0, 1000, 'ease-out');
await pauseChannel(0);
setChannelVolume(0, 1.0); // Reset for resume
}
async resumeWithFade(): Promise<void> {
setChannelVolume(0, 0);
await resumeChannel(0);
await fadeVolume(0, 1.0, 1000, 'ease-in');
}
}
Why Easing Matters​
Human Perception​
- Linear transitions sound mechanical and unnatural
- Eased transitions match how we naturally expect sound to behave
- Logarithmic perception - our ears are more sensitive to changes at lower volumes
Professional Audio Standards​
- Broadcasting: Smooth fades prevent jarring transitions
- Gaming: Immersive audio requires seamless volume changes
- Music Production: Crossfades and automation use easing curves
Technical Benefits​
- CPU Efficiency: Fewer audio dropouts with smooth transitions
- Memory Management: Gradual changes prevent sudden resource spikes
- User Experience: Professional-feeling audio enhances perceived quality
Volume Persistence​
Save and restore user preferences:
class VolumeManager {
private readonly STORAGE_KEY = 'audioChannelVolumes';
saveVolumes(): void {
const volumes = {
music: getChannelVolume(0),
sfx: getChannelVolume(1),
voice: getChannelVolume(2),
};
localStorage.setItem(this.STORAGE_KEY, JSON.stringify(volumes));
}
loadVolumes(): void {
const saved = localStorage.getItem(this.STORAGE_KEY);
if (saved) {
const volumes = JSON.parse(saved);
setChannelVolume(0, volumes.music || 0.7);
setChannelVolume(1, volumes.sfx || 0.8);
setChannelVolume(2, volumes.voice || 1.0);
}
}
}