From 3e89d2998588f8e35c524e523ba2ee853f0f6475 Mon Sep 17 00:00:00 2001 From: Maze Winther Date: Mon, 20 Apr 2026 11:31:17 +0200 Subject: refactor: restructure files to their domains, new preview overlay system, and dep graph --- apps/web/src/lib/media/audio-mastering.ts | 103 ------------------------------ 1 file changed, 103 deletions(-) delete mode 100644 apps/web/src/lib/media/audio-mastering.ts (limited to 'apps/web/src/lib/media/audio-mastering.ts') diff --git a/apps/web/src/lib/media/audio-mastering.ts b/apps/web/src/lib/media/audio-mastering.ts deleted file mode 100644 index f901c3bf..00000000 --- a/apps/web/src/lib/media/audio-mastering.ts +++ /dev/null @@ -1,103 +0,0 @@ -const MASTER_LIMITER_THRESHOLD_DB = -1; -const MASTER_LIMITER_KNEE_DB = 0; -const MASTER_LIMITER_RATIO = 20; -const MASTER_LIMITER_ATTACK_SECONDS = 0.001; -const MASTER_LIMITER_RELEASE_SECONDS = 0.12; -const MASTER_OUTPUT_HEADROOM = 0.98; - -export function getAudioBufferPeak({ - audioBuffer, -}: { - audioBuffer: AudioBuffer; -}): number { - let peak = 0; - - for (let channel = 0; channel < audioBuffer.numberOfChannels; channel++) { - const channelData = audioBuffer.getChannelData(channel); - for (let index = 0; index < channelData.length; index++) { - const magnitude = Math.abs(channelData[index]); - if (magnitude > peak) { - peak = magnitude; - } - } - } - - return peak; -} - -export function createAudioMasteringChain({ - audioContext, - destination, -}: { - audioContext: AudioContext | OfflineAudioContext; - destination: AudioNode; -}): { - input: GainNode; -} { - const input = audioContext.createGain(); - const limiter = audioContext.createDynamicsCompressor(); - const outputGain = audioContext.createGain(); - - limiter.threshold.value = MASTER_LIMITER_THRESHOLD_DB; - limiter.knee.value = MASTER_LIMITER_KNEE_DB; - limiter.ratio.value = MASTER_LIMITER_RATIO; - limiter.attack.value = MASTER_LIMITER_ATTACK_SECONDS; - limiter.release.value = MASTER_LIMITER_RELEASE_SECONDS; - outputGain.gain.value = MASTER_OUTPUT_HEADROOM; - - input.connect(limiter); - limiter.connect(outputGain); - outputGain.connect(destination); - - return { input }; -} - -export async function applyAudioMasteringToBuffer({ - audioBuffer, -}: { - audioBuffer: AudioBuffer; -}): Promise { - if (getAudioBufferPeak({ audioBuffer }) <= MASTER_OUTPUT_HEADROOM) { - return audioBuffer; - } - - const offlineContext = new OfflineAudioContext( - audioBuffer.numberOfChannels, - Math.max(1, audioBuffer.length), - audioBuffer.sampleRate, - ); - const source = offlineContext.createBufferSource(); - source.buffer = audioBuffer; - - const { input } = createAudioMasteringChain({ - audioContext: offlineContext, - destination: offlineContext.destination, - }); - source.connect(input); - source.start(0); - - const renderedBuffer = await offlineContext.startRendering(); - clampAudioBufferPeak({ - audioBuffer: renderedBuffer, - maxPeak: MASTER_OUTPUT_HEADROOM, - }); - return renderedBuffer; -} - -function clampAudioBufferPeak({ - audioBuffer, - maxPeak, -}: { - audioBuffer: AudioBuffer; - maxPeak: number; -}): void { - for (let channel = 0; channel < audioBuffer.numberOfChannels; channel++) { - const channelData = audioBuffer.getChannelData(channel); - for (let index = 0; index < channelData.length; index++) { - channelData[index] = Math.max( - -maxPeak, - Math.min(maxPeak, channelData[index]), - ); - } - } -} -- cgit v1.3.1