112 lines
3.7 KiB
JavaScript
112 lines
3.7 KiB
JavaScript
class AudioEnhancer {
|
|
constructor(videoElement) {
|
|
if (!window.AudioContext) {
|
|
this.isSupported = false;
|
|
return;
|
|
}
|
|
this.isSupported = true;
|
|
this.isEnabled = false;
|
|
this.videoElement = videoElement;
|
|
this.audioContext = new AudioContext();
|
|
this.sourceNode = this.audioContext.createMediaElementSource(this.videoElement);
|
|
|
|
this.preamp = this.audioContext.createGain();
|
|
this.compressor = this.audioContext.createDynamicsCompressor();
|
|
this.bandFrequencies = [60, 170, 310, 600, 1000, 3000, 6000, 12000, 14000, 16000];
|
|
this.filters = this.bandFrequencies.map(freq => {
|
|
const filter = this.audioContext.createBiquadFilter();
|
|
filter.type = 'peaking';
|
|
filter.frequency.value = freq;
|
|
filter.Q.value = 1.41;
|
|
filter.gain.value = 0;
|
|
return filter;
|
|
});
|
|
|
|
this.connectNodes();
|
|
}
|
|
|
|
connectNodes() {
|
|
this.sourceNode.disconnect();
|
|
if (this.isEnabled) {
|
|
let lastNode = this.preamp;
|
|
this.sourceNode.connect(this.preamp);
|
|
this.filters.forEach(filter => {
|
|
lastNode.connect(filter);
|
|
lastNode = filter;
|
|
});
|
|
lastNode.connect(this.compressor);
|
|
this.compressor.connect(this.audioContext.destination);
|
|
} else {
|
|
this.sourceNode.connect(this.audioContext.destination);
|
|
}
|
|
}
|
|
|
|
toggle(state) {
|
|
this.isEnabled = state;
|
|
this.connectNodes();
|
|
}
|
|
|
|
setCompressor(settings) {
|
|
if (!this.isSupported || !settings) return;
|
|
this.compressor.threshold.value = settings.threshold || -24;
|
|
this.compressor.knee.value = settings.knee || 30;
|
|
this.compressor.ratio.value = settings.ratio || 12;
|
|
this.compressor.attack.value = settings.attack || 0.003;
|
|
this.compressor.release.value = settings.release || 0.25;
|
|
}
|
|
|
|
changeGain(bandIndex, gainValue) {
|
|
if (!this.isSupported || bandIndex < 0 || bandIndex >= this.filters.length) return;
|
|
this.filters[bandIndex].gain.value = gainValue;
|
|
}
|
|
|
|
changePreamp(gainValue) {
|
|
if (!this.isSupported) return;
|
|
const linearValue = Math.pow(10, gainValue / 20);
|
|
this.preamp.gain.value = linearValue;
|
|
}
|
|
|
|
applySettings(settings) {
|
|
if (!this.isSupported || !settings) return;
|
|
|
|
this.toggle(settings.enabled);
|
|
|
|
if (typeof settings.preamp === 'number') {
|
|
this.changePreamp(settings.preamp);
|
|
}
|
|
|
|
if (Array.isArray(settings.bands)) {
|
|
settings.bands.forEach((gain, index) => {
|
|
this.changeGain(index, gain);
|
|
});
|
|
}
|
|
|
|
if (settings.compressor) {
|
|
this.setCompressor(settings.compressor);
|
|
} else {
|
|
this.setCompressor({});
|
|
}
|
|
}
|
|
|
|
getSettings() {
|
|
if (!this.isSupported) return { enabled: false, preamp: 0, bands: new Array(10).fill(0), customPresets: [] };
|
|
const preampDB = 20 * Math.log10(this.preamp.gain.value);
|
|
const bandGains = this.filters.map(filter => filter.gain.value);
|
|
return { enabled: this.isEnabled, preamp: preampDB, bands: bandGains };
|
|
}
|
|
|
|
destroy() {
|
|
if (!this.isSupported) return;
|
|
try {
|
|
this.sourceNode.disconnect();
|
|
this.preamp.disconnect();
|
|
this.compressor.disconnect();
|
|
this.filters.forEach(filter => filter.disconnect());
|
|
if (this.audioContext.state !== 'closed') {
|
|
this.audioContext.close();
|
|
}
|
|
} catch (e) {
|
|
console.error("Error al destruir AudioEnhancer:", e);
|
|
}
|
|
}
|
|
} |