murmuraba
Version:
Real-time audio noise reduction with advanced chunked processing for web applications
132 lines (131 loc) • 4.61 kB
JavaScript
/**
* 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;
}
}