Skip to content

Latest commit

 

History

History
434 lines (342 loc) · 24 KB

File metadata and controls

434 lines (342 loc) · 24 KB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

damp is a high-quality audio limiter and automated mastering engine written in C++. It was originally developed as the core of the "AI Mastering" service. Now open source under the GNU AGPL-3.0 (the vendored core DSP library deps/bakuage is MIT-licensed; other vendored deps keep their own licenses).

Repository Structure

├── CMakeLists.txt          # Main build configuration (CMake 3.12+)
├── Dockerfile              # Production Docker image (Ubuntu 22.04, multi-stage build)
├── Dockerfile.ci           # CI build environment (Ubuntu 22.04, Intel IPP, valgrind, Ruby, Python)
├── Gemfile / Gemfile.lock  # Ruby dependencies (rspec, rubocop, thor, etc.)
├── Pipfile / Pipfile.lock  # Python 3.11 dependencies (scikit-learn, numpy, scipy)
├── deps/                   # Git submodules and internal libraries
│   └── bakuage/            # Core DSP library (filters, loudness, DFT, memory, etc.)
├── src/                    # C++ source code for all executables
│   ├── phase_limiter/      # Main limiter + auto-mastering algorithms
│   ├── audio_analyzer/     # Audio analysis (loudness, spectrum, sound quality)
│   ├── audio_visualizer/   # Audio visualization output
│   ├── clear_mixer/        # Clear mixer tool
│   ├── spectrogram/        # Spectrogram generator
│   ├── snd_file_info/      # Sound file info utility
│   ├── effect_test/        # Effect testing tool
│   ├── gpu/                # GPU acceleration (OpenCL kernels, experimental)
│   ├── ml/                 # Machine learning model integration
│   ├── mastering_gui/      # Cross-platform GUI (Dear ImGui + GLFW + OpenGL3)
│   ├── rest_api/           # REST API server
│   ├── build_test/         # Build verification test
│   ├── bench/              # Google Benchmark-based performance benchmarks
│   └── test/               # Google Test unit tests
├── spec/                   # Ruby RSpec integration tests
│   ├── phase_limiter_spec.rb   # Phase limiter smoke + sync tests
│   ├── audio_analyzer_spec.rb  # Audio analyzer output validation
│   └── spec_helper.rb
├── script/                 # Utility scripts (Ruby + Python + Bash)
├── scripts/                # Windows dev helpers (rebuild.bat, run_all_modes.ps1, run_specific.ps1, run_validation.ps1)
├── resource/               # Runtime data (analysis data, mastering references, presets)
│   └── presets/            # Factory mastering presets (JSON)
├── test_data/              # Test audio files (WAV, MP3)
├── prebuilt/               # Prebuilt binaries/libraries (win64)
├── ci/                     # CI support files (licenses, release_files.txt)
└── .github/workflows/      # GitHub Actions CI (active)
    └── ci.yml              # Windows self-hosted build + test + release pipeline

Language & Toolchain Versions

  • C++: C++17 (set in CMakeLists.txt), compiled with GCC (Linux), MSVC (Windows), Clang (macOS). Linux builds use -Werror -Wall.
  • Ruby: 3.2.0 (.ruby-version)
  • Python: 3.11.0 (.python-version), managed via pyenv + pipenv
  • CMake: 3.12+
  • Build generator: Ninja (preferred for OOM recovery) or Make

Build System

CMake Configuration

The project uses CMake with platform-specific configurations for Linux, macOS, and Windows.

# Linux release build (Sandy Bridge support for broader compatibility)
cmake -GNinja -DCMAKE_BUILD_TYPE=Release -DSANDYBRIDGE_SUPPORT=ON -DDISABLE_IPP=ON .
ninja -j$(nproc)

# Debug build (for valgrind testing)
cmake -GNinja -DCMAKE_BUILD_TYPE=Debug .
ninja -j$(nproc)

# Build with GUI (requires OpenGL, GLFW3 fetched automatically)
cmake -GNinja -DCMAKE_BUILD_TYPE=Release -DBUILD_MASTERING_GUI=ON .
ninja damp_gui

# Windows (MSVC)
cmake -DCMAKE_BUILD_TYPE=Release -DSANDYBRIDGE_SUPPORT=ON .
cmake --build . --config Release

Key CMake Options

  • SANDYBRIDGE_SUPPORT (ON/OFF) — AVX only for broader CPU compatibility. OFF = AVX2+FMA3
  • DISABLE_IPP (ON/OFF) — Build without Intel IPP (simpler setup; defines BAKUAGE_DISABLE_IPP, disables DFT-dependent features)
  • ENABLE_FFTW (ON/OFF) — Build with FFTW. Required for mastering2 and mastering3 modes (they use STFT-based spectral processing). When OFF those modes throw at runtime.
  • BUILD_MASTERING_GUI (ON/OFF) — Build the cross-platform mastering GUI (fetches ImGui + GLFW via CMake FetchContent)
  • DISABLE_TARGET_GUI (ON/OFF) — Skip building GUI even if BUILD_MASTERING_GUI is ON
  • DISABLE_TARGET_BENCH (ON/OFF) — Skip building benchmarks
  • DISABLE_TARGET_TEST (ON/OFF) — Skip building test executable
  • ENABLE_OPENCL (ON/OFF) — GPU acceleration (experimental)
  • ENABLE_WERROR (ON/OFF, default ON) — Treat warnings as errors
  • Build type: Release (production), Debug (valgrind)

All executables are written to <build dir>/bin (CMAKE_RUNTIME_OUTPUT_DIRECTORY).

Build Targets (executables)

Target Description
damp Main audio limiter/mastering tool
damp_analyzer Audio analysis and sound quality measurement
damp_visualizer Audio visualization generator
damp_mixer Audio mixing tool
damp_spectrogram Spectrogram image generator
damp_fileinfo Sound file metadata utility
damp_effecttest Effect testing utility
damp_server REST API server
damp_buildtest Build verification
damp_test Google Test unit tests
damp_bench Google Benchmark benchmarks
damp_gui Cross-platform GUI mastering suite (requires -DBUILD_MASTERING_GUI=ON)

Git Submodules

Initialize all submodules before building:

git submodule update --init --recursive

Submodules in deps/:

  • bakuage — Core DSP library (internal, under deps/bakuage/)
  • eigen — Linear algebra library
  • libsimdpp — SIMD abstraction library
  • picojson — JSON parser
  • googletest — Google Test framework
  • gflags — Command-line flag parsing
  • optim — Optimization library
  • CImg — Image processing library
  • hnsw — Approximate nearest neighbor search
  • tiny-process-library — Process management (unused; not compiled on any platform)

System Dependencies (Linux)

  • libsndfile, libtbb, libtbbmalloc, libtbbmalloc_proxy
  • Intel IPP (optional — located at /opt/intel/ipp or $IPPROOT, use -DDISABLE_IPP=ON to skip)
  • libpng, zlib, Boost (system, filesystem, serialization, math_tr1, iostreams)
  • ffmpeg (runtime, for audio format conversion)
  • pthread

Testing

C++ Unit Tests (Google Test)

# Run all tests
bin/damp_test

# With sound quality validation data
bin/damp_test --sound_quality2_analysis_data=/path/to/analysis_data

Test source files are in src/test/. Key test areas:

  • clear_mixer_filter3.cpp, clear_mixer_filter4.cpp — Clear mixer filter tests
  • delay_filter2.cpp — Delay filter tests
  • fir_filter_bank.cpp, fir_resample_filter.cpp — FIR filter tests
  • loudness.cpp — Loudness measurement tests
  • peak.cpp — Peak detection tests
  • sound_quality2.cpp — Sound quality calculator validation
  • vector_math.cpp — SIMD vector math tests
  • gpu_vector_math.cpp — GPU vector math tests (OpenCL)
  • ml_model.cpp — Machine learning model tests
  • rest_api.cpp — REST API endpoint tests
  • lof.cpp — Local outlier factor tests

Ruby Integration Tests (RSpec)

bundle install
bundle exec rspec

Test files in spec/:

  • phase_limiter_spec.rb — Smoke tests (various mastering modes) and sync tests (sample-level frame count matching across format conversions)
  • audio_analyzer_spec.rb — Validates JSON output fields (channels, loudness, peak, spectrum, etc.)

Ruby Linting (RuboCop)

bundle exec rubocop -a    # Auto-correct
git diff --exit-code       # Verify no uncommitted style changes (enforced in CI)

Configuration in .rubocop.yml:

  • Target Ruby 3.2
  • Rails mode enabled
  • Non-ASCII comments allowed (Japanese comments are common)
  • Relaxed metrics (line length, method length, block length, ABC size disabled)
  • Max cyclomatic complexity: 8
  • Max class length: 300

Python Linting

pyenv exec pipenv install
pyenv exec pipenv run autopep8 -i script/*.py

Valgrind Memory Checks

CI runs valgrind on debug builds for all major executables (damp_analyzer, damp in multiple modes, damp_visualizer, damp_mixer, and the damp_test binary).

Benchmarks

bin/damp_bench                  # Google Benchmark suite
hyperfine -w 1 -m 10 'bin/damp_analyzer ...'    # CLI benchmarking

CI/CD

GitHub Actions (.github/workflows/ci.yml)

Three-platform pipeline, build → test → release per platform:

  • Windows: self-hosted runner ([self-hosted, Windows, X64]). NuGet Intel IPP + TBB, conda Boost/libpng/FFTW. Full build with IPP, FFTW, and the GUI.
  • Linux: self-hosted runner ([self-hosted, Linux, X64]). System dev packages (see ci.yml header for the runner contract), DISABLE_IPP=ON, FFTW on, CLI tools only (no GUI — needs X11 dev headers). Also builds and runs damp_test (gtest).
  • macOS: GitHub-hosted macos-15-intel (the codebase requires x86-64 SIMD; Apple-Silicon images cannot build it). Brew deps, DISABLE_IPP=ON, FFTW on, CLI only. Build + smoke test in one job.
  • Triggers: push to main, pull_request to main, v* tags, workflow_dispatch
  • Security: jobs on self-hosted runners are skipped for PRs from forks (github.event.pull_request.head.repo.full_name == github.repository gate) so fork code never executes on project hardware. Top-level permissions: contents: read; only release jobs get contents: write.
  • sound_quality2_cache: gitignored generated artifact; every build job regenerates it from in-repo resource/analysis_data, and release packaging hard-fails if it is missing.
  • Tests: binary --version smoke tests, preset JSON validation, fast mastering runs (mastering6 + mastering5 on Windows; default/mastering2/mastering6 on Linux). The full slow mode matrix runs when workflow_dispatch is invoked with run_mastering_tests=true.
  • Release: Push a v* tag to publish damp-windows-x64.zip, damp-linux-x64.tar.xz, and damp-macos-x64.tar.gz to a GitHub Release.

Key Conventions

Code Style

  • C++: C++17 standard. Uses -Werror -Wall on Linux (controlled by ENABLE_WERROR, default ON). Comments are frequently in Japanese.
  • Ruby: Enforced by RuboCop (see .rubocop.yml). Frozen string literals required.
  • Python: Enforced by autopep8.

Architecture Notes

  • The bakuage library (deps/bakuage/) is the core DSP engine — all executables link against it as a static library.
  • SIMD is used extensively via libsimdpp (AVX/AVX2/FMA3). The phase_limiter::DefaultSimdType is float32x8.
  • Memory management uses custom aligned allocators (bakuage::AlignedMalloc) for SIMD alignment (64-byte cache line).
  • Command-line parsing uses gflags (DEFINE_bool/string/int32/double macros).
  • JSON I/O uses picojson.
  • Audio I/O uses libsndfile (via bakuage/sndfile_wrapper.h) and ffmpeg for format conversion.
  • Image output uses CImg with PNG support (no display, cimg_display=0).
  • Parallelism uses Intel TBB.
  • Eigen is used for linear algebra (parallelization disabled: EIGEN_DONT_PARALLELIZE).

Important Flags / Defines

  • SIMDPP_ARCH_X86_AVX, SIMDPP_ARCH_X86_AVX2, SIMDPP_ARCH_X86_FMA3 — SIMD instruction set selection
  • BA_FMA_ENABLED — FMA instruction support in bakuage
  • DAMP_ENABLE_FFTW — Enable FFTW backend (replaces legacy PHASELIMITER_ENABLE_FFTW)
  • ARMA_DONT_USE_HDF5 — Avoids HDF5 linking issues with Armadillo
  • EIGEN_DONT_PARALLELIZE — Disables Eigen's internal parallelization
  • cimg_display=0 — Disables CImg display (headless operation)
  • cimg_use_png — Enables PNG support in CImg

Runtime Data

  • resource/analysis_data/ — Pre-computed analysis data used by damp_analyzer
  • resource/detection_preparation*.json — Genre-specific detection data
  • resource/mastering_reference.json — Mastering reference parameters
  • resource/trained_mastering_model.json — Trained mastering ML model
  • resource/progression_mapping.json — Progression mapping data
  • resource/sound_quality2_cache — Precomputed sound quality model (generated by damp_analyzer --mode=sound_quality2_preparation)
  • resource/presets/ — Factory mastering presets (JSON)
  • test_data/ — Test audio files (test1.mp3, test2.wav, test5.wav, icon images)

Mastering Modes

The damp engine supports six distinct mastering modes (selected via --mastering_mode):

  • classic — 9-band loudness matching against mastering_reference.json. Fast and transparent. (mode 0)
  • mastering2 — STFT + per-mel-band compression against a reference JSON. Requires --mastering2_config_file (e.g. resource/mastering2_config.json; the CLI has no default and errors clearly if it is omitted). Requires FFTW build. (mode 1)
  • mastering3 — Simulated-annealing over per-band compression parameters minimizing an acoustic-entropy cost. Slower; tunable via --mastering3_iteration. Requires FFTW build. (mode 2)
  • mastering5 — Differential-evolution search guided by a pre-trained sound-quality ML model. Requires --sound_quality2_cache (generate with damp_analyzer --mode=sound_quality2_preparation --analysis_data_dir=resource/analysis_data --sound_quality2_cache=resource/sound_quality2_cache). (mode 3)
  • mastering6 — Configurable 2-8-band processor with envelope compression, tanh saturation, M/S width, spectral tilt, TPDF dither. (mode 4)
  • mastering_a — Professional 8-stage chain: Corrective EQ → Dynamic EQ → Multiband Compression → Transient Shaping → Harmonic Saturation (tube/tape/transformer) → Stereo Imaging → Look-ahead Limiter → Final Polish. 28 user-facing knobs. (mode 5)

Note: mode integer 4 in the GUI dropdown maps to mastering6, not "mastering4" — the engine numbering skips 4.

Mastering 6 Algorithm

The mastering6 algorithm (src/phase_limiter/auto_mastering6.h/cpp) is a modern multiband mastering processor with:

  • Multiband dynamics: Configurable 2-8 bands with ERB-spaced crossover frequencies, per-band soft-knee compression with envelope following
  • Harmonic saturation: Frequency-dependent tanh soft clipping that adds analog warmth
  • Stereo imaging: Per-band M/S width control with auto-narrowing bass and auto-widening highs
  • Spectral tilt: Brightness control via frequency-dependent gain adjustment
  • Reference matching: Loads mastering_reference.json for spectral target matching
  • TPDF dithering: Triangular probability density function dithering for 24-bit output

User-facing parameters (set via gflags):

Flag Range Description
mastering6_intensity 0-1 Overall processing intensity
mastering6_warmth 0-1 Harmonic saturation amount
mastering6_width 0-2 Stereo width multiplier (1 = original)
mastering6_dynamics 0-1 Dynamic range preservation (0 = heavy compression)
mastering6_brightness -1 to 1 Spectral tilt (-1 = dark, 0 = neutral, 1 = bright)
mastering6_band_count 2-8 Number of processing bands
mastering6_dither bool Enable TPDF dithering

Mastering A Algorithm

The mastering_a algorithm (src/phase_limiter/auto_mastering_a.h/cpp) is a professional-grade 8-stage mastering chain modeled after the workflows of top mastering engineers and the algorithms found in professional mastering software (iZotope Ozone, FabFilter Pro-L, Waves Abbey Road). This is the first algorithm in the new "A" family (letter-based naming).

Signal chain (in order):

  1. Corrective EQ — FFT-based spectral analysis compares input to a target curve (or reference track), designs a correction FIR filter, and applies transparent tonal correction. Limited to +/-6dB per band for safe mastering.

  2. Dynamic EQ — 3-band frequency-selective dynamic processing:

    • Low (200-400Hz): De-mud — reduces boxiness when low-mids are too loud
    • Mid (2-5kHz): De-harsh — reduces ear fatigue from aggressive upper-mids
    • High (6-12kHz): De-ess — reduces sibilance in the treble
    • Only activates when signal exceeds threshold (unlike static EQ)
  3. Multiband Compression — 4-band (120Hz/1.2kHz/6kHz crossovers) with:

    • Soft-knee compression curve with configurable ratio and threshold
    • Band-specific attack/release scaling (slower for bass)
    • Stereo-linked envelope following
    • Parallel compression (NY-style) wet/dry mix
  4. Transient Shaping — Dual-envelope transient detection (SPL Transient Designer principle):

    • Fast envelope tracks transients, slow envelope tracks sustained level
    • Independent attack shaping (-1 soften, +1 sharpen/punch up)
    • Independent sustain shaping (-1 reduce body, +1 boost body)
  5. Harmonic Saturation — Three selectable analog models:

    • Tube (12AX7): Asymmetric soft clipping, odd harmonics (3rd, 5th, 7th). Warm, growly character.
    • Tape (Studer A800): Magnetic hysteresis approximation, head bump (+dB at 80Hz), HF roll-off above 15kHz. Smooth, cohesive "glue."
    • Transformer (Neve 1073): Even harmonics (2nd, 4th) via quadratic waveshaper. Thick, fat coloration.
    • Drive and wet/dry mix controls
  6. Stereo Imaging — Per-band M/S (Mid/Side) processing:

    • 3-band split (bass / mid / high) with independent width per band
    • Bass mono-ification below configurable frequency (for vinyl/club compatibility)
    • Uses FIR band-splitting for phase-accurate processing
  7. Look-ahead Limiter — Transparent brick-wall limiting:

    • 5ms look-ahead anticipates peaks before they occur
    • Multi-stage release envelope (fast/medium/slow) for program-dependent behavior
    • True peak ceiling control
  8. Final Polish — Last touches:

    • Air band enhancement: harmonic exciter above 8kHz adds shimmer and openness
    • Sub-bass tightening: reduces sub-bass (<60Hz) ringing and overshoot
    • DC offset removal (5Hz high-pass)
    • TPDF dithering at 24-bit level

User-facing parameters (28 total, set via gflags):

Flag Range Description
mastering_a_intensity 0-1 Master intensity (scales all stages)
mastering_a_corrective_eq_enabled bool Enable corrective EQ stage
mastering_a_corrective_eq_amount 0-1 Corrective EQ strength
mastering_a_deq_low_gain -12 to +6 dB Dynamic EQ de-mud gain
mastering_a_deq_mid_gain -12 to +6 dB Dynamic EQ de-harsh gain
mastering_a_deq_high_gain -12 to +6 dB Dynamic EQ de-ess gain
mastering_a_deq_threshold -30 to 0 dB Dynamic EQ activation threshold
mastering_a_comp_threshold -30 to 0 dB Multiband comp threshold
mastering_a_comp_ratio 1-8 Compression ratio
mastering_a_comp_attack 0.1-100 ms Compression attack time
mastering_a_comp_release 10-1000 ms Compression release time
mastering_a_comp_mix 0-1 Parallel compression wet/dry
mastering_a_transient_attack -1 to +1 Transient attack shaping
mastering_a_transient_sustain -1 to +1 Transient sustain shaping
mastering_a_saturation_model 0/1/2 Saturation: tube/tape/transformer
mastering_a_saturation_drive 0-1 Saturation drive amount
mastering_a_saturation_mix 0-1 Saturation wet/dry mix
mastering_a_stereo_low_width 0-2 Low-band stereo width
mastering_a_stereo_mid_width 0-2 Mid-band stereo width
mastering_a_stereo_high_width 0-2 High-band stereo width
mastering_a_stereo_bass_mono_freq 0-300 Hz Bass mono crossover
mastering_a_limiter_ceiling -3 to 0 dB Limiter ceiling
mastering_a_limiter_release 10-500 ms Limiter release time
mastering_a_air_amount 0-1 Air band enhancement
mastering_a_sub_bass_tighten 0-1 Sub-bass tightening
mastering_a_target_loudness -24 to -6 LUFS Target loudness
mastering_a_dither bool Enable TPDF dithering
mastering_a_reference_match 0-1 Reference spectrum matching

Mastering GUI

The damp_gui target provides a cross-platform graphical interface for the mastering engine.

Architecture

  • Framework: Dear ImGui + GLFW + OpenGL3 (immediate-mode GUI)
  • Processing: Invokes the damp CLI binary as a subprocess
  • Presets: JSON files loaded from resource/presets/ (factory) and user_presets/ (user-created), both resolved relative to the executable directory
  • Dependencies: Fetched automatically via CMake FetchContent (ImGui v1.89.9, GLFW 3.3.8)

Resource Path Discovery

The GUI auto-discovers resource files (mastering_reference.json, analysis_data/, sound_quality2_cache, mastering2_config.json, ffmpeg) and the resource/presets/ directory at startup by searching candidate paths relative to the executable directory, walking up to 4 parent levels (so it works both from build/bin/ in a source tree and from an unzipped release). Discovered paths are stored as absolute paths because the damp subprocess may inherit a different working directory.

Existence is tested with stat(), not fopen(): analysis_data and resource/presets are directories, and fopen() on a directory fails — that previously made the GUI report "Could not find analysis_data" and "No factory presets found" even though both were present.

When a preset is loaded, its serialized path fields (e.g. sound_quality2_cache) are only adopted if the file actually exists (ApplyPresetPath in main.cpp); otherwise the auto-discovered path is kept and pushed back into the config. Factory presets carry relative paths like ./sound_quality2_cache that are usually invalid, so bypassing this check breaks the mastering subprocess.

GUI Source Files

File Purpose
src/mastering_gui/main.cpp Entry point, ImGui setup, all GUI panel rendering (6 tabs), main loop
src/mastering_gui/mastering_config.h Config struct with all mastering parameters (incl. mastering6, mastering_a), JSON serialization, command-line builder
src/mastering_gui/preset_manager.h Preset scanning, loading, saving (factory + user presets)
src/mastering_gui/process_runner.h Background subprocess execution with real-time progress parsing
src/mastering_gui/file_dialog.h Cross-platform native file dialogs (zenity/kdialog/osascript/PowerShell)
src/mastering_gui/audio_analysis.h AudioAnalyzer subprocess wrapper, parses damp_analyzer JSON output into AudioAnalysis struct
src/mastering_gui/metering_panel.h ImGui drawing widgets: meter bars, waveform, spectrum, spectrum comparison, stats table

GUI Tabs

Tab Description
File Input/output file selection, output format (WAV/MP3/AAC), bit depth, sample rate
Mastering Auto-mastering mode selection (Classic through Mastering A), mode-specific controls, reverb
Limiter & Dynamics Pre-processing, compression, limiter settings, loudness target, quality
Presets Factory and user preset grid with tooltips, save/load
Advanced Performance, optimization, oversampling, noise update, time range, paths
Analysis Audio metering (LUFS/peak/RMS bars), A/B comparison table, waveform display, spectrum comparison

Audio Analysis & A/B Comparison

The Analysis tab provides:

  • Level meters: LUFS loudness, true peak, and RMS meters for input and output with color-coded bars
  • A/B comparison table: Side-by-side metrics with delta highlighting (green = gain, red = loss)
  • Waveform display: Input and output waveform visualizations
  • Spectrum comparison: Before/after frequency spectrum overlay with legend
  • Auto-analyze: Optionally triggers damp_analyzer on both input and output after mastering completes

Factory Presets

38 production mastering presets inspired by iconic mastering styles. See resource/presets/ for the full set. Naming convention: m2_* use mastering2, m6_* use mastering6, ma_* use mastering_a; the rest are engineer/platform/genre styles on various modes.