UNPKG

murmuraba

Version:

Real-time audio noise reduction with advanced chunked processing for web applications

132 lines (131 loc) 4.61 kB
/** * Domain Layer - Gain Control Business Logic * Pure business logic with no dependencies on frameworks or infrastructure */ export const MEDICAL_GAIN_POLICY = { minGain: 0.5, maxGain: 3.0, defaultGain: 1.0, step: 0.1 }; export const BROADCAST_GAIN_POLICY = { minGain: 0.1, maxGain: 5.0, defaultGain: 1.0, step: 0.05 }; export class GainValue { constructor(value) { this.value = value; } static create(value, policy = MEDICAL_GAIN_POLICY) { const clampedValue = Math.max(policy.minGain, Math.min(policy.maxGain, value)); return new GainValue(clampedValue); } getValue() { return this.value; } getDbValue() { return 20 * Math.log10(Math.max(0.001, this.value)); } increment(policy) { return GainValue.create(this.value + policy.step, policy); } decrement(policy) { return GainValue.create(this.value - policy.step, policy); } equals(other) { return Math.abs(this.value - other.value) < 0.001; } isNormalLevel() { return Math.abs(this.value - 1.0) < 0.001; } isBoostLevel() { return this.value > 1.5; } toString() { return `${this.value.toFixed(1)}x`; } } export var GainPreset; (function (GainPreset) { GainPreset["LOW"] = "LOW"; GainPreset["NORMAL"] = "NORMAL"; GainPreset["HIGH"] = "HIGH"; GainPreset["BOOST"] = "BOOST"; })(GainPreset || (GainPreset = {})); export class GainPresetService { static getPresetValue(preset) { const value = this.presetValues.get(preset) ?? 1.0; return GainValue.create(value); } static getAllPresets() { return [ { preset: GainPreset.LOW, value: this.getPresetValue(GainPreset.LOW), description: '🔇 Quiet environments' }, { preset: GainPreset.NORMAL, value: this.getPresetValue(GainPreset.NORMAL), description: '🔊 Standard level' }, { preset: GainPreset.HIGH, value: this.getPresetValue(GainPreset.HIGH), description: '📢 Noisy environments' }, { preset: GainPreset.BOOST, value: this.getPresetValue(GainPreset.BOOST), description: '🚀 Maximum amplification' } ]; } } GainPresetService.presetValues = new Map([ [GainPreset.LOW, 0.7], [GainPreset.NORMAL, 1.0], [GainPreset.HIGH, 1.5], [GainPreset.BOOST, 2.0] ]); export class GainController { constructor(repository, eventPublisher, policy = MEDICAL_GAIN_POLICY) { this.repository = repository; this.eventPublisher = eventPublisher; this.policy = policy; } async getCurrentGain() { return await this.repository.getCurrentGain(); } async setGain(targetGain) { const oldGain = await this.repository.getCurrentGain(); const newGain = GainValue.create(targetGain, this.policy); if (!oldGain.equals(newGain)) { await this.repository.setGain(newGain); this.eventPublisher.publishGainChanged(oldGain, newGain); } return newGain; } async applyPreset(preset) { const oldGain = await this.repository.getCurrentGain(); const newGain = GainPresetService.getPresetValue(preset); await this.repository.setGain(newGain); this.eventPublisher.publishGainChanged(oldGain, newGain); this.eventPublisher.publishPresetApplied(preset, newGain); return newGain; } async incrementGain() { const currentGain = await this.repository.getCurrentGain(); const newGain = currentGain.increment(this.policy); await this.repository.setGain(newGain); this.eventPublisher.publishGainChanged(currentGain, newGain); return newGain; } async decrementGain() { const currentGain = await this.repository.getCurrentGain(); const newGain = currentGain.decrement(this.policy); await this.repository.setGain(newGain); this.eventPublisher.publishGainChanged(currentGain, newGain); return newGain; } async saveCurrentAsPreset(name) { const currentGain = await this.repository.getCurrentGain(); await this.repository.savePreset(name, currentGain); } async loadNamedPreset(name) { const presetGain = await this.repository.loadPreset(name); if (presetGain) { const oldGain = await this.repository.getCurrentGain(); await this.repository.setGain(presetGain); this.eventPublisher.publishGainChanged(oldGain, presetGain); return presetGain; } return null; } }