-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsimple_compressor.py
More file actions
69 lines (51 loc) · 2.34 KB
/
simple_compressor.py
File metadata and controls
69 lines (51 loc) · 2.34 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
import numpy as np
class SimpleCompressor:
"""
Simple dynamic range compressor using logarithmic waveshaping.
Compresses audio toward +/-1 on a logarithmic scale, making quiet sounds
louder while keeping peaks under control.
"""
def __init__(self, strength: float = 1.0, sample_rate: int = 44100):
"""
Initialize compressor.
Args:
strength: 0.0 = none; value can be greater than 1.0
sample_rate: Audio sample rate (unused but kept for API compatibility)
"""
self.strength = strength
self._sample_rate = sample_rate
def set_sample_rate(self, sample_rate: int) -> None:
"""Update sample rate (for API compatibility)."""
self._sample_rate = sample_rate
def reset(self) -> None:
"""Reset compressor state (no state to reset for waveshaper)."""
pass
def process(self, audio: np.ndarray, strength: float | None = None) -> np.ndarray:
"""
Process audio through logarithmic compressor.
Uses the formula: out = sign(in) * (1 - (1 - |in|)^((1-strength)*2 + 0.5))
- strength=0: exponent=0.5 (sqrt, mild expansion)
- strength=0.5: exponent=1 (linear, no change)
- strength=1: exponent=2.5 (strong compression toward +/-1)
Args:
audio: Input audio array (n_samples, n_channels)
strength: Override strength value; uses self.strength if None
Returns:
Compressed audio array
"""
audio = audio.copy()
# Use provided strength or fall back to instance strength
effective_strength = strength if strength is not None else self.strength
# Calculate exponent from strength (0.5 to 2.5)
exponent = (1 - effective_strength) * 2 + 0.5
# Get absolute values
abs_audio = np.abs(audio)
# Avoid log(0) by clipping to small value
abs_audio = np.clip(abs_audio, 1e-10, None)
# Logarithmic compression: compress toward 1
# Formula: out = sign(in) * (1 - (1 - |in|)^exponent)
# This pushes values toward +/-1
compressed = 1 - np.power(1 - abs_audio, exponent)
# Restore sign
audio = np.sign(audio) * compressed
return audio