murmuraba
Version:
Real-time audio noise reduction with advanced chunked processing for web applications
110 lines (109 loc) • 2.9 kB
JavaScript
/**
* Centralized Gain Control Utilities
* Eliminates code duplication and provides consistent gain management
*/
export const DEFAULT_GAIN_CONFIG = {
min: 0.5,
max: 3.0,
default: 1.0,
step: 0.1
};
export const GAIN_PRESETS = {
LOW: 0.7,
NORMAL: 1.0,
HIGH: 1.5,
BOOST: 2.0
};
/**
* Validates and clamps gain value within acceptable range
*/
export function validateGain(gain, config = DEFAULT_GAIN_CONFIG) {
if (typeof gain !== 'number' || isNaN(gain)) {
return config.default;
}
return Math.max(config.min, Math.min(config.max, gain));
}
/**
* Converts gain value to decibels for UI display
*/
export function gainToDb(gain) {
return 20 * Math.log10(Math.max(0.001, gain));
}
/**
* Converts decibels to gain value
*/
export function dbToGain(db) {
return Math.pow(10, db / 20);
}
/**
* Gets gain preset by name
*/
export function getGainPreset(preset) {
return GAIN_PRESETS[preset];
}
/**
* Gets descriptive text for gain level
*/
export function getGainDescription(gain) {
if (gain < 1.0)
return '⬇️ Reduced input level';
if (gain === 1.0)
return '✅ Normal input level';
if (gain <= 1.5)
return '⬆️ Increased input level';
if (gain <= 2.0)
return '📈 High input level';
return '⚠️ Maximum boost - watch for clipping';
}
/**
* Advanced Gain Controller Class
* Encapsulates gain control logic with validation and events
*/
export class GainController {
constructor(initialGain = DEFAULT_GAIN_CONFIG.default, config = DEFAULT_GAIN_CONFIG) {
this.listeners = new Set();
this.config = config;
this._currentGain = validateGain(initialGain, config);
}
get currentGain() {
return this._currentGain;
}
setGain(gain) {
const validatedGain = validateGain(gain, this.config);
if (validatedGain !== this._currentGain) {
this._currentGain = validatedGain;
this.notifyListeners();
return true;
}
return false;
}
incrementGain() {
const newGain = this._currentGain + this.config.step;
this.setGain(newGain);
return this._currentGain;
}
decrementGain() {
const newGain = this._currentGain - this.config.step;
this.setGain(newGain);
return this._currentGain;
}
applyPreset(preset) {
this.setGain(getGainPreset(preset));
}
getDescription() {
return getGainDescription(this._currentGain);
}
getDbValue() {
return gainToDb(this._currentGain);
}
onGainChange(callback) {
this.listeners.add(callback);
return () => this.listeners.delete(callback);
}
notifyListeners() {
this.listeners.forEach(callback => callback(this._currentGain));
}
destroy() {
this.listeners.clear();
}
}