Metadata-Version: 2.4
Name: rs_audio_stats
Version: 1.2.4
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Rust
Classifier: Topic :: Multimedia :: Sound/Audio :: Analysis
Summary: High-performance audio analysis library with EBU R128 loudness measurement, powered by Rust
Keywords: audio,loudness,ebu-r128,analysis,normalization
Home-Page: https://pypi.org/project/rs-audio-stats/
Author: Hiroshi Tamura
License: MIT
Requires-Python: >=3.10
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
Project-URL: Homepage, https://pypi.org/project/rs-audio-stats/
Project-URL: Documentation, https://pypi.org/project/rs-audio-stats/

# rs_audio_stats

High-performance audio analysis library with Rust-powered ultra-fast EBU R128 loudness measurement

## Overview

rs_audio_stats delivers **dramatically superior performance** over traditional Python audio libraries through its **Rust-powered core engine**. It provides EBU R128 standard (ITU-R BS.1770-4) compliant loudness measurement, true peak detection, RMS calculations, and audio normalization capabilities.

## 🚀 Exceptional Performance with Rust

### ⚡ Speed Comparison
- **10-50x faster** than traditional Python libraries
- **Memory efficient** massive file processing without crashes
- **Low-latency** real-time streaming support
- **Multi-core optimization** maximizes CPU utilization

### 🛠️ Rust Technical Advantages
- **Zero-cost abstractions**: No runtime overhead
- **Memory safety**: No segmentation faults or memory leaks
- **SIMD optimization**: Leverages modern CPU parallel processing instructions
- **Native performance**: Equivalent to C/C++ execution speed

## Installation

```bash
pip install rs_audio_stats
```

## Quick Start

```python
import rs_audio_stats as ras

# Analyze audio file
info, results = ras.analyze_audio("audio.wav", True, False, False, False, True, False, False)
print(f"Integrated Loudness: {results.integrated_loudness:.1f} LUFS")
print(f"True Peak: {results.true_peak:.1f} dBFS")

# Batch analyze directory
results = ras.batch_analyze_directory("audio_folder/", True, False, False, False, True, False, False)
for file_path, (info, analysis) in results.items():
    print(f"{file_path}: {analysis.integrated_loudness:.1f} LUFS")
```

## 📊 Audio Information Extraction

### Get Sample Rate, Channels, Bit Depth (-sr, -ch, -bt)

```python
import rs_audio_stats as ras

# Get audio file information
info = ras.get_audio_info_py("audio.wav")

print(f"Sample Rate: {info.sample_rate} Hz")        # 44100 Hz
print(f"Channels: {info.channels}")                 # 2
print(f"Bit Depth: {info.bit_depth} bit")           # 16 bit
print(f"Sample Format: {info.sample_format}")       # PCM
```

### Get Duration (-du, -tm)

```python
import rs_audio_stats as ras

info = ras.get_audio_info_py("audio.wav")

print(f"Duration (seconds): {info.duration_seconds:.2f} sec")      # 183.45 sec
print(f"Duration (formatted): {info.duration_formatted}")          # 03:03.45
```

### Get Total Samples and Format Detection (-f, -fe, -fea)

```python
import rs_audio_stats as ras

info = ras.get_audio_info_py("audio.wav")

print(f"Total Samples: {info.total_samples:,} samples")  # 8,088,000 samples

# Calculate file size
file_size = info.total_samples * info.channels * (info.bit_depth // 8)
print(f"Calculated File Size: {file_size:,} bytes")      # 32,352,000 bytes
```

## 🎚️ EBU R128 Loudness Analysis

### Integrated Loudness Measurement (-i)

```python
import rs_audio_stats as ras

# Measure integrated loudness
info, results = ras.analyze_audio("audio.wav", integrated_loudness=True)

print(f"Integrated Loudness: {results.integrated_loudness:.1f} LUFS")

# Check broadcast standards
if results.integrated_loudness >= -23.0:
    print("✅ Meets EBU R128 broadcast standard (-23 LUFS)")
else:
    print(f"⚠️ Below broadcast standard")
```

### Short-term & Momentary Loudness Measurement (-s, -m)

```python
import rs_audio_stats as ras

# Measure short-term (3s) & momentary (400ms) loudness
info, results = ras.analyze_audio("audio.wav", 
    short_term_loudness=True, momentary_loudness=True)

print(f"Short-term Loudness: {results.short_term_loudness:.1f} LUFS")
print(f"Momentary Loudness: {results.momentary_loudness:.1f} LUFS")
```

### Loudness Range and Peak Measurement (-l, -tp)

```python
import rs_audio_stats as ras

# Measure loudness range (LRA) and true peak
info, results = ras.analyze_audio("audio.wav", 
    loudness_range=True, true_peak=True)

print(f"Loudness Range: {results.loudness_range:.1f} LU")
print(f"True Peak: {results.true_peak:.1f} dBFS")

# Dynamic range evaluation
if results.loudness_range > 15.0:
    print("🎵 High dynamic range")
elif results.loudness_range > 7.0:
    print("🎶 Moderate dynamic range")
else:
    print("📻 Compressed audio")
```

### RMS Measurement (-rm, -ra)

```python
import rs_audio_stats as ras

# Measure RMS max and average values
info, results = ras.analyze_audio("audio.wav", 
    rms_max=True, rms_average=True)

print(f"RMS Max: {results.rms_max:.1f} dBFS")
print(f"RMS Average: {results.rms_average:.1f} dBFS")
print(f"RMS Dynamic Range: {results.rms_max - results.rms_average:.1f} dB")
```

### Complete Loudness Analysis

```python
import rs_audio_stats as ras

# Measure all loudness metrics at once
info, results = ras.analyze_audio_all("audio.wav")

print("=== Complete Loudness Analysis ===")
print(f"Integrated Loudness: {results.integrated_loudness:.1f} LUFS")
print(f"Short-term Loudness: {results.short_term_loudness:.1f} LUFS") 
print(f"Momentary Loudness: {results.momentary_loudness:.1f} LUFS")
print(f"Loudness Range: {results.loudness_range:.1f} LU")
print(f"True Peak: {results.true_peak:.1f} dBFS")
print(f"RMS Max: {results.rms_max:.1f} dBFS")
print(f"RMS Average: {results.rms_average:.1f} dBFS")
```

## 🎛️ Audio Normalization

### True Peak Normalization (-norm-tp)

```python
import rs_audio_stats as ras

# Normalize true peak to -1.0 dBFS
ras.normalize_true_peak("input.wav", -1.0, "output_peak.wav")

# Convenient wrapper function
ras.normalize_to_dbfs("input.wav", -1.0)  # Auto-generates input_peaked.wav
```

### Integrated Loudness Normalization (-norm-i)

```python
import rs_audio_stats as ras

# Normalize for broadcast (-23 LUFS)
ras.normalize_integrated_loudness("input.wav", -23.0, "broadcast.wav")

# Normalize for podcast (-16 LUFS)  
ras.normalize_integrated_loudness("input.wav", -16.0, "podcast.wav")

# Convenient wrapper function
ras.normalize_to_lufs("input.wav", -23.0)  # Auto-generates input_normalized.wav
```

### Short-term & Momentary Loudness Normalization (-norm-s, -norm-m)

```python
import rs_audio_stats as ras

# Short-term loudness normalization
ras.normalize_short_term_loudness("input.wav", -18.0, "short_term.wav")

# Momentary loudness normalization
ras.normalize_momentary_loudness("input.wav", -16.0, "momentary.wav")
```

### RMS Normalization (-norm-rm, -norm-ra)

```python
import rs_audio_stats as ras

# RMS max normalization
ras.normalize_rms_max("input.wav", -12.0, "rms_max.wav")

# RMS average normalization
ras.normalize_rms_average("input.wav", -20.0, "rms_avg.wav")
```

## 🔄 Batch Processing

### Directory Batch Analysis

```python
import rs_audio_stats as ras

# Analyze all audio files in folder
results = ras.batch_analyze_directory("audio_folder/", 
    integrated_loudness=True, true_peak=True, loudness_range=True)

print(f"Analyzed files: {len(results)}")

# Statistical information
loudness_values = []
for file_path, (info, analysis) in results.items():
    filename = file_path.split("\\")[-1]  # filename only
    print(f"{filename}: {analysis.integrated_loudness:.1f} LUFS")
    loudness_values.append(analysis.integrated_loudness)

avg_loudness = sum(loudness_values) / len(loudness_values)
print(f"Average Loudness: {avg_loudness:.1f} LUFS")
```

### Export Results (-csv, -tsv, -xml, -json)

```python
import rs_audio_stats as ras

# Execute batch analysis
results = ras.batch_analyze_directory("audio_folder/", 
    integrated_loudness=True, true_peak=True, loudness_range=True)

# Export to all formats
ras.export_to_csv(results, "analysis_results.csv")
ras.export_to_tsv(results, "analysis_results.tsv") 
ras.export_to_xml(results, "analysis_results.xml")
ras.export_to_json(results, "analysis_results.json")

print("✅ Exported to all formats")
```

## 🎯 Real-world Examples

### Broadcast Quality Check

```python
import rs_audio_stats as ras

def broadcast_check(file_path):
    info, results = ras.analyze_audio_all(file_path)
    
    issues = []
    if results.integrated_loudness < -24.0 or results.integrated_loudness > -22.0:
        issues.append(f"Loudness out of range: {results.integrated_loudness:.1f} LUFS")
    if results.true_peak > -1.0:
        issues.append(f"Peak too high: {results.true_peak:.1f} dBFS")
    
    if not issues:
        print("✅ Broadcast standard compliant")
    else:
        for issue in issues:
            print(f"❌ {issue}")

broadcast_check("broadcast_content.wav")
```

### Music Streaming Optimization

```python
import rs_audio_stats as ras

def optimize_for_streaming(input_file, platform="spotify"):
    targets = {
        "spotify": -14.0,    # LUFS
        "apple_music": -16.0,
        "youtube": -14.0
    }
    
    target_lufs = targets.get(platform, -14.0)
    output_file = f"{input_file.split('.')[0]}_{platform}.wav"
    
    # Peak normalization → Loudness normalization
    temp_file = "temp_peak.wav"
    ras.normalize_true_peak(input_file, -1.0, temp_file)
    ras.normalize_integrated_loudness(temp_file, target_lufs, output_file)
    
    import os
    os.remove(temp_file)  # Remove temp file
    
    print(f"✅ Optimized for {platform}: {output_file}")

optimize_for_streaming("my_song.wav", "spotify")
```

### Podcast Batch Processing

```python
import rs_audio_stats as ras
import os

def process_podcast_episodes(episodes_folder, output_folder):
    os.makedirs(output_folder, exist_ok=True)
    
    for file in os.listdir(episodes_folder):
        if file.endswith(('.wav', '.mp3', '.flac')):
            input_path = os.path.join(episodes_folder, file)
            output_path = os.path.join(output_folder, f"podcast_{file}")
            
            # Podcast recommended settings (-16 LUFS, -3 dBFS)
            temp_file = os.path.join(output_folder, f"temp_{file}")
            ras.normalize_true_peak(input_path, -3.0, temp_file)
            ras.normalize_integrated_loudness(temp_file, -16.0, output_path)
            os.remove(temp_file)
            
            print(f"✅ Processed: {file}")

process_podcast_episodes("raw_episodes/", "ready_episodes/")
```

## 📋 Convenient Functions

```python
import rs_audio_stats as ras

# Get loudness only
loudness = ras.get_loudness("audio.wav")
print(f"Loudness: {loudness:.1f} LUFS")

# Get true peak only  
peak = ras.get_true_peak("audio.wav")
print(f"True Peak: {peak:.1f} dBFS")
```

## 🏆 Why Choose rs_audio_stats

### Comparison with Traditional Python Libraries

| Feature | rs_audio_stats (Rust) | Traditional Python Libraries |
|---------|----------------------|------------------------------|
| **Processing Speed** | 🚀 **10-50x faster** | 🐌 Slow |
| **Memory Usage** | 🟢 **Efficient** | 🔴 Heavy consumption |
| **Large File Processing** | ✅ **Stable** | ❌ Crash-prone |
| **CPU Utilization** | 📈 **Multi-core** | 📉 Single-core |
| **Error Resistance** | 🛡️ **Memory safe** | ⚠️ Segmentation faults |

### 🎯 Real-world Performance Examples

```python
# Batch processing 1000 files time comparison
# Traditional library: 45 minutes
# rs_audio_stats:      2 minutes    ← 22x faster!

# 60-minute audio file analysis time
# Traditional library: 8.5 seconds
# rs_audio_stats:      0.3 seconds  ← 28x faster!
```

## Supported Formats

- **Lossless**: WAV, FLAC, WavPack, Monkey's Audio
- **Lossy**: MP3, AAC/M4A, OGG/Vorbis, Opus
- **Others**: Many more via Symphonia decoder

## Requirements

- **Python**: 3.10+
- **OS**: Windows, macOS, Linux
- **Dependencies**: None (pre-compiled binary)
- **CPU**: SIMD instructions supported for additional acceleration

## License

MIT License
