first commit

This commit is contained in:
2026-08-21 08:37:51 -03:00
commit 881a99b0a8
214 changed files with 61407 additions and 0 deletions

View File

@@ -0,0 +1,134 @@
from __future__ import annotations
import struct
import numpy as np
from app.livekit.adapters.audio_gain import (
GainEmitter,
SoftClipGain,
tts_output_gain_from_env,
)
def _pcm(*samples: int) -> bytes:
return struct.pack("<" + "h" * len(samples), *samples)
def _samples(pcm: bytes) -> list[int]:
return list(struct.unpack("<" + "h" * (len(pcm) // 2), pcm))
def test_gain_1_0_is_disabled_and_passthrough() -> None:
g = SoftClipGain(gain=1.0)
assert g.enabled is False
pcm = _pcm(1000, -2000, 3000)
assert g.process(pcm) == pcm
def test_normal_level_is_boosted_near_linear() -> None:
g = SoftClipGain(gain=2.0) # ceiling default -1 dBFS
# sinal baixo (~ -30 dBFS): boost deve ser praticamente 2x
out = _samples(g.process(_pcm(1000, -1000)))
assert abs(out[0] - 2000) <= 40
assert abs(out[1] + 2000) <= 40
def test_hot_peaks_never_clip_past_ceiling() -> None:
ceiling = 0.891 # ~ -1 dBFS
g = SoftClipGain(gain=2.0, ceiling=ceiling)
limit = int(ceiling * 32768) + 1
# picos quentes que, com 2x linear, estourariam o fundo de escala
out = _samples(g.process(_pcm(30000, -30000, 25000, -25000)))
assert all(abs(s) <= limit for s in out), out
# e continua monotonicamente crescente (sem wraparound/inversao de fase)
assert out[0] > 0 and out[1] < 0
def test_monotonic_transfer_curve() -> None:
g = SoftClipGain(gain=2.0)
xs = list(range(0, 32000, 1000))
ys = [_samples(g.process(_pcm(x)))[0] for x in xs]
assert all(b >= a for a, b in zip(ys, ys[1:])), ys
def test_odd_length_bytes_do_not_crash() -> None:
g = SoftClipGain(gain=2.0)
pcm = _pcm(1000, -1000) + b"\x7f" # 1 byte solto
out = g.process(pcm)
assert len(out) == len(pcm)
assert out[-1:] == b"\x7f"
def test_empty_input() -> None:
assert SoftClipGain(gain=2.0).process(b"") == b""
def test_env_loader_defaults_to_disabled(monkeypatch) -> None:
monkeypatch.delenv("TTS_OUTPUT_GAIN", raising=False)
monkeypatch.delenv("TTS_OUTPUT_CEILING_DBFS", raising=False)
g = tts_output_gain_from_env()
assert g.gain == 1.0
assert g.enabled is False
def test_env_loader_reads_gain_and_ceiling(monkeypatch) -> None:
monkeypatch.setenv("TTS_OUTPUT_GAIN", "2.0")
monkeypatch.setenv("TTS_OUTPUT_CEILING_DBFS", "-6")
g = tts_output_gain_from_env()
assert g.gain == 2.0
assert abs(g.ceiling - 10 ** (-6 / 20.0)) < 1e-6
class _FakeEmitter:
def __init__(self) -> None:
self.pushed: list[bytes] = []
self.initialized = False
self.flushed = False
def initialize(self, **kwargs) -> None:
self.initialized = True
def push(self, data: bytes) -> None:
self.pushed.append(data)
def flush(self) -> None:
self.flushed = True
def test_gain_emitter_transforms_push_and_forwards_rest() -> None:
inner = _FakeEmitter()
em = GainEmitter(inner, SoftClipGain(gain=2.0))
em.initialize(sample_rate=24000)
em.push(_pcm(1000, -1000))
em.flush()
assert inner.initialized is True
assert inner.flushed is True
assert len(inner.pushed) == 1
# o que chegou ao emitter real foi amplificado
out = _samples(inner.pushed[0])
assert abs(out[0] - 2000) <= 40
def test_gain_emitter_matches_numpy_reference() -> None:
gain = SoftClipGain(gain=2.0, ceiling=0.891)
pcm = _pcm(500, -12000, 28000, -31000, 0)
ref_x = np.frombuffer(pcm, dtype="<i2").astype(np.float32) / 32768.0
ref_y = 0.891 * np.tanh((2.0 / 0.891) * ref_x)
ref = np.clip(np.rint(ref_y * 32768.0), -32768.0, 32767.0).astype("<i2")
assert gain.process(pcm) == ref.tobytes()
def test_gain_configuration_rejects_non_finite_and_out_of_range_values(monkeypatch) -> None:
monkeypatch.setenv("TTS_OUTPUT_GAIN", "nan")
monkeypatch.setenv("TTS_OUTPUT_CEILING_DBFS", "inf")
gain = tts_output_gain_from_env()
assert gain.gain == 1.0
monkeypatch.setenv("TTS_OUTPUT_GAIN", "-2")
monkeypatch.setenv("TTS_OUTPUT_CEILING_DBFS", "-200")
gain = tts_output_gain_from_env()
assert gain.ceiling == 0.05
assert gain.gain == 0.0