aboutsummaryrefslogtreecommitdiffziptar.gz
path: root/scripts/test_audio_report.py
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/test_audio_report.py')
-rw-r--r--scripts/test_audio_report.py44
1 files changed, 44 insertions, 0 deletions
diff --git a/scripts/test_audio_report.py b/scripts/test_audio_report.py
new file mode 100644
index 0000000..87862ca
--- /dev/null
+++ b/scripts/test_audio_report.py
@@ -0,0 +1,44 @@
+import array
+import math
+import struct
+import sys
+import tempfile
+import unittest
+from pathlib import Path
+
+sys.path.insert(0, str(Path(__file__).resolve().parent))
+import audio_report as ar
+
+
+def wav_bytes(frames, rate=8000, channels=2, data_size=None):
+ raw = frames.tobytes()
+ size = len(raw) if data_size is None else data_size
+ return struct.pack("<4sI4s4sIHHIIHH4sI", b"RIFF", 36 + size, b"WAVE", b"fmt ", 16, 1, channels,
+ rate, rate * channels * 2, channels * 2, 16, b"data", size) + raw
+
+
+class AudioReportTests(unittest.TestCase):
+ def test_reads_to_eof_even_with_placeholder_data_size(self):
+ frames = array.array("h", [1000, -1000] * 8000) # 1 s stereo at 8 kHz
+ with tempfile.TemporaryDirectory() as tmp:
+ path = Path(tmp) / "a.wav"
+ path.write_bytes(wav_bytes(frames, data_size=0)) # killed writer: size never fixed
+ rate, channels, samples = ar.read_wav(path)
+ self.assertEqual((rate, channels, len(samples)), (8000, 2, 16000))
+
+ def test_levels_per_second_of_mono_mix(self):
+ # second 0: full-scale square on both channels (0 dBFS); second 1: silence
+ loud = [16384 if (i // 20) % 2 else -16384 for i in range(8000)]
+ frames = array.array("h", [v for s in loud for v in (s, s)] + [0, 0] * 8000)
+ lv = ar.levels(8000, 2, frames)
+ self.assertEqual(len(lv), 2)
+ self.assertAlmostEqual(lv[0][1], 20 * math.log10(0.5), places=3) # rms of ±0.5 square
+ self.assertEqual(lv[1][1], -120.0)
+
+ def test_opposite_channels_cancel_in_the_mix(self):
+ frames = array.array("h", [8000, -8000] * 8000)
+ self.assertEqual(ar.levels(8000, 2, frames)[0][1], -120.0)
+
+
+if __name__ == "__main__":
+ unittest.main()