forked from ChelseaKR/olive-bark-logger
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest_calibrate.py
More file actions
131 lines (102 loc) · 4.53 KB
/
Copy pathtest_calibrate.py
File metadata and controls
131 lines (102 loc) · 4.53 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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
"""Calibration math, the level meter, and the calibrate CLI."""
from __future__ import annotations
import pytest
from monitor import __version__
from monitor.calibrate import (
compute_offset,
main_calibrate,
main_tune,
measure_levels,
meter_bar,
suggest_threshold,
)
from monitor.capture import LoudRegion, synthetic_session
from monitor.level import SILENCE_FLOOR_DBFS
from store import EventStore
def test_compute_offset():
assert compute_offset(measured_dbfs=-50.0, reference_spl_db=60.0) == 110.0
def test_suggest_threshold_uses_median_plus_margin():
assert suggest_threshold([-40, -40, -40], margin_db=6.0) == -34.0
def test_suggest_threshold_empty():
assert suggest_threshold([], margin_db=6.0) == SILENCE_FLOOR_DBFS + 6.0
def test_meter_bar_clamps():
assert meter_bar(10.0, width=10).startswith("[##########]") # above ceil -> full
assert meter_bar(-200.0, width=10).startswith("[----------]") # below floor -> empty
def test_meter_bar_midscale():
bar = meter_bar(-30.0, floor=-60.0, ceil=0.0, width=10)
assert bar.startswith("[#####-----]")
def test_measure_levels_respects_cap():
source = synthetic_session(10.0, [LoudRegion(0.0, 10.0, 0.3)], frame_size=1600)
levels = measure_levels(source, max_frames=5)
assert len(levels) == 5
assert all(lvl > -20 for lvl in levels) # loud tone is well above silence
def test_main_calibrate_version_flag_prints_and_exits(capsys):
# argparse's `action="version"` prints to stdout and exits 0 before any source
# (live or fake) is touched, so this needs no --config/--reference-db at all.
with pytest.raises(SystemExit) as exc_info:
main_calibrate(["--version"])
assert exc_info.value.code == 0
assert f"olive-calibrate {__version__}" in capsys.readouterr().out
def test_main_tune_version_flag_prints_and_exits(capsys):
# Same guarantee for olive-tune: --version must short-circuit before the live
# meter loop, which needs real hardware and would otherwise hang the test.
with pytest.raises(SystemExit) as exc_info:
main_tune(["--version"])
assert exc_info.value.code == 0
assert f"olive-tune {__version__}" in capsys.readouterr().out
def test_main_calibrate_stores_offset(tmp_path, capsys):
db = tmp_path / "olive.db"
cfg = tmp_path / "cfg.json"
cfg.write_text(f'{{"db_path": "{db}"}}')
def factory(config):
return synthetic_session(3.0, [LoudRegion(0.0, 3.0, 0.3)], frame_size=config.frame_size)
rc = main_calibrate(
["--config", str(cfg), "--reference-db", "70", "--seconds", "2"], source_factory=factory
)
assert rc == 0
assert "offset" in capsys.readouterr().out
with EventStore(db) as store:
calib = store.get_calibration()
assert calib is not None
offset, note = calib
# measured ~ -10.5 dBFS for amplitude 0.3, so offset ~ 70 - (-10.5) = ~80.5
assert 75.0 < offset < 86.0
assert "70.0 dB" in note
# Provenance not supplied -> recorded as not recorded.
assert "Reference instrument not recorded" in note
def test_main_calibrate_appends_and_records_reference_instrument(tmp_path, capsys):
# R2: the reference-instrument provenance is stored both structurally (column on
# the append-only history) and in the human-readable calibration note.
db = tmp_path / "olive.db"
cfg = tmp_path / "cfg.json"
cfg.write_text(f'{{"db_path": "{db}"}}')
def factory(config):
return synthetic_session(3.0, [LoudRegion(0.0, 3.0, 0.3)], frame_size=config.frame_size)
# Seed an existing epoch so we can prove calibrate appends (never updates).
with EventStore(db) as store:
store.add_calibration(1.0, "old", effective_from=0.0)
rc = main_calibrate(
[
"--config",
str(cfg),
"--reference-db",
"70",
"--seconds",
"2",
"--reference-instrument",
"Brand X, IEC 61672 Class 2",
],
source_factory=factory,
)
assert rc == 0
capsys.readouterr()
with EventStore(db) as store:
history = store.calibration_history()
calib = store.get_calibration()
assert len(history) == 2 # appended, not overwritten
latest = history[-1]
assert latest.reference_instrument == "Brand X, IEC 61672 Class 2"
assert "Reference instrument: Brand X, IEC 61672 Class 2." in (latest.note or "")
# Backward-compatible accessor surfaces the same provenance-bearing note.
assert calib is not None
assert "Reference instrument: Brand X, IEC 61672 Class 2." in calib[1]