# TASK-007

## Title

Spectral Analyzer

---

## Objective

Implement the first frequency-domain analyzer for AI MusiMuse.

This analyzer extracts deterministic spectral features from decoded audio.

These features become the foundation for future:

- Similarity Search
- Music DNA
- Genre Estimation
- Mood Estimation
- Recommendation Engine

No rhythm, harmony, embeddings, or machine learning should be implemented.

---

# Expected Commit Message

Add spectral analyzer

---

# Requirements

Read SPEC.md before implementing anything.

Follow all AI Rules.

Follow the Analysis Framework introduced in previous tasks.

Do not violate architectural boundaries.

---

# Scope

Create

```
src/analyzer/spectral/
```

Files

```
__init__.py
spectral_analyzer.py
```

Register the analyzer through

```
build_default_registry()
```

No CLI changes are required.

The existing

```
musimuse analyze
```

must automatically execute this analyzer.

---

# Analyzer

Create

```
SpectralAnalyzer
```

inherits from

```
Analyzer
```

Name

```
spectral
```

Version

```
1.0.0
```

---

# Shared FFT Configuration

Create

```
src/core/dsp.py
```

Define shared constants

```python
FFT_SIZE = 4096

HOP_LENGTH = 1024

WINDOW = "hann"
```

No analyzer may hardcode FFT parameters.

All future analyzers must reuse these constants.

---

# Shared DSP Utilities

To avoid duplicated DSP code, implement reusable spectrum utilities.

Create

```
src/dsp/spectrum.py
```

Implement reusable helper functions.

Minimum API:

```python
hann_window()

compute_stft()

compute_magnitude_spectrum()

compute_power_spectrum()
```

Function signatures may evolve as the project grows.

The SpectralAnalyzer must use these shared utilities.

Future analyzers must reuse this module instead of implementing FFT logic independently.

The DSP package becomes the single source of truth for frequency-domain processing.

---

# DSP Requirements

Use

```
numpy
```

for numerical calculations.

Use

```
scipy.signal
```

where appropriate.

Use vectorized operations.

Avoid Python loops over individual samples.

---

# Features

The analyzer must calculate

---

## Spectral Centroid

Feature

```
spectral_centroid
```

Unit

```
Hz
```

---

## Spectral Bandwidth

Feature

```
spectral_bandwidth
```

Unit

```
Hz
```

---

## Spectral Rolloff

Feature

```
spectral_rolloff
```

Definition

Frequency below which 85% of spectral energy exists.

Unit

```
Hz
```

---

## Spectral Flatness

Feature

```
spectral_flatness
```

Range

```
0.0 – 1.0
```

---

## Zero Crossing Rate

Feature

```
zero_crossing_rate
```

Range

```
0.0 – 1.0
```

---

## Spectral Flux

Feature

```
spectral_flux
```

Definition

Average normalized frame-to-frame spectral difference.

---

# Channel Handling

Mono

Analyze directly.

Stereo

Convert to mono using

```python
(left + right) / 2
```

before spectral analysis.

Do not calculate independent spectra for left and right channels.

---

# Output

Expected FeatureSet

```
spectral_centroid

spectral_bandwidth

spectral_rolloff

spectral_flatness

zero_crossing_rate

spectral_flux
```

---

# Numerical Stability

Correctly handle

- silence
- zero-energy frames
- empty audio
- NaN values
- infinite values

Raise

```
AnalysisError
```

when appropriate.

---

# Persistence

The analyzer must never access SQLite.

Persistence remains the responsibility of the existing AnalysisPipeline.

The analyzer only returns FeatureSet.

---

# Logging

The analyzer must not perform logging.

The pipeline remains responsible for logging.

---

# Tests

Create tests covering

- sine wave
- white noise
- silence
- impulse
- constant signal
- mono audio
- stereo audio
- spectral centroid
- spectral bandwidth
- spectral rolloff
- spectral flatness
- zero crossing rate
- spectral flux
- deterministic output
- NaN handling
- infinity handling
- empty audio
- feature names
- feature units
- pipeline integration
- persistence integration

---

# Forbidden

Do NOT implement

- tempo detection
- beat detection
- onset detection
- MFCC
- chroma
- harmony
- key detection
- loudness normalization
- Music DNA
- similarity scoring
- embeddings

---

# Definition of Done

✓ SpectralAnalyzer implemented

✓ Registered through build_default_registry()

✓ Shared FFT configuration implemented

✓ Shared DSP utilities implemented

✓ Uses NumPy vectorized operations

✓ Uses SciPy where appropriate

✓ Produces deterministic results

✓ Handles mono and stereo

✓ Handles silence correctly

✓ Handles invalid input safely

✓ Produces immutable FeatureSet

✓ Automatically persists features through the existing pipeline

✓ Tests pass

✓ Ruff passes

✓ Black passes

✓ isort passes

---

# Architectural Notes

This task introduces the project's shared frequency-domain processing layer.

The SpectralAnalyzer is intentionally built on top of reusable DSP utilities rather than implementing FFT internally.

From this point onward, every analyzer requiring spectral information must reuse the shared DSP utilities.

No analyzer should independently implement

- FFT
- STFT
- Hann window generation
- magnitude spectrum
- power spectrum

The DSP package becomes the single source of truth for frequency-domain processing throughout AI MusiMuse.

This guarantees

- deterministic analysis
- consistent FFT parameters
- reduced code duplication
- easier maintenance
- reusable infrastructure for future analyzers

The extracted spectral features intentionally remain low-level.

Future analyzers such as Dynamics, Rhythm, Harmony, Similarity, and Music DNA must build upon these features instead of recomputing spectral statistics.

## Performance

The implementation should avoid unnecessary memory allocations whenever possible.

Large temporary arrays should be minimized.

Shared FFT windows and reusable buffers may be cached internally if this does not violate analyzer statelessness.

The implementation should be designed to scale efficiently to music libraries containing tens of thousands of tracks.