godosa-engine

git clone https://git.godosa.eu/godosa-engine

master

raw · 1770 bytes

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()