y-brehm / waveAlign

Python repo for audio loudness matching in order to end the loudness war between DJs.
3 stars 0 forks source link

waveAlign

End the Loudness War between DJs

testing status LICENSE PLACEHOLDER

WaveAlign is a Python command-line tool designed to end the loudness war between DJs by aligning the loudness levels of songs to a specific LUFS level. Loudness Units relative to Full Scale (LUFS) alignment provides several advantages as compared to peak normalization:

It was developed with DJs in mind, which is why all waveAligned tracks retain their metadata as well as timing accuracy for lossy formats (e.g. mp3). The integrity and accuracy of meticulously created cue points within tools such as Rekodbox(R) remains unchanged at their respective positions prior to processing.

QuickstartDetailsFull FeaturesetRun Tests

Quickstart

⚡️ Requirements

⚙️ Installation via GitHub Repo

Clone the Repository

Navigate to your desired directory and use the following command to clone the repository:

git clone https://github.com/y-brehm/wavealign
Compile the mp3processor

Navigate to the mp3processor directory and use cmake to build the mp3processor:

cd src/wavealign/mp3processor
cmake -DCMAKE_BUILD_TYPE=Release .
cmake --build . --config Release

🚀 Usage

Display Argument Parser Help
python3 -m wavealign.batch_process_files -h
Start with Read-Only Mode

Determine the LUFS levels of your songs and an overall possible maximum LUFS level without clipping for your library.

python3 -m wavealign.batch_process_files -i ./your/songs --read_only
Select an Audio Output Folder

An audio output folder is optional, however not specifying it will overwrite your original files with the loudness-aligned versions. Nested input folder structures are supported but will be dissolved in the case of a specified output directory.

Target Loudness Level

The default target is set to -12 dB LUFS, but is user-adjustable between -10 dB LUFS and -30 dB LUFS. If a target value would result in clipping, waveAlign will skip all potentially clipped filed. Additionally a log file is created with information on skipped files.

Example

Processing files from the ./your/songs folder with a loudness target of -16 dB LUFS, storing the processed files in the ./output folder:

python3 -m wavealign.batch_process_files -i ./your/songs -o ./output -t -16

Details

🎶 Supported file types

All Rekordbox(r) supported file types except .m4a and .aac are supported:

.wav, .aiff, .aif, .mp3, .flac

🔌 waveAlignment of your USB Stick

We recommend running waveAlign on your USB stick every time you export new tracks from your library management tool (e.g. Rekordbox(r)). Simply run:

python3 -m wavealign.batch_process_files -i ./<path_to_your_stick>

This will ensure that your mobile music library is always loudness-aligned.

Running waveAlign on your USB stick has an additional advantage: It leaves your original music library on your PC untouched. This means you always have access to your original files, while your USB stick carries the loudness-aligned tracks for your gigs.

💻 waveAlignment of your library

While it is recommended to use waveAlign directly on the files on your USB stick, it is also possible to run waveAlign on your full music library. Please make sure to backup your source files before running. Also you will need to re-analyze your files within your music library tool (e.g. Rekordbox(r)) after waveAlignment.

All metadata as well as timing information, such as cue points, will be retained after processing your library. This is also true for lossy formats (e.g. mp3) which usually require de-coding and en-coding for processing.

In case you add new tracks after processing just run waveAlign again.

🎛️ Detailed preferences

The default settings of WaveAlign, -12 LUFS (target level) and LUFS-S (window size), are optimized for most use cases, so there's usually no need to specify a user target level or a different target window.

Full featureset

python wavealign.py [-i INPUT] [-o OUTPUT] [-w WINDOW_SIZE] [-t TARGET] [-r]

📋 Arguments

-i, --input (str): Specify an input directory to look for audio. Nested structures are allowed.
-o, --output (str): Specify the output directory to save the processed data. If set to None, the original data is overwritten. Nested folder structures will be dissolved.
-w, --window_size (enum, optional): Specify the window size. Follows the Reaper LUFS calculation windows: LUFS-S (3 seconds), LUFS-M (4 seconds), LUFS-I (integrated - whole file)
-t, --target (int, optional): Specify the target loudness level in dB. Has to be between -30 and -9. Default is -14.
-r, --read_only (bool, optional): Run in read-only mode. Only outputs LUFS of input files without processing them. Also outputs library dependent maximum LUFS. Default is False.
-v, --verbose (bool, optional): Save additional debugging information in log file.

💾 Caching

WaveAlign employs an efficient caching mechanism to optimize its processing time, which is utilized when input and output folders are identical. Caching makes use of a YAML file, which is generated in the input folder after each run. The cache file is a record of all processed files in previous runs including the filepath, last modification time and target LUFS.

When running waveAlign the cache file is read and input files are checked against the cache. The input file is skipped if the file path, last modification date as well as current LUFS target setting match with cache data.

If you apply changes to your USB stick after waveAlignment, just re-run the waveAlign.

📻 Lossy Format Handling

WaveAlign utilizes a modified version of mp3gain to prevent unnecessary de- and encoding of lossy file formats such as .mp3. This ensures the timing accuracy of output files and maintains the integrity of timing-dependent information such as cue points.

Run Tests

Make sure you have poetry installed.

Create a local virtual environment using poetry and activate it:

cd <path_to_wavealign_repository>
poetry install --with dev
poetry shell

After that tests can be run from the main directory:

pytest