Commit d14eb8b1 authored by Lauros Pajunen's avatar Lauros Pajunen
Browse files

Merge remote-tracking branch 'origin/main' into 1154-add-rtpdump-support-no-pi-appliance

parents c6ebdc86 5a2155b7
Loading
Loading
Loading
Loading
Loading
+126 −0
Original line number Diff line number Diff line
import pytest
import subprocess
import itertools
import sys
from enum import Enum
from pathlib import Path
from tempfile import TemporaryDirectory

HERE = Path(__file__).absolute().parent
TESTV_DIR = HERE.parent / "scripts/testv"
OUTPUT_FOLDER_IF_KEEP_FILES = HERE.joinpath("output-ambi_converter-be")

sys.path.append(str(HERE.parent / "scripts"))
from pyaudio3dtools import audiofile, audioarray


class AMBI_CONVENTION(int, Enum):
    ACN_SN3D = 0
    ACN_N3D = 1
    FUMA_MAXN = 2
    FUMA_FUMA = 3
    SID_SN3D = 4
    SID_N3D = 5


def run_ambi_converter(
    bin_path: Path,
    infile: Path,
    outfile: str,
    convention_in: AMBI_CONVENTION,
    convention_out: AMBI_CONVENTION,
):
    cmd = [
        str(bin_path),
        str(infile),
        outfile,
        f"{int(convention_in)}",
        f"{int(convention_out)}",
    ]
    print(" ".join(cmd))

    p = subprocess.run(cmd, capture_output=True)
    if p.returncode != 0:
        msg = f"{p.stdout.decode('utf8')}\n{p.stderr.decode('utf8')}"
        pytest.fail(f"Ambisonics converter run failed:\n{msg}")


# test all ambisonics orders from 1 to 3
INPUT_CH_NUM = [4, 9, 16]
INPUT_FS = [16, 32, 48]
INPUT_FILES = [
    TESTV_DIR / f"spectral_test_{ch}ch_{fs}kHz.wav"
    for ch in INPUT_CH_NUM
    for fs in INPUT_FS
]
CONVENTIONS = [c for c in AMBI_CONVENTION]
AMBI_CONVERTER_PATH_FLOAT = HERE.parent / "ambi_converter_flt"
AMBI_CONVERTER_PATH_FIXED = HERE.parent / "ambi_converter_fx"
THRESHOLD_FAIL = 1

CONVENTIONS_FULL_COMBI = list(itertools.product(CONVENTIONS, CONVENTIONS))
CONVENTIONS_TEST_PARAMS = [
    (c_in.value, c_out.value) for c_in, c_out in CONVENTIONS_FULL_COMBI
]
CONVENTIONS_TEST_PARAMS_IDS = [
    f"{c_in.name}-to-{c_out.name}" for c_in, c_out in CONVENTIONS_FULL_COMBI
]


@pytest.mark.parametrize("infile", INPUT_FILES, ids=[p.name for p in INPUT_FILES])
@pytest.mark.parametrize(
    "convention_in,convention_out",
    CONVENTIONS_TEST_PARAMS,
    ids=CONVENTIONS_TEST_PARAMS_IDS,
)
def test_ambi_converter(
    infile: Path,
    convention_in: AMBI_CONVENTION,
    convention_out: AMBI_CONVENTION,
    keep_files,
    # needs to be passed to correctly report errors
    test_info,
):
    if (
        convention_out != AMBI_CONVENTION.ACN_SN3D
        and convention_in != AMBI_CONVENTION.ACN_SN3D
    ):
        pytest.xfail("One of in and out convention needs to be ACN_SN3D")

    if keep_files:
        OUTPUT_FOLDER_IF_KEEP_FILES.mkdir(exist_ok=True, parents=True)

    with TemporaryDirectory() as tmp_dir:
        output_dir = OUTPUT_FOLDER_IF_KEEP_FILES if keep_files else tmp_dir

        outfile_base = Path(output_dir) / (
            infile.stem + f"-{str(convention_in)}-to-{str(convention_out)}"
        )

        outfile_flt = str(outfile_base) + "-flt.wav"
        outfile_fx = str(outfile_base) + "-fx.wav"

        run_ambi_converter(
            AMBI_CONVERTER_PATH_FLOAT,
            infile,
            outfile_flt,
            convention_in,
            convention_out,
        )

        run_ambi_converter(
            AMBI_CONVERTER_PATH_FIXED,
            infile,
            outfile_fx,
            convention_in,
            convention_out,
        )

        s_flt, _ = audiofile.readfile(outfile_flt)
        s_fx, _ = audiofile.readfile(outfile_fx)

        cmp_result = audioarray.compare(s_flt, s_fx, fs=48000, per_frame=False)
        if abs(cmp_result["max_abs_diff"]) > THRESHOLD_FAIL:
            pytest.fail(
                f"Difference between float and fixed ambi_converter output found! Max abs diff: {cmp_result['max_abs_diff']}"
            )