./normalize.sh /Users/viktor/Music/input.mp3ВХОДНОЙ ФАЙЛ
/path/to/input.mp3
|
| Main.main()
v
+--------------------------------------------------------------------------+
| 1. Загрузка и декодирование |
| |
| AudioLoader.load(inputFile) |
| -> openPcmStream(inputFile) |
| -> buildDecodedFormat(baseFormat) |
| -> readPcm16Samples(pcmStream) |
| -> toChannelData(interleavedSamples, channels) |
| |
| Результат: |
| DecodedAudio |
| - AudioFormat |
| - double[][] channels |
+--------------------------------------------------------------------------+
|
| Equalizer.apply(audio, EqualizerSettings.defaultEightBand())
v
+--------------------------------------------------------------------------+
| 2. Частотная обработка эквалайзером |
| |
| copyChannels(audio.getChannels()) |
| applyPreamp(equalizedChannels, preampDb) |
| |
| Дальше по каждой полосе: |
| LowShelfBand.createCoefficients(sampleRate) |
| PeakingBand.createCoefficients(sampleRate) |
| HighShelfBand.createCoefficients(sampleRate) |
| |
| И по каждому каналу: |
| new BiquadFilter(coefficients).process(channel) |
| |
| Порядок полос из пресета: |
| 63 Hz LowShelf +2.0 dB |
| 125 Hz Peaking +1.0 dB |
| 250 Hz Peaking +0.5 dB |
| 500 Hz Peaking -0.5 dB |
| 1000 Hz Peaking -1.5 dB |
| 2000 Hz Peaking +0.5 dB |
| 4000 Hz Peaking +1.0 dB |
| 8000 Hz HighShelf +1.5 dB |
| |
| Результат: |
| DecodedAudio после EQ |
+--------------------------------------------------------------------------+
|
| LufsNormalizer.normalize(equalizedAudio)
v
+--------------------------------------------------------------------------+
| 3. Измерение loudness и нормализация |
| |
| LoudnessMeter.measureIntegratedLufs(...) |
| -> KWeightingFilter.apply(channels, sampleRate) |
| -> деление на блоки 400 ms / шаг 100 ms |
| -> absolute gate (-70 LUFS) |
| -> relative gate (ungated LUFS - 10 LU) |
| |
| Дальше: |
| requestedGain = targetLUFS - inputLUFS |
| applyGainWithPeakLimit(normalizedChannels, requestedGain) |
| повторное measureIntegratedLufs(...) |
| |
| Результат: |
| LufsNormalizationResult |
| - inputLufs |
| - outputLufs |
| - requestedGainDb |
| - appliedGainDb |
| - peakLimited |
+--------------------------------------------------------------------------+
|
| Mp3Writer.write(outputFile, result.getAudio())
v
+--------------------------------------------------------------------------+
| 4. Сборка PCM и кодирование в MP3 |
| |
| toInterleavedPcm16(audio.getChannels()) |
| resolveChannelMode(audio.getFormat()) |
| new LameEncoder(...) |
| encodeBuffer(...) |
| encodeFinish(...) |
| Files.write(outputFile, mp3Bytes) |
| |
| Результат: |
| /path/to/input_lufs.mp3 |
+--------------------------------------------------------------------------+
|
v
ГОТОВЫЙ ВЫХОДНОЙ ФАЙЛ