diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index ba1e69ae7d7e5ee795ca332229ab0922bf832ea4..55f66e41886dabb947795653d68a03defda8cdd2 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -274,6 +274,7 @@ stages: - if: $MANUAL_PIPELINE_TYPE == 'ivas-conformance-linux' when: never - if: $MANUAL_PIPELINE_TYPE == 'check-clipping' + when: never - if: $MANUAL_PIPELINE_TYPE == 'test-branch-vs-input-passthrough' when: never - when: on_success @@ -1750,7 +1751,6 @@ test-branch-vs-input-passthrough: junit: - report-junit.xml - # --------------------------------------------------------------- # Scheduled jobs on main # --------------------------------------------------------------- diff --git a/scripts/diff_report.py b/scripts/diff_report.py index 0b9cec591a5eb698af524a8ff22fef5dc11d8069..df32b03a448ab2795872ace42446c6cb7e812de6 100644 --- a/scripts/diff_report.py +++ b/scripts/diff_report.py @@ -48,7 +48,7 @@ def main(args): df_test = pd.read_csv(args.csv_test, sep=";") for col in COLUMNS_TO_COMPARE: - df_ref[col] = df_ref[col] - df_test[col] + df_ref[col] = df_test[col] - df_ref[col] df_ref.to_csv(args.csv_diff, index=False, sep=";") return 0 diff --git a/scripts/parse_xml_report.py b/scripts/parse_xml_report.py index d1c5f30e476abe4c66f27647a4952df1963491a9..d68637c64977f7538957ce1b0cb3d6c47c311e13 100644 --- a/scripts/parse_xml_report.py +++ b/scripts/parse_xml_report.py @@ -15,7 +15,7 @@ PROPERTIES = ["MLD", "MAXIMUM ABS DIFF", "MIN_SSNR", "MIN_ODG"] IVAS_FORMATS = { "Stereo": r"stereo", "ISM": r"ISM", - "Multichannel": r"Multi-channel", + "Multichannel": r"Multi-channel|MC", "MASA": r"(? (int, str): @@ -53,15 +56,20 @@ def cmp_pcm( else: nchannels = pyivastest.constants.OC_TO_NCHANNELS[out_config.upper()] - s1, _ = pyaudio3dtools.audiofile.readfile( + s1, fs1 = pyaudio3dtools.audiofile.readfile( ref_file, nchannels, fs, outdtype=np.int16 ) - s2, _ = pyaudio3dtools.audiofile.readfile( + s2, fs2 = pyaudio3dtools.audiofile.readfile( cmp_file, nchannels, fs, outdtype=np.int16 ) # In case of wav input, override the nchannels with the one from the wav header nchannels = s1.shape[1] + fs = fs1 + + if fs1 != fs2: + reason = "FAIL: Sampling rate differs." + return 1, reason # In case number of channels do not match, fail already now. Could happen in case of # comparison to input with for a non-passthrough mode. @@ -129,14 +137,31 @@ def cmp_pcm( reason += msg + " - " if get_odg: - for n in range(nchannels): - pqeval_output = pqevalaudio_wrapper(s1[:, n], s2[:, n], fs) - - match_odg = re.search(ODG_PATTERN_PQEVALAUDIO, pqeval_output) - odg = float(match_odg.groups()[0]) - msg = f"Channel {n} ODG: {odg}" - reason += " - " + msg - print(msg) + odg_files = {} + for f in [odg_input, odg_test, odg_ref]: + # Load PEAQ test files and ensure 48 kHz sampling rate + s, fs = pyaudio3dtools.audiofile.readfile( + f, nchannels, fs, outdtype=np.int16 + ) + odg_files[f] = np.clip( + pyaudio3dtools.audioarray.resample(s.astype(float), fs, 48000), + -32768, + 32767, + ).astype(np.int16) + + pqeval_output = pqevalaudio_wrapper(odg_files[odg_input], odg_files[odg_ref], 48000) + match_odg = re.search(ODG_PATTERN_PQEVALAUDIO, pqeval_output) + odg_ref = float(match_odg.groups()[0]) + + pqeval_output = pqevalaudio_wrapper(odg_files[odg_input], odg_files[odg_test], 48000) + match_odg = re.search(ODG_PATTERN_PQEVALAUDIO, pqeval_output) + odg_test = float(match_odg.groups()[0]) + + odg = odg_test - odg_ref # Todo: store both rather than difference? + + msg = f"ODG: {odg}" + reason += " - " + msg + print(msg) return output_differs, reason diff --git a/tests/codec_be_on_mr_nonselection/test_param_file.py b/tests/codec_be_on_mr_nonselection/test_param_file.py index 390edcf29b26b987e0727d2a7753d2d32580fdac..905d5a6aad7948d742069162930aaf4c14376eb8 100644 --- a/tests/codec_be_on_mr_nonselection/test_param_file.py +++ b/tests/codec_be_on_mr_nonselection/test_param_file.py @@ -32,7 +32,6 @@ __doc__ = """ Execute tests specified via a parameter file. """ -import errno import filecmp import os import platform @@ -52,6 +51,7 @@ from tests.constants import ( SCRIPTS_DIR, MAX_ENC_DIFF, ) +from tests.renderer.utils import check_and_makedir, binauralize_input_and_output PASSTHROUGH_CONF = [ (r"[\s\S]*", "EXT"), # Any input with EXT output is pass-through @@ -82,6 +82,45 @@ VALID_DEC_OUTPUT_CONF = [ "EXT", ] +INPUT_FMT = [ + (r"-stereo", "STEREO"), + (r"-sba\s?[-+]?1", "FOA"), + (r"-sba\s?[-+]?2", "HOA2"), + (r"-sba\s?[-+]?3", "HOA3"), + (r"-mc\s5_1\s", "5_1"), + (r"-mc\s7_1\s", "7_1"), + (r"-mc\s5_1_2", "5_1_2"), + (r"-mc\s5_1_4", "5_1_4"), + (r"-mc\s7_1_4", "7_1_4"), + (r"-ism\s?[-+]?1", "ISM1"), + (r"-ism\s?[-+]?2", "ISM2"), + (r"-ism\s?[-+]?3", "ISM3"), + (r"-ism\s?[-+]?4", "ISM4"), + (r"-masa\s?1", "MASA1"), + (r"-masa\s?2", "MASA2"), + (r"-ism_masa\s?1\s?1", "OMASA_1_1"), + (r"-ism_masa\s?2\s?1", "OMASA_2_1"), + (r"-ism_masa\s?3\s?1", "OMASA_3_1"), + (r"-ism_masa\s?4\s?1", "OMASA_4_1"), + (r"-ism_masa\s?1\s?2", "OMASA_1_2"), + (r"-ism_masa\s?2\s?2", "OMASA_2_2"), + (r"-ism_masa\s?3\s?2", "OMASA_3_2"), + (r"-ism_masa\s?4\s?2", "OMASA_4_2"), + (r"-ism_sba\s?1\s?[-+]?1", "OSBA_1_1"), + (r"-ism_sba\s?2\s?[-+]?1", "OSBA_2_1"), + (r"-ism_sba\s?3\s?[-+]?1", "OSBA_3_1"), + (r"-ism_sba\s?4\s?[-+]?1", "OSBA_4_1"), + (r"-ism_sba\s?1\s?[-+]?2", "OSBA_1_2"), + (r"-ism_sba\s?2\s?[-+]?2", "OSBA_2_2"), + (r"-ism_sba\s?3\s?[-+]?2", "OSBA_3_2"), + (r"-ism_sba\s?4\s?[-+]?2", "OSBA_4_2"), + (r"-ism_sba\s?1\s?[-+]?3", "OSBA_1_3"), + (r"-ism_sba\s?2\s?[-+]?3", "OSBA_2_3"), + (r"-ism_sba\s?3\s?[-+]?3", "OSBA_3_3"), + (r"-ism_sba\s?4\s?[-+]?3", "OSBA_4_3"), + (r".*", "MONO"), +] + PARAM_FILE_ID = ( "stv" if PARAM_FILE.stem == "self_test" @@ -118,15 +157,6 @@ with open(PARAM_FILE, "r", encoding="UTF-8") as fp: param_file_test_dict[tag] = (enc_opts, dec_opts, sim_opts, eid_opts) -def check_and_makedir(dir_path): - if not os.path.exists(dir_path): - try: - os.makedirs(dir_path) - except OSError as e: - if e.errno != errno.EEXIST: - raise # raises the error again - - def convert_test_string_to_tag(test_string): """ Convert a test string (i.e. the test tag from the parameter file) to a tag string. @@ -152,6 +182,7 @@ def convert_test_string_to_tag(test_string): # hack to have stv/ltv/evs in the test name @pytest.mark.parametrize("param_file_id", [PARAM_FILE_ID]) def test_param_file_tests( + test_info, props_to_record, encoder_only, decoder_only, @@ -175,8 +206,68 @@ def test_param_file_tests( get_odg, compare_to_input, ): + enc_opts, dec_opts, sim_opts, eid_opts = param_file_test_dict[test_tag] + run_test( + test_info, + props_to_record, + encoder_only, + decoder_only, + dut_encoder_frontend, + dut_decoder_frontend, + ref_encoder_frontend, + ref_decoder_frontend, + enc_opts, + dec_opts, + sim_opts, + eid_opts, + reference_path, + dut_base_path, + test_vector_path, + update_ref, + rootdir, + keep_files, + test_tag, + get_mld, + get_mld_lim, + abs_tol, + get_ssnr, + get_enc_stats, + get_odg, + compare_to_input, + ) + + +def run_test( + test_info, + props_to_record, + encoder_only, + decoder_only, + dut_encoder_frontend: EncoderFrontend, + dut_decoder_frontend: DecoderFrontend, + ref_encoder_frontend: EncoderFrontend, + ref_decoder_frontend: DecoderFrontend, + enc_opts, + dec_opts, + sim_opts, + eid_opts, + reference_path, + dut_base_path, + test_vector_path, + update_ref, + rootdir, + keep_files, + test_tag, + get_mld, + get_mld_lim, + abs_tol, + get_ssnr, + get_enc_stats, + get_odg, + compare_to_input, +): + # If compare_to_input is set, only run pass-through test cases if compare_to_input: passthrough = [ @@ -206,6 +297,7 @@ def test_param_file_tests( fs = enc_split.pop() sampling_rate = int(fs) bitrate = enc_split.pop() + in_sr = sampling_rate # bitrate can be a filename: remove leading "../" if bitrate.startswith("../"): @@ -349,6 +441,7 @@ def test_param_file_tests( output_file = dec_split.pop() bitstream_file_dec = dec_split.pop() sampling_rate = int(dec_split.pop()) + out_sr = sampling_rate if len(dec_split) > 0: output_config = dec_split.pop() if output_config.upper() not in VALID_DEC_OUTPUT_CONF: @@ -396,9 +489,57 @@ def test_param_file_tests( ) if update_ref in [0, 2]: + + # Output file names for comparison dut_output_file = f"{dut_base_path}/param_file/dec/{output_file}" ref_output_file = f"{reference_path}/param_file/dec/{output_file}" + # Check if we need to render to mono, stereo or binaural for PEAQ comparison + odg_input = None + odg_test = None + odg_ref = None + if get_odg: + + # Find input format + in_fmt = [(a, b) for (a, b) in INPUT_FMT if re.search(a, enc_opts)][0][1] + + record_property = ( + dut_decoder_frontend.record_property + if dut_decoder_frontend + else ref_decoder_frontend.record_property + ) + + (odg_input, odg_test) = binauralize_input_and_output( + record_property, + props_to_record, + test_info, + testv_file, + dut_output_file, + ref_output_file, + in_fmt, + output_config, + enc_opts, + dec_opts, + in_sr, + out_sr, + ) + + (_ , odg_ref) = binauralize_input_and_output( + record_property, + props_to_record, + test_info, + testv_file, + ref_output_file, + ref_output_file, + in_fmt, + output_config, + enc_opts, + dec_opts, + in_sr, + out_sr, + skip_input_rendering=True, + ) + # set to false per default even if this is no JBM case - makes later check for failure easier tracefile_last_rtp_numbers_differ = False @@ -443,6 +584,9 @@ def test_param_file_tests( allow_differing_lengths=allow_differing_lengths, get_ssnr=get_ssnr, get_odg=get_odg, + odg_input=odg_input, + odg_test=odg_test, + odg_ref=odg_ref, ref_jbm_tf=ref_tracefile_dec, cut_jbm_tf=dut_tracefile_dec, ) diff --git a/tests/codec_be_on_mr_nonselection/test_sba.py b/tests/codec_be_on_mr_nonselection/test_sba.py index 4bd81cdfd302bec7129b6652616441287bc71d04..576ffd8a2fd34ef9668da8ee69fbbc7c74d2cf94 100644 --- a/tests/codec_be_on_mr_nonselection/test_sba.py +++ b/tests/codec_be_on_mr_nonselection/test_sba.py @@ -45,6 +45,7 @@ from ..cmp_stats_files import cmp_stats_files from ..constants import TESTV_DIR, MAX_ENC_FILE_LENGTH_DIFF, MAX_ENC_STATS_DIFF from tests.testconfig import use_ltv +from tests.renderer.utils import check_and_makedir, binauralize_input_and_output tag_list = ["ltvFOA" if use_ltv else "stvFOA"] tag_list_HOA2 = ["ltvHOA2" if use_ltv else "stv2OA"] @@ -79,19 +80,13 @@ tag_list_plc = tag_list plc_patterns = ["PLperc12mblen5", "PLperc40mblen50", "PLperc42mblen2"] ivas_br_plc = ["13200", "16400", "32000", "64000", "96000", "256000"] - -def check_and_makedir(dir_path): - if not os.path.exists(dir_path): - try: - os.makedirs(dir_path) - except OSError as e: - if e.errno != errno.EEXIST: - raise # raises the error again - +# SBA order to IVAS_rend format table +SBA_FORMAT={1: "FOA", 2: "HOA2", 3: "HOA3"} @pytest.mark.parametrize("tag", tag_list) @pytest.mark.parametrize("sampling_rate", sample_rate_list) def test_pca_enc( + test_info, props_to_record, dut_encoder_frontend: EncoderFrontend, dut_decoder_frontend: DecoderFrontend, @@ -136,6 +131,8 @@ def test_pca_enc( else: assert 0 + input_config = SBA_FORMAT[abs(int(sba_order))] + if not decoder_only: sba_enc( dut_encoder_frontend, @@ -163,6 +160,7 @@ def test_pca_enc( if not encoder_only: sba_dec( + test_info, props_to_record, test_vector_path, dut_decoder_frontend, @@ -175,11 +173,14 @@ def test_pca_enc( dtx, sid, max_bw, + input_config, output_config, update_ref, gain_flag, keep_files, decoder_only, + cut_gain=cut_gain, + cut_testv=cut_testv, plc_pattern=plc_pattern, get_mld=get_mld, get_mld_lim=get_mld_lim, @@ -198,6 +199,7 @@ def test_pca_enc( @pytest.mark.parametrize("gain_flag", gain_list) @pytest.mark.parametrize("sid", SID_list) def test_sba_enc_system( + test_info, props_to_record, dut_encoder_frontend: EncoderFrontend, dut_decoder_frontend: DecoderFrontend, @@ -270,6 +272,8 @@ def test_sba_enc_system( else: cut_gain = "1.0" + input_config = SBA_FORMAT[abs(int(sba_order))] + if not decoder_only: ref_stats_file, dut_stats_file = sba_enc( dut_encoder_frontend, @@ -332,6 +336,7 @@ def test_sba_enc_system( if not encoder_only: sba_dec( + test_info, props_to_record, test_vector_path, dut_decoder_frontend, @@ -344,11 +349,14 @@ def test_sba_enc_system( dtx, sid, max_bw, + input_config, output_config, update_ref, gain_flag, keep_files, decoder_only, + cut_gain=cut_gain, + cut_testv=cut_testv, plc_pattern=plc_pattern, get_mld=get_mld, get_mld_lim=get_mld_lim, @@ -363,6 +371,7 @@ def test_sba_enc_system( @pytest.mark.parametrize("bitrate", ivas_br_HOA2) @pytest.mark.parametrize("tag", tag_list_HOA2) def test_spar_hoa2_enc_system( + test_info, props_to_record, dut_encoder_frontend: EncoderFrontend, dut_decoder_frontend: DecoderFrontend, @@ -405,6 +414,8 @@ def test_spar_hoa2_enc_system( else: assert 0 + input_config = SBA_FORMAT[abs(int(sba_order))] + if not decoder_only: ref_stats_file, dut_stats_file = sba_enc( dut_encoder_frontend, @@ -467,6 +478,7 @@ def test_spar_hoa2_enc_system( if not encoder_only: sba_dec( + test_info, props_to_record, test_vector_path, dut_decoder_frontend, @@ -479,11 +491,14 @@ def test_spar_hoa2_enc_system( dtx, sid, max_bw, + input_config, output_config, update_ref, gain_flag, keep_files, decoder_only, + cut_gain=cut_gain, + cut_testv=cut_testv, plc_pattern=plc_pattern, get_mld=get_mld, get_mld_lim=get_mld_lim, @@ -498,6 +513,7 @@ def test_spar_hoa2_enc_system( @pytest.mark.parametrize("bitrate", ivas_br_HOA3) @pytest.mark.parametrize("tag", tag_list_HOA3) def test_spar_hoa3_enc_system( + test_info, props_to_record, dut_encoder_frontend: EncoderFrontend, dut_decoder_frontend: DecoderFrontend, @@ -540,6 +556,8 @@ def test_spar_hoa3_enc_system( else: assert 0 + input_config = SBA_FORMAT[abs(int(sba_order))] + if not decoder_only: ref_stats_file, dut_stats_file = sba_enc( dut_encoder_frontend, @@ -596,6 +614,7 @@ def test_spar_hoa3_enc_system( if not encoder_only: sba_dec( + test_info, props_to_record, test_vector_path, dut_decoder_frontend, @@ -608,11 +627,14 @@ def test_spar_hoa3_enc_system( dtx, sid, max_bw, + input_config, output_config, update_ref, gain_flag, keep_files, decoder_only, + cut_gain=cut_gain, + cut_testv=cut_testv, plc_pattern=plc_pattern, get_mld=get_mld, get_mld_lim=get_mld_lim, @@ -629,6 +651,7 @@ def test_spar_hoa3_enc_system( @pytest.mark.parametrize("tag", tag_list_bw_force) @pytest.mark.parametrize("sample_rate_bw_idx", sample_rate_bw_idx_list) def test_sba_enc_BWforce_system( + test_info, props_to_record, dut_encoder_frontend: EncoderFrontend, dut_decoder_frontend: DecoderFrontend, @@ -683,6 +706,8 @@ def test_sba_enc_BWforce_system( else: assert 0 + input_config = SBA_FORMAT[abs(int(sba_order))] + if not decoder_only: ref_stats_file, dut_stats_file = sba_enc( dut_encoder_frontend, @@ -745,6 +770,7 @@ def test_sba_enc_BWforce_system( if not encoder_only: sba_dec( + test_info, props_to_record, test_vector_path, dut_decoder_frontend, @@ -757,11 +783,14 @@ def test_sba_enc_BWforce_system( dtx, sid, max_bw, + input_config, output_config, update_ref, gain_flag, keep_files, decoder_only, + cut_gain=cut_gain, + cut_testv=cut_testv, plc_pattern=plc_pattern, get_mld=get_mld, get_mld_lim=get_mld_lim, @@ -780,6 +809,7 @@ def test_sba_enc_BWforce_system( @pytest.mark.parametrize("sampling_rate", sample_rate_list) @pytest.mark.parametrize("gain_flag", gain_list) def test_sba_plc_system( + test_info, props_to_record, dut_encoder_frontend: EncoderFrontend, dut_decoder_frontend: DecoderFrontend, @@ -848,6 +878,8 @@ def test_sba_plc_system( else: cut_gain = "1.0" + input_config = SBA_FORMAT[abs(int(sba_order))] + if not decoder_only: sba_enc( dut_encoder_frontend, @@ -875,6 +907,7 @@ def test_sba_plc_system( if not encoder_only: sba_dec( + test_info, props_to_record, test_vector_path, dut_decoder_frontend, @@ -887,11 +920,14 @@ def test_sba_plc_system( dtx, sid, max_bw, + input_config, output_config, update_ref, gain_flag, keep_files, decoder_only, + cut_gain=cut_gain, + cut_testv=cut_testv, plc_pattern=plc_pattern, get_mld=get_mld, get_mld_lim=get_mld_lim, @@ -1030,6 +1066,7 @@ def sba_enc( def sba_dec( + test_info, props_to_record, test_vector_path, dut_decoder_frontend, @@ -1042,11 +1079,14 @@ def sba_dec( dtx, sid, max_bw, + input_config, output_config, update_ref, gain_flag, keep_files, decoder_only, + cut_gain="1.0", + cut_testv=False, plc_pattern=None, get_mld=False, get_mld_lim=0, @@ -1122,10 +1162,64 @@ def sba_dec( plc_file=plc_file, ) + # Check if we need to render to mono, stereo or binaural for PEAQ comparison + odg_input = None + odg_test = None + odg_ref = None + if get_odg: + enc_opts = "" + dec_opts = "" + input_file = f"{test_vector_path}/{tag}.wav" + if cut_testv: + if cut_gain == "1.0": + input_file = f"{test_vector_path}/{tag}_cut.wav" + else: + input_file = f"{test_vector_path}/{tag}_cut_{cut_gain}.wav" + in_fmt = input_config + in_sr = sampling_rate + out_sr = sampling_rate + + (odg_input, odg_test) = binauralize_input_and_output( + dut_decoder_frontend.record_property, + props_to_record, + test_info, + input_file, + dut_out_file, + ref_out_file, + in_fmt, + output_config, + enc_opts, + dec_opts, + in_sr, + out_sr, + ) + + (_, odg_ref) = binauralize_input_and_output( + dut_decoder_frontend.record_property, + props_to_record, + test_info, + input_file, + ref_out_file, + ref_out_file, + in_fmt, + output_config, + enc_opts, + dec_opts, + in_sr, + out_sr, + skip_input_rendering=True, + ) + + allow_differing_lengths = False if compare_to_input: # If comparing to input, set input as reference and allow different length ref_out_file = f"{test_vector_path}/{tag}.wav" + if gain_flag != -1: + ref_out_file = f"{test_vector_path}/{tag}_Gain{gain_flag}.wav" + else: + ref_out_file = f"{test_vector_path}/{tag}.wav" + allow_differing_lengths = True sampling_rate_Hz = int(sampling_rate) * 1000 @@ -1140,6 +1234,9 @@ def sba_dec( allow_differing_lengths=allow_differing_lengths, get_ssnr=get_ssnr, get_odg=get_odg, + odg_input=odg_input, + odg_test=odg_test, + odg_ref=odg_ref, ) text_to_parse = reason diff --git a/tests/conftest.py b/tests/conftest.py index bb9e8ca3871c6e252fcb2bdcdd0c7392fc1df5ee..d290c7dbc6cda84cb044910e1f24b0468aba4efa 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -274,7 +274,7 @@ def pytest_addoption(parser): help="Compare output to the input file instead of reference output. N.B. Only applicable to pass-through tests.", default=False, ) - + @pytest.fixture(scope="session", autouse=True) def update_ref(request): @@ -387,6 +387,10 @@ def dut_encoder_path(request) -> str: return path +# fixture returns test information, enabling per-testcase SNR +@pytest.fixture +def test_info(request): + return request class EncoderFrontend: def __init__(self, path, enc_type, record_property, timeout=None) -> None: @@ -1042,6 +1046,7 @@ def compare_to_input(request) -> bool: return request.config.getoption("--compare_to_input") + def pytest_configure(config): config.addinivalue_line("markers", "serial: mark test to run only in serial") if config.option.param_file: diff --git a/tests/hrtf_binary_loading/utils.py b/tests/hrtf_binary_loading/utils.py index b0077edf082fba180c82482b51bae7995edcb40f..4e74a32f7fc8301578e50878971073efbf9a2dad 100644 --- a/tests/hrtf_binary_loading/utils.py +++ b/tests/hrtf_binary_loading/utils.py @@ -37,7 +37,7 @@ from typing import Optional import pytest -from tests.renderer.utils import check_BE, run_cmd, run_renderer, test_info +from tests.renderer.utils import check_BE, run_cmd, run_renderer from .constants import * diff --git a/tests/renderer/constants.py b/tests/renderer/constants.py index b7326a0a7864f5b69c5f86f6cfb81adc1213cf3b..4800cd365582ff7965d54a2db06e187e162ffdc0 100644 --- a/tests/renderer/constants.py +++ b/tests/renderer/constants.py @@ -340,3 +340,11 @@ HR_TRAJECTORIES_TO_TEST = [ """ Frame Size """ FRAMING_TO_TEST = ["5ms", "20ms"] + +PEAQ_SUPPORTED_FMT = [ + "MONO", + "STEREO", + "BINAURAL", + "BINAURAL_ROOM_IR", + "BINAURAL_ROOM_REVERB", +] \ No newline at end of file diff --git a/tests/renderer/test_renderer.py b/tests/renderer/test_renderer.py index 80c935c4f6525e15da1eb217b151f74c89189f82..bb999ba6390b10e34d0dde75e6645f79fe2c6796 100644 --- a/tests/renderer/test_renderer.py +++ b/tests/renderer/test_renderer.py @@ -50,7 +50,7 @@ from .constants import ( CUSTOM_LAYOUT_DIR, METADATA_SCENES_TO_TEST, ) -from .utils import run_renderer, compare_renderer_args, test_info +from .utils import run_renderer, compare_renderer_args from ..conftest import props_to_record ############################################################################## diff --git a/tests/renderer/utils.py b/tests/renderer/utils.py index f987fe4229052d420f454692ede3b7a4f4b9310f..9a149bd7eac471391e70d507a8dbdd7b3d35f1b8 100644 --- a/tests/renderer/utils.py +++ b/tests/renderer/utils.py @@ -40,6 +40,9 @@ from typing import Dict, Optional, Union import numpy as np import pytest +import re +import errno +import tempfile from .compare_audio import compare_audio_arrays from .constants import ( @@ -52,6 +55,7 @@ from .constants import ( FORMAT_TO_FILE_SMOKETEST, RENDERER_CMD, BIN_SUFFIX_MERGETARGET, + PEAQ_SUPPORTED_FMT, ) sys.path.append(SCRIPTS_DIR) @@ -60,12 +64,6 @@ from ..cmp_pcm import cmp_pcm from ..conftest import parse_properties -# fixture returns test information, enabling per-testcase SNR -@pytest.fixture -def test_info(request): - return request - - def run_cmd(cmd, env=None): logging.info(f"\nRunning command\n{' '.join(cmd)}\n") try: @@ -171,6 +169,10 @@ def run_renderer( get_ssnr=False, get_odg=False, aeid: Optional[Union[Path, int]] = None, + in_file=None, + out_file=None, + sr=48, + render_for_peaq=False, ) -> str: # prepare arguments and filepaths if trj_file is not None: @@ -241,25 +243,27 @@ def run_renderer( else: FORMAT_TO_FILE = FORMAT_TO_FILE_SMOKETEST - if metadata_input is not None: - in_file = metadata_input - in_name = metadata_input.stem - elif not isinstance(in_fmt, str): - in_file = FORMAT_TO_FILE[in_fmt.stem] - in_name = in_fmt.stem - else: - in_file = FORMAT_TO_FILE[in_fmt] - in_name = in_fmt - - out_file_stem = f"{in_name}_to_{out_name}{trj_name}{non_diegetic_pan}{refrot_name}{refvec_name}{refveclev_name}{config_name}{framing_name}{hrtf_file_name}{name_extension}{aeid_name}.wav" + if in_file is None: + if metadata_input is not None: + in_file = metadata_input + in_name = metadata_input.stem + elif not isinstance(in_fmt, str): + in_file = FORMAT_TO_FILE[in_fmt.stem] + in_name = in_fmt.stem + else: + in_file = FORMAT_TO_FILE[in_fmt] + in_name = in_fmt - out_file = str(output_path_base.joinpath(out_file_stem)) + if out_file is None: + out_file_stem = f"{in_name}_to_{out_name}{trj_name}{non_diegetic_pan}{refrot_name}{refvec_name}{refveclev_name}{config_name}{framing_name}{hrtf_file_name}{name_extension}{aeid_name}.wav" + out_file = str(output_path_base.joinpath(out_file_stem)) cmd = RENDERER_CMD[:] cmd[2] = str(in_file) cmd[4] = str(in_fmt) cmd[6] = str(out_file) cmd[8] = str(out_fmt) + cmd[10] = str(sr) if test_info.config.option.create_ref: cmd[0] += BIN_SUFFIX_MERGETARGET @@ -307,7 +311,7 @@ def run_renderer( # run the renderer run_cmd(cmd, env) - if test_info.config.option.create_cut: + if test_info.config.option.create_cut and not render_for_peaq: # CUT creation mode will run a comparison with REF out_file_ref = str(OUTPUT_PATH_REF.joinpath(out_file_stem)) @@ -374,3 +378,229 @@ def compare_renderer_args( pytest.fail( f"CuT not BE to REF! SNR : {snr:3.2f} dB, Gain CuT: {gain_b:1.3f}, Max Diff = {int(max_diff)}" ) + + +def binauralize_input_and_output( + record_property, + props_to_record, + test_info, + input_file, + dut_output_file, + ref_output_file, + in_fmt, + output_config, + enc_opts, + dec_opts, + in_sr, + out_sr, + skip_input_rendering=False, +): + + # Use current folder as location for temporary directory, since scene description does not handle spaces in path + with tempfile.TemporaryDirectory(dir=".") as tmp_dir: + tmp_dir = Path(tmp_dir) + scene_out = str(tmp_dir.joinpath("scene_out.txt")) + scene_in = str(tmp_dir.joinpath("scene_in.txt")) + + # File names for binauralized input, if needed + dut_output_file_binaural = dut_output_file[0:-4] + ".BINAURAL.wav" + ref_output_file_binaural = ref_output_file[0:-4] + ".BINAURAL.wav" + + # Identify metadata + in_meta_files = [ + str(SCRIPTS_DIR.joinpath(m)) if m != "NULL" else m + for m in re.findall(r"\b\S+\.csv|NULL\b", enc_opts) + ] # All .csv or NULL files in enc_opts are ISM metadata files. + n_obj = len(in_meta_files) + + # If extended metadata is not used, strip the metadata for the external renderer + extended_md_used = ( + re.search(r"-ism\s?\+[1-4]", enc_opts) + and not "OMASA" in in_fmt + and not "OSBA" in in_fmt + ) + if not extended_md_used and n_obj > 0: + truncated_meta_files = [] + for md in in_meta_files: + md_out_file = str(tmp_dir.joinpath(os.path.basename(md))) + with open(md_out_file, "w") as fp_out, open(md, "r") as fp_in: + for line in fp_in: + fp_out.write( + ",".join(line.split(",")[:2]) + "\n" + ) # Keep only first two elements: azim, elev + truncated_meta_files.append(md_out_file) + in_meta_files = truncated_meta_files + + in_meta_files = in_meta_files + [ + str(SCRIPTS_DIR.joinpath(m)) for m in re.findall(r"\b\S+\.met\b", enc_opts) + ] # All .met files in enc_opts are MASA metadata files. + out_meta_files = None + if output_config == "EXT": + out_meta_files = [] + if n_obj > 0: + out_meta_files = out_meta_files + [ + f"{dut_output_file}.{i}.csv" for i in range(0, n_obj) + ] + if "MASA" in in_fmt: + out_meta_files = out_meta_files + [f"{dut_output_file}.met"] + if output_config == "EXT": + output_config = in_fmt + if output_config == "": + output_config = "MONO" # EVS mono + metadata_input = None + + if "OSBA" in in_fmt or "OMASA" in in_fmt: + scene_description_file(in_fmt, scene_in, n_obj, input_file, in_meta_files) + input_file = scene_in + in_meta_files = None + in_fmt = "META" + + if "OSBA" in output_config or "OMASA" in output_config: + scene_description_file( + output_config, scene_out, n_obj, dut_output_file, out_meta_files + ) + dut_output_file = scene_out + out_meta_files = None + output_config = "META" + + # Identify headtracking and orientation trajectories + trj_file = findstr(r"-t\s+(\S+)", dec_opts) + non_diegetic_pan = findstr(r"-non_diegetic_pan\s+(\S+)", dec_opts) + if non_diegetic_pan is not None: + output_config = "STEREO" + name_extension = None + refrot_file = findstr(r"-rf\s+(\S+)", dec_opts) + rot_tmp_file = findstr(r"-rvf\s+(\S+)", dec_opts) + refveclev_file = None + refvec_file = None + if "-otr ref_vec_lev".upper() in dec_opts.upper(): + refveclev_file = rot_tmp_file + else: + if "-otr ref_vec".upper() in dec_opts.upper(): + refvec_file = rot_tmp_file + + # Rendering configuration + config_file = findstr(r"-render_config\s+(\S+)", dec_opts) + binary_suffix = "_ref" + frame_size = findstr(r"-fr\s+(\S+)", dec_opts) + # hrtf_file = findstr(r'-hrtf\s+(\S+)', dec_opts) + hrtf_file = None # Default HRTFs used for binaural rendering of output + + aeid = findstr(r"-aeid\s+(\S+)", dec_opts) + + if not output_config.upper() in PEAQ_SUPPORTED_FMT: + # Render output to BINAURAL + output_reformat = "BINAURAL" + + check_and_makedir(str(Path(dut_output_file_binaural).parent)) + + run_renderer( + record_property, + props_to_record, + test_info, + output_config, + output_reformat, + metadata_input, + out_meta_files, + trj_file, + non_diegetic_pan, + name_extension, + refrot_file, + refvec_file, + refveclev_file, + config_file, + binary_suffix, + frame_size, + hrtf_file, + aeid, + in_file=dut_output_file, + out_file=dut_output_file_binaural, + sr=out_sr, + render_for_peaq=True, + ) + # Update output_config to rendered format + output_config = output_reformat + else: + dut_output_file_binaural = dut_output_file + + if in_fmt.upper() != output_config.upper() and not skip_input_rendering: + # Render input to match output_config + out_fmt = output_config + + check_and_makedir(str(Path(ref_output_file_binaural).parent)) + + run_renderer( + record_property, + props_to_record, + test_info, + in_fmt, + out_fmt, + metadata_input, + in_meta_files, + trj_file, + non_diegetic_pan, + name_extension, + refrot_file, + refvec_file, + refveclev_file, + config_file, + binary_suffix, + frame_size, + hrtf_file, + aeid, + in_file=input_file, + out_file=ref_output_file_binaural, + sr=in_sr, + render_for_peaq=True, + ) + else: + ref_output_file_binaural = input_file + return (ref_output_file_binaural, dut_output_file_binaural) + + +def findstr(exp, s, one_element=True): + result = [SCRIPTS_DIR.joinpath(x) for x in re.findall(exp, s)] + if len(result) == 0: + return None + if one_element: + return result[0] + return result + + +def check_and_makedir(dir_path): + if not os.path.exists(dir_path): + try: + os.makedirs(dir_path) + except OSError as e: + if e.errno != errno.EEXIST: + raise # raises the error again + + +def scene_description_file(in_fmt, metadata_tmp, n_obj, input_file, in_meta_files): + with open(metadata_tmp, "w") as fp_meta: + currdir = Path( + metadata_tmp + ).parent # File names must be relative to config file location + fp_meta.write(f"{os.path.relpath(input_file, currdir)}\n") # Input file + fp_meta.write(f"{n_obj+1}\n") # Number of sources + for n in range(0, n_obj): + if in_meta_files[n] == "NULL": + md_file = "1\n1,0,0" # NULL metadata position: azim=0,elev=0 for 1 frame, looped throughout all frames. + else: + md_file = os.path.relpath(in_meta_files[n], currdir) + fp_meta.write(f"ISM\n{n+1}\n{md_file}\n") # ISM metadata + if "OSBA" in in_fmt: + fp_meta.write( + "gain_dB:-6\n" + ) # Set -6 dB on all components for OSBA to match IVAS_dec + fp_meta.write(f"{in_fmt.split('_')[0][1:]}\n") # SBA or MASA + fp_meta.write(f"{n_obj+1}\n") + fp_meta.write(f"{in_fmt.split('_')[-1]}\n") # SBA or MASA parameter + if "OMASA" in in_fmt: + fp_meta.write( + f"{os.path.relpath(in_meta_files[n_obj], currdir)}\n" + ) # MASA metadata + if "OSBA" in in_fmt: + fp_meta.write( + "gain_dB:-6\n" + ) # Set -6 dB on all components for OSBA to match IVAS_dec diff --git a/tests/split_rendering/utils.py b/tests/split_rendering/utils.py index 1ea1e50aba2ff7a5fbc0ed0e2d01182e7c432eb4..bb826752adef5d2d731f0cb15e17a3c38f285c22 100644 --- a/tests/split_rendering/utils.py +++ b/tests/split_rendering/utils.py @@ -39,7 +39,7 @@ from typing import Tuple import numpy as np import pytest -from tests.renderer.utils import check_BE, run_cmd, test_info, run_ivas_isar_enc_cmd, run_ivas_isar_dec_cmd, run_isar_post_rend_cmd, run_isar_ext_rend_cmd +from tests.renderer.utils import check_BE, run_cmd, run_ivas_isar_enc_cmd, run_ivas_isar_dec_cmd, run_isar_post_rend_cmd, run_isar_ext_rend_cmd from tests.split_rendering.constants import * sys.path.append(SCRIPTS_DIR) diff --git a/tests/test_enc_passthrough.py b/tests/test_enc_passthrough.py new file mode 100644 index 0000000000000000000000000000000000000000..be9b7909fdbd3e148c3a695ee2bdc94ccbca6f55 --- /dev/null +++ b/tests/test_enc_passthrough.py @@ -0,0 +1,180 @@ +__copyright__ = """ +(C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, +Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., +Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, +Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other +contributors to this repository. All Rights Reserved. + +This software is protected by copyright law and by international treaties. +The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, +Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., +Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, +Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other +contributors to this repository retain full ownership rights in their respective contributions in +the software. This notice grants no license of any kind, including but not limited to patent +license, nor is any license granted by implication, estoppel or otherwise. + +Contributors are required to enter into the IVAS codec Public Collaboration agreement before making +contributions. + +This software is provided "AS IS", without any express or implied warranties. The software is in the +development stage. It is intended exclusively for experts who have experience with such software and +solely for the purpose of inspection. All implied warranties of non-infringement, merchantability +and fitness for a particular purpose are hereby disclaimed and excluded. + +Any dispute, controversy or claim arising under or in relation to providing this software shall be +submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in +accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and +the United Nations Convention on Contracts on the International Sales of Goods. +""" + +__doc__ = """ +Execute tests specified via a parameter file. +""" +import pytest + +from tests.codec_be_on_mr_nonselection.test_param_file import run_test +from tests.conftest import DecoderFrontend, EncoderFrontend +from tests.constants import SCRIPTS_DIR +import os.path + +BITRATES = [13200, 16400, 24400, 32000, 48000, 64000, 80000, 96000, 128000, 160000, 192000, 256000, 384000, 512000] +BW = [16, 32, 48] + +FORMAT = [ + ("STEREO","-stereo","stvST{bw}c.wav","STEREO"), + ("SBA1","-sba 1", "stvFOA{bw}c.wav","FOA"), + ("SBA2","-sba 2", "stv2OA{bw}c.wav","HOA2"), + ("SBA3","-sba 3", "stv3OA{bw}c.wav","HOA3"), + ("MC-5_1","-mc 5_1", "stv51MC{bw}c.wav","5_1"), + ("MC-5_1_2","-mc 5_1_2", "stv512MC{bw}c.wav","5_1_2"), + ("MC-5_1_4","-mc 5_1_4", "stv514MC{bw}c.wav","5_1_4"), + ("MC-7_1","-mc 7_1", "stv71MC{bw}c.wav","7_1"), + ("MC-7_1_4","-mc 7_1_4", "stv714MC{bw}c.wav","7_1_4"), + ("ISM1","-ism 1 testv/stvISM1.csv", "stv1ISM{bw}s.wav","EXT"), + ("ISM2","-ism 2 testv/stvISM1.csv testv/stvISM2.csv", "stv2ISM{bw}s.wav","EXT"), + ("ISM3","-ism 3 testv/stvISM1.csv testv/stvISM2.csv testv/stvISM3.csv", "stv3ISM{bw}s.wav","EXT"), + ("ISM4","-ism 4 testv/stvISM1.csv testv/stvISM2.csv testv/stvISM3.csv testv/stvISM4.csv", "stv4ISM{bw}s.wav","EXT"), + ("MASA1-1Dir","-masa 1 testv/stv1MASA1TC48c.met","stv1MASA1TC{bw}c.wav","EXT"), + ("MASA1-2Dir","-masa 1 testv/stv2MASA1TC48c.met","stv2MASA1TC{bw}c.wav","EXT"), + ("MASA2-1Dir","-masa 2 testv/stv1MASA2TC48c.met","stv1MASA2TC{bw}c.wav","EXT"), + ("MASA2-2Dir","-masa 2 testv/stv2MASA2TC48c.met","stv2MASA2TC{bw}c.wav","EXT"), + ("OMASA-1-1-1Dir","-ism_masa 1 1 testv/stvISM1.csv testv/stv1MASA1TC48c.met","stvOMASA_1ISM_1MASA1TC{bw}c.wav","BINAURAL"), + ("OMASA-2-1-1Dir","-ism_masa 2 1 testv/stvISM1.csv testv/stvISM2.csv testv/stv1MASA1TC48c.met","stvOMASA_2ISM_1MASA1TC{bw}c.wav","BINAURAL"), + ("OMASA-3-1-1Dir","-ism_masa 3 1 testv/stvISM1.csv testv/stvISM2.csv testv/stvISM3.csv testv/stv1MASA1TC48c.met","stvOMASA_3ISM_1MASA1TC{bw}c.wav","BINAURAL"), + ("OMASA-4-1-1Dir","-ism_masa 4 1 testv/stvISM1.csv testv/stvISM2.csv testv/stvISM3.csv testv/stvISM4.csv testv/stv1MASA1TC48c.met","stvOMASA_4ISM_1MASA1TC{bw}c.wav","BINAURAL"), + ("OMASA-1-2-1Dir","-ism_masa 1 2 testv/stvISM1.csv testv/stv1MASA2TC48c.met","stvOMASA_1ISM_1MASA2TC{bw}c.wav","BINAURAL"), + ("OMASA-2-2-1Dir","-ism_masa 2 2 testv/stvISM1.csv testv/stvISM2.csv testv/stv1MASA2TC48c.met","stvOMASA_2ISM_1MASA2TC{bw}c.wav","BINAURAL"), + ("OMASA-3-2-1Dir","-ism_masa 3 2 testv/stvISM1.csv testv/stvISM2.csv testv/stvISM3.csv testv/stv1MASA2TC48c.met","stvOMASA_3ISM_1MASA2TC{bw}c.wav","BINAURAL"), + ("OMASA-4-2-1Dir","-ism_masa 4 2 testv/stvISM1.csv testv/stvISM2.csv testv/stvISM3.csv testv/stvISM4.csv testv/stv1MASA2TC48c.met","stvOMASA_4ISM_1MASA2TC{bw}c.wav","BINAURAL"), + ("OMASA-1-1-2Dir","-ism_masa 1 1 testv/stvISM1.csv testv/stv2MASA1TC48c.met","stvOMASA_1ISM_2MASA1TC{bw}c.wav","BINAURAL"), + ("OMASA-2-1-2Dir","-ism_masa 2 1 testv/stvISM1.csv testv/stvISM2.csv testv/stv2MASA1TC48c.met","stvOMASA_2ISM_2MASA1TC{bw}c.wav","BINAURAL"), + ("OMASA-3-1-2Dir","-ism_masa 3 1 testv/stvISM1.csv testv/stvISM2.csv testv/stvISM3.csv testv/stv2MASA1TC48c.met","stvOMASA_3ISM_2MASA1TC{bw}c.wav","BINAURAL"), + ("OMASA-4-1-2Dir","-ism_masa 4 1 testv/stvISM1.csv testv/stvISM2.csv testv/stvISM3.csv testv/stvISM4.csv testv/stv2MASA1TC48c.met","stvOMASA_4ISM_2MASA1TC{bw}c.wav","BINAURAL"), + ("OMASA-1-2-2Dir","-ism_masa 1 2 testv/stvISM1.csv testv/stv2MASA2TC48c.met","stvOMASA_1ISM_2MASA2TC{bw}c.wav","BINAURAL"), + ("OMASA-2-2-2Dir","-ism_masa 2 2 testv/stvISM1.csv testv/stvISM2.csv testv/stv2MASA2TC48c.met","stvOMASA_2ISM_2MASA2TC{bw}c.wav","BINAURAL"), + ("OMASA-3-2-2Dir","-ism_masa 3 2 testv/stvISM1.csv testv/stvISM2.csv testv/stvISM3.csv testv/stv2MASA2TC48c.met","stvOMASA_3ISM_2MASA2TC{bw}c.wav","BINAURAL"), + ("OMASA-4-2-2Dir","-ism_masa 4 2 testv/stvISM1.csv testv/stvISM2.csv testv/stvISM3.csv testv/stvISM4.csv testv/stv2MASA2TC48c.met","stvOMASA_4ISM_2MASA2TC{bw}c.wav","BINAURAL"), + # OSBA only supported for HOA3 in ivas-float-update for now + # ("OSBA-1-1","-ism_sba 1 1 testv/stvISM1.csv","stvOSBA_1ISM_FOA{bw}c.wav", "EXT"), + # ("OSBA-2-1","-ism_sba 2 1 testv/stvISM1.csv testv/stvISM2.csv","stvOSBA_2ISM_FOA{bw}c.wav", "EXT"), + # ("OSBA-3-1","-ism_sba 3 1 testv/stvISM1.csv testv/stvISM2.csv testv/stvISM3.csv","stvOSBA_3ISM_FOA{bw}c.wav", "EXT"), + # ("OSBA-4-1","-ism_sba 4 1 testv/stvISM1.csv testv/stvISM2.csv testv/stvISM3.csv testv/stvISM4.csv", "stvOSBA_4ISM_FOA{bw}c.wav", "EXT"), + # ("OSBA-1-2","-ism_sba 1 2 testv/stvISM1.csv","stvOSBA_1ISM_2OA{bw}c.wav", "EXT"), + # ("OSBA-2-2","-ism_sba 2 2 testv/stvISM1.csv testv/stvISM2.csv","stvOSBA_2ISM_2OA{bw}c.wav", "EXT"), + # ("OSBA-3-2","-ism_sba 3 2 testv/stvISM1.csv testv/stvISM2.csv testv/stvISM3.csv","stvOSBA_3ISM_2OA{bw}c.wav", "EXT"), + # ("OSBA-4-2","-ism_sba 4 2 testv/stvISM1.csv testv/stvISM2.csv testv/stvISM3.csv testv/stvISM4.csv", "stvOSBA_4ISM_2OA{bw}c.wav", "EXT"), + ("OSBA-1-3","-ism_sba 1 3 testv/stvISM1.csv","stvOSBA_1ISM_3OA{bw}c.wav", "EXT"), + ("OSBA-2-3","-ism_sba 2 3 testv/stvISM1.csv testv/stvISM2.csv","stvOSBA_2ISM_3OA{bw}c.wav", "EXT"), + ("OSBA-3-3","-ism_sba 3 3 testv/stvISM1.csv testv/stvISM2.csv testv/stvISM3.csv","stvOSBA_3ISM_3OA{bw}c.wav", "EXT"), + ("OSBA-4-3","-ism_sba 4 3 testv/stvISM1.csv testv/stvISM2.csv testv/stvISM3.csv testv/stvISM4.csv", "stvOSBA_4ISM_3OA{bw}c.wav", "EXT"), +] + +test_dict = {} +for fmt, in_fmt, in_file, out_fmt in FORMAT: + for br in BITRATES: + for bw in BW: + + # Filter out unsupported bitrate combinations + if fmt == "STEREO" and br > 256000: + continue + if fmt == "ISM1" and br > 128000: + continue + if fmt == "ISM2" and (br < 16400 or br > 256000): + continue + if fmt == "ISM3" and (br < 24400 or br > 384000): + continue + if fmt == "ISM4" and br < 24400: + continue + + # Filter out cases where the input file does not exist for this bandwidth + if not os.path.isfile(os.path.join(SCRIPTS_DIR, f"testv/{in_file.format(bw=bw)}")): + continue + + tag = f"{fmt}-{br}-{bw}" + enc_opts = f"{in_fmt} {br} {bw} testv/{in_file.format(bw=bw)} bit" + dec_opts = f"{out_fmt} {bw} bit out.wav" + sim_opts = "" + eid_opts = "" + test_dict[tag] = (enc_opts, dec_opts, sim_opts, eid_opts) + + + +@pytest.mark.parametrize("test_tag", list(test_dict.keys())) +def test_enc( + test_info, + props_to_record, + encoder_only, + decoder_only, + dut_encoder_frontend: EncoderFrontend, + dut_decoder_frontend: DecoderFrontend, + ref_encoder_frontend: EncoderFrontend, + ref_decoder_frontend: DecoderFrontend, + reference_path, + dut_base_path, + test_vector_path, + update_ref, + rootdir, + keep_files, + test_tag, + get_mld, + get_mld_lim, + abs_tol, + get_ssnr, + get_enc_stats, + get_odg, + compare_to_input, +): + + enc_opts, dec_opts, sim_opts, eid_opts = test_dict[test_tag] + + run_test( + test_info, + props_to_record, + encoder_only, + decoder_only, + dut_encoder_frontend, + dut_decoder_frontend, + ref_encoder_frontend, + ref_decoder_frontend, + enc_opts, + dec_opts, + sim_opts, + eid_opts, + reference_path, + dut_base_path, + test_vector_path, + update_ref, + rootdir, + keep_files, + test_tag, + get_mld, + get_mld_lim, + abs_tol, + get_ssnr, + get_enc_stats, + get_odg, + compare_to_input, + ) + + \ No newline at end of file