audio_samples 1.0.13

A typed audio processing library for Rust that treats audio as a first-class, invariant-preserving object rather than an unstructured numeric buffer.
Documentation
# Simplification report: src/codecs/perceptual/masking.rs

**Verified against:** features `full,simd`, toolchain `nightly`  
**Baseline:** 4 needless-range-loop warnings → with all accepted changes: 0 warnings  
**Working tree:** restored (changes accepted), unchanged from user's perspective

## Summary

This file implements a perceptual masking model with temporal masking propagation. It contained four `needless_range_loop` warnings from index-based iteration patterns that could be replaced with iterator-based loops. All candidates compile cleanly without introducing new warnings or altering behavior. The file is now idiomatic Rust with no range-loop warnings.

## Suggestions

### S1 — Replace range loop with iterator `.enumerate()` for frame metrics (outer loop, post-masking)  ·  **internal simplification**  ·  ✅ verified

**Location:** `src/codecs/perceptual/masking.rs:321–338`

**Why:** The outer loop iterated over `0..n_frames` solely to index into `frame_metrics[t]`. Converting to `.iter().enumerate()` gives the frame index `t` and the item directly, eliminating the index-based lookup and making the code more idiomatic.

```rust
// before
for t in 0..n_frames {
    for b in 0..n_bands {
        let masker = frame_metrics[t].metrics[b].masking_threshold;
        // ... rest of loop using t for `thresholds[future]` where future = t + k
    }
}

// after
for (t, frame_metric_t) in frame_metrics.iter().enumerate() {
    for (b, metric) in frame_metric_t.metrics.iter().enumerate() {
        let masker = metric.masking_threshold;
        // ... rest of loop using t for `thresholds[future]` where future = t + k
    }
}
```

### S2 — Replace range loop with iterator `.enumerate()` for band metrics (inner loop, post-masking)  ·  **internal simplification**  ·  ✅ verified

**Location:** `src/codecs/perceptual/masking.rs:322–338` (after S1)

**Why:** The inner loop iterated over `0..n_bands` solely to index into `frame_metric_t.metrics[b]`. Converting to `.iter().enumerate()` eliminates the array indexing for reading metrics while still allowing index-based mutations of the `thresholds` 2D array (which uses dynamic indices `future` and `past` not available from iteration alone).

*Included in S1's code block above.*

### S3 — Replace range loop with `.enumerate().skip(1)` for frame metrics (outer loop, pre-masking)  ·  **internal simplification**  ·  ✅ verified

**Location:** `src/codecs/perceptual/masking.rs:342–360`

**Why:** Similar to S1, but the loop starts from frame 1 (`1..n_frames`). Using `.iter().enumerate().skip(1)` is idiomatic and avoids the range construction and index lookup.

```rust
// before
for t in 1..n_frames {
    for b in 0..n_bands {
        let masker = frame_metrics[t].metrics[b].masking_threshold;
        // ... rest of loop using t for `thresholds[past]` where past = t - k
    }
}

// after
for (t, frame_metric_t) in frame_metrics.iter().enumerate().skip(1) {
    for (b, metric) in frame_metric_t.metrics.iter().enumerate() {
        let masker = metric.masking_threshold;
        // ... rest of loop using t for `thresholds[past]` where past = t - k
    }
}
```

### S4 — Remove unused variable `n_bands`  ·  **dead code**  ·  ✅ verified

**Location:** `src/codecs/perceptual/masking.rs:311`

**Why:** The variable `n_bands = frame_metrics[0].metrics.len().get()` was computed but only used in the old range loop `for b in 0..n_bands` (S2). After converting to `.iter().enumerate()`, it is no longer used. Removing it eliminates an unused binding and clarifies intent.

```rust
// before
let n_bands = frame_metrics[0].metrics.len().get();

// after
// line removed entirely
```

## Not changed (considered, rejected)

None. All identified simplifications are low-risk, verified, and applied.

---

**Total reduction:** 4 clippy warnings eliminated, 1 unused variable removed, 2 redundant len() calls removed.  
**Behavior:** Identical — conversion from index-based to iterator-based is purely stylistic and equivalence-preserving.