Files

32 KiB

Volume Normalization Modal - Design Document

Overview

The Volume Normalization Modal is a PyQt6 dialog component that enables users to configure audio loudness normalization settings before downloading tracks. The feature integrates with the existing Download tab and provides both preset configurations and custom parameter tuning. Settings persist globally across application sessions, ensuring consistent audio processing behavior.

Key Design Goals

  1. User-Friendly Configuration: Provide preset options for non-technical users while allowing advanced customization
  2. Persistent Settings: Store user preferences to avoid reconfiguration across sessions
  3. Seamless Integration: Integrate with existing downloader and config modules without breaking changes
  4. Validation and Safety: Ensure all parameters conform to FFmpeg loudnorm specifications
  5. Consistent UI/UX: Match existing modal styling and application design patterns

Architecture

System Context

The Volume Normalization Modal operates within a three-layer architecture:

┌─────────────────────────────────────────────────────────────┐
│                    UI Layer (PyQt6)                         │
│  ┌──────────────────────────────────────────────────────┐   │
│  │  DownloadTab                                         │   │
│  │  ├─ Normalization Settings Button                   │   │
│  │  └─ Preset Indicator                                │   │
│  │                                                      │   │
│  │  NormalizationModal (Dialog)                        │   │
│  │  ├─ Preset Selection (Radio Buttons)                │   │
│  │  ├─ Parameter Input Fields (I, TP, LRA)            │   │
│  │  ├─ Validation & Error Display                      │   │
│  │  └─ Apply/Cancel Buttons                            │   │
│  └──────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────┘
                            ↓
┌─────────────────────────────────────────────────────────────┐
│                  Config Layer (Persistence)                 │
│  ┌──────────────────────────────────────────────────────┐   │
│  │  Config Module (src/core/config.py)                 │   │
│  │  ├─ Normalization Settings Storage                  │   │
│  │  ├─ Preset Definitions                              │   │
│  │  └─ Default Configuration                           │   │
│  └──────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────┘
                            ↓
┌─────────────────────────────────────────────────────────────┐
│                  Core Layer (Processing)                    │
│  ┌──────────────────────────────────────────────────────┐   │
│  │  YouTubeDownloader (src/core/downloader.py)         │   │
│  │  ├─ normalize_volume() - Uses Config settings       │   │
│  │  ├─ Parameter Validation                            │   │
│  │  └─ FFmpeg Command Construction                     │   │
│  └──────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────┘

Data Flow

  1. Initialization: Application starts → Config loads saved settings → Modal displays current preset
  2. User Interaction: User selects preset/custom params → Modal validates → User clicks Apply
  3. Persistence: Modal saves settings to Config → Config persists to storage
  4. Download: Download initiated → Downloader reads settings from Config → FFmpeg applies normalization

Components and Interfaces

1. NormalizationModal Class

File: src/ui/components/normalization_modal_qt.py

Responsibilities:

  • Display preset selection interface
  • Manage custom parameter input fields
  • Validate user input against FFmpeg specifications
  • Handle apply/cancel operations
  • Load and display current settings

Key Methods:

class NormalizationModal(QDialog):
    """Modal dialog for configuring volume normalization settings."""
    
    settings_applied = pyqtSignal(dict)  # Emitted when Apply is clicked
    
    def __init__(self, parent, config):
        """Initialize modal with current settings from config."""
        
    def _load_current_settings(self):
        """Load saved settings from Config module."""
        
    def _on_preset_selected(self, preset_name: str):
        """Handle preset selection - update fields and enable/disable editing."""
        
    def _on_parameter_changed(self, param_name: str, value: str):
        """Handle parameter input changes - validate and update UI."""
        
    def _validate_parameters(self) -> tuple[bool, str]:
        """Validate all parameters against FFmpeg specifications."""
        
    def _update_parameter_fields(self, params: dict):
        """Update input fields with parameter values."""
        
    def _enable_custom_editing(self, enabled: bool):
        """Enable/disable custom parameter input fields."""
        
    def _on_apply(self):
        """Save settings and close modal."""
        
    def _on_cancel(self):
        """Close modal without saving."""
        
    def get_current_settings(self) -> dict:
        """Return current settings as dict."""

Signals:

  • settings_applied(dict): Emitted when Apply is clicked with new settings

2. DownloadTab Integration

File: src/ui/tabs/download_tab_qt.py (modifications)

Changes:

  • Add "Normalization Settings" button to control panel
  • Add preset indicator label showing current active preset
  • Connect button to open NormalizationModal
  • Display tooltip with current parameters on hover

New Methods:

def _open_normalization_modal(self):
    """Open the normalization settings modal."""
    
def _update_preset_indicator(self, preset_name: str):
    """Update the preset indicator label."""
    
def _on_normalization_settings_applied(self, settings: dict):
    """Handle settings applied from modal."""

3. Config Module Extensions

File: src/core/config.py (modifications)

New Class: NormalizationSettings

class NormalizationSettings:
    """Manages normalization settings persistence."""
    
    # Preset definitions
    PRESETS = {
        'Quiet': {'I': -18, 'TP': -1.5, 'LRA': 11},
        'Normal': {'I': -14, 'TP': -1.5, 'LRA': 11},
        'Loud': {'I': -10, 'TP': -1.5, 'LRA': 11},
        'Very Loud': {'I': -6, 'TP': -1.5, 'LRA': 11},
    }
    
    # Parameter validation ranges
    PARAM_RANGES = {
        'I': (-23, 0),      # Integrated Loudness (LUFS)
        'TP': (-5, 0),      # True Peak (dBFS)
        'LRA': (1, 20),     # Loudness Range (LU)
    }
    
    @classmethod
    def load_settings(cls) -> dict:
        """Load normalization settings from storage."""
        
    @classmethod
    def save_settings(cls, preset: str, custom_params: dict = None) -> bool:
        """Save normalization settings to storage."""
        
    @classmethod
    def get_default_settings(cls) -> dict:
        """Return default settings (Normal preset)."""
        
    @classmethod
    def validate_parameters(cls, params: dict) -> tuple[bool, str]:
        """Validate parameters against ranges."""
        
    @classmethod
    def get_preset_params(cls, preset_name: str) -> dict:
        """Get parameters for a preset."""

Storage Format (JSON in config file):

{
  "normalization": {
    "current_preset": "Normal",
    "custom_parameters": {
      "I": -14,
      "TP": -1.5,
      "LRA": 11
    }
  }
}

4. Downloader Module Integration

File: src/core/downloader.py (modifications)

Changes to normalize_volume method:

def normalize_volume(self, filepath: str, timeout: int = 60) -> bool:
    """Normalize audio loudness using configured settings."""
    
    if not self.ffmpeg:
        return True
    
    # Load current settings from Config
    settings = NormalizationSettings.load_settings()
    params = settings.get('custom_parameters', {})
    
    # Validate parameters
    valid, error_msg = NormalizationSettings.validate_parameters(params)
    if not valid:
        logger.error(f"Invalid normalization parameters: {error_msg}")
        return False
    
    # Construct FFmpeg filter string
    filter_str = f"loudnorm=I={params['I']}:TP={params['TP']}:LRA={params['LRA']}"
    
    # ... rest of implementation

Data Models

Normalization Settings Structure

{
    "current_preset": str,           # "Quiet", "Normal", "Loud", "Very Loud", or "Custom"
    "custom_parameters": {
        "I": float,                  # Integrated Loudness (-23 to 0 LUFS)
        "TP": float,                 # True Peak (-5 to 0 dBFS)
        "LRA": float,                # Loudness Range (1 to 20 LU)
    }
}

Preset Definitions

PRESETS = {
    "Quiet": {
        "I": -18,
        "TP": -1.5,
        "LRA": 11,
        "description": "For content that should remain quiet"
    },
    "Normal": {
        "I": -14,
        "TP": -1.5,
        "LRA": 11,
        "description": "Default, suitable for most music"
    },
    "Loud": {
        "I": -10,
        "TP": -1.5,
        "LRA": 11,
        "description": "For content that should be louder"
    },
    "Very Loud": {
        "I": -6,
        "TP": -1.5,
        "LRA": 11,
        "description": "For maximum loudness"
    }
}

Parameter Validation Ranges

PARAM_RANGES = {
    "I": {
        "min": -23,
        "max": 0,
        "unit": "LUFS",
        "description": "Integrated Loudness"
    },
    "TP": {
        "min": -5,
        "max": 0,
        "unit": "dBFS",
        "description": "True Peak"
    },
    "LRA": {
        "min": 1,
        "max": 20,
        "unit": "LU",
        "description": "Loudness Range"
    }
}

Module Changes

Config Module (src/core/config.py)

Additions:

  1. Add NormalizationSettings class with preset definitions and validation logic
  2. Add storage path constant for normalization settings
  3. Add methods to load/save normalization settings
  4. Add default settings initialization

Storage Location: Settings stored in application config directory (platform-specific):

  • Windows: %APPDATA%/dl_yt/config.json
  • macOS: ~/Library/Application Support/dl_yt/config.json
  • Linux: ~/.config/dl_yt/config.json

Downloader Module (src/core/downloader.py)

Modifications:

  1. Update __init__ to load normalization settings from Config
  2. Modify normalize_volume to use configured parameters instead of hardcoded values
  3. Add parameter validation before FFmpeg command construction
  4. Add logging for parameter usage and validation failures

Backward Compatibility: If no settings are configured, default to "Normal" preset (existing behavior)

DownloadTab Module (src/ui/tabs/download_tab_qt.py)

Additions:

  1. Add "Normalization Settings" button to control panel
  2. Add preset indicator label
  3. Add method to open NormalizationModal
  4. Add method to handle settings changes
  5. Connect modal signals to update UI

Button Placement: In the control panel area, positioned after "Browse Output" button


UI/UX Design

Modal Layout

┌─────────────────────────────────────────────────────────┐
│ Volume Normalization Settings                        [X] │
├─────────────────────────────────────────────────────────┤
│                                                         │
│ Current Preset: Normal                                  │
│ Parameters: I=-14 TP=-1.5 LRA=11                       │
│                                                         │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Presets:                                            │ │
│ │ ○ Quiet      (I=-18, TP=-1.5, LRA=11)              │ │
│ │ ● Normal     (I=-14, TP=-1.5, LRA=11)              │ │
│ │ ○ Loud       (I=-10, TP=-1.5, LRA=11)              │ │
│ │ ○ Very Loud  (I=-6, TP=-1.5, LRA=11)               │ │
│ │ ○ Custom                                            │ │
│ └─────────────────────────────────────────────────────┘ │
│                                                         │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Custom Parameters (disabled):                       │ │
│ │ Integrated Loudness (I):  [-14]  LUFS              │ │
│ │ True Peak (TP):           [-1.5] dBFS              │ │
│ │ Loudness Range (LRA):     [11]   LU                │ │
│ └─────────────────────────────────────────────────────┘ │
│                                                         │
│ [Error message area - hidden when no errors]           │
│                                                         │
│                              [Cancel]  [Apply]         │
└─────────────────────────────────────────────────────────┘

Styling

  • Background: #212121 (dark gray, matching DeleteModal)
  • Text Color: #ffffff (white for primary, #cccccc for secondary)
  • Input Fields: QLineEdit/QDoubleSpinBox with dark theme
  • Buttons:
    • Cancel: Gray (#757575)
    • Apply: Blue (#2196F3) when enabled, gray when disabled
  • Modal Size: 500x400 pixels
  • Font: 11pt for labels, 12pt for buttons

Error Display

Error messages appear in a red-tinted area above the buttons:

  • Non-numeric input: "Parameter must be a number"
  • Out of range: "Parameter {name} must be between {min} and {max}"
  • Save failure: "Failed to save settings. Please try again."

Download Tab Integration

Preset indicator in control panel:

[Normalization Settings] | Preset: Normal (I=-14, TP=-1.5, LRA=11)

Tooltip on hover shows full parameter details.


State Management

Modal State Lifecycle

┌─────────────────────────────────────────────────────────┐
│                    CLOSED                               │
│  (Settings not loaded, modal not visible)               │
└────────────────────┬────────────────────────────────────┘
                     │ User clicks "Normalization Settings"
                     ↓
┌─────────────────────────────────────────────────────────┐
│                    OPENING                              │
│  (Load settings from Config, populate UI)               │
└────────────────────┬────────────────────────────────────┘
                     │ Settings loaded
                     ↓
┌─────────────────────────────────────────────────────────┐
│                    OPEN                                 │
│  (Modal visible, user can interact)                     │
└────────┬──────────────────────────────────┬─────────────┘
         │ User clicks Cancel               │ User clicks Apply
         ↓                                  ↓
    CLOSED                          VALIDATING
    (Discard changes)               (Check parameters)
                                         │
                                    ┌────┴────┐
                                    │          │
                              Valid │          │ Invalid
                                    ↓          ↓
                                SAVING    ERROR
                                (Persist) (Show error)
                                    │          │
                                    └────┬─────┘
                                         │
                                    CLOSED

Settings Loading

  1. Application Startup:

    • Config module loads settings from storage
    • If missing/corrupted, use defaults
    • Log warning if loading fails
  2. Modal Open:

    • Load current settings from Config
    • Display current preset as selected
    • Populate parameter fields
    • Enable/disable custom fields based on preset
  3. Download Initiation:

    • Downloader reads settings from Config
    • Validate parameters before use
    • Log parameters being applied

Settings Saving

  1. Apply Button Clicked:

    • Validate all parameters
    • If invalid, show error and don't save
    • If valid, save to Config
    • Emit signal with new settings
    • Close modal
  2. Config Save:

    • Write to persistent storage
    • Log success/failure
    • Notify UI of changes

Integration Points

1. DownloadTab ↔ NormalizationModal

Connection:

# In DownloadTab.__init__
self.normalization_modal = NormalizationModal(self, self.config)
self.normalization_modal.settings_applied.connect(self._on_normalization_settings_applied)
self.normalization_btn.clicked.connect(self._open_normalization_modal)

Data Flow:

  • DownloadTab passes Config instance to modal
  • Modal emits settings_applied signal when Apply clicked
  • DownloadTab updates preset indicator

2. NormalizationModal ↔ Config

Connection:

# In NormalizationModal
settings = NormalizationSettings.load_settings()
NormalizationSettings.save_settings(preset, custom_params)

Data Flow:

  • Modal reads current settings on open
  • Modal saves settings on Apply
  • Config handles persistence

3. Downloader ↔ Config

Connection:

# In YouTubeDownloader.normalize_volume
settings = NormalizationSettings.load_settings()
params = settings['custom_parameters']

Data Flow:

  • Downloader reads settings before normalization
  • Downloader validates parameters
  • Downloader constructs FFmpeg command with parameters

4. Backward Compatibility

Existing Code:

  • Current normalize_volume uses hardcoded: loudnorm=I=-14:TP=-1.5:LRA=11
  • This matches the "Normal" preset

Migration:

  • If no settings exist, default to "Normal" preset
  • Existing behavior preserved
  • No breaking changes to API

Correctness Properties

A property is a characteristic or behavior that should hold true across all valid executions of a system—essentially, a formal statement about what the system should do. Properties serve as the bridge between human-readable specifications and machine-verifiable correctness guarantees.

Property 1: Preset Selection Updates Parameters

For any preset selection (Quiet, Normal, Loud, Very Loud), selecting that preset shall update the parameter input fields to display the correct values for that preset.

Validates: Requirements 2.3

Property 2: Non-Custom Presets Disable Editing

For any non-Custom preset selection, the parameter input fields shall be disabled (read-only) and cannot be edited by the user.

Validates: Requirements 2.4

Property 3: Custom Preset Enables Editing

When the Custom preset is selected, the parameter input fields shall be enabled and editable by the user.

Validates: Requirements 2.5

Property 4: Modal Loads Current Settings

For any application state with saved normalization settings, opening the NormalizationModal shall display the currently active preset as pre-selected.

Validates: Requirements 2.6

Property 5: Parameter Validation Enforces Ranges

For any parameter value entered in a custom parameter field, if the value is outside the allowed range (I: -23 to 0, TP: -5 to 0, LRA: 1 to 20), an error message shall be displayed and the Apply button shall remain disabled.

Validates: Requirements 3.3, 3.4, 8.2, 8.3

Property 6: Cancel Discards Changes

For any changes made in the NormalizationModal, clicking Cancel shall close the modal without saving any changes, and the previous settings shall remain active.

Validates: Requirements 1.9

Property 7: Apply Saves Settings

For any valid parameter configuration in the NormalizationModal, clicking Apply shall save the settings to persistent storage and close the modal.

Validates: Requirements 1.10, 4.1

Property 8: Settings Persist Across Sessions

For any normalization settings saved via Apply, when the application is restarted, the NormalizationModal shall load and display the previously saved settings.

Validates: Requirements 4.3

Property 9: Downloader Uses Configured Settings

For any download initiated after normalization settings are configured, the Downloader shall use the current settings from Config to construct the FFmpeg loudnorm filter string.

Validates: Requirements 5.1, 5.2, 5.3

Property 10: Settings Button Always Enabled

For any application state (downloads running or idle), the "Normalization Settings" button in the Download tab shall be enabled and clickable.

Validates: Requirements 6.4

Property 11: Modal Opens on Button Click

When the user clicks the "Normalization Settings" button in the Download tab, the NormalizationModal shall open and display the current settings.

Validates: Requirements 6.3

Property 12: Preset Indicator Shows Current Preset

For any active normalization preset, the Download tab shall display an indicator showing the current preset name.

Validates: Requirements 7.4

Property 13: Default Settings on First Run

When the application starts for the first time with no saved normalization settings, the NormalizationModal shall display the "Normal" preset as selected with parameters I=-14, TP=-1.5, LRA=11.

Validates: Requirements 4.5, 12.1, 12.2

Property 14: All Presets Valid

For all preset definitions (Quiet, Normal, Loud, Very Loud), all parameters shall conform to FFmpeg loudnorm specifications: I between -23 and 0, TP between -5 and 0, LRA between 1 and 20.

Validates: Requirements 10.1, 10.2, 10.3, 10.4

Property 15: Configuration Structure Correct

For any saved normalization settings, the stored configuration shall include the keys: current_preset (string) and custom_parameters (dict with I, TP, LRA keys).

Validates: Requirements 11.2

Property 16: Invalid Parameters Prevent Apply

For any invalid parameter value (non-numeric or out of range), the Apply button shall remain disabled until all parameters are corrected to valid values.

Validates: Requirements 8.1, 8.3, 8.4

Property 17: Downloader Validates Before Processing

When the Downloader receives normalization parameters, the parameters shall be validated against the allowed ranges before constructing the FFmpeg command.

Validates: Requirements 10.5

Property 18: Failed Normalization Doesn't Stop Download

If normalization fails during audio processing, the download process shall continue and the file shall be saved without normalization applied.

Validates: Requirements 5.5

Property 19: Modal Changes Don't Affect Running Downloads

When the NormalizationModal is open and the user changes settings, any currently running downloads shall continue using the previously configured settings until the next download is initiated.

Validates: Requirements 6.6

Property 20: Corrupted Config Uses Defaults

If the configuration file is corrupted or missing, the application shall use the default "Normal" preset settings and log a warning.

Validates: Requirements 11.5, 12.4


Error Handling

Input Validation Errors

Error Condition Message Action
Non-numeric input "Parameter must be a number" Show error, disable Apply
Value < minimum "Parameter {name} must be between {min} and {max}" Show error, disable Apply
Value > maximum "Parameter {name} must be between {min} and {max}" Show error, disable Apply
Empty field "Parameter {name} is required" Show error, disable Apply

Configuration Errors

Error Condition Message Action
Config file missing Log warning, use defaults Application continues
Config file corrupted Log warning, use defaults Application continues
Save failure "Failed to save settings. Please try again." Show error in modal
Load failure Log warning, use defaults Application continues

FFmpeg Errors

Error Condition Action
Invalid parameters Log error, skip normalization
FFmpeg timeout Log error, skip normalization
FFmpeg not found Log error, skip normalization
File processing error Log error, skip normalization

Recovery Strategies

  1. Validation Failure: User corrects input, error clears, Apply becomes enabled
  2. Save Failure: User clicks Apply again, or closes and reopens modal
  3. Load Failure: Application uses defaults, user can reconfigure
  4. FFmpeg Failure: Download continues without normalization, user can retry

Testing Strategy

Unit Testing

Test Categories:

  1. Modal UI Tests:

    • Verify modal opens/closes correctly
    • Verify preset selection updates fields
    • Verify custom fields enable/disable appropriately
    • Verify buttons are positioned and styled correctly
  2. Validation Tests:

    • Test numeric validation (reject non-numeric input)
    • Test range validation (reject out-of-range values)
    • Test error message display
    • Test Apply button enable/disable based on validation
  3. Settings Persistence Tests:

    • Test saving settings to Config
    • Test loading settings from Config
    • Test default settings when no config exists
    • Test corrupted config handling
  4. Integration Tests:

    • Test modal signal emission
    • Test DownloadTab receives settings changes
    • Test Downloader uses configured settings
    • Test FFmpeg command construction with parameters
  5. Edge Cases:

    • Test with boundary values (min/max for each parameter)
    • Test with missing config file
    • Test with corrupted config file
    • Test rapid preset switching
    • Test modal open/close cycles

Property-Based Testing

Property Test Configuration:

  • Minimum 100 iterations per property test
  • Use hypothesis or similar PBT library for Python
  • Tag each test with: Feature: volume-normalization-modal, Property {number}: {property_text}

Property Tests:

  1. Property 1: Preset Selection Updates Parameters

    • Generate random preset names
    • Verify parameter fields match preset values
    • Tag: Feature: volume-normalization-modal, Property 1: Preset Selection Updates Parameters
  2. Property 5: Parameter Validation Enforces Ranges

    • Generate random parameter values (in and out of range)
    • Verify validation result matches expected range
    • Tag: Feature: volume-normalization-modal, Property 5: Parameter Validation Enforces Ranges
  3. Property 7: Apply Saves Settings

    • Generate random valid parameter configurations
    • Apply settings, verify they're saved to Config
    • Tag: Feature: volume-normalization-modal, Property 7: Apply Saves Settings
  4. Property 8: Settings Persist Across Sessions

    • Generate random settings, save them
    • Simulate application restart
    • Verify settings are loaded correctly
    • Tag: Feature: volume-normalization-modal, Property 8: Settings Persist Across Sessions
  5. Property 9: Downloader Uses Configured Settings

    • Generate random valid parameters
    • Configure settings, initiate download
    • Verify FFmpeg command uses correct parameters
    • Tag: Feature: volume-normalization-modal, Property 9: Downloader Uses Configured Settings
  6. Property 14: All Presets Valid

    • For each preset, verify all parameters are in valid ranges
    • Tag: Feature: volume-normalization-modal, Property 14: All Presets Valid
  7. Property 15: Configuration Structure Correct

    • Generate random settings, save them
    • Verify saved structure contains required keys
    • Tag: Feature: volume-normalization-modal, Property 15: Configuration Structure Correct

Test Coverage Goals

  • Unit Tests: 90%+ coverage of modal and config classes
  • Property Tests: All 20 correctness properties covered
  • Integration Tests: All component interactions tested
  • Edge Cases: All boundary conditions and error scenarios tested

Implementation Phases

Phase 1: Core Infrastructure

  • Create NormalizationSettings class in Config module
  • Define preset configurations and validation ranges
  • Implement settings load/save functionality

Phase 2: Modal Component

  • Create NormalizationModal class
  • Implement preset selection UI
  • Implement custom parameter input fields
  • Implement validation and error display

Phase 3: Integration

  • Integrate modal with DownloadTab
  • Add "Normalization Settings" button
  • Add preset indicator
  • Connect signals and slots

Phase 4: Downloader Updates

  • Modify normalize_volume to use Config settings
  • Add parameter validation
  • Update FFmpeg command construction

Phase 5: Testing

  • Write unit tests for all components
  • Write property-based tests for correctness properties
  • Write integration tests
  • Test edge cases and error scenarios

Deployment Considerations

Configuration Migration

For users upgrading from previous versions:

  1. Check if normalization settings exist
  2. If not, create with default "Normal" preset
  3. Log migration event
  4. No user action required

Backward Compatibility

  • Existing normalize_volume behavior preserved
  • Default settings match current hardcoded values
  • No breaking changes to public APIs
  • Graceful degradation if settings unavailable

Performance Impact

  • Minimal: Settings loaded once at startup
  • Settings lookup is O(1) dictionary access
  • No additional FFmpeg overhead
  • No UI performance impact

Future Enhancements

  1. Preset Management: Allow users to create and save custom presets
  2. Per-Track Settings: Apply different settings to different tracks
  3. Batch Operations: Apply settings to multiple files
  4. Settings Export/Import: Share settings between users
  5. Advanced Visualization: Show loudness graphs and analysis
  6. A/B Comparison: Compare before/after audio samples