lufsgen 0.2.0

A rust crate to get LUFS of audio files.
Documentation

LUFS Generator for Android

Cross-compiled Rust binary that calculates LUFS (Loudness Units Full Scale) for audio files on Android using streaming audio decoders.

Prerequisites

  • Android NDK (tested with 23.2.8568313)
  • Rust toolchain

Build Steps

Step 1: Set environment variables

export NDK_HOME=/path/to/android-ndk
export CC_aarch64_linux_android=${NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android29-clang
export CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER=${NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android29-clang

Step 2: Build Rust Binary

cargo build --release --target aarch64-linux-android

The binary will be at: target/aarch64-linux-android/release/lufsgen

Step 3: Deploy to Android

scp -P 8022 target/aarch64-linux-android/release/lufsgen 192.168.136.29:~/
# or with adb
adb push target/aarch64-linux-android/release/lufsgen /data/local/tmp/
adb shell chmod 755 /data/local/tmp/lufsgen

Step 4: Run on Android

# Calculate LUFS for a single file
~/lufsgen /sdcard/music.mp3

# Scan a directory
~/lufsgen /sdcard/Music

# Save results to file
~/lufsgen /sdcard/Music /sdcard/lufs_results.txt

Usage

lufsgen <audio-file>          Calculate LUFS for a single file
lufsgen <directory>           Scan directory for audio files
lufsgen <file/dir> <output>   Save results to file

Output Format

The binary outputs filename|lufs per line:

song.mp3|-12.5
track2.wav|-10.3

Supported Audio Formats

  • MP3 (.mp3)
  • WAV (.wav)
  • AAC (.aac, .m4a, .mp4)
  • OGG (.ogg, .oga)
  • FLAC (.flac)

How It Works

This project uses Symphonia, a pure Rust multimedia framework, to decode audio files. The streaming decoder:

  1. Auto-detects audio format from file content (not just extension)
  2. Decodes audio chunk-by-chunk (8192 samples per chunk)
  3. Feeds samples to EBU R128 loudness analyzer
  4. Returns the integrated LUFS value

This approach is memory-efficient and suitable for mobile devices.

Desktop Testing

cargo build --release
cargo run --release -- /path/to/music.mp3

Troubleshooting

Build fails

Make sure the NDK path is correct and the clang compiler exists:

ls ${NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android29-clang

Permission denied

Make the binary executable:

adb shell chmod 755 /data/local/tmp/lufsgen

M4A/MP4 file fails with "Failed to detect audio format"

Some M4A files have metadata (moov atom) at the end of the file, which Symphonia cannot detect. Convert the file with FFmpeg to move metadata to the beginning:

ffmpeg -i input.m4a -c:a copy -movflags +faststart output.m4a

The -c:a copy flag copies the audio without re-encoding (fast, no quality loss). The -movflags +faststart flag optimizes for streaming by moving the moov atom to the front.

Library Usage

This is also a library that can be used in other Rust projects:

use lufsgen::{LufsCalculator, is_audio_file};

// Check if file is supported
if is_audio_file("song.mp3") {
    // Calculate LUFS
    let lufs = LufsCalculator::new().calculate_from_file("song.mp3")?;
    println!("LUFS: {}", lufs);
}

See lib.rs for the full API documentation.