Metadata-Version: 2.3
Name: tempobox
Version: 0.3.0
Summary: Extract temporal properties (envelope, periodicity, temporal fine structure) from sound signals
Author: Erdem Baha Topbas
Author-email: Erdem Baha Topbas <erdembaha.topbas@uzh.ch>
Requires-Dist: librosa>=0.11.0
Requires-Dist: loguru>=0.7.3
Requires-Dist: matplotlib>=3.10.8
Requires-Dist: numpy>=2.4.4
Requires-Dist: polars>=1.39.3
Requires-Dist: scipy>=1.17.1
Requires-Dist: soundfile>=0.13.1
Requires-Dist: tqdm>=4.67.3
Requires-Python: >=3.11
Description-Content-Type: text/markdown

# Tempobox

Extract temporal properties from sound signals by decomposing audio into three fundamental acoustic components: **envelope**, **periodicity**, and **temporal fine structure (TFS)**.

## Overview

This library enables acoustic research and speech processing by separating sound signals into their core temporal components:

- **Envelope**: The overall amplitude contour or modulation of the signal
- **Periodicity**: The repeating/cyclical characteristics of the signal
- **Temporal Fine Structure (TFS)**: The fine details and rapid fluctuations within each cycle

These components can be extracted individually, in pairs, or regenerated to reconstruct the original signal. The library also supports generating speech chimeras by mixing temporal components from different audio sources.

## Installation

We suggest using uv to install packages and handle Python environments.

```bash
uv add tempobox
```

If you wish to use pip, you can install this package by

```bash
pip install tempobox
```

## Quick Start

### Interactive Terminal UI

The easiest way to get started is using the interactive Terminal User Interface (TUI):

```bash
# Launch the TUI
tempobox
# or using uv
uv run -m tempobox
```

The TUI provides an intuitive workflow for:

- Loading audio files
- Selecting temporal components to extract
- Visualizing results
- Saving outputs

### Extract temporal properties from audio (Python)

```python
from tempobox import Waveform

# Load audio from file
waveform = Waveform.from_file("audio.wav")

# Extract envelope only
envelope = waveform.extract("env")

# Extract periodicity and TFS (removes envelope)
per_tfs = waveform.extract("per", "tfs")

# Save extracted waveform to WAV file
envelope.save("envelope.wav")

# Plot waveform
waveform.plot(save_path="plot.png")
```

### Use extraction functions directly

```python
from tempobox import extract_env, extract_per, extract_tfs
import numpy as np

# Use pre-loaded numpy array and sample rate
waveform = np.random.randn(16000)  # 1 second of audio at 16kHz
sr = 16000

# Extract individual components
envelope = extract_env(waveform, sr=sr)
periodicity = extract_per(waveform)
tfs = extract_tfs(waveform)

# Extract combinations
from tempobox import extract_env_and_per, extract_env_and_tfs, extract_per_and_tfs
env_and_per = extract_env_and_per(waveform, sr=sr)
env_and_tfs = extract_env_and_tfs(waveform)
per_and_tfs = extract_per_and_tfs(waveform)
```

### Regenerate audio from components

```python
from tempobox import extract_env, extract_per, extract_tfs, Waveform

waveform = Waveform.from_file("audio.wav")

# Extract components
envelope = waveform.extract("env")
periodicity = waveform.extract("per")
tfs = waveform.extract("tfs")

# Save individual components
envelope.save("envelope.wav")
periodicity.save("periodicity.wav")
tfs.save("tfs.wav")
```

### Reconstruct audio from individual components

```python
from tempobox.api import reconstruct_from_waveforms
from tempobox import Waveform

# Load extracted components (or extract them)
env = Waveform.from_file("envelope.wav")
per = Waveform.from_file("periodicity.wav")
tfs = Waveform.from_file("tfs.wav")

# Reconstruct the original signal from components
reconstructed = reconstruct_from_waveforms(env, tfs, per)
reconstructed.save("reconstructed.wav")
```

### Batch process multiple audio files

```python
from tempobox import BatchProcessor

# Create processor from directory
batch = BatchProcessor.from_directory("audio_files/", glob_pattern="*.wav")

# Extract from all files with progress tracking
results = batch.extract("env", "per", "tfs", verbose=True)

# Access results
print(f"Successful: {results.success_count}, Failed: {results.failure_count}")
for filepath, waveform in results.successful.items():
    print(f"Processed: {filepath}")
```

### Evaluate extraction quality

```python
from tempobox import Evaluator
import numpy as np

# Create evaluator from two signals
evaluator = Evaluator(baseline, to_evaluate, baseline_sr, to_evaluate_sr)

# Or create from Waveform objects
evaluator = Evaluator.from_waveforms(baseline_waveform, to_evaluate_waveform)

# Calculate various quality metrics
snr_value = evaluator.snr()  # Higher is better
mse_value = evaluator.mse()  # Lower is better
mfcc_cosine_sim = evaluator.mfcc_cosine_similarity()  # Higher is better

print(f"SNR: {snr_value:.2f} dB")
print(f"MSE: {mse_value:.4f}")
print(f"MFCC Similarity: {mfcc_cosine_sim:.4f}")
```

### Generate speech chimeras

Mix temporal components from different audio sources:

```python
from tempobox import generate_chimera

# Create chimera: envelope from speaker A, TFS from speaker B
chimera = generate_chimera(
    envelope_source="speaker_a.wav",
    tfs_source="speaker_b.wav",
    sr=22050
)
```

You can also pass pre-loaded numpy arrays instead of file paths:

```python
import librosa
import numpy as np

audio_a, sr = librosa.load("speaker_a.wav")
audio_b, sr = librosa.load("speaker_b.wav")

chimera = generate_chimera(
    envelope_source=audio_a,
    tfs_source=audio_b,
    sr=sr
)
```

## API Reference

### Waveform Class

**`Waveform(signal: np.ndarray, sr: int)`**

Main class for working with audio waveforms and extracting temporal features.

**Class Methods:**

- `from_file(file_path: str | Path) -> Waveform` - Load audio from file using librosa

**Instance Methods:**

- `extract(*properties: TemporalProperty, **kwargs) -> Waveform` - Extract temporal properties
  - `*properties`: Any combination of `"env"`, `"per"`, `"tfs"`
  - Returns new Waveform with extracted components
- `save(file_path: str | Path) -> None` - Save waveform to WAV file using soundfile
- `plot(figsize: tuple[int, int] = (12, 4), save_path: str | Path | None = None) -> None` - Plot and optionally save waveform visualization
- `duration() -> float` - Get duration in seconds
- `resample(target_sr: int) -> Waveform` - Resample to target sample rate
- `__len__() -> int` - Get number of samples
- `__str__() -> str` - Human-readable representation

**Properties:**

- `signal: np.ndarray` - Audio samples (1D array)
- `sr: int` - Sample rate in Hz

### Batch Processing

**`BatchProcessor(filepaths: list[str | Path])`**

Process multiple audio files efficiently with lazy loading and progress tracking.

**Class Methods:**

- `from_directory(directory: str | Path, glob_pattern: str = "**/*.wav") -> BatchProcessor` - Load files from directory

**Instance Methods:**

- `extract(*properties: str, verbose: bool = True, **kwargs) -> BatchResults` - Extract temporal components from all files
- `__len__() -> int` - Get number of files to process

**`BatchResults`**

Results container from batch processing operations.

**Properties:**

- `successful: dict[str, Waveform]` - Successfully processed files mapping filepath to extracted Waveform
- `failed: dict[str, str]` - Failed files mapping filepath to error message
- `success_count: int` - Number of successfully processed files
- `failure_count: int` - Number of failed files
- `total_count: int` - Total files processed

### Reconstruction

**`reconstruct_from_waveforms(env: Waveform, tfs: Waveform, per: Waveform) -> Waveform`**

Reconstruct audio signal from temporal component Waveforms. Automatically handles sample rate mismatches by resampling.

**`reconstruct(env: np.ndarray, tfs: np.ndarray, per: np.ndarray) -> np.ndarray`**

Reconstruct audio signal from numpy arrays of temporal components.

### Quality Evaluation

**`Evaluator(baseline: np.ndarray, to_evaluate: np.ndarray, baseline_sr: int, to_evaluate_sr: int)`**

Evaluate the quality of extracted or processed signals against a baseline.

**Class Methods:**

- `from_waveforms(baseline: Waveform, to_evaluate: Waveform) -> Evaluator` - Create from Waveform objects

**Instance Methods:**

- `snr() -> float` - Signal-to-Noise Ratio in dB (higher is better)
- `mse() -> float` - Mean Squared Error (lower is better)
- `mfcc_cosine_similarity(n_mfcc: int = 80) -> float` - MFCC cosine similarity (higher is better)

### Extraction Functions

All extraction functions accept a waveform and return a numpy array of the same shape.

- `extract_env(waveform, sr, cutoff=30, order=5)` - Extract envelope (amplitude modulation)
- `extract_per(waveform)` - Extract periodicity (cyclical characteristics)
- `extract_tfs(waveform)` - Extract temporal fine structure (fine details within cycles)
- `extract_env_and_per(waveform, sr, cutoff=30, order=5)` - Extract envelope and periodicity (removes TFS)
- `extract_env_and_tfs(waveform)` - Extract envelope and TFS (removes periodicity)
- `extract_per_and_tfs(waveform)` - Extract periodicity and TFS (removes envelope)

### Utility Functions

- `generate_chimera(envelope_source, tfs_source, sr, cutoff=30, order=5)` - Generate speech chimera from two audio sources (numpy arrays or file paths)
  - Returns numpy array with envelope from first source and TFS from second source

### Accessing API Elements

The primary API and extraction functions are available at the package level for easy access:

```python
from tempobox import (
    Waveform,
    BatchProcessor,
    Evaluator,
    generate_chimera,
    reconstruct,
    reconstruct_from_waveforms,
    extract_env,
    extract_per,
    extract_tfs,
    extract_env_and_per,
    extract_env_and_tfs,
    extract_per_and_tfs,
)

# Internal metric functions available in core
from tempobox.core.metrics import snr, mse, mfcc_cosine_similarity
```

## Package Structure

The package is organized into several modules:

- **`api/`** - User-facing API (all classes and functions users interact with directly)
  - `waveform.py` - Main `Waveform` class for audio processing
  - `extractions.py` - Temporal component extraction functions
  - `chimera.py` - Speech chimera generation
  - `reconstruct.py` - Signal reconstruction from components
  - `batchprocessor.py` - Batch processing of multiple files
  - `evaluator.py` - Signal quality evaluation with `Evaluator` class
  
- **`core/`** - Internal utilities (lower-level signal processing and helper functions)
  - `signal_processing.py` - Filtering and signal processing
  - `periodicity.py` - Cycle and periodicity manipulation
  - `transforms.py` - Core signal transformations (IPC, ITW)
  - `metrics.py` - Signal quality metric functions (used by Evaluator)
  - `array_utils.py` - Array manipulation utilities
  - `constants.py` - Package constants
  - `validation.py` - Input validation utilities
  - `plotting.py` - Visualization utilities
  
- **`tui/`** - Terminal user interface for interactive audio processing

### Version History

- **0.3.0** - Signal reconstruction, batch processing, quality evaluation (Evaluator), loguru migration
- **0.2.1** - Input validation, logging support, comprehensive test coverage (115 tests, 63%)
- **0.2.0** - Refactored package architecture for better organization
- **0.1.1** - TUI support added
- **0.1.0** - Initial release

### Extraction Algorithms

The library uses signal processing techniques to decompose audio:

- **Infinite Peak Clipping (IPC)**: Converts signal to ±1 signs, removing amplitude information
- **Hilbert Transform**: Extracts instantaneous amplitude (envelope)
- **Isochronous Time Warping (ITW)**: Removes periodicity by normalizing cycle lengths
- **Butterworth Filtering**: Low-pass filtering for envelope smoothing
- **Zero-crossing Detection**: Identifies signal cycles for cycle-based operations

### Component Interactions

The three components can be combined to reconstruct the signal with minimal loss. Periodicity can be reinjected to the envelope and temporal fine structure arrays to acquire env_per, and tfs_per, respectively. The multiplication of these two approximates the original signal.

## Features

### Text User Interface (TUI)

The integrated TUI makes audio processing accessible without programming:

- **File Loading**: Browse and load audio files with a file path input
- **Feature Selection**: Toggle checkboxes to select envelope, periodicity, and TFS
- **Real-time Info**: Display audio duration, sample rate, and sample count
- **Visualization**: Generate and save side-by-side comparison plots
- **Error Handling**: Clear error messages and status notifications
- **Navigation**: Intuitive screen-based navigation with back buttons

### Programmatic API

For advanced workflows and automation:

- Load and manipulate waveforms directly in Python
- Extract components individually or in combinations
- Generate speech chimeras by mixing audio sources
- Create custom visualizations with utility functions
- Integrate with other signal processing libraries

## Requirements

- Python ≥ 3.11
- numpy ≥ 2.4.4
- scipy ≥ 1.17.1
- librosa ≥ 0.11.0
- matplotlib ≥ 3.10.8 (for visualization)

### Optional Dependencies (for TUI)

- Textual ≥ 8.2.3 (included in dev dependencies)

## Examples

### Speech Processing

Extract components to analyze speaker-independent acoustic properties:

```python
from tempobox import Waveform

waveform = Waveform.from_file("speech.wav")
envelope = waveform.extract("env")
tfs = waveform.extract("tfs")

# Save for analysis
envelope.save("speech_envelope.wav")
tfs.save("speech_tfs.wav")

# Envelope captures prosody and speaking rate
# TFS captures speaker identity and phonetic details
```

### Audio Synthesis

Create synthetic speech by mixing temporal components:

```python
from tempobox import generate_chimera

# Mix speaker A's prosody with speaker B's voice quality
chimera = generate_chimera(
    envelope_source="speaker_a.wav",
    tfs_source="speaker_b.wav",
    sr=22050
)
```

### Visualization

Compare original and extracted components:

```python
from tempobox import Waveform
from tempobox.tui.utils import side_by_side_plotting

waveform = Waveform.from_file("audio.wav")
extracted = waveform.extract("env", "per")

# Create comparison plot
side_by_side_plotting(waveform, extracted, "ENV+PER", save_path="comparison.png")
```

## References

This library implements techniques commonly used in auditory research and speech processing:

TODO: Add references

## License

MIT

## Contributing

Contributions are welcome! Please feel free to submit pull requests or open issues.
