From b95b30843211c55adac39bb82be0b581c99b26c2 Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Thu, 15 Feb 2024 12:36:59 +0100 Subject: [PATCH] [format] python files using `isort --profile black . && black .` --- ci/collect_artifacts.py | 3 +- ci/combine_genpatt_and_jbm_profile.py | 4 +- ci/comment_defines.py | 10 +- .../mergeNewsletterRam.py | 2 +- .../mergeNewsletterRom.py | 6 +- .../parseNewsletterRam.py | 47 +- .../parseNewsletterRom.py | 50 +- .../parseNewsletterWmops.py | 2 +- ci/get_id_of_last_job_occurence.py | 10 +- ci/run_evs_be_test.py | 11 +- ci/run_evs_be_win_test.py | 125 +- ci/run_scheduled_sanitizer_test.py | 23 +- ci/setup_pages.py | 7 +- ci/test_vectors_available.py | 14 +- scripts/IvasBuildAndRun.py | 4 +- scripts/IvasBuildAndRunChecks.py | 15 +- scripts/batch_comp_audio.py | 3 +- scripts/cut_bs.py | 28 +- scripts/mem_analysis.py | 119 +- scripts/parse_mld.py | 31 +- scripts/parse_mld_xml.py | 42 +- scripts/parse_selftest_summary.py | 2 +- scripts/plot_meta_data.py | 11 +- scripts/prepare_combined_format_inputs.py | 144 +- scripts/prepare_mem_dryrun.py | 21 +- scripts/pyaudio3dtools/__init__.py | 6 +- scripts/pyaudio3dtools/audio3dtools.py | 5 +- scripts/pyaudio3dtools/audioarray.py | 32 +- scripts/pyaudio3dtools/audiofile.py | 1 - scripts/pyaudio3dtools/spatialaudioformat.py | 264 +- scripts/pyivastest/IvasBaseClass.py | 117 +- scripts/pyivastest/IvasModeAnalyzer.py | 45 +- scripts/pyivastest/IvasModeCollector.py | 26 +- scripts/pyivastest/IvasModeRunner.py | 138 +- scripts/pyivastest/IvasScriptsCommon.py | 39 +- scripts/pyivastest/IvasSvnBuilder.py | 85 +- scripts/pyivastest/__init__.py | 19 +- scripts/pyivastest/constants.py | 25 +- scripts/pyivastest/ivas_svn.py | 2 +- ...generate_acoustic_environments_metadata.py | 2709 +++++++++++++---- scripts/reverb/text_to_binary_payload.py | 220 +- scripts/runIvasCodec.py | 15 +- scripts/self_test.py | 66 +- .../lc3plus/split_rend_lc3plus_cmdlines.py | 42 +- scripts/strip_split_rendering.py | 108 +- tests/cmp_pcm.py | 18 +- .../test_masa_enc_dec.py | 37 +- .../test_param_file.py | 53 +- .../test_sba_bs_dec_plc.py | 51 +- .../test_sba_bs_enc.py | 31 +- tests/codec_be_on_mr_selection/__init__.py | 21 +- tests/codec_be_on_mr_selection/constants.py | 3 +- .../test_experiments.py | 7 +- tests/conftest.py | 26 +- tests/create_short_testvectors.py | 21 +- tests/cut_pcm.py | 24 +- tests/hrtf_binary_loading/constants.py | 6 +- .../test_renderer_ROM_vs_file.py | 9 +- tests/hrtf_binary_loading/utils.py | 2 +- tests/prepare_pytests.py | 31 +- tests/renderer/test_renderer.py | 264 +- tests/renderer/utils.py | 21 +- tests/run_pytests.py | 21 +- tests/scale_pcm.py | 15 +- tests/test_26444.py | 39 +- tests/test_param_file_ltv.py | 53 +- tests/testconfig.py | 8 +- 67 files changed, 3746 insertions(+), 1713 deletions(-) diff --git a/ci/collect_artifacts.py b/ci/collect_artifacts.py index d3228ba2e8..702f7fa3ef 100755 --- a/ci/collect_artifacts.py +++ b/ci/collect_artifacts.py @@ -1,9 +1,8 @@ #! /usr/bin/env python3 -import pathlib import argparse +import pathlib import re - TEST_TYPES = ["sanitizers"] diff --git a/ci/combine_genpatt_and_jbm_profile.py b/ci/combine_genpatt_and_jbm_profile.py index dd3ffe5858..4d2fd38a00 100644 --- a/ci/combine_genpatt_and_jbm_profile.py +++ b/ci/combine_genpatt_and_jbm_profile.py @@ -30,8 +30,8 @@ """ import argparse -import numpy as np +import numpy as np ERR_MAGIC_NUM_DLY_PROF = -1 ERR_MAGIC_NUM_G192 = 27424 @@ -54,7 +54,7 @@ def combine_error_profiles(genpatt_file, jbm_dly_profile, output_file): # insert lost frames based on .g192 file err_idx = np.where(ep == ERR_MAGIC_NUM_G192)[0] dly[err_idx] = -1 - + with open(output_file, "w") as f: for d in dly: f.write(f"{int(d)}\n") diff --git a/ci/comment_defines.py b/ci/comment_defines.py index 0b6e345703..7f6a77af4b 100755 --- a/ci/comment_defines.py +++ b/ci/comment_defines.py @@ -1,5 +1,5 @@ -import re import argparse +import re def process_file(file_path: str, defines_re): @@ -13,7 +13,9 @@ def process_file(file_path: str, defines_re): for i, line in enumerate(lines): for name, regex in defines_re.items(): # Spaces are replaced with underscores to avoid matching on multiple runs - lines[i] = regex.sub(lambda x: f"/* {x.group(0).replace(' ', '_')} */", line) + lines[i] = regex.sub( + lambda x: f"/* {x.group(0).replace(' ', '_')} */", line + ) if lines[i] != line: num_subbed[name] += 1 @@ -41,7 +43,9 @@ def main(args): if __name__ == "__main__": - parser = argparse.ArgumentParser(description="Comment out preprocessor defines in c/c++ files") + parser = argparse.ArgumentParser( + description="Comment out preprocessor defines in c/c++ files" + ) parser.add_argument("-f", "--files", nargs="+", required=True, type=str) parser.add_argument("-d", "--defines", nargs="+", required=True, type=str) main(parser.parse_args()) diff --git a/ci/complexity_measurements/mergeNewsletterRam.py b/ci/complexity_measurements/mergeNewsletterRam.py index 6df5ee70fc..40b5f75c59 100755 --- a/ci/complexity_measurements/mergeNewsletterRam.py +++ b/ci/complexity_measurements/mergeNewsletterRam.py @@ -29,8 +29,8 @@ # 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. import csv -import sys import re +import sys newsletterFilename = "" newsletterFilenameLast = "" diff --git a/ci/complexity_measurements/mergeNewsletterRom.py b/ci/complexity_measurements/mergeNewsletterRom.py index 0d410f28ef..0e75f26f58 100755 --- a/ci/complexity_measurements/mergeNewsletterRom.py +++ b/ci/complexity_measurements/mergeNewsletterRom.py @@ -29,8 +29,8 @@ # 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. import csv -import sys import re +import sys newsletterFilename = "" newsletterFilenameLast = "" @@ -65,7 +65,9 @@ with open(newsletterFilenameTROM, "r") as csvfile: # now we have the following format # PROM enc, PROM dec, PROM com, PROM rend, PROM total, TROM enc, TROM dec, TROM com, TROM rend, TROM total -print("conf;PROM enc;PROM dec;PROM com;PROM rend;PROM total;TROM enc;TROM dec;TROM com;TROM rend;TROM total;total") +print( + "conf;PROM enc;PROM dec;PROM com;PROM rend;PROM total;TROM enc;TROM dec;TROM com;TROM rend;TROM total;total" +) for key in rom_table: rom = rom_table[key] diff --git a/ci/complexity_measurements/parseNewsletterRam.py b/ci/complexity_measurements/parseNewsletterRam.py index 4c432094ea..6fe1cd8993 100755 --- a/ci/complexity_measurements/parseNewsletterRam.py +++ b/ci/complexity_measurements/parseNewsletterRam.py @@ -31,8 +31,8 @@ """ import csv -import sys import re +import sys newsletterFilename = "" newsletterFilenameLast = "" @@ -133,30 +133,25 @@ for key in ram_table: max_total_encdec[0] = re.sub(" ", "_", key) max_total_encdec[1] = total_encdec - + print( - revision, # string revision $tmp[1] - shortDate, # string shortDate $tmp[2] - fullDate, # string fullDate $tmp[3] - - max_total_encdec[1], # value maxTotalRamCodecScore $tmp[4] - - max_total_enc[0], # string maxTotalRamEnc $tmp[5] - max_total_enc[1], # value maxTotalRamEnc $tmp[6] - max_total_dec[0], # string maxTotalRamDec $tmp[7] - max_total_dec[1], # value maxTotalRamDecScore $tmp[8] - - max_stack_encdec[1], # value maxStackCodecScore $tmp[9] - max_stack_enc[0], # string maxStackEnc $tmp[10] - max_stack_enc[1], # value maxStackEncScore $tmp[11] - max_stack_dec[0], # string maxStackDec $tmp[12] - max_stack_dec[1], # value maxStackDecScore $tmp[13] - - max_heap_encdec[1], # value maxHeapCodecScore $tmp[14] - max_heap_enc[0], # string maxHeapEnc $tmp[15] - max_heap_enc[1], # value maxHeapEncScore $tmp[16] - max_heap_dec[0], # string maxHeapDec $tmp[17] - max_heap_dec[1], # value maxHeapDecScore $tmp[19] - - newsletterFilenameLast, # string logFile $tmp[19] + revision, # string revision $tmp[1] + shortDate, # string shortDate $tmp[2] + fullDate, # string fullDate $tmp[3] + max_total_encdec[1], # value maxTotalRamCodecScore $tmp[4] + max_total_enc[0], # string maxTotalRamEnc $tmp[5] + max_total_enc[1], # value maxTotalRamEnc $tmp[6] + max_total_dec[0], # string maxTotalRamDec $tmp[7] + max_total_dec[1], # value maxTotalRamDecScore $tmp[8] + max_stack_encdec[1], # value maxStackCodecScore $tmp[9] + max_stack_enc[0], # string maxStackEnc $tmp[10] + max_stack_enc[1], # value maxStackEncScore $tmp[11] + max_stack_dec[0], # string maxStackDec $tmp[12] + max_stack_dec[1], # value maxStackDecScore $tmp[13] + max_heap_encdec[1], # value maxHeapCodecScore $tmp[14] + max_heap_enc[0], # string maxHeapEnc $tmp[15] + max_heap_enc[1], # value maxHeapEncScore $tmp[16] + max_heap_dec[0], # string maxHeapDec $tmp[17] + max_heap_dec[1], # value maxHeapDecScore $tmp[19] + newsletterFilenameLast, # string logFile $tmp[19] ) diff --git a/ci/complexity_measurements/parseNewsletterRom.py b/ci/complexity_measurements/parseNewsletterRom.py index 830ef945b9..2416a6fd0b 100755 --- a/ci/complexity_measurements/parseNewsletterRom.py +++ b/ci/complexity_measurements/parseNewsletterRom.py @@ -32,8 +32,8 @@ """ import csv -import sys import re +import sys newsletterFilename = "" newsletterFilenameLast = "" @@ -101,7 +101,7 @@ for key in rom_table: trom_total = int(rom[9]) total_encdec = prom_total + trom_total - + if prom_enc > max_prom_enc[1]: max_prom_enc[0] = re.sub(" ", "_", key) max_prom_enc[1] = prom_enc @@ -140,29 +140,25 @@ for key in rom_table: print( - revision, # string revision $tmp[1] - shortDate, # string shortDate $tmp[2] - fullDate, # string fullDate $tmp[3] - - max_total_encdec[1], # value maxTotalRomCodecScore $tmp[4] - - max_prom_enc[0], # string maxPROMEnc $tmp[5] - max_prom_enc[1], # value maxPROMEncScore $tmp[6] - max_prom_dec[0], # string maxPROMDec $tmp[7] - max_prom_dec[1], # value maxPROMDecScore $tmp[8] - max_prom_com[0], # string maxPROMCom $tmp[9] - max_prom_com[1], # value maxPROMComScore $tmp[10] - max_prom_rend[0], # string maxPROMRend $tmp[11] - max_prom_rend[1], # value maxPROMRendScore $tmp[12] - - max_trom_enc[0], # string maxTROMEnc $tmp[13] - max_trom_enc[1], # value maxTROMEncScore $tmp[14] - max_trom_dec[0], # string maxTROMDec $tmp[15] - max_trom_dec[1], # value maxTROMDecScore $tmp[16] - max_trom_com[0], # string maxTROMCom $tmp[17] - max_trom_com[1], # value maxTROMComScore $tmp[18] - max_trom_rend[0], # string maxTROMRend $tmp[19] - max_trom_rend[1], # value maxTROMRendScore $tmp[20] - - newsletterFilenameLast, # string logFile $tmp[21] + revision, # string revision $tmp[1] + shortDate, # string shortDate $tmp[2] + fullDate, # string fullDate $tmp[3] + max_total_encdec[1], # value maxTotalRomCodecScore $tmp[4] + max_prom_enc[0], # string maxPROMEnc $tmp[5] + max_prom_enc[1], # value maxPROMEncScore $tmp[6] + max_prom_dec[0], # string maxPROMDec $tmp[7] + max_prom_dec[1], # value maxPROMDecScore $tmp[8] + max_prom_com[0], # string maxPROMCom $tmp[9] + max_prom_com[1], # value maxPROMComScore $tmp[10] + max_prom_rend[0], # string maxPROMRend $tmp[11] + max_prom_rend[1], # value maxPROMRendScore $tmp[12] + max_trom_enc[0], # string maxTROMEnc $tmp[13] + max_trom_enc[1], # value maxTROMEncScore $tmp[14] + max_trom_dec[0], # string maxTROMDec $tmp[15] + max_trom_dec[1], # value maxTROMDecScore $tmp[16] + max_trom_com[0], # string maxTROMCom $tmp[17] + max_trom_com[1], # value maxTROMComScore $tmp[18] + max_trom_rend[0], # string maxTROMRend $tmp[19] + max_trom_rend[1], # value maxTROMRendScore $tmp[20] + newsletterFilenameLast, # string logFile $tmp[21] ) diff --git a/ci/complexity_measurements/parseNewsletterWmops.py b/ci/complexity_measurements/parseNewsletterWmops.py index c479deed06..3f884fd3aa 100755 --- a/ci/complexity_measurements/parseNewsletterWmops.py +++ b/ci/complexity_measurements/parseNewsletterWmops.py @@ -31,8 +31,8 @@ """ import csv -import sys import re +import sys newsletterFilename = "" newsletterFilenameLast = "" diff --git a/ci/get_id_of_last_job_occurence.py b/ci/get_id_of_last_job_occurence.py index d1faca502f..449902f50a 100755 --- a/ci/get_id_of_last_job_occurence.py +++ b/ci/get_id_of_last_job_occurence.py @@ -31,6 +31,7 @@ """ import argparse + import requests PER_PAGE_SUFFIX = "?per_page=50" @@ -50,13 +51,13 @@ def get_job_id(branch_name, job_name): for pl in resp_pls.json(): if pl["ref"] == branch_name: url_jobs = url_pls + f"/{pl['id']}/jobs" - + # only one of the suffixes here - this assumes only max of 50 jobs per pipeline # so only one page needed resp_jobs = requests.get(url_jobs + PER_PAGE_SUFFIX) if job_name not in resp_jobs.text: - continue + continue # find actual job by name for job in resp_jobs.json(): @@ -71,7 +72,8 @@ def get_job_id(branch_name, job_name): return job_id -if __name__ == '__main__': + +if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument("branch_name") parser.add_argument("job_name") @@ -79,4 +81,4 @@ if __name__ == '__main__': args = parser.parse_args() job_id = get_job_id(args.branch_name, args.job_name) - print(job_id) \ No newline at end of file + print(job_id) diff --git a/ci/run_evs_be_test.py b/ci/run_evs_be_test.py index 70370b540b..3103a800c8 100755 --- a/ci/run_evs_be_test.py +++ b/ci/run_evs_be_test.py @@ -28,13 +28,12 @@ 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. """ -import subprocess +import concurrent.futures import pathlib +import subprocess import sys -import concurrent.futures from threading import Lock - README_FILES_PARALLEL = [ "Readme_AMRWB_IO_enc.txt", "Readme_AMRWB_IO_dec.txt", @@ -47,6 +46,7 @@ BINARY_PATHS = ["./bin/EVS_cod", "./bin/EVS_dec"] FOLDER_PATHS = ["testv"] BIN_PATHS = BINARY_PATHS * 2 + def main(): if not environment_is_correct(): @@ -56,7 +56,10 @@ def main(): # run first part in parallel with concurrent.futures.ThreadPoolExecutor() as executor: executor.map( - run_file, README_FILES_PARALLEL, BIN_PATHS, [result_dict] * len(README_FILES_PARALLEL) + run_file, + README_FILES_PARALLEL, + BIN_PATHS, + [result_dict] * len(README_FILES_PARALLEL), ) # JBM test can not run concurrently with the others diff --git a/ci/run_evs_be_win_test.py b/ci/run_evs_be_win_test.py index caa2ef2f93..4a93756787 100644 --- a/ci/run_evs_be_win_test.py +++ b/ci/run_evs_be_win_test.py @@ -28,34 +28,34 @@ the United Nations Convention on Contracts on the International Sales of Goods. """ -from multiprocessing import Pool import argparse -import subprocess import os import shutil +import subprocess import sys +from multiprocessing import Pool def run_condition(eval_cmd, diff_cmd, id_count): - """ Run ENC or DEC command string and compare output with EVS test vectors. """ + """Run ENC or DEC command string and compare output with EVS test vectors.""" cmd = subprocess.run(eval_cmd.split(), capture_output=True, text=True, check=True) # diff - diff_fails = '' - if ';' in diff_cmd: + diff_fails = "" + if ";" in diff_cmd: # JBM cases - diff_cmd1, diff_cmd2 = diff_cmd.split(';') + diff_cmd1, diff_cmd2 = diff_cmd.split(";") cmd1 = subprocess.run(diff_cmd1.split(), stdout=subprocess.DEVNULL, check=False) cmd2 = subprocess.run(diff_cmd2.split(), stdout=subprocess.DEVNULL, check=False) if cmd1.returncode != 0: - diff_fails += f'{diff_cmd1}\n' + diff_fails += f"{diff_cmd1}\n" if cmd2.returncode != 0: - diff_fails += f'{diff_cmd2}\n' + diff_fails += f"{diff_cmd2}\n" else: cmd = subprocess.run(diff_cmd.split(), stdout=subprocess.DEVNULL, check=False) if cmd.returncode != 0: - diff_fails += f'{diff_cmd}\n' + diff_fails += f"{diff_cmd}\n" if diff_fails: return diff_fails else: @@ -79,17 +79,31 @@ def environment_is_correct(paths): return ret -if __name__ == '__main__': +if __name__ == "__main__": parser = argparse.ArgumentParser( - description='Run 26.444 test with parallel processes ') - parser.add_argument('-p', type=int, default=os.cpu_count(), - help='Number of processes (default cpu_count)') - parser.add_argument('-test_dir', type=str, default='./', - help='testvec directory from 26.444)') - parser.add_argument('-enc_bin', type=str, default='./bin/IVAS_cod.exe', - help='Encoder binary (default ./bin/IVAS_cod.exe)') - parser.add_argument('-dec_bin', type=str, default='./bin/IVAS_dec.exe', - help='Decoder binary (default ./bin/IVAS_dec.exe)') + description="Run 26.444 test with parallel processes " + ) + parser.add_argument( + "-p", + type=int, + default=os.cpu_count(), + help="Number of processes (default cpu_count)", + ) + parser.add_argument( + "-test_dir", type=str, default="./", help="testvec directory from 26.444)" + ) + parser.add_argument( + "-enc_bin", + type=str, + default="./bin/IVAS_cod.exe", + help="Encoder binary (default ./bin/IVAS_cod.exe)", + ) + parser.add_argument( + "-dec_bin", + type=str, + default="./bin/IVAS_dec.exe", + help="Decoder binary (default ./bin/IVAS_dec.exe)", + ) args = parser.parse_args() test_vec_dir = args.test_dir @@ -97,12 +111,19 @@ if __name__ == '__main__': enc_bin = args.enc_bin dec_bin = args.dec_bin - README_FILES = ['Readme_AMRWB_IO_dec.txt', 'Readme_AMRWB_IO_enc.txt', 'Readme_EVS_dec.txt', - 'Readme_EVS_enc.txt', 'Readme_JBM_dec.txt'] + README_FILES = [ + "Readme_AMRWB_IO_dec.txt", + "Readme_AMRWB_IO_enc.txt", + "Readme_EVS_dec.txt", + "Readme_EVS_enc.txt", + "Readme_JBM_dec.txt", + ] scripts = [os.path.join(test_vec_dir, script) for script in README_FILES] - if not environment_is_correct([f'{test_vec_dir}/testv'] + scripts + [enc_bin, dec_bin]): + if not environment_is_correct( + [f"{test_vec_dir}/testv"] + scripts + [enc_bin, dec_bin] + ): sys.exit(1) pool = Pool(processes) @@ -113,43 +134,53 @@ if __name__ == '__main__': with open(script) as file: tmp_dir = None eval_cmd = None - diff_cmd = '' + diff_cmd = "" for line in file: - if line.startswith('TMP='): + if line.startswith("TMP="): assert tmp_dir is None tmp_dir = line.split('"')[1] if os.path.exists(tmp_dir): shutil.rmtree(tmp_dir) os.makedirs(tmp_dir) - line = line.replace('testv', f'{test_vec_dir}/testv') - line = line if tmp_dir is None else line.replace( - '$TMP/', f'{tmp_dir}/') - if '$CUT_DEC_BIN' in line: - eval_cmd = dec_bin + ' -q ' + ' '.join(line.split()[1:]) - if '$CUT_ENC_BIN' in line: - eval_cmd = enc_bin + ' -q ' + ' '.join(line.split()[1:]) - if '$DIFF_BIN' in line: - if 'Readme_JBM_dec.txt' in script: - if '-w' not in line.split()[1]: - diff_cmd = 'FC.exe ' + ' '.join(line.split()[1:]).replace('/', '\\').replace('\n', '/n') + line = line.replace("testv", f"{test_vec_dir}/testv") + line = line if tmp_dir is None else line.replace("$TMP/", f"{tmp_dir}/") + if "$CUT_DEC_BIN" in line: + eval_cmd = dec_bin + " -q " + " ".join(line.split()[1:]) + if "$CUT_ENC_BIN" in line: + eval_cmd = enc_bin + " -q " + " ".join(line.split()[1:]) + if "$DIFF_BIN" in line: + if "Readme_JBM_dec.txt" in script: + if "-w" not in line.split()[1]: + diff_cmd = "FC.exe " + " ".join(line.split()[1:]).replace( + "/", "\\" + ).replace("\n", "/n") continue - diff_cmd += ';FC.exe ' + ' '.join(line.split()[1:]).replace('/', '\\').replace('\n', '/n').replace('-w', '/W') + diff_cmd += ";FC.exe " + " ".join(line.split()[1:]).replace( + "/", "\\" + ).replace("\n", "/n").replace("-w", "/W") else: - diff_cmd = 'FC.exe ' + ' '.join(line.split()[1:]).replace('/', '\\').replace('\n', '/n') - results.append(pool.apply_async( - run_condition, args=(eval_cmd, diff_cmd, id_count))) + diff_cmd = "FC.exe " + " ".join(line.split()[1:]).replace( + "/", "\\" + ).replace("\n", "/n") + results.append( + pool.apply_async( + run_condition, args=(eval_cmd, diff_cmd, id_count) + ) + ) id_count = id_count + 1 - print('Total number of conditions for', '"' + - os.path.basename(script) + '": ' + str(id_count - 1)) + print( + "Total number of conditions for", + '"' + os.path.basename(script) + '": ' + str(id_count - 1), + ) results = [r.get() for r in results if r.get()] if results: - print(f'\n --- {len(results)} test conditions failed ---') - print(''.join(results)) - with open('failed.txt', 'w') as f: - print(f' --- {len(results)} test conditions failed ---', file=f) - print(''.join(results), file=f) + print(f"\n --- {len(results)} test conditions failed ---") + print("".join(results)) + with open("failed.txt", "w") as f: + print(f" --- {len(results)} test conditions failed ---", file=f) + print("".join(results), file=f) sys.exit(1) else: - print('\n *** All tests passed! ***') + print("\n *** All tests passed! ***") sys.exit(0) diff --git a/ci/run_scheduled_sanitizer_test.py b/ci/run_scheduled_sanitizer_test.py index fcea405370..fa5202ef94 100755 --- a/ci/run_scheduled_sanitizer_test.py +++ b/ci/run_scheduled_sanitizer_test.py @@ -30,19 +30,18 @@ """ import argparse -import sys -import subprocess import pathlib +import subprocess +import sys CI_SCRIPT_DIR = "./ci" sys.path.append(CI_SCRIPT_DIR) from collect_artifacts import ( - find_failed_files_for_sanitizer_test, collect_for_sanitizer_test, + find_failed_files_for_sanitizer_test, ) from combine_genpatt_and_jbm_profile import combine_error_profiles - SCRIPT_DIR = pathlib.Path("./scripts").resolve() DURATION = "120" CFG = "ci_linux_ltv.json" @@ -55,7 +54,9 @@ N_FRAMES_DLY_PROFILE = 7500 GENPATT_CMD = f"gen-patt -tailstat -fer -g192 -gamma 0 -rate 0.15 -tol 0.001 -reset -n {N_FRAMES_DLY_PROFILE} {EP_FILE}" MC_MODES = ["5_1", "5_1_2", "5_1_4", "7_1", "7_1_4"] AMBISONICS_MODES = ["HOA3", "HOA2", "FOA", "PlanarHOA3", "PlanarHOA2", "PlanarFOA"] -TIMEOUT = 60 * 15 # timeout of 15 minutes per en/decoding to safeguard against endless loops +TIMEOUT = ( + 60 * 15 +) # timeout of 15 minutes per en/decoding to safeguard against endless loops CONSOLE_OUT_FILE = "output_san.txt" @@ -82,11 +83,11 @@ def get_modes(in_format: str) -> list: in_format_for_script = "MC" elif "-" in in_format: # hyphen indicates combined format - scene_format, object_format = in_format.split('-') + scene_format, object_format = in_format.split("-") if scene_format in AMBISONICS_MODES: in_format_for_script = "OSBA" else: - assert(scene_format == "MASA") + assert scene_format == "MASA" in_format_for_script = "OMASA" cmd = [ @@ -214,15 +215,11 @@ def run_check(in_format: str, out_formats: list, tests: list, run_fec: bool = Tr cmd_fec = cmd_no_fec + ["--decoder_only", "-J", DLY_PROFILE_OUT] print( - "======== Script command line WITH plc: ========\n{}".format( - " ".join(cmd_fec) - ) + "======== Script command line WITH plc: ========\n{}".format(" ".join(cmd_fec)) ) with open(CONSOLE_OUT_FILE, "a") as f: - proc = subprocess.Popen( - cmd_fec, stdout=subprocess.PIPE, stderr=subprocess.PIPE - ) + proc = subprocess.Popen(cmd_fec, stdout=subprocess.PIPE, stderr=subprocess.PIPE) for c in iter(lambda: proc.stdout.read(1), b""): sys.stdout.buffer.write(c) f.write(c.decode("utf8")) diff --git a/ci/setup_pages.py b/ci/setup_pages.py index cc90753de5..10a2e9e84e 100755 --- a/ci/setup_pages.py +++ b/ci/setup_pages.py @@ -1,8 +1,9 @@ #!/usr/bin/env python3 import os -import sys import pathlib import subprocess +import sys + from get_id_of_last_job_occurence import get_job_id JOBS = [ @@ -34,7 +35,9 @@ def main(): job_public = job + "-public" if job == "coverage-test-on-main-scheduled": job_public = "coverage" - pathlib.Path("coverage_stv").rename(public_folder.joinpath("coverage_stv")) + pathlib.Path("coverage_stv").rename( + public_folder.joinpath("coverage_stv") + ) pathlib.Path(job_public).rename(public_folder.joinpath(job_public)) diff --git a/ci/test_vectors_available.py b/ci/test_vectors_available.py index ecff222fdf..6c11898560 100644 --- a/ci/test_vectors_available.py +++ b/ci/test_vectors_available.py @@ -1,17 +1,23 @@ -import pytest -import pathlib -import json import itertools +import json +import pathlib + +import pytest TEST_CONFIG_DIR = pathlib.Path(__file__).parent.parent.joinpath("scripts/config") TEST_CONFIGS = [f for f in TEST_CONFIG_DIR.iterdir() if f.name.startswith("ci_linux")] + def get_testvectors_from_config(config) -> list: with open(config) as f: cfg = json.load(f) return list(cfg["inpaths"].values()) -TESTVECTORS = sorted(set(itertools.chain(*[get_testvectors_from_config(cfg) for cfg in TEST_CONFIGS]))) + +TESTVECTORS = sorted( + set(itertools.chain(*[get_testvectors_from_config(cfg) for cfg in TEST_CONFIGS])) +) + @pytest.mark.parametrize("testvector", TESTVECTORS) def test_vectors_available(testvector): diff --git a/scripts/IvasBuildAndRun.py b/scripts/IvasBuildAndRun.py index b1aae9c520..6113c2ae3e 100755 --- a/scripts/IvasBuildAndRun.py +++ b/scripts/IvasBuildAndRun.py @@ -33,9 +33,9 @@ import os.path import sys -from pyivastest.IvasSvnBuilder import * -from pyivastest import IvasScriptsCommon import pyivastest.constants as constants +from pyivastest import IvasScriptsCommon +from pyivastest.IvasSvnBuilder import * class IvasBuildAndRun(IvasScriptsCommon.IvasScript): diff --git a/scripts/IvasBuildAndRunChecks.py b/scripts/IvasBuildAndRunChecks.py index ac0b142777..4bca48a672 100755 --- a/scripts/IvasBuildAndRunChecks.py +++ b/scripts/IvasBuildAndRunChecks.py @@ -33,10 +33,9 @@ import os.path import sys -from pyivastest.IvasSvnBuilder import * -from pyivastest import IvasScriptsCommon import pyivastest.constants as constants - +from pyivastest import IvasScriptsCommon +from pyivastest.IvasSvnBuilder import * RET_CODE_FAILURE = 101 @@ -92,7 +91,8 @@ class IvasBuildAndRunChecks(IvasScriptsCommon.IvasScript): "--rebuild", help="force a rebuild of the binaries", action="store_true" ) self.parser.add_argument( - "--usan_supp_file", help="suppression file for undef behaviour sanitizer", + "--usan_supp_file", + help="suppression file for undef behaviour sanitizer", default=None, ) @@ -184,7 +184,9 @@ class IvasBuildAndRunChecks(IvasScriptsCommon.IvasScript): checks_ret_val.append(ret_val) if self.args["create_html_output"]: cmd = ["git", "rev-parse", "HEAD"] - commit_hash = subprocess.run(cmd, capture_output=True).stdout.decode("utf8") + commit_hash = subprocess.run(cmd, capture_output=True).stdout.decode( + "utf8" + ) br.build_and_run_dict[check]["analyzer"].write_html_file( check, self.args["create_html_output"], commit_hash ) @@ -211,10 +213,11 @@ class IvasBuildAndRunChecks(IvasScriptsCommon.IvasScript): failed_encs = runner.failed_modes["enc"] failed_decs = runner.failed_modes["dec"] if len(failed_encs) > 0 or len(failed_decs) > 0 or ret_val != 0: - returncode = RET_CODE_FAILURE + returncode = RET_CODE_FAILURE return returncode + if __name__ == "__main__": script = IvasBuildAndRunChecks() sys.exit(script.run()) diff --git a/scripts/batch_comp_audio.py b/scripts/batch_comp_audio.py index ccb12ccf19..6854f41f30 100755 --- a/scripts/batch_comp_audio.py +++ b/scripts/batch_comp_audio.py @@ -40,8 +40,9 @@ import subprocess import sys import threading from itertools import repeat -from pyaudio3dtools.audiofile import readfile + from pyaudio3dtools.audioarray import compare +from pyaudio3dtools.audiofile import readfile FILES_EQUAL = "File A = File B" SNR_EXPR = r"SNR\s+=(.+)dB\s*\(.+= (.+)\)" diff --git a/scripts/cut_bs.py b/scripts/cut_bs.py index 2f3959100f..37f19733df 100755 --- a/scripts/cut_bs.py +++ b/scripts/cut_bs.py @@ -30,9 +30,9 @@ the United Nations Convention on Contracts on the International Sales of Goods. """ -import struct import argparse import os.path +import struct import sys SID_BITS = {35, 48, 104} @@ -111,16 +111,27 @@ def cut_from_start(fp, fp_out, start_frame=0, start_with_sid=False): if __name__ == "__main__": - my_parser = argparse.ArgumentParser( - description="Cut a G.192 bit stream file" + my_parser = argparse.ArgumentParser(description="Cut a G.192 bit stream file") + my_parser.add_argument( + "--sid", + "-s", + help="Cut away all frames before the first SID frame", + action="store_true", ) my_parser.add_argument( - "--sid", "-s", help="Cut away all frames before the first SID frame", action="store_true" + "--frame", + "-f", + type=int, + help="Number of frames to cut from the start of the file.", + default=0, ) my_parser.add_argument( - "--frame", "-f", type=int, help="Number of frames to cut from the start of the file.", default=0 + "--length", + "-l", + type=int, + help="Cut bitstream to this length (in frames)", + default=-1, ) - my_parser.add_argument("--length", "-l", type=int, help="Cut bitstream to this length (in frames)", default=-1) my_parser.add_argument("bs_in", type=str, help="G.192 bit stream file name to cut") my_parser.add_argument("bs_out", type=str, help="Cut G.192 bit stream file name") my_args = my_parser.parse_args() @@ -144,6 +155,7 @@ if __name__ == "__main__": elif my_args.length: fr_cnt = cut_to_length(fp_in, fp_out, my_args.length) if fr_cnt != my_args.length: - print(f"Warning! Could not cut to length {my_args.length} as bitstream only contained {fr_cnt} frames!") + print( + f"Warning! Could not cut to length {my_args.length} as bitstream only contained {fr_cnt} frames!" + ) print(f"Cut {my_args.bs_in} to {fr_cnt} frames") - diff --git a/scripts/mem_analysis.py b/scripts/mem_analysis.py index fa2030c033..e3f3d8afe4 100644 --- a/scripts/mem_analysis.py +++ b/scripts/mem_analysis.py @@ -1,48 +1,59 @@ #!/usr/bin/env python3 -import os import argparse import csv -import sys +import os import struct +import sys + +import matplotlib.pyplot as plt import numpy as np import pandas as pd -import matplotlib.pyplot as plt # set matplotlib in interactive mode (plots figure and return control) # plt.ion() # plt.close('all') -parser = argparse.ArgumentParser(description='Analyze memory output file') -parser.add_argument('input',type=str,help='Memory analysis file (e.g. mem_analysis.csv)') +parser = argparse.ArgumentParser(description="Analyze memory output file") +parser.add_argument( + "input", type=str, help="Memory analysis file (e.g. mem_analysis.csv)" +) args = parser.parse_args() -fileIn = args.input +fileIn = args.input # read input .csv file -df = pd.read_csv(fileIn, header=None, names=['action_type', 'frame', 'name', 'line_no', 'mem_size']) -Nframes = max(df['frame']) +df = pd.read_csv( + fileIn, header=None, names=["action_type", "frame", "name", "line_no", "mem_size"] +) +Nframes = max(df["frame"]) # merge identical memory blocks -> create new column 'count' -df = df.groupby(df.columns.tolist(),as_index=False).size() -df = df.rename(columns={'size': 'count'}) +df = df.groupby(df.columns.tolist(), as_index=False).size() +df = df.rename(columns={"size": "count"}) # remove column 'action_type' -df.drop(columns = ['action_type']) +df.drop(columns=["action_type"]) # merge records with the same signature but different frame number -> create list of frames (sort in ascending order) -df = df.groupby(['name', 'line_no', 'mem_size', 'count'],as_index=False).agg({'frame': list}) -df['frame'] = df['frame'].apply(np.sort) -df['list_len'] = df['frame'].apply(len) # auxiliary column -> length of the list +df = df.groupby(["name", "line_no", "mem_size", "count"], as_index=False).agg( + {"frame": list} +) +df["frame"] = df["frame"].apply(np.sort) +df["list_len"] = df["frame"].apply(len) # auxiliary column -> length of the list # merge records with the same name and frame but different line number -> sum memory sizes and counts -df = df.groupby(['name', 'list_len'],as_index=False).agg({'line_no': list, 'mem_size': sum, 'count':sum, 'frame':'first'}) +df = df.groupby(["name", "list_len"], as_index=False).agg( + {"line_no": list, "mem_size": sum, "count": sum, "frame": "first"} +) # sort by memory size (put inter-frame memory blocks to the bottom) -select_inter = (df['list_len'] == 2) & (df.apply(lambda row : row['frame'][-1] - row['frame'][0], axis = 1) >= Nframes) +select_inter = (df["list_len"] == 2) & ( + df.apply(lambda row: row["frame"][-1] - row["frame"][0], axis=1) >= Nframes +) df_inter = df[select_inter] -df_inter = df_inter.sort_values(by=['mem_size'], ascending=False) +df_inter = df_inter.sort_values(by=["mem_size"], ascending=False) df_intra = df[~select_inter] -df_intra = df_intra.sort_values(by=['list_len'], ascending=True) +df_intra = df_intra.sort_values(by=["list_len"], ascending=True) # plot inter-frame memory blocks in horizontal bar graph (use .broken_barh method) fig, ax = plt.subplots() @@ -52,53 +63,77 @@ y_tick_labels = [] y_low = 1 for index, row in df_inter.iterrows(): l = f"{row['name']} on lines: {row['line_no']}, total memory size: {row['count']}x{row['mem_size']}" - fms = row['frame'].reshape((-1,2)) # convert frame numbers to two-column format - fms[:,1] -= fms[:,0] # second column should now represent the duration of the segment + fms = row["frame"].reshape((-1, 2)) # convert frame numbers to two-column format + fms[:, 1] -= fms[ + :, 0 + ] # second column should now represent the duration of the segment fmsT = fms.T fms_list = list(zip(fmsT[0], fmsT[1])) c = next(colors) - ax.broken_barh(xranges=fms_list, yrange=(y_low, row['count']), label=l, color=c) - y_ticks.append(y_low + 0.5 * row['count']) - y_tick_labels.append(row['name']) - y_low += row['count'] + 0.5 + ax.broken_barh(xranges=fms_list, yrange=(y_low, row["count"]), label=l, color=c) + y_ticks.append(y_low + 0.5 * row["count"]) + y_tick_labels.append(row["name"]) + y_low += row["count"] + 0.5 print(l + f", {row['count'] * fms.shape[0]/Nframes:.3f} mallocs per frame") - + # plot intra-frame memory blocks in horizontal bar graph (use .broken_barh method) -df_intra = df_intra.groupby(['name'],as_index=False).agg({'list_len': list, 'line_no': list, 'mem_size': list, 'count': list, 'frame': list}) +df_intra = df_intra.groupby(["name"], as_index=False).agg( + {"list_len": list, "line_no": list, "mem_size": list, "count": list, "frame": list} +) for index, row in df_intra.iterrows(): # repeat for all grouped memory records in the row - for j in range(len(row['list_len'])): + for j in range(len(row["list_len"])): l = f"{row['name']} on lines: {row['line_no'][j]}, total memory size: {row['count'][j]}x{row['mem_size'][j]}" - fms = row['frame'][j].astype(float).reshape((-1,2)) # convert frame numbers to two-column format - fms[:,1] -= fms[:,0] # second column should now represent the duration of the segment - idx_zero = fms[:,1] == 0 # find zero-length segments -> these are intra-frame memory blocks + fms = ( + row["frame"][j].astype(float).reshape((-1, 2)) + ) # convert frame numbers to two-column format + fms[:, 1] -= fms[ + :, 0 + ] # second column should now represent the duration of the segment + idx_zero = ( + fms[:, 1] == 0 + ) # find zero-length segments -> these are intra-frame memory blocks fms[idx_zero, 0] += 0.1 fms[idx_zero, 1] = 0.8 fmsT = fms.T fms_list = list(zip(fmsT[0], fmsT[1])) c = next(colors) - ax.broken_barh(xranges=fms_list, yrange=(y_low, row['count'][j]), label=l, color=c, alpha=0.6) + ax.broken_barh( + xranges=fms_list, + yrange=(y_low, row["count"][j]), + label=l, + color=c, + alpha=0.6, + ) print(l + f", {row['count'][j] * fms.shape[0]/Nframes:.3f} mallocs per frame") - y_ticks.append(y_low + 0.5 * max(row['count'])) - y_tick_labels.append(row['name']) - y_low += max(row['count']) + 0.5 + y_ticks.append(y_low + 0.5 * max(row["count"])) + y_tick_labels.append(row["name"]) + y_low += max(row["count"]) + 0.5 ax.set_yticks(y_ticks) ax.set_yticklabels(y_tick_labels) -ax.set_ylabel('Memory size') -ax.set_xlabel('Frame') -ax.set_title('Memory analysis') +ax.set_ylabel("Memory size") +ax.set_xlabel("Frame") +ax.set_title("Memory analysis") # shrink current axis's height by 20% on the bottom to fit the legend box = ax.get_position() ax.set_position([box.x0, box.y0 + box.height * 0.2, box.width, box.height * 0.8]) - -# insert the legend below the graph -ax.legend(loc="upper left", bbox_to_anchor=(0, -0.1), ncol=2, borderaxespad=0, fontsize='small') + +# insert the legend below the graph +ax.legend( + loc="upper left", + bbox_to_anchor=(0, -0.1), + ncol=2, + borderaxespad=0, + fontsize="small", +) # magnify to "almost" fullscreen size (select the alternative for your backend) fig = plt.gcf() -fig.set_size_inches(15, 9) # we need to set the size manually, otherwise savefig will save the figure in the default size +fig.set_size_inches( + 15, 9 +) # we need to set the size manually, otherwise savefig will save the figure in the default size mng = plt.get_current_fig_manager() mng.full_screen_toggle() # mng.frame.Maximize(True) @@ -106,5 +141,5 @@ mng.full_screen_toggle() # mng.window.state('zoomed') # show and save the figure (use block=True to wait until Figure is closed manually) -plt.savefig(os.path.splitext(args.input)[0] + '.png', dpi=100, bbox_inches='tight') +plt.savefig(os.path.splitext(args.input)[0] + ".png", dpi=100, bbox_inches="tight") plt.show(block=True) diff --git a/scripts/parse_mld.py b/scripts/parse_mld.py index 2a60e176e3..b999e83903 100644 --- a/scripts/parse_mld.py +++ b/scripts/parse_mld.py @@ -3,27 +3,30 @@ import argparse import re - # Main routine -if __name__ == '__main__': - parser = argparse.ArgumentParser(description='Parse HTML report to extract MLD values') - parser.add_argument('html_report',type=str,help='HTML report input file, e.g. report.html') - parser.add_argument('csv_file',type=str,help='Output CSV file, e.g. output.csv') +if __name__ == "__main__": + parser = argparse.ArgumentParser( + description="Parse HTML report to extract MLD values" + ) + parser.add_argument( + "html_report", type=str, help="HTML report input file, e.g. report.html" + ) + parser.add_argument("csv_file", type=str, help="Output CSV file, e.g. output.csv") args = parser.parse_args() html_report = args.html_report - csv_file = args.csv_file - + csv_file = args.csv_file + mld = {} - - with open(html_report,'r') as infile: + + with open(html_report, "r") as infile: for line in infile.readlines(): - if "col-name" in line: - test_name = re.search('\[(.*)\]', line).group(1) + if "col-name" in line: + test_name = re.search("\[(.*)\]", line).group(1) mld[test_name] = 0.0 if "MLD" in line: mld_val = float(line.split()[1]) mld[test_name] = mld_val - - with open(csv_file,'w') as outfile: + + with open(csv_file, "w") as outfile: for test_name in mld: - outfile.write(test_name + ';' + str(mld[test_name])+'\n') \ No newline at end of file + outfile.write(test_name + ";" + str(mld[test_name]) + "\n") diff --git a/scripts/parse_mld_xml.py b/scripts/parse_mld_xml.py index e3b6dd57ae..fb1dc8e73a 100644 --- a/scripts/parse_mld_xml.py +++ b/scripts/parse_mld_xml.py @@ -8,30 +8,44 @@ Parse a junit report and create a MLD summary report. """ # Main routine -if __name__ == '__main__': - parser = argparse.ArgumentParser(description='Parse a junit report and create a MLD summary report.') - parser.add_argument('xml_report',type=str,help='XML junit report input file, e.g. report-junit.xml') - parser.add_argument('csv_file',type=str,help='Output CSV file, e.g. mld.csv') +if __name__ == "__main__": + parser = argparse.ArgumentParser( + description="Parse a junit report and create a MLD summary report." + ) + parser.add_argument( + "xml_report", + type=str, + help="XML junit report input file, e.g. report-junit.xml", + ) + parser.add_argument("csv_file", type=str, help="Output CSV file, e.g. mld.csv") args = parser.parse_args() xml_report = args.xml_report - csv_file = args.csv_file + csv_file = args.csv_file tree = ElementTree.parse(xml_report) testsuite = tree.find(".//testsuite") - print(f"Found testsuite with {testsuite.get('tests')} tests and {testsuite.get('failures')} failures.") + print( + f"Found testsuite with {testsuite.get('tests')} tests and {testsuite.get('failures')} failures." + ) testcases = tree.findall(".//testcase") - with open(csv_file,'w') as outfile: + with open(csv_file, "w") as outfile: for testcase in testcases: - if testcase.find('.//skipped') == None: - if testcase.get('file') == None: - fulltestname = testcase.get('classname').replace('.','/') + ".py::" + testcase.get('name') + if testcase.find(".//skipped") == None: + if testcase.get("file") == None: + fulltestname = ( + testcase.get("classname").replace(".", "/") + + ".py::" + + testcase.get("name") + ) else: - fulltestname = testcase.get('file') + "::" + testcase.get('name') - if testcase.find('.//property') == None: + fulltestname = testcase.get("file") + "::" + testcase.get("name") + if testcase.find(".//property") == None: mld_val = None else: - mld_val = testcase.find('.//property').get('value') # Currently MLD is the only set property. If more are added updates are needed here. - outfile.write(fulltestname + ';' + str(mld_val)+'\n') + mld_val = testcase.find(".//property").get( + "value" + ) # Currently MLD is the only set property. If more are added updates are needed here. + outfile.write(fulltestname + ";" + str(mld_val) + "\n") diff --git a/scripts/parse_selftest_summary.py b/scripts/parse_selftest_summary.py index 8f03942e25..21aaa9e96e 100755 --- a/scripts/parse_selftest_summary.py +++ b/scripts/parse_selftest_summary.py @@ -32,8 +32,8 @@ """Parse the output from self_test.py, self_test_summary.txt, and check for test success.""" -import sys import re +import sys from pathlib import Path HERE = Path(__file__).parent.resolve() diff --git a/scripts/plot_meta_data.py b/scripts/plot_meta_data.py index 78d7bf5314..cc7962447f 100755 --- a/scripts/plot_meta_data.py +++ b/scripts/plot_meta_data.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -__license__ = \ -""" +__license__ = """ (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, @@ -31,8 +30,7 @@ __license__ = \ the United Nations Convention on Contracts on the International Sales of Goods. """ -__doc__ = \ -""" +__doc__ = """ Script to plot meta data. USAGE : plot_meta_data.py text_file containing the data @@ -72,10 +70,11 @@ The following format of C code is to be used for dumping metadata to plot using """ import sys + import numpy as np -from bokeh.plotting import figure, show, output_file, save from bokeh.layouts import column from bokeh.palettes import Set3 +from bokeh.plotting import figure, output_file, save, show class metadata: @@ -211,4 +210,4 @@ if __name__ == "__main__": ) ) exit() - sys.exit(main(sys.argv)) \ No newline at end of file + sys.exit(main(sys.argv)) diff --git a/scripts/prepare_combined_format_inputs.py b/scripts/prepare_combined_format_inputs.py index c1ff088151..c081b75bb1 100755 --- a/scripts/prepare_combined_format_inputs.py +++ b/scripts/prepare_combined_format_inputs.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -__license__ = \ -""" +__license__ = """ (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, @@ -35,109 +34,144 @@ import os import shutil import numpy as np +from pyaudio3dtools import audioarray, audiofile -from pyaudio3dtools import audiofile, audioarray def main(): FS = [48, 32, 16] # scripts/testv/ path - input_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'testv') - output_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'testv') + input_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "testv") + output_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "testv") - print(f'Writing new files into {output_dir}') + print(f"Writing new files into {output_dir}") # # prepare combined input for OMASA tests force_overwrite = False # overwrite existing files # define MASA test item files - masa_alts = ({'masa_meta_file': 'stv2MASA2TC{}c.met', - 'masa_audio_file': 'stv2MASA2TC{}c.wav', - 'masa_tag': '2MASA2TC'}, - {'masa_meta_file': 'stv2MASA1TC{}c.met', - 'masa_audio_file': 'stv2MASA1TC{}c.wav', - 'masa_tag': '2MASA1TC'}, - {'masa_meta_file': 'stv1MASA2TC{}c.met', - 'masa_audio_file': 'stv1MASA2TC{}c.wav', - 'masa_tag': '1MASA2TC'}, - {'masa_meta_file': 'stv1MASA1TC{}c.met', - 'masa_audio_file': 'stv1MASA1TC{}c.wav', - 'masa_tag': '1MASA1TC'}) - - sba_alts = ({'sba_audio_file': 'stvFOA{}c.wav', - 'sba_tag': 'FOA'}, - {'sba_audio_file': 'stv2OA{}c.wav', - 'sba_tag': '2OA'}, - {'sba_audio_file': 'stv3OA{}c.wav', - 'sba_tag': '3OA'}) + masa_alts = ( + { + "masa_meta_file": "stv2MASA2TC{}c.met", + "masa_audio_file": "stv2MASA2TC{}c.wav", + "masa_tag": "2MASA2TC", + }, + { + "masa_meta_file": "stv2MASA1TC{}c.met", + "masa_audio_file": "stv2MASA1TC{}c.wav", + "masa_tag": "2MASA1TC", + }, + { + "masa_meta_file": "stv1MASA2TC{}c.met", + "masa_audio_file": "stv1MASA2TC{}c.wav", + "masa_tag": "1MASA2TC", + }, + { + "masa_meta_file": "stv1MASA1TC{}c.met", + "masa_audio_file": "stv1MASA1TC{}c.wav", + "masa_tag": "1MASA1TC", + }, + ) + + sba_alts = ( + {"sba_audio_file": "stvFOA{}c.wav", "sba_tag": "FOA"}, + {"sba_audio_file": "stv2OA{}c.wav", "sba_tag": "2OA"}, + {"sba_audio_file": "stv3OA{}c.wav", "sba_tag": "3OA"}, + ) # files containing 1-4 ISMs as channels - ism_files = ('stv1ISM48s.wav', 'stv2ISM48s.wav', 'stv3ISM48s.wav', 'stv4ISM48s.wav') + ism_files = ("stv1ISM48s.wav", "stv2ISM48s.wav", "stv3ISM48s.wav", "stv4ISM48s.wav") # per-object metadata - ism_meta_files = ('stvISM1.csv', 'stvISM2.csv', 'stvISM3.csv', 'stvISM4.csv') + ism_meta_files = ("stvISM1.csv", "stvISM2.csv", "stvISM3.csv", "stvISM4.csv") wrote_files = [] for fs in FS: - for enum_idx, (ism_audio_file, ism_meta_file) in enumerate(zip(ism_files, ism_meta_files)): + for enum_idx, (ism_audio_file, ism_meta_file) in enumerate( + zip(ism_files, ism_meta_files) + ): n_isms = enum_idx + 1 - ism_audio, ism_fs = audiofile.readfile(filename=os.path.join(input_dir, ism_audio_file)) + ism_audio, ism_fs = audiofile.readfile( + filename=os.path.join(input_dir, ism_audio_file) + ) # no stv MASA files in other sampling rates available currently if fs == 48: for masa_item in masa_alts: - masa_tag = masa_item['masa_tag'] - masa_audio_file = masa_item['masa_audio_file'].format(fs) - meta_file = masa_item['masa_meta_file'].format(fs) + masa_tag = masa_item["masa_tag"] + masa_audio_file = masa_item["masa_audio_file"].format(fs) + meta_file = masa_item["masa_meta_file"].format(fs) - omasa_file_body = f'stvOMASA_{n_isms}ISM_{masa_tag}{fs}c' - omasa_file = os.path.join(output_dir, f'{omasa_file_body}.wav') + omasa_file_body = f"stvOMASA_{n_isms}ISM_{masa_tag}{fs}c" + omasa_file = os.path.join(output_dir, f"{omasa_file_body}.wav") if not os.path.exists(omasa_file) or force_overwrite: - audiofile.combinefiles(in_filenames=[os.path.join(input_dir, ism_audio_file), - os.path.join(input_dir, masa_audio_file)], - out_file=omasa_file, - in_fs=fs * 1000) + audiofile.combinefiles( + in_filenames=[ + os.path.join(input_dir, ism_audio_file), + os.path.join(input_dir, masa_audio_file), + ], + out_file=omasa_file, + in_fs=fs * 1000, + ) wrote_files.append(omasa_file) # copy ISM metadata files under names matching the combined file for ism_idx in range(n_isms): - ism_file_name = os.path.join(output_dir, f'{omasa_file_body}_ISM{ism_idx+1}{os.path.splitext(ism_meta_file)[1]}') + ism_file_name = os.path.join( + output_dir, + f"{omasa_file_body}_ISM{ism_idx+1}{os.path.splitext(ism_meta_file)[1]}", + ) if not os.path.exists(ism_file_name) or force_overwrite: - shutil.copyfile(os.path.join(input_dir, ism_meta_file), ism_file_name) + shutil.copyfile( + os.path.join(input_dir, ism_meta_file), ism_file_name + ) wrote_files.append(ism_file_name) # copy MASA metadata file under a matching name - masa_meta_name = os.path.join(output_dir, f'{omasa_file_body}{os.path.splitext(meta_file)[1]}') + masa_meta_name = os.path.join( + output_dir, f"{omasa_file_body}{os.path.splitext(meta_file)[1]}" + ) if not os.path.exists(masa_meta_name) or force_overwrite: - shutil.copyfile(os.path.join(input_dir, meta_file), masa_meta_name) + shutil.copyfile( + os.path.join(input_dir, meta_file), masa_meta_name + ) wrote_files.append(masa_meta_name) for sba_item in sba_alts: - sba_tag = sba_item['sba_tag'] - sba_audio_file = sba_item['sba_audio_file'].format(fs) + sba_tag = sba_item["sba_tag"] + sba_audio_file = sba_item["sba_audio_file"].format(fs) - osba_file_body = f'stvOSBA_{n_isms}ISM_{sba_tag}{fs}c' - osba_file = os.path.join(output_dir, f'{osba_file_body}.wav') + osba_file_body = f"stvOSBA_{n_isms}ISM_{sba_tag}{fs}c" + osba_file = os.path.join(output_dir, f"{osba_file_body}.wav") if not os.path.exists(osba_file) or force_overwrite: - audiofile.combinefiles(in_filenames=[os.path.join(input_dir, ism_audio_file), - os.path.join(input_dir, sba_audio_file)], - out_file=osba_file, - in_fs=fs * 1000) + audiofile.combinefiles( + in_filenames=[ + os.path.join(input_dir, ism_audio_file), + os.path.join(input_dir, sba_audio_file), + ], + out_file=osba_file, + in_fs=fs * 1000, + ) wrote_files.append(osba_file) # copy ISM metadata files under names matching the combined file for ism_idx in range(n_isms): - ism_file_name = os.path.join(output_dir, f'{osba_file_body}_ISM{ism_idx+1}{os.path.splitext(ism_meta_file)[1]}') + ism_file_name = os.path.join( + output_dir, + f"{osba_file_body}_ISM{ism_idx+1}{os.path.splitext(ism_meta_file)[1]}", + ) if not os.path.exists(ism_file_name) or force_overwrite: - shutil.copyfile(os.path.join(input_dir, ism_meta_file), ism_file_name) + shutil.copyfile( + os.path.join(input_dir, ism_meta_file), ism_file_name + ) wrote_files.append(ism_file_name) - # info print. helps setting up .gitignore if len(wrote_files) > 0: - print('New files written: {}'.format('\n'.join(wrote_files))) + print("New files written: {}".format("\n".join(wrote_files))) + if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/scripts/prepare_mem_dryrun.py b/scripts/prepare_mem_dryrun.py index 20da546c19..ff186a4510 100755 --- a/scripts/prepare_mem_dryrun.py +++ b/scripts/prepare_mem_dryrun.py @@ -1,10 +1,12 @@ #!/usr/bin/env python3 -import re, os, fnmatch +import fnmatch +import os +import re -sub = ['free','malloc','calloc'] -dirs = ['./lib_com','./lib_enc','./lib_dec','./lib_rend'] -suffix = '*.c' +sub = ["free", "malloc", "calloc"] +dirs = ["./lib_com", "./lib_enc", "./lib_dec", "./lib_rend"] +suffix = "*.c" skip = 0 @@ -13,18 +15,17 @@ for d in dirs: for path, ds, files in os.walk(d): for filename in fnmatch.filter(files, suffix): fileIn = os.path.join(path, filename) - with open(fileIn, 'r') as f_in: + with open(fileIn, "r") as f_in: lines = f_in.readlines() - with open(fileIn, 'w') as f_out: + with open(fileIn, "w") as f_out: skip = 0 for line in lines: - if re.search(r'#define\W+WMC_TOOL_SKIP', line): + if re.search(r"#define\W+WMC_TOOL_SKIP", line): skip = 1 - elif re.search(r'#undef\W+WMC_TOOL_SKIP', line): + elif re.search(r"#undef\W+WMC_TOOL_SKIP", line): skip = 0 else: if not skip: for s in sub: - line = re.sub(r'\b%s\b' % (s), '%s' % (s+'_'), line) + line = re.sub(r"\b%s\b" % (s), "%s" % (s + "_"), line) f_out.write(line) - diff --git a/scripts/pyaudio3dtools/__init__.py b/scripts/pyaudio3dtools/__init__.py index d4588ecbeb..ccf53c51e1 100644 --- a/scripts/pyaudio3dtools/__init__.py +++ b/scripts/pyaudio3dtools/__init__.py @@ -40,8 +40,4 @@ Imports functions class """ -from . import ( - audioarray, - audiofile, - spatialaudioformat, -) +from . import audioarray, audiofile, spatialaudioformat diff --git a/scripts/pyaudio3dtools/audio3dtools.py b/scripts/pyaudio3dtools/audio3dtools.py index e185a7a58f..0fec5c6ce9 100755 --- a/scripts/pyaudio3dtools/audio3dtools.py +++ b/scripts/pyaudio3dtools/audio3dtools.py @@ -34,10 +34,7 @@ import argparse import logging import os -from pyaudio3dtools import ( - audiofile, - spatialaudioformat, -) +from pyaudio3dtools import audiofile, spatialaudioformat main_logger = logging.getLogger("__main__") logger = main_logger.getChild(__name__) diff --git a/scripts/pyaudio3dtools/audioarray.py b/scripts/pyaudio3dtools/audioarray.py index 6a1b5b56e2..8fabd5ca1c 100644 --- a/scripts/pyaudio3dtools/audioarray.py +++ b/scripts/pyaudio3dtools/audioarray.py @@ -32,16 +32,16 @@ import logging import math -from typing import Callable, Iterable, Optional, Tuple - -import numpy as np import multiprocessing as mp -import scipy.signal as sig -import scipy.io.wavfile as wavfile -import subprocess import platform +import subprocess import tempfile from pathlib import Path +from typing import Callable, Iterable, Optional, Tuple + +import numpy as np +import scipy.io.wavfile as wavfile +import scipy.signal as sig main_logger = logging.getLogger("__main__") logger = main_logger.getChild(__name__) @@ -226,7 +226,13 @@ def cut(x: np.ndarray, limits: Tuple[int, int]) -> np.ndarray: return y -def compare(ref: np.ndarray, test: np.ndarray, fs: int, per_frame: bool = True, get_mld: bool = False) -> dict: +def compare( + ref: np.ndarray, + test: np.ndarray, + fs: int, + per_frame: bool = True, + get_mld: bool = False, +) -> dict: """Compare two audio arrays Parameters @@ -314,13 +320,13 @@ def compare(ref: np.ndarray, test: np.ndarray, fs: int, per_frame: bool = True, result["nframes_diff_percentage"] = nframes_diff_percentage if get_mld: - + mld_max = 0 toolsdir = Path(__file__).parent.parent.joinpath("tools") if platform.system() == "Windows": - mld = toolsdir.joinpath( "Win32").joinpath("mld.exe" ) + mld = toolsdir.joinpath("Win32").joinpath("mld.exe") elif platform.system() in ["Linux", "Darwin"]: - mld = toolsdir.joinpath(platform.system()).joinpath( "mld" ) + mld = toolsdir.joinpath(platform.system()).joinpath("mld") else: assert False, f"MLD tool not available for {platform.system()}" @@ -328,11 +334,11 @@ def compare(ref: np.ndarray, test: np.ndarray, fs: int, per_frame: bool = True, for i in range(nchannels): tmpfile_ref = Path(tmpdir).joinpath(f"ref_ch{i+1}.wav") tmpfile_test = Path(tmpdir).joinpath(f"test_ch{i+1}.wav") - r48 = resample(ref[:,i], fs, 48000); - t48 = resample(test[:,i], fs, 48000); + r48 = resample(ref[:, i], fs, 48000) + t48 = resample(test[:, i], fs, 48000) wavfile.write(str(tmpfile_ref), 48000, r48) wavfile.write(str(tmpfile_test), 48000, t48) - out = subprocess.check_output([mld,tmpfile_ref,tmpfile_test]) + out = subprocess.check_output([mld, tmpfile_ref, tmpfile_test]) mld_max = max(mld_max, float(out.split()[3])) result["MLD"] = mld_max diff --git a/scripts/pyaudio3dtools/audiofile.py b/scripts/pyaudio3dtools/audiofile.py index e790de7e09..d3153e21db 100644 --- a/scripts/pyaudio3dtools/audiofile.py +++ b/scripts/pyaudio3dtools/audiofile.py @@ -42,7 +42,6 @@ from typing import Optional, Tuple import numpy as np import scipy.io.wavfile as wav - from pyaudio3dtools import audioarray, spatialaudioformat diff --git a/scripts/pyaudio3dtools/spatialaudioformat.py b/scripts/pyaudio3dtools/spatialaudioformat.py index c223b28917..ee8c6315be 100644 --- a/scripts/pyaudio3dtools/spatialaudioformat.py +++ b/scripts/pyaudio3dtools/spatialaudioformat.py @@ -357,150 +357,126 @@ _format_configs = { "altname": "meta", }, # OSBA Formats - "OSBA_ISM1_HOA3": - { - "name": "OSBA_ISM1_HOA3", - "ambi_order": 3, - "isplanar": False, - "nchannels": 17, - "isloudspeaker": False, - "isheadphones": False, - "lfe_index": [], - "altname": "osba3_ism1", - - }, - "OSBA_ISM1_HOA2": - { - "name": "OSBA_ISM1_HOA2", - "ambi_order": 2, - "isplanar": False, - "nchannels": 10, - "isloudspeaker": False, - "isheadphones": False, - "lfe_index": [], - "altname": "osba2_ism1", - - }, - "OSBA_ISM1_FOA": - { - "name": "OSBA_ISM1_FOA", - "ambi_order": 1, - "isplanar": False, - "nchannels": 5, - "isloudspeaker": False, - "isheadphones": False, - "lfe_index": [], - "altname": "osba1_ism1", - - }, - "OSBA_ISM2_HOA3": - { - "name": "OSBA_ISM2_HOA3", - "ambi_order": 3, - "isplanar": False, - "nchannels": 18, - "isloudspeaker": False, - "isheadphones": False, - "lfe_index": [], - "altname": "osba3_ism2", - - }, - "OSBA_ISM2_HOA2": - { - "name": "OSBA_ISM2_HOA2", - "ambi_order": 2, - "isplanar": False, - "nchannels": 11, - "isloudspeaker": False, - "isheadphones": False, - "lfe_index": [], - "altname": "osba2_ism2", - - }, - "OSBA_ISM2_FOA": - { - "name": "OSBA_ISM2_FOA", - "ambi_order": 1, - "isplanar": False, - "nchannels": 6, - "isloudspeaker": False, - "isheadphones": False, - "lfe_index": [], - "altname": "osba1_ism2", - - }, - "OSBA_ISM3_HOA3": - { - "name": "OSBA_ISM3_HOA3", - "ambi_order": 3, - "isplanar": False, - "nchannels": 19, - "isloudspeaker": False, - "isheadphones": False, - "lfe_index": [], - "altname": "osba3_ism3", - - }, - "OSBA_ISM3_HOA2": - { - "name": "OSBA_ISM3_HOA2", - "ambi_order": 2, - "isplanar": False, - "nchannels": 12, - "isloudspeaker": False, - "isheadphones": False, - "lfe_index": [], - "altname": "osba2_ism3", - - }, - "OSBA_ISM3_FOA": - { - "name": "OSBA_ISM3_FOA", - "ambi_order": 1, - "isplanar": False, - "nchannels": 7, - "isloudspeaker": False, - "isheadphones": False, - "lfe_index": [], - "altname": "osba1_ism3", - - }, - "OSBA_ISM4_HOA3": - { - "name": "OSBA_ISM4_HOA3", - "ambi_order": 3, - "isplanar": False, - "nchannels": 20, - "isloudspeaker": False, - "isheadphones": False, - "lfe_index": [], - "altname": "osba3_ism4", - - }, - "OSBA_ISM4_HOA2": - { - "name": "OSBA_ISM4_HOA2", - "ambi_order": 2, - "isplanar": False, - "nchannels": 13, - "isloudspeaker": False, - "isheadphones": False, - "lfe_index": [], - "altname": "osba2_ism4", - - }, - "OSBA_ISM4_FOA": - { - "name": "OSBA_ISM4_FOA", - "ambi_order": 1, - "isplanar": False, - "nchannels": 8, - "isloudspeaker": False, - "isheadphones": False, - "lfe_index": [], - "altname": "osba1_ism4", - - }, + "OSBA_ISM1_HOA3": { + "name": "OSBA_ISM1_HOA3", + "ambi_order": 3, + "isplanar": False, + "nchannels": 17, + "isloudspeaker": False, + "isheadphones": False, + "lfe_index": [], + "altname": "osba3_ism1", + }, + "OSBA_ISM1_HOA2": { + "name": "OSBA_ISM1_HOA2", + "ambi_order": 2, + "isplanar": False, + "nchannels": 10, + "isloudspeaker": False, + "isheadphones": False, + "lfe_index": [], + "altname": "osba2_ism1", + }, + "OSBA_ISM1_FOA": { + "name": "OSBA_ISM1_FOA", + "ambi_order": 1, + "isplanar": False, + "nchannels": 5, + "isloudspeaker": False, + "isheadphones": False, + "lfe_index": [], + "altname": "osba1_ism1", + }, + "OSBA_ISM2_HOA3": { + "name": "OSBA_ISM2_HOA3", + "ambi_order": 3, + "isplanar": False, + "nchannels": 18, + "isloudspeaker": False, + "isheadphones": False, + "lfe_index": [], + "altname": "osba3_ism2", + }, + "OSBA_ISM2_HOA2": { + "name": "OSBA_ISM2_HOA2", + "ambi_order": 2, + "isplanar": False, + "nchannels": 11, + "isloudspeaker": False, + "isheadphones": False, + "lfe_index": [], + "altname": "osba2_ism2", + }, + "OSBA_ISM2_FOA": { + "name": "OSBA_ISM2_FOA", + "ambi_order": 1, + "isplanar": False, + "nchannels": 6, + "isloudspeaker": False, + "isheadphones": False, + "lfe_index": [], + "altname": "osba1_ism2", + }, + "OSBA_ISM3_HOA3": { + "name": "OSBA_ISM3_HOA3", + "ambi_order": 3, + "isplanar": False, + "nchannels": 19, + "isloudspeaker": False, + "isheadphones": False, + "lfe_index": [], + "altname": "osba3_ism3", + }, + "OSBA_ISM3_HOA2": { + "name": "OSBA_ISM3_HOA2", + "ambi_order": 2, + "isplanar": False, + "nchannels": 12, + "isloudspeaker": False, + "isheadphones": False, + "lfe_index": [], + "altname": "osba2_ism3", + }, + "OSBA_ISM3_FOA": { + "name": "OSBA_ISM3_FOA", + "ambi_order": 1, + "isplanar": False, + "nchannels": 7, + "isloudspeaker": False, + "isheadphones": False, + "lfe_index": [], + "altname": "osba1_ism3", + }, + "OSBA_ISM4_HOA3": { + "name": "OSBA_ISM4_HOA3", + "ambi_order": 3, + "isplanar": False, + "nchannels": 20, + "isloudspeaker": False, + "isheadphones": False, + "lfe_index": [], + "altname": "osba3_ism4", + }, + "OSBA_ISM4_HOA2": { + "name": "OSBA_ISM4_HOA2", + "ambi_order": 2, + "isplanar": False, + "nchannels": 13, + "isloudspeaker": False, + "isheadphones": False, + "lfe_index": [], + "altname": "osba2_ism4", + }, + "OSBA_ISM4_FOA": { + "name": "OSBA_ISM4_FOA", + "ambi_order": 1, + "isplanar": False, + "nchannels": 8, + "isloudspeaker": False, + "isheadphones": False, + "lfe_index": [], + "altname": "osba1_ism4", + }, } # Channel indices of planar Ambisonic components of ACN diff --git a/scripts/pyivastest/IvasBaseClass.py b/scripts/pyivastest/IvasBaseClass.py index ce19cc0f55..bad578f753 100644 --- a/scripts/pyivastest/IvasBaseClass.py +++ b/scripts/pyivastest/IvasBaseClass.py @@ -30,16 +30,23 @@ the United Nations Convention on Contracts on the International Sales of Goods. """ +import filecmp +import json import logging import logging.handlers import os -import sys -import filecmp -import json import platform -from .constants import LOG_FILE_EXT, DECODER_OUTPUT_CONFIGS, LOG_FILE_DIR,SCRIPTS_CONFIGS_DIR, DEFAULT_IVAS_FORMAT_FILE -from copy import deepcopy import re +import sys +from copy import deepcopy + +from .constants import ( + DECODER_OUTPUT_CONFIGS, + DEFAULT_IVAS_FORMAT_FILE, + LOG_FILE_DIR, + LOG_FILE_EXT, + SCRIPTS_CONFIGS_DIR, +) PROGRESS = 70 CONSOLE = 80 @@ -302,31 +309,39 @@ class IvasBaseClass(object): @staticmethod def get_enc_file_name(path: str, item_base_name: str, mode: str) -> str: - return os.path.join(path, "enc", ''.join([item_base_name, "_", mode, ".192"])) - + return os.path.join(path, "enc", "".join([item_base_name, "_", mode, ".192"])) @staticmethod - def get_enc_log_file_name(path: str, item_base_name: str, mode: str, log_dir = LOG_FILE_DIR) -> str: - enc_log_name_tmp = ''.join([item_base_name, "_", mode, ".enc", LOG_FILE_EXT]) + def get_enc_log_file_name( + path: str, item_base_name: str, mode: str, log_dir=LOG_FILE_DIR + ) -> str: + enc_log_name_tmp = "".join([item_base_name, "_", mode, ".enc", LOG_FILE_EXT]) enc_log_name = os.path.join(path, log_dir, enc_log_name_tmp) return enc_log_name @staticmethod - def get_dec_file_name(path: str, item_base_name:str, output_config:str, out_ext=".wav") -> str: + def get_dec_file_name( + path: str, item_base_name: str, output_config: str, out_ext=".wav" + ) -> str: output_config_desc = IvasBaseClass.get_oc_desc(output_config) - dec_file_name = os.path.join(path, "dec", - ''.join([item_base_name, ".dec.", output_config_desc, out_ext])) + dec_file_name = os.path.join( + path, "dec", "".join([item_base_name, ".dec.", output_config_desc, out_ext]) + ) return dec_file_name @staticmethod - def get_dec_log_file_name(path: str, item_base_name:str, output_config:str, log_dir = LOG_FILE_DIR): + def get_dec_log_file_name( + path: str, item_base_name: str, output_config: str, log_dir=LOG_FILE_DIR + ): output_config_desc = IvasBaseClass.get_oc_desc(output_config) - dec_log_name_tmp = ''.join([item_base_name, ".dec.", output_config_desc, LOG_FILE_EXT]) + dec_log_name_tmp = "".join( + [item_base_name, ".dec.", output_config_desc, LOG_FILE_EXT] + ) dec_log_name = os.path.join(path, log_dir, dec_log_name_tmp) return dec_log_name @staticmethod - def get_oc_desc(output_config:str) -> str: + def get_oc_desc(output_config: str) -> str: if output_config.upper() not in DECODER_OUTPUT_CONFIGS: output_config_desc = os.path.splitext(os.path.basename(output_config))[0] else: @@ -343,7 +358,7 @@ class IvasBaseClass(object): format_file = os.path.join(SCRIPTS_CONFIGS_DIR, format_file) if not os.path.exists(format_file): return None - with open(format_file, 'r') as fp: + with open(format_file, "r") as fp: all_formats = IvasBaseClass.generate_all_formats(json.load(fp)) return all_formats @@ -352,9 +367,11 @@ class IvasBaseClass(object): def generate_all_formats(all_formats_json: dict) -> dict: all_formats = None if all_formats_json is not None: - if 'version' in all_formats_json: - if all_formats_json['version'] == 2: - all_formats = IvasBaseClass.generate_all_formats_v2(all_formats_json) + if "version" in all_formats_json: + if all_formats_json["version"] == 2: + all_formats = IvasBaseClass.generate_all_formats_v2( + all_formats_json + ) else: all_formats = all_formats_json return all_formats @@ -366,36 +383,56 @@ class IvasBaseClass(object): if ivas_format != "version": if all_formats is None: all_formats = {} - all_formats.update({ivas_format:{}}) + all_formats.update({ivas_format: {}}) for mode_group in all_formats_json[ivas_format]: - for bw in all_formats_json[ivas_format][mode_group]['bitrates']: - for br in all_formats_json[ivas_format][mode_group]['bitrates'][bw]: - new_mode_dict=deepcopy(all_formats_json[ivas_format][mode_group]) - if new_mode_dict['rs'] == True: + for bw in all_formats_json[ivas_format][mode_group]["bitrates"]: + for br in all_formats_json[ivas_format][mode_group]["bitrates"][ + bw + ]: + new_mode_dict = deepcopy( + all_formats_json[ivas_format][mode_group] + ) + if new_mode_dict["rs"] == True: table_bitrate = br - bitrate = all_formats_json[ivas_format][mode_group]['bitrates'][bw][br] - mode_bitrate = br.replace("/","_") + bitrate = all_formats_json[ivas_format][mode_group][ + "bitrates" + ][bw][br] + mode_bitrate = br.replace("/", "_") else: - #make sure the modes have the same names as the v1 ones... - if br%1000 == 0 and (br > 10000 and not all_formats_json[ivas_format][mode_group]['amr']): + # make sure the modes have the same names as the v1 ones... + if br % 1000 == 0 and ( + br > 10000 + and not all_formats_json[ivas_format][mode_group][ + "amr" + ] + ): table_bitrate = br // 1000 mode_bitrate = str(table_bitrate) else: - table_bitrate = (br // 100)/10 - mode_bitrate = f"{table_bitrate:04.1f}".replace(".","_") - bitrate=br - new_mode_dict.pop('bitrates') - new_mode_dict['bw'] = bw - new_mode_dict['bitrate']=bitrate - new_mode_dict['table_name'] = new_mode_dict['table_name'].format(table_bitrate=table_bitrate, bandwidth=bw.upper()) - new_mode_dict['encoptions'] = [x.format(bandwidth=bw) for x in new_mode_dict['encoptions']] - - new_mode=mode_group.format(bitrate=mode_bitrate,bandwidth=bw) - all_formats[ivas_format].update({new_mode:new_mode_dict}) - + table_bitrate = (br // 100) / 10 + mode_bitrate = f"{table_bitrate:04.1f}".replace( + ".", "_" + ) + bitrate = br + new_mode_dict.pop("bitrates") + new_mode_dict["bw"] = bw + new_mode_dict["bitrate"] = bitrate + new_mode_dict["table_name"] = new_mode_dict[ + "table_name" + ].format(table_bitrate=table_bitrate, bandwidth=bw.upper()) + new_mode_dict["encoptions"] = [ + x.format(bandwidth=bw) + for x in new_mode_dict["encoptions"] + ] + + new_mode = mode_group.format( + bitrate=mode_bitrate, bandwidth=bw + ) + all_formats[ivas_format].update({new_mode: new_mode_dict}) return all_formats + if __name__ == "__main__": import time diff --git a/scripts/pyivastest/IvasModeAnalyzer.py b/scripts/pyivastest/IvasModeAnalyzer.py index 9f52a90636..8d1dd2ddf0 100644 --- a/scripts/pyivastest/IvasModeAnalyzer.py +++ b/scripts/pyivastest/IvasModeAnalyzer.py @@ -30,17 +30,16 @@ the United Nations Convention on Contracts on the International Sales of Goods. """ +import functools +import logging +import operator import os import re -import operator from copy import deepcopy -import logging -import functools -from pyivastest.IvasModeCollector import IvasModeCollector from pyivastest.constants import LOG_FILE_EXT from pyivastest.IvasBaseClass import IvasBaseClass - +from pyivastest.IvasModeCollector import IvasModeCollector INSTRUMENTED_RESULTS = { "WMOPS": { @@ -288,27 +287,32 @@ class IvasModeAnalyzer(IvasModeCollector): Returns ------- - + First value extracted from the line in the log file containing all keywords """ - + if type(keywords) != list: keywords = [keywords] - + if os.path.exists(filename): fp = open(filename) loglines = fp.readlines() fp.close() - matching_lines = [line for line in loglines if all(keyword in line for keyword in keywords)] + matching_lines = [ + line + for line in loglines + if all(keyword in line for keyword in keywords) + ] for line in matching_lines: - all_values_on_line = [float(s) for s in line.split() if re.match(r'^[0-9\.]*$', s)] + all_values_on_line = [ + float(s) for s in line.split() if re.match(r"^[0-9\.]*$", s) + ] if all_values_on_line: return all_values_on_line[position] - + return -1.0 - def sort_log_modes(self): list_to_sort = [] @@ -527,13 +531,18 @@ class IvasModeAnalyzer(IvasModeCollector): elif encdec == 4: if max_or_add == "add": total = number_format.format( - float(enc_value) + float(dec_value) + float(com_value) + float(rend_value) + float(enc_value) + + float(dec_value) + + float(com_value) + + float(rend_value) ) elif max_or_add == "max": total = number_format.format( max( float(enc_value) + float(com_value), - float(dec_value) + float(com_value) + float(rend_value), + float(dec_value) + + float(com_value) + + float(rend_value), ) ) result_line = [ @@ -686,7 +695,9 @@ class IvasModeAnalyzer(IvasModeCollector): if self.global_bitstream_processing is not None: suffices = self.get_bs_processing_suffices(self.global_bitstream_processing) - dec_item_base_name = "_".join([x for x in [item, mode, suffices] if x is not None]) + dec_item_base_name = "_".join( + [x for x in [item, mode, suffices] if x is not None] + ) log_name = IvasBaseClass.get_dec_log_file_name(self.dir, dec_item_base_name, oc) return log_name @@ -944,10 +955,10 @@ class IvasModeAnalyzer(IvasModeCollector): ------- """ - + if not os.path.exists(os.path.dirname(csv_file_name)): os.makedirs(os.path.dirname(csv_file_name)) - + with open(csv_file_name + ".csv", "w", newline="\n") as f: header = result_table.pop(0) # write header diff --git a/scripts/pyivastest/IvasModeCollector.py b/scripts/pyivastest/IvasModeCollector.py index fbba5f6ae2..3255dc3a8a 100644 --- a/scripts/pyivastest/IvasModeCollector.py +++ b/scripts/pyivastest/IvasModeCollector.py @@ -30,15 +30,16 @@ the United Nations Convention on Contracts on the International Sales of Goods. """ -import re import json +import logging import os import os.path import platform -import logging +import re from copy import deepcopy -from pyivastest import IvasBaseClass -from pyivastest import constants + +from pyivastest import IvasBaseClass, constants + class IvasModeCollector(IvasBaseClass.IvasBaseClass): """ @@ -70,15 +71,24 @@ class IvasModeCollector(IvasBaseClass.IvasBaseClass): self.all_formats = formats_dict else: if not formats_fname: - formats_fname = os.path.join(constants.SCRIPTS_CONFIGS_DIR, constants.DEFAULT_IVAS_FORMAT_FILE) + formats_fname = os.path.join( + constants.SCRIPTS_CONFIGS_DIR, constants.DEFAULT_IVAS_FORMAT_FILE + ) self.all_formats = self.read_format_dict(formats_fname) if self.all_formats is None: # fall back to standard self.logger.warning( "IVAS Format dictonary file {} does not exist, falling back to {}!".format( - formats_fname,constants.DEFAULT_IVAS_FORMAT_FILE)) - self.all_formats = self.read_format_dict(os.path.join(constants.SCRIPTS_CONFIGS_DIR, constants.DEFAULT_IVAS_FORMAT_FILE)) - #fp.close() + formats_fname, constants.DEFAULT_IVAS_FORMAT_FILE + ) + ) + self.all_formats = self.read_format_dict( + os.path.join( + constants.SCRIPTS_CONFIGS_DIR, + constants.DEFAULT_IVAS_FORMAT_FILE, + ) + ) + # fp.close() self.flat_mode_list = None have_site_config_file = False diff --git a/scripts/pyivastest/IvasModeRunner.py b/scripts/pyivastest/IvasModeRunner.py index 79da317d0e..27f013ee8d 100644 --- a/scripts/pyivastest/IvasModeRunner.py +++ b/scripts/pyivastest/IvasModeRunner.py @@ -30,24 +30,24 @@ the United Nations Convention on Contracts on the International Sales of Goods. """ -import os -import subprocess -import threading import concurrent.futures -import time +import json import logging import logging.handlers +import os import platform +import re +import subprocess +import threading +import time import traceback from copy import deepcopy -import re -import json -from pyivastest import IvasModeCollector -from pyivastest import constants -from pyaudio3dtools.spatialaudioformat import Format as spformat -import pyaudio3dtools.audiofile as af import pyaudio3dtools.audioarray as ar +import pyaudio3dtools.audiofile as af +from pyaudio3dtools.spatialaudioformat import Format as spformat +from pyivastest import IvasModeCollector, constants + BW_TO_SR = {"nb": 8, "wb": 16, "swb": 32, "fb": 48} RET_CODE_TIMEOUT_EXP = 9999 @@ -260,10 +260,14 @@ class IvasModeRunner(IvasModeCollector.IvasModeCollector): if self.pcm_out is True: out_ext = ".pcm" - dec_log_name = self.get_dec_log_file_name(self.dir_name,item_base_name,output_config) + dec_log_name = self.get_dec_log_file_name( + self.dir_name, item_base_name, output_config + ) dec_log = open(dec_log_name, "w") if config["enc_returncode"] == 0: - dec_file_name = self.get_dec_file_name(self.dir_name, item_base_name, output_config, out_ext) + dec_file_name = self.get_dec_file_name( + self.dir_name, item_base_name, output_config, out_ext + ) if self.sample_rate_dec_out: out_sr = self.sample_rate_dec_out else: @@ -323,7 +327,13 @@ class IvasModeRunner(IvasModeCollector.IvasModeCollector): dec_log.write(" ".join(dec_cmd)) try: - cur_dec_result = subprocess.run(dec_cmd, capture_output=True, text=True, env=self.run_env, timeout=self.timeout) + cur_dec_result = subprocess.run( + dec_cmd, + capture_output=True, + text=True, + env=self.run_env, + timeout=self.timeout, + ) returncode = cur_dec_result.returncode dec_log.write(cur_dec_result.stderr) dec_log.write(cur_dec_result.stdout) @@ -333,11 +343,12 @@ class IvasModeRunner(IvasModeCollector.IvasModeCollector): if returncode != 0: fail_string = "Decoding {} to {} failed!" if returncode == RET_CODE_TIMEOUT_EXP: - fail_string = fail_string[:-1] + f" due to timeout after {self.timeout} seconds!" + fail_string = ( + fail_string[:-1] + + f" due to timeout after {self.timeout} seconds!" + ) - self.logger.error( - fail_string.format(enc_file_name, dec_file_name) - ) + self.logger.error(fail_string.format(enc_file_name, dec_file_name)) self.lock.acquire() if self.stats: self.stats["num_dec_errors"] += 1 @@ -494,7 +505,10 @@ class IvasModeRunner(IvasModeCollector.IvasModeCollector): str(sample_rate_in), "_", config["cmd"]["in_config"].upper(), - "_L{}-{}s".format("_".join(str(self.start_time).split(".")), "_".join(str(self.end_time).split("."))), + "_L{}-{}s".format( + "_".join(str(self.start_time).split(".")), + "_".join(str(self.end_time).split(".")), + ), ".pcm", ] ) @@ -547,9 +561,13 @@ class IvasModeRunner(IvasModeCollector.IvasModeCollector): elif config["cmd"]["in_config"][0:4] == "OSBA": # get number of ISMs expected osba_ism_config = config["cmd"]["in_config"][5:9] - osba_ism_format_dict = spformat.get_format_dict(osba_ism_config) + osba_ism_format_dict = spformat.get_format_dict( + osba_ism_config + ) wav_info = af.get_wav_file_info(in_file_name_transformed) - osba_ambi_config = spformat.detect_format(wav_info["channels"] - osba_ism_format_dict["nchannels"]) + osba_ambi_config = spformat.detect_format( + wav_info["channels"] - osba_ism_format_dict["nchannels"] + ) in_format = f"OSBA_{osba_ism_config}_{osba_ambi_config}" # save in config as json file @@ -570,16 +588,27 @@ class IvasModeRunner(IvasModeCollector.IvasModeCollector): # first check if start time exceeds signal length start_time_samples = int(float(self.start_time) * fs) if start_time_samples >= in_len: - raise RuntimeError("Signal is shorter than given start time") + raise RuntimeError( + "Signal is shorter than given start time" + ) end_time_samples = int(float(self.end_time) * fs) cut_len_samples = end_time_samples - start_time_samples - if cut_len_samples + start_time_samples < in_len or start_time_samples > 0: + if ( + cut_len_samples + start_time_samples < in_len + or start_time_samples > 0 + ): end_time_samples = min(end_time_samples, in_len) - sig = ar.cut(sig, (start_time_samples, end_time_samples)) + sig = ar.cut( + sig, (start_time_samples, end_time_samples) + ) - pcm_log.write("Limit signal length to {}:{} samples".format(start_time_samples, end_time_samples)) + pcm_log.write( + "Limit signal length to {}:{} samples".format( + start_time_samples, end_time_samples + ) + ) af.writefile(pcm_name_cpy_transformed, sig, fs) resamp_in_path = pcm_name_cpy_transformed @@ -587,7 +616,12 @@ class IvasModeRunner(IvasModeCollector.IvasModeCollector): pcm_name_transformed = self.transform_path(pcm_name) pcm_log.write("Resampling to {}".format(out_fs)) - af.convertfile(resamp_in_path, pcm_name_transformed, in_fs=fs, out_fs=out_fs) + af.convertfile( + resamp_in_path, + pcm_name_transformed, + in_fs=fs, + out_fs=out_fs, + ) in_config = config["cmd"]["in_config"].upper() @@ -641,9 +675,9 @@ class IvasModeRunner(IvasModeCollector.IvasModeCollector): # metadata is either explicitly taken from the respective command line args or, # if not given, the default pattern form the config is used to get filenames in - # the same dir as the input file. NULL for ISM MD has to be explicitly given, + # the same dir as the input file. NULL for ISM MD has to be explicitly given, # otherwise this may hapen without the user being aware and lead to unexpected results. - # If the default filenames from the configs do not point to existing files, the + # If the default filenames from the configs do not point to existing files, the # codec will complain later nummetadata = enc_dec_cmd["nummetadata"] if nummetadata > 0: @@ -657,21 +691,26 @@ class IvasModeRunner(IvasModeCollector.IvasModeCollector): # if not enough md files explicitly given, try default pattern from config if len(md_files) != nummetadata: - default = os.path.join(in_dir, enc_dec_cmd["metadatafilenames"][0]) + default = os.path.join( + in_dir, enc_dec_cmd["metadatafilenames"][0] + ) for i in range(len(md_files), nummetadata): md_f = default.format(item=item_base_name, mdi=i + 1) if not os.path.exists(md_f): - self.logger.warning(f"Can't find default md file {md_f} for item {item_base_name}. Default to NULL") + self.logger.warning( + f"Can't find default md file {md_f} for item {item_base_name}. Default to NULL" + ) md_f = "NULL" md_files.append(md_f) - if "MASA" in in_format: masa_md = self.global_masa_metadata # if not explicitly given, try default pattern from config if masa_md is None: - default = os.path.join(in_dir, enc_dec_cmd["metadatafilenames"][-1]) + default = os.path.join( + in_dir, enc_dec_cmd["metadatafilenames"][-1] + ) masa_md = default.format(item=item_base_name) md_files.append(masa_md) @@ -709,16 +748,24 @@ class IvasModeRunner(IvasModeCollector.IvasModeCollector): # inject the input file's ambisonic order if pcm_name in self.pcm_info: enc_cmd = [ - x.format(ambi_order=self.pcm_info[pcm_name]["ambi_order"]) - if "{ambi_order}" in x - else x + ( + x.format(ambi_order=self.pcm_info[pcm_name]["ambi_order"]) + if "{ambi_order}" in x + else x + ) for x in enc_cmd ] enc_log = open(enc_log_name, "w") enc_log.write(" ".join(enc_cmd)) try: - enc_result = subprocess.run(enc_cmd, capture_output=True, text=True, env=self.run_env, timeout=self.timeout) + enc_result = subprocess.run( + enc_cmd, + capture_output=True, + text=True, + env=self.run_env, + timeout=self.timeout, + ) error = enc_result.returncode enc_log.write(enc_result.stderr) enc_log.write(enc_result.stdout) @@ -813,7 +860,9 @@ class IvasModeRunner(IvasModeCollector.IvasModeCollector): if error != 0: fail_string = "Encoding failed for {}" if error == RET_CODE_TIMEOUT_EXP: - fail_string = fail_string + f" due to timeout after {self.timeout} seconds" + fail_string = ( + fail_string + f" due to timeout after {self.timeout} seconds" + ) self.lock.acquire() if self.stats: @@ -1089,9 +1138,11 @@ class IvasModeRunner(IvasModeCollector.IvasModeCollector): None, list( map( - lambda x: mode_dec_files[x][0] - if not os.path.exists(mode_dec_files[x][1]) - else None, + lambda x: ( + mode_dec_files[x][0] + if not os.path.exists(mode_dec_files[x][1]) + else None + ), range(len(mode_dec_files)), ) ), @@ -1371,7 +1422,6 @@ class IvasModeRunner(IvasModeCollector.IvasModeCollector): "Binaries: Encoder {}, Decoder {}".format(self.encoder, self.decoder) ) - def check_and_create_out_dirs(self): if not os.path.exists(self.dir_name): self.logger.console( @@ -1524,7 +1574,9 @@ class IvasModeRunner(IvasModeCollector.IvasModeCollector): with self.dec_queue["condition"]: dec_queue_empty = len(self.dec_queue["dec_entries"]) == 0 all_encoded = self.dec_queue["all_encoded"] - all_modes_done = self.stats["num_modes"] == self.stats["num_modes_finished"] + all_modes_done = ( + self.stats["num_modes"] == self.stats["num_modes_finished"] + ) if dec_queue_empty and all_encoded and all_modes_done: self.dec_queue["condition"].notify() @@ -1535,7 +1587,9 @@ class IvasModeRunner(IvasModeCollector.IvasModeCollector): # can not reuse dec_queue_empty here, since there might be new items after waiting while len(self.dec_queue["dec_entries"]) != 0: config = self.dec_queue["dec_entries"].pop(0) - tasks_dec.append(executor.submit(self.ivas_dec_thread, config)) + tasks_dec.append( + executor.submit(self.ivas_dec_thread, config) + ) self.dec_queue["condition"].notify() diff --git a/scripts/pyivastest/IvasScriptsCommon.py b/scripts/pyivastest/IvasScriptsCommon.py index 02cf6a6b8b..f50307fd0d 100644 --- a/scripts/pyivastest/IvasScriptsCommon.py +++ b/scripts/pyivastest/IvasScriptsCommon.py @@ -31,14 +31,15 @@ """ import argparse -import os import json -import re -import multiprocessing -from pyivastest.IvasBaseClass import * -import pyivastest.constants as constants import logging +import multiprocessing +import os import platform +import re + +import pyivastest.constants as constants +from pyivastest.IvasBaseClass import * # make sure we have colored output using shell escapes correctly on windows if platform.system() == "Windows": # Only if we are running on Windows @@ -142,9 +143,9 @@ class IvasScriptArgParser(argparse.ArgumentParser): type=int, ) self.add_argument( - "--timeout", - help="Timeout duration for an individual encoder/decoder run", - default=None, + "--timeout", + help="Timeout duration for an individual encoder/decoder run", + default=None, ) if not minimal: self.add_argument( @@ -577,23 +578,27 @@ def runner_setup(runner, args): end = float(arg) except ValueError: try: - start, end = arg.split(':') + start, end = arg.split(":") start = float(start) end = float(end) except ValueError: raise ValueError(f"Given duration string {arg} is invalid") - + runner.end_time = end runner.start_time = start if "fer_file" in args.keys() or "ber_file" in args.keys(): # assert that the eid-xor tool is there - bin_ext="" + bin_ext = "" if platform.system() == "Windows": - bin_ext=".exe" - eid_xor_path = os.path.join(runner.config["utilPath"], "".join(["eid-xor", bin_ext])) + bin_ext = ".exe" + eid_xor_path = os.path.join( + runner.config["utilPath"], "".join(["eid-xor", bin_ext]) + ) if not os.path.isfile(eid_xor_path): - raise FileNotFoundError(f"Could not find {eid_xor_path} (needed for error pattern insertion)") + raise FileNotFoundError( + f"Could not find {eid_xor_path} (needed for error pattern insertion)" + ) if args["fer_file"]: fer_suffix = "fer_{}".format( @@ -688,7 +693,7 @@ def runner_setup(runner, args): metadata_files = list() if args["ism_metadata_files"] != []: for f in args["ism_metadata_files"]: - md_f = f + md_f = f if os.path.isfile(f): md_f = os.path.abspath(f) metadata_files.append(md_f) @@ -715,7 +720,9 @@ def analyzer_setup(analyzer, args): # assert that the eid-xor tool is there eid_xor_path = os.path.join(analyzer.config["utilPath"], "eid-xor") if not os.path.isfile(eid_xor_path): - raise FileNotFoundError(f"Could not find {eid_xor_path} (needed for error pattern insertion)") + raise FileNotFoundError( + f"Could not find {eid_xor_path} (needed for error pattern insertion)" + ) if args["fer_file"]: fer_suffix = "fer_{}".format( diff --git a/scripts/pyivastest/IvasSvnBuilder.py b/scripts/pyivastest/IvasSvnBuilder.py index e57eb210da..ca4859ffd6 100644 --- a/scripts/pyivastest/IvasSvnBuilder.py +++ b/scripts/pyivastest/IvasSvnBuilder.py @@ -30,24 +30,24 @@ the United Nations Convention on Contracts on the International Sales of Goods. """ -import re import fileinput +import json +import logging import os +import platform +import re import shutil import subprocess -import platform -import json +import urllib.parse import xml.etree.ElementTree -import logging from getpass import getpass -import urllib.parse from multiprocessing import cpu_count -from pyivastest.IvasModeRunner import * -from pyivastest.IvasModeAnalyzer import * +import pyivastest.constants as constants import pyivastest.ivas_svn as svn from pyivastest.IvasBaseClass import * -import pyivastest.constants as constants +from pyivastest.IvasModeAnalyzer import * +from pyivastest.IvasModeRunner import * class IvasBuilder(IvasBaseClass): @@ -60,7 +60,7 @@ class IvasBuilder(IvasBaseClass): enable_logging=False, console_logger_level="", logger_name="IvasBuilder", - log_level=logging.DEBUG + log_level=logging.DEBUG, ): super().__init__( enable_logging=enable_logging, @@ -307,45 +307,44 @@ class IvasBuilder(IvasBaseClass): # remove also in the target directory if it exists if os.path.abspath(make_dir) != os.path.abspath(sub_dir): if os.path.exists( - os.path.join(sub_dir, "".join(["IVAS_cod", self.binary_ext])) + os.path.join(sub_dir, "".join(["IVAS_cod", self.binary_ext])) ): os.remove(os.path.join(sub_dir, "".join(["IVAS_cod", self.binary_ext]))) if os.path.exists( - os.path.join(sub_dir, "".join(["IVAS_dec", self.binary_ext])) + os.path.join(sub_dir, "".join(["IVAS_dec", self.binary_ext])) ): os.remove(os.path.join(sub_dir, "".join(["IVAS_dec", self.binary_ext]))) if os.path.exists( - os.path.join(sub_dir, "".join(["EVS_cod", self.binary_ext])) + os.path.join(sub_dir, "".join(["EVS_cod", self.binary_ext])) ): os.remove(os.path.join(sub_dir, "".join(["EVS_cod", self.binary_ext]))) if os.path.exists( - os.path.join(sub_dir, "".join(["EVS_dec", self.binary_ext])) + os.path.join(sub_dir, "".join(["EVS_dec", self.binary_ext])) ): os.remove(os.path.join(sub_dir, "".join(["EVS_dec", self.binary_ext]))) - build_success = -1 if self.system == "Windows": - make_sln = os.path.join(make_dir, "Workspace_msvc", "Workspace_msvc.sln") - clean_cmd = [self.msbuild, make_sln, "/t:clean"] - build_log.write(" ".join(clean_cmd)) - build_log.write("\n") - make_cmd = [self.msbuild, make_sln] + make_options - build_result = subprocess.run( - clean_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE - ) - build_log.write(build_result.stderr.decode("cp1252")) - build_log.write(build_result.stderr.decode("cp1252")) - build_log.write(" ".join(make_cmd)) - build_log.write("\n") - build_result = subprocess.run( - list(filter(None, make_cmd)), - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - ) - build_success = build_result.returncode - build_log.write(build_result.stderr.decode("cp1252")) - build_log.write(build_result.stderr.decode("cp1252")) + make_sln = os.path.join(make_dir, "Workspace_msvc", "Workspace_msvc.sln") + clean_cmd = [self.msbuild, make_sln, "/t:clean"] + build_log.write(" ".join(clean_cmd)) + build_log.write("\n") + make_cmd = [self.msbuild, make_sln] + make_options + build_result = subprocess.run( + clean_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE + ) + build_log.write(build_result.stderr.decode("cp1252")) + build_log.write(build_result.stderr.decode("cp1252")) + build_log.write(" ".join(make_cmd)) + build_log.write("\n") + build_result = subprocess.run( + list(filter(None, make_cmd)), + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) + build_success = build_result.returncode + build_log.write(build_result.stderr.decode("cp1252")) + build_log.write(build_result.stderr.decode("cp1252")) else: clean_cmd = ["make", "-C", make_dir, "clean"] build_log.write(" ".join(clean_cmd)) @@ -477,7 +476,7 @@ class IvasSvnBuilder(IvasBuilder): console_logger_level=console_logger_level, logger_name=logger_name, log_level=log_level, - msbuild=msbuild + msbuild=msbuild, ) self.svn_url = svn_url # check if we have a complete url or just the path part @@ -705,7 +704,7 @@ class IvasBuilderAndRunner(IvasBaseClass): console_logger_level=console_logger_level, logger_name=".".join([logger_name, "builder"]), log_level=log_level, - msbuild=msbuild + msbuild=msbuild, ) elif svn_url: self.builder = IvasSvnBuilder( @@ -718,7 +717,7 @@ class IvasBuilderAndRunner(IvasBaseClass): console_logger_level=console_logger_level, logger_name=".".join([logger_name, "svnbuilder"]), log_level=log_level, - msbuild=msbuild + msbuild=msbuild, ) self.build_and_run_dict = {} self.site_config = site_config @@ -756,7 +755,7 @@ class IvasBuilderAndRunner(IvasBaseClass): console_logger_level=console_logger_level, logger_name=logger_name, log_level=log_level, - msbuild=msbuild + msbuild=msbuild, ) def add_build_and_run_config( @@ -1118,7 +1117,9 @@ class IvasBuilderAndRunner(IvasBaseClass): ret_val = 0 if self.build_and_run_dict[cfg_name]["analyzer"].get_errors: failed_modes = self.build_and_run_dict[cfg_name]["runner"].failed_modes - _, n_runtime_err = self.build_and_run_dict[cfg_name]["analyzer"].get_errors(failed_modes) + _, n_runtime_err = self.build_and_run_dict[cfg_name][ + "analyzer" + ].get_errors(failed_modes) ret_val = int(n_runtime_err > 0) return ret_val @@ -1189,7 +1190,7 @@ class IvasBuilderAndRunner(IvasBaseClass): n_cpus = cpu_count() # do not use all cores to avoid weird getting-stuck issues observed on Mac... - make_options = ["-j" ,f"{n_cpus - 2}"] + make_options = ["-j", f"{n_cpus - 2}"] run_tool = "" run_env = dict() if defines_to_enable is None: @@ -1207,7 +1208,9 @@ class IvasBuilderAndRunner(IvasBaseClass): # for undefined behaviou sanitizer, pass suppression file if given if clang_n == "3" and usan_supp_file is not None: - run_env["UBSAN_OPTIONS"] = f"suppressions={usan_supp_file},report_error_type=1" + run_env["UBSAN_OPTIONS"] = ( + f"suppressions={usan_supp_file},report_error_type=1" + ) elif check == "VALGRIND": defines_to_disable_check.extend(["RAM_COUNTING_TOOL"]) diff --git a/scripts/pyivastest/__init__.py b/scripts/pyivastest/__init__.py index 866d29f48d..5ab768973f 100644 --- a/scripts/pyivastest/__init__.py +++ b/scripts/pyivastest/__init__.py @@ -28,7 +28,6 @@ the United Nations Convention on Contracts on the International Sales of Goods. """ - """ pyivastest ==== @@ -41,11 +40,13 @@ Imports functions class """ -from . import constants -from . import IvasBaseClass -from . import IvasModeAnalyzer -from . import IvasModeCollector -from . import IvasModeRunner -from . import IvasScriptsCommon -from . import IvasSvnBuilder -from . import ivas_svn +from . import ( + IvasBaseClass, + IvasModeAnalyzer, + IvasModeCollector, + IvasModeRunner, + IvasScriptsCommon, + IvasSvnBuilder, + constants, + ivas_svn, +) diff --git a/scripts/pyivastest/constants.py b/scripts/pyivastest/constants.py index 287dad73d9..5cdf733da1 100644 --- a/scripts/pyivastest/constants.py +++ b/scripts/pyivastest/constants.py @@ -41,7 +41,10 @@ SCRIPTS_BASE_DIR = os.path.realpath( ) SCRIPTS_CONFIGS_DIR = os.path.realpath(os.path.join(SCRIPTS_BASE_DIR, "config")) SW_FILES_BASE_DIR = os.path.realpath( - os.path.join(os.path.dirname(__file__), "../switchPaths/",) + os.path.join( + os.path.dirname(__file__), + "../switchPaths/", + ) ) OC_TO_NCHANNELS = { "MONO": 1, @@ -65,9 +68,23 @@ OC_TO_NCHANNELS = { "MASA1TC": 1, "MASA2TC": 2, } -DECODER_OUTPUT_CONFIGS = {"MONO", "STEREO", "BINAURAL", "BINAURAL_ROOM_IR", "BINAURAL_ROOM_REVERB", "5_1", "7_1", "5_1_4", "5_1_2", - "7_1_4", "FOA", "HOA2", "HOA3", "EXT"} +DECODER_OUTPUT_CONFIGS = { + "MONO", + "STEREO", + "BINAURAL", + "BINAURAL_ROOM_IR", + "BINAURAL_ROOM_REVERB", + "5_1", + "7_1", + "5_1_4", + "5_1_2", + "7_1_4", + "FOA", + "HOA2", + "HOA3", + "EXT", +} LOG_FILE_EXT = ".txt" -LOG_FILE_DIR ="logs" +LOG_FILE_DIR = "logs" DEFAULT_IVAS_FORMAT_FILE = "ivas_modes.json" SPAR_BITRATES = [] diff --git a/scripts/pyivastest/ivas_svn.py b/scripts/pyivastest/ivas_svn.py index c7a2bd6899..a7b1b9eeb0 100644 --- a/scripts/pyivastest/ivas_svn.py +++ b/scripts/pyivastest/ivas_svn.py @@ -30,8 +30,8 @@ the United Nations Convention on Contracts on the International Sales of Goods. """ -import urllib import subprocess +import urllib import xml.etree.ElementTree diff --git a/scripts/reverb/generate_acoustic_environments_metadata.py b/scripts/reverb/generate_acoustic_environments_metadata.py index 0982b0f7ae..58017d983b 100644 --- a/scripts/reverb/generate_acoustic_environments_metadata.py +++ b/scripts/reverb/generate_acoustic_environments_metadata.py @@ -37,40 +37,44 @@ # -from bitarray import bitarray import math from enum import Enum -import numpy as np +import numpy as np +from bitarray import bitarray # Set to True to print quantized values print_quantized = False max_quantization_error = { - 'duration' : 0, - 'frequency' : 0, - 'dsr' : 0, - 'distance' : 0, - 'absorption' : 0 + "duration": 0, + "frequency": 0, + "dsr": 0, + "distance": 0, + "absorption": 0, } def update_quantization_error(name, quantized_value, value): if value == 0: if quantized_value != 0: - print(' {}: value = 0, quantized value = {}'.format(name, quantized_value)) + print( + " {}: value = 0, quantized value = {}".format(name, quantized_value) + ) else: - max_quantization_error[name] = max(abs(quantized_value - value) / value, max_quantization_error[name]) + max_quantization_error[name] = max( + abs(quantized_value - value) / value, max_quantization_error[name] + ) if print_quantized: - print(' {}: {}'.format(name, quantized_value)) + print(" {}: {}".format(name, quantized_value)) def get_id_code(id): - code = format(id % 128, '07b') + '0' + code = format(id % 128, "07b") + "0" id //= 128 while id > 0: - code = format(id % 128, '07b') + '1' + code + code = format(id % 128, "07b") + "1" + code id = id // 128 return code @@ -78,79 +82,371 @@ def get_id_code(id): def get_count_or_index_code(n): # 0, 1, ... 63 countOrIndexLoCodes = [ - '0111', '100', '01100', '01101', '01010', '01011', '01000', '01001', '001111', '001110', - '001101', '001100', '001011', '001010', '001001', '001000', '000111', '000110', '000101', '000100', - '000011', '000010', '000001', '000000', '111111', '111110', '111101', '111100', '111011', '111010', - '111001', '111000', '1101111', '1101110', '1101101', '1101100', '1101011', '1101010', '1101001', '1101000', - '1100111', '1100110', '1100101', '1100100', '1100011', '1100010', '1100001', '1100000', '1011111', '1011110', - '1011101', '1011100', '1011011', '1011010', '1011001', '1011000', '1010111', '1010110', '1010101', '1010100', - '1010011', '1010010', '1010001', '1010000'] + "0111", + "100", + "01100", + "01101", + "01010", + "01011", + "01000", + "01001", + "001111", + "001110", + "001101", + "001100", + "001011", + "001010", + "001001", + "001000", + "000111", + "000110", + "000101", + "000100", + "000011", + "000010", + "000001", + "000000", + "111111", + "111110", + "111101", + "111100", + "111011", + "111010", + "111001", + "111000", + "1101111", + "1101110", + "1101101", + "1101100", + "1101011", + "1101010", + "1101001", + "1101000", + "1100111", + "1100110", + "1100101", + "1100100", + "1100011", + "1100010", + "1100001", + "1100000", + "1011111", + "1011110", + "1011101", + "1011100", + "1011011", + "1011010", + "1011001", + "1011000", + "1010111", + "1010110", + "1010101", + "1010100", + "1010011", + "1010010", + "1010001", + "1010000", + ] # 1, 2, ... 15 countOrIndexHiCode = [ - '001', '000', '110', '101', '100', '0111', '0101', '1111', '1110', '01101', - '01001', '01000', '011001', '0110001', '0110000'] + "001", + "000", + "110", + "101", + "100", + "0111", + "0101", + "1111", + "1110", + "01101", + "01001", + "01000", + "011001", + "0110001", + "0110000", + ] assert 0 <= n < 16 * 64 code = countOrIndexLoCodes[n % 64] if n < 64: - code += '0' + code += "0" else: - code += '1' + countOrIndexHiCode[n // 64 - 1] + code += "1" + countOrIndexHiCode[n // 64 - 1] return code def get_duration_code(duration): # 1, 2, ... 30 secondsCode = [ - '0011', '0001', '0000', '1111', '1101', '1100', '1011', '1001', '1000', '01110', - '01101', '01100', '01011', '01001', '01000', '00101', '11101', '11100', '10101', '011111', - '011110', '010101', '001001', '001000', '101001', '0101001', '0101000', '1010001', '10100001', '10100000' ] + "0011", + "0001", + "0000", + "1111", + "1101", + "1100", + "1011", + "1001", + "1000", + "01110", + "01101", + "01100", + "01011", + "01001", + "01000", + "00101", + "11101", + "11100", + "10101", + "011111", + "011110", + "010101", + "001001", + "001000", + "101001", + "0101001", + "0101000", + "1010001", + "10100001", + "10100000", + ] # 0, 0.1, ... 1.0 deciSecondsCode = [ - '110', '100', '101', '0110', '0111', '111', '0100', '0101', '0010', '0011', '000' ] + "110", + "100", + "101", + "0110", + "0111", + "111", + "0100", + "0101", + "0010", + "0011", + "000", + ] # 0, 1, ..., 99 millisecondsCode = [ - '1111010', '1111011', '1111000', '1111001', '1111110', '1111111', '1111100', '1111101', '1110010', '1110011', - '11001', '1110000', '1110001', '1110110', '1110111', '1110100', '1110101', '0101010', '0101011', '0101000', - '10010', '0101001', '0101110', '0101111', '0101100', '0101101', '0100010', '0100011', '0100000', '0100001', - '10011', '0100110', '0100111', '0100100', '0100101', '0111010', '0111011', '0111000', '0111001', '0111110', - '10000', '0111111', '0111100', '0111101', '0110010', '0110011', '0110000', '0110001', '0110110', '0110111', - '10001', '0110100', '0110101', '0001010', '0001011', '0001000', '0001001', '0001110', '0001111', '0001100', - '10110', '0001101', '0000010', '0000011', '0000000', '0000001', '0000110', '0000111', '0000100', '0000101', - '10111', '0011010', '0011011', '0011000', '0011001', '0011110', '0011111', '0011100', '0011101', '0010010', - '10100', '0010011', '0010000', '0010001', '0010110', '0010111', '0010100', '0010101', '1101010', '1101011', - '10101', '1101000', '1101001', '1101110', '1101111', '1101100', '1101101', '1100010', '1100011', '110000' ] + "1111010", + "1111011", + "1111000", + "1111001", + "1111110", + "1111111", + "1111100", + "1111101", + "1110010", + "1110011", + "11001", + "1110000", + "1110001", + "1110110", + "1110111", + "1110100", + "1110101", + "0101010", + "0101011", + "0101000", + "10010", + "0101001", + "0101110", + "0101111", + "0101100", + "0101101", + "0100010", + "0100011", + "0100000", + "0100001", + "10011", + "0100110", + "0100111", + "0100100", + "0100101", + "0111010", + "0111011", + "0111000", + "0111001", + "0111110", + "10000", + "0111111", + "0111100", + "0111101", + "0110010", + "0110011", + "0110000", + "0110001", + "0110110", + "0110111", + "10001", + "0110100", + "0110101", + "0001010", + "0001011", + "0001000", + "0001001", + "0001110", + "0001111", + "0001100", + "10110", + "0001101", + "0000010", + "0000011", + "0000000", + "0000001", + "0000110", + "0000111", + "0000100", + "0000101", + "10111", + "0011010", + "0011011", + "0011000", + "0011001", + "0011110", + "0011111", + "0011100", + "0011101", + "0010010", + "10100", + "0010011", + "0010000", + "0010001", + "0010110", + "0010111", + "0010100", + "0010101", + "1101010", + "1101011", + "10101", + "1101000", + "1101001", + "1101110", + "1101111", + "1101100", + "1101101", + "1100010", + "1100011", + "110000", + ] # 10, 20, ... 990 microsecondsCode = [ - '110111100', '10010', '110111101', '10011', '1101111110', '10000', '1101111111', '10001', '1101111100', '10110', - '1101111101', '10111', '110110010', '10100', '110110011', '10101', '110110000', '001010', '110110001', '001011', - '110110110', '001000', '110110111', '001001', '110110100', '001110', '110110101', '001111', '110011010', '001100', - '110011011', '001101', '110011000', '000010', '110011001', '000011', '110011110', '000000', '110011111', '000001', - '110011100', '000110', '110011101', '000111', '110010010', '000100', '110010011', '000101', '110010000', '011010', - '110010001', '011011', '110010110', '011000', '110010111', '011001', '110010100', '011110', '110010101', '011111', - '110101010', '011100', '110101011', '011101', '110101000', '010010', '110101001', '010011', '110101110', '010000', - '110101111', '010001', '110101100', '010110', '110101101', '010111', '110100010', '010100', '110100011', '010101', - '110100000', '111010', '110100001', '111011', '110100110', '111000', '110100111', '111001', '110100100', '111110', - '110100101', '111111', '110111010', '111100', '110111011', '111101', '110111000', '11000', '110111001' ] - - duration_dus = round(np.float32(duration) * np.float32(100000)) # [deca us] + "110111100", + "10010", + "110111101", + "10011", + "1101111110", + "10000", + "1101111111", + "10001", + "1101111100", + "10110", + "1101111101", + "10111", + "110110010", + "10100", + "110110011", + "10101", + "110110000", + "001010", + "110110001", + "001011", + "110110110", + "001000", + "110110111", + "001001", + "110110100", + "001110", + "110110101", + "001111", + "110011010", + "001100", + "110011011", + "001101", + "110011000", + "000010", + "110011001", + "000011", + "110011110", + "000000", + "110011111", + "000001", + "110011100", + "000110", + "110011101", + "000111", + "110010010", + "000100", + "110010011", + "000101", + "110010000", + "011010", + "110010001", + "011011", + "110010110", + "011000", + "110010111", + "011001", + "110010100", + "011110", + "110010101", + "011111", + "110101010", + "011100", + "110101011", + "011101", + "110101000", + "010010", + "110101001", + "010011", + "110101110", + "010000", + "110101111", + "010001", + "110101100", + "010110", + "110101101", + "010111", + "110100010", + "010100", + "110100011", + "010101", + "110100000", + "111010", + "110100001", + "111011", + "110100110", + "111000", + "110100111", + "111001", + "110100100", + "111110", + "110100101", + "111111", + "110111010", + "111100", + "110111011", + "111101", + "110111000", + "11000", + "110111001", + ] + + duration_dus = round(np.float32(duration) * np.float32(100000)) # [deca us] quantized_duration = round(np.float32(duration), 5) - update_quantization_error('duration', quantized_duration, duration) + update_quantization_error("duration", quantized_duration, duration) - dus = duration_dus # [deca us] - s = dus // 100000 # 0, 1, ... 30 [s] + dus = duration_dus # [deca us] + s = dus // 100000 # 0, 1, ... 30 [s] ms = (dus % 100000) // 100 # 0, 1, ... 999 [ms] - dus = (dus % 100) # 0, 1, ... 99 [deca us] - ds = ms // 100 # 0, 1, ... 9 [deci s] - ms = ms % 100 # 0, 1, ... 99 [ms] + dus = dus % 100 # 0, 1, ... 99 [deca us] + ds = ms // 100 # 0, 1, ... 9 [deci s] + ms = ms % 100 # 0, 1, ... 99 [ms] if s >= 1 and ds == 0: s -= 1 - ds = 10 # 0, 1, ... 10 [deci s] + ds = 10 # 0, 1, ... 10 [deci s] assert 0 <= s <= 30 assert 0 <= ds <= 10 @@ -160,50 +456,79 @@ def get_duration_code(duration): code = deciSecondsCode[ds] if ms > 0 or dus > 0: - code += '1' + millisecondsCode[ms] + code += "1" + millisecondsCode[ms] if dus > 0: - code += '1' + microsecondsCode[dus - 1] + code += "1" + microsecondsCode[dus - 1] else: - code += '0' + code += "0" else: - code += '0' + code += "0" if s > 0: # long range mode not implemented - code += '1' + secondsCode[s - 1] + code += "1" + secondsCode[s - 1] else: - code += '0' + code += "0" return code def get_frequency_code(frequency): frequencyCode = { - 16.0 : '100011', 20.0 : '001110', 25.0 : '001111', 31.5 : '1001', 40.0 : '001100', - 50.0 : '001101', 63.0 : '0000', 80.0 : '011010', 100.0 : '011011', 125.0 : '0001', - 160.0 : '011000', 200.0 : '011001', 250.0 : '1110', 315.0 : '011110', 400.0 : '011111', - 500.0 : '1111', 630.0 : '011100', 800.0 : '011101', 1000.0 : '1100', 1250.0 : '010010', - 1600.0 : '010011', 2000.0 : '1101', 2500.0 : '010000', 3150.0 : '010001', 4000.0 : '1010', - 5000.0 : '010110', 6300.0 : '010111', 8000.0 : '1011', 10000.0: '010100', 12500.0: '010101', - 16000.0: '0010', 20000.0: '10000', 25000.0: '10001010', 31500.0: '10001011', 40000.0: '1000100', } + 16.0: "100011", + 20.0: "001110", + 25.0: "001111", + 31.5: "1001", + 40.0: "001100", + 50.0: "001101", + 63.0: "0000", + 80.0: "011010", + 100.0: "011011", + 125.0: "0001", + 160.0: "011000", + 200.0: "011001", + 250.0: "1110", + 315.0: "011110", + 400.0: "011111", + 500.0: "1111", + 630.0: "011100", + 800.0: "011101", + 1000.0: "1100", + 1250.0: "010010", + 1600.0: "010011", + 2000.0: "1101", + 2500.0: "010000", + 3150.0: "010001", + 4000.0: "1010", + 5000.0: "010110", + 6300.0: "010111", + 8000.0: "1011", + 10000.0: "010100", + 12500.0: "010101", + 16000.0: "0010", + 20000.0: "10000", + 25000.0: "10001010", + 31500.0: "10001011", + 40000.0: "1000100", + } assert 16 <= frequency <= 40000 if frequency in frequencyCode.keys(): quantized_frequency = frequency - code = frequencyCode[quantized_frequency] + '0' + code = frequencyCode[quantized_frequency] + "0" else: # exact frequency not found, use frequency refinement to approximate f_low = max([k for k in frequencyCode.keys() if k < frequency]) refinement = round(51 * math.log(frequency / f_low, 2)) - 1 if 0 <= refinement <= 15: quantized_frequency = f_low * 2 ** ((refinement + 1) / 51) - code = frequencyCode[f_low] + '1' + format(refinement, '04b') + code = frequencyCode[f_low] + "1" + format(refinement, "04b") else: # choose next lower / higher frequency f_high = min([k for k in frequencyCode.keys() if k > frequency]) quantized_frequency = f_low if refinement < 0 else f_high - code = frequencyCode[quantized_frequency] + '0' + code = frequencyCode[quantized_frequency] + "0" - update_quantization_error('frequency', quantized_frequency, frequency) + update_quantization_error("frequency", quantized_frequency, frequency) return code @@ -211,67 +536,211 @@ def get_frequency_code(frequency): def get_frequency_hop_code(value): index = -1 tolerance = 1e-5 - hop_sizes = [2 ** (1/12), 2 ** (1/6), 2 ** (1/4), 2 ** (1/3), 2 ** (1/2), 2 ** (1), 2 ** (2)] + hop_sizes = [ + 2 ** (1 / 12), + 2 ** (1 / 6), + 2 ** (1 / 4), + 2 ** (1 / 3), + 2 ** (1 / 2), + 2 ** (1), + 2 ** (2), + ] for idx, hop in enumerate(hop_sizes): - if math.isclose(value, hop, rel_tol = tolerance): + if math.isclose(value, hop, rel_tol=tolerance): index = idx break assert 0 <= index <= 6 return [ - '0010', # 2^(1/12) - '0011', # 2^(1/6) - '0000', # 2^(1/4) - '01', # 2^(1/3) - '0001', # 2^(1/2) - '11', # 2^1 - '10'][index] # 2^2 + "0010", # 2^(1/12) + "0011", # 2^(1/6) + "0000", # 2^(1/4) + "01", # 2^(1/3) + "0001", # 2^(1/2) + "11", # 2^1 + "10", + ][ + index + ] # 2^2 def get_dsr_code(dsr): # -150.0, -149.0, ... -10.0 dsrCode = [ - '10001100', '10001101', '100011110', '100011111', '100011100', '100011101', '10000010', '10000011', '10000000', '10000001', - '10000110', '10000111', '10000100', '10000101', '011101010', '011101011', '011101000', '011101001', '011101110', '011101111', - '011101100', '011101101', '011100010', '011100011', '011100000', '011100001', '011100110', '011100111', '011100100', '011100101', - '011111010', '011111011', '011111000', '011111001', '011111110', '011111111', '011111100', '011111101', '011110010', '011110011', - '011110000', '011110001', '011110110', '011110111', '011110100', '011110101', '011001010', '011001011', '011001000', '011001001', - '011001110', '011001111', '011001100', '011001101', '011000010', '011000011', '011000000', '011000001', '011000110', '011000111', - '011000100', '011000101', '011011010', '011011011', '011011000', '011011001', '011011110', '011011111', '011011100', '011011101', - '010100', '010101', '100110', '100111', '100100', '100101', '111010', '111011', '111000', '111001', - '111110', '111111', '111100', '111101', '110010', '110011', '110000', '110001', '110110', '110111', - '110100', '110101', '001010', '001011', '001000', '001001', '001110', '001111', '001100', '001101', - '000010', '000011', '000000', '000001', '000110', '000111', '000100', '000101', '101010', '101011', - '101000', '101001', '101110', '101111', '101100', '101101', '010010', '010011', '010000', '010001', - '010110', '011010010', '011010011', '011010000', '011010001', '011010110', '011010111', '011010100', '011010101', '010111010', - '010111011', '010111000', '010111001', '010111110', '010111111', '010111100', '010111101', '10001010', '10001011', '10001000', - '10001001' ] + "10001100", + "10001101", + "100011110", + "100011111", + "100011100", + "100011101", + "10000010", + "10000011", + "10000000", + "10000001", + "10000110", + "10000111", + "10000100", + "10000101", + "011101010", + "011101011", + "011101000", + "011101001", + "011101110", + "011101111", + "011101100", + "011101101", + "011100010", + "011100011", + "011100000", + "011100001", + "011100110", + "011100111", + "011100100", + "011100101", + "011111010", + "011111011", + "011111000", + "011111001", + "011111110", + "011111111", + "011111100", + "011111101", + "011110010", + "011110011", + "011110000", + "011110001", + "011110110", + "011110111", + "011110100", + "011110101", + "011001010", + "011001011", + "011001000", + "011001001", + "011001110", + "011001111", + "011001100", + "011001101", + "011000010", + "011000011", + "011000000", + "011000001", + "011000110", + "011000111", + "011000100", + "011000101", + "011011010", + "011011011", + "011011000", + "011011001", + "011011110", + "011011111", + "011011100", + "011011101", + "010100", + "010101", + "100110", + "100111", + "100100", + "100101", + "111010", + "111011", + "111000", + "111001", + "111110", + "111111", + "111100", + "111101", + "110010", + "110011", + "110000", + "110001", + "110110", + "110111", + "110100", + "110101", + "001010", + "001011", + "001000", + "001001", + "001110", + "001111", + "001100", + "001101", + "000010", + "000011", + "000000", + "000001", + "000110", + "000111", + "000100", + "000101", + "101010", + "101011", + "101000", + "101001", + "101110", + "101111", + "101100", + "101101", + "010010", + "010011", + "010000", + "010001", + "010110", + "011010010", + "011010011", + "011010000", + "011010001", + "011010110", + "011010111", + "011010100", + "011010101", + "010111010", + "010111011", + "010111000", + "010111001", + "010111110", + "010111111", + "010111100", + "010111101", + "10001010", + "10001011", + "10001000", + "10001001", + ] d = math.log10(dsr) * 10 d = round(d + 150) assert 0 <= d <= 140 - quantized_dsr = np.float32(np.power(np.float32(10), np.float32(d - 150) / np.float32(10))) # C decoder uses float precision math - update_quantization_error('dsr', quantized_dsr, dsr) + quantized_dsr = np.float32( + np.power(np.float32(10), np.float32(d - 150) / np.float32(10)) + ) # C decoder uses float precision math + update_quantization_error("dsr", quantized_dsr, dsr) return dsrCode[d] -def usquant(x,qlow,delta,cbsize): - nbits = math.ceil(math.log2(cbsize)) # nextpow2 - index = max(0,min(cbsize-1, round( ( x - qlow ) / delta ))) - return format(index,'0'+ str(nbits) + 'b') + +def usquant(x, qlow, delta, cbsize): + nbits = math.ceil(math.log2(cbsize)) # nextpow2 + index = max(0, min(cbsize - 1, round((x - qlow) / delta))) + return format(index, "0" + str(nbits) + "b") + def get_angle_code(angle): assert 0 <= angle <= 360 return usquant(angle, 0, 20, 19) + def get_outer_attenuation_code(att): assert 0 <= att <= 1 return usquant(20 * math.log10(att), -90, 3, 31) + class fgdMethod(Enum): - Individual_Frequencies = '00' - Start_Hop_Amount = '01' - Default_Banding = '10' + Individual_Frequencies = "00" + Start_Hop_Amount = "01" + Default_Banding = "10" def get_default_grid_nr_bands(code): @@ -282,51 +751,253 @@ def get_default_grid_nr_bands(code): def get_distance_code(distance, isSmallScene): # 0, 1, ... 99 metersCode = [ - '111101', '110010', '110011', '110000', '110001', '110110', '110111', '110100', '110101', '001010', - '001011', '001000', '001001', '001110', '001111', '001100', '001101', '000010', '000011', '000000', - '000001', '000110', '000111', '000100', '000101', '011010', '011011', '011000', '011001', '011110', - '011111', '011100', '011101', '010010', '010011', '010000', '010001', '010110', '010111', '010100', - '010101', '101010', '101011', '101000', '101001', '101110', '101111', '101100', '101101', '10000', - '1000100', '1000101', '10001110', '10001111', '10001100', '10001101', '10011010', '10011011', '10011000', '10011001', - '10011110', '10011111', '10011100', '10011101', '10010010', '10010011', '10010000', '10010001', '10010110', '10010111', - '10010100', '10010101', '11101010', '11101011', '11101000', '11101001', '11101110', '11101111', '11101100', '11101101', - '11100010', '11100011', '11100000', '11100001', '11100110', '11100111', '11100100', '11100101', '11111010', '11111011', - '11111000', '11111001', '11111110', '11111111', '11111100', '11111101', '11110010', '11110011', '11110000', '11110001' ] + "111101", + "110010", + "110011", + "110000", + "110001", + "110110", + "110111", + "110100", + "110101", + "001010", + "001011", + "001000", + "001001", + "001110", + "001111", + "001100", + "001101", + "000010", + "000011", + "000000", + "000001", + "000110", + "000111", + "000100", + "000101", + "011010", + "011011", + "011000", + "011001", + "011110", + "011111", + "011100", + "011101", + "010010", + "010011", + "010000", + "010001", + "010110", + "010111", + "010100", + "010101", + "101010", + "101011", + "101000", + "101001", + "101110", + "101111", + "101100", + "101101", + "10000", + "1000100", + "1000101", + "10001110", + "10001111", + "10001100", + "10001101", + "10011010", + "10011011", + "10011000", + "10011001", + "10011110", + "10011111", + "10011100", + "10011101", + "10010010", + "10010011", + "10010000", + "10010001", + "10010110", + "10010111", + "10010100", + "10010101", + "11101010", + "11101011", + "11101000", + "11101001", + "11101110", + "11101111", + "11101100", + "11101101", + "11100010", + "11100011", + "11100000", + "11100001", + "11100110", + "11100111", + "11100100", + "11100101", + "11111010", + "11111011", + "11111000", + "11111001", + "11111110", + "11111111", + "11111100", + "11111101", + "11110010", + "11110011", + "11110000", + "11110001", + ] # 0, 1, ... 9 hectometersCode = [ - '000', '001', '110', '111', '100', '101', '0110', '0111', '0100', '0101' ] + "000", + "001", + "110", + "111", + "100", + "101", + "0110", + "0111", + "0100", + "0101", + ] # 1, 2, ... 10 kilometersCode = [ - '10', '011', '001', '000', '111', '0101', '0100', '1101', '11001', '11000' ] + "10", + "011", + "001", + "000", + "111", + "0101", + "0100", + "1101", + "11001", + "11000", + ] # 0, 1, ... 99 centimetersCode = [ - '110010', '110011', '110000', '110001', '110110', '110111', '110100', '110101', '0101010', '0101011', - '0101000', '0101001', '0101110', '0101111', '0101100', '0101101', '0100010', '0100011', '0100000', '0100001', - '0100110', '0100111', '0100100', '0100101', '0111010', '0111011', '0111000', '0111001', '0111110', '0111111', - '0111100', '0111101', '0110010', '0110011', '0110000', '0110001', '0110110', '0110111', '0110100', '0110101', - '0001010', '0001011', '0001000', '0001001', '0001110', '0001111', '0001100', '0001101', '0000010', '0000011', - '0000000', '0000001', '0000110', '0000111', '0000100', '0000101', '0011010', '0011011', '0011000', '0011001', - '0011110', '0011111', '0011100', '0011101', '0010010', '0010011', '0010000', '0010001', '0010110', '0010111', - '0010100', '0010101', '101010', '101011', '101000', '101001', '101110', '101111', '101100', '101101', - '100010', '100011', '100000', '100001', '100110', '100111', '100100', '100101', '1111010', '1111011', - '1111000', '1111001', '1111110', '1111111', '1111100', '1111101', '111010', '111011', '111000', '111001' ] - - distance_cm = round(np.float32(distance) * np.float32(100)) # distance in cm + "110010", + "110011", + "110000", + "110001", + "110110", + "110111", + "110100", + "110101", + "0101010", + "0101011", + "0101000", + "0101001", + "0101110", + "0101111", + "0101100", + "0101101", + "0100010", + "0100011", + "0100000", + "0100001", + "0100110", + "0100111", + "0100100", + "0100101", + "0111010", + "0111011", + "0111000", + "0111001", + "0111110", + "0111111", + "0111100", + "0111101", + "0110010", + "0110011", + "0110000", + "0110001", + "0110110", + "0110111", + "0110100", + "0110101", + "0001010", + "0001011", + "0001000", + "0001001", + "0001110", + "0001111", + "0001100", + "0001101", + "0000010", + "0000011", + "0000000", + "0000001", + "0000110", + "0000111", + "0000100", + "0000101", + "0011010", + "0011011", + "0011000", + "0011001", + "0011110", + "0011111", + "0011100", + "0011101", + "0010010", + "0010011", + "0010000", + "0010001", + "0010110", + "0010111", + "0010100", + "0010101", + "101010", + "101011", + "101000", + "101001", + "101110", + "101111", + "101100", + "101101", + "100010", + "100011", + "100000", + "100001", + "100110", + "100111", + "100100", + "100101", + "1111010", + "1111011", + "1111000", + "1111001", + "1111110", + "1111111", + "1111100", + "1111101", + "111010", + "111011", + "111000", + "111001", + ] + + distance_cm = round(np.float32(distance) * np.float32(100)) # distance in cm quantized_distance = round(np.float32(distance), 2) - update_quantization_error('distance', quantized_distance, distance) + update_quantization_error("distance", quantized_distance, distance) - cm = distance_cm # [cm] - m = cm // 100 # [m] - hm = m // 100 # [hm] - km = hm // 10 # [km] + cm = distance_cm # [cm] + m = cm // 100 # [m] + hm = m // 100 # [hm] + km = hm // 10 # [km] - cm = (cm % 100) # 0, 1, ... 99 [cm] - m = (m % 100) # 0, 1, ... 99 [m] - hm = (hm % 10) # 0, 1, ... 9 [hm] + cm = cm % 100 # 0, 1, ... 99 [cm] + m = m % 100 # 0, 1, ... 99 [m] + hm = hm % 10 # 0, 1, ... 9 [hm] assert 0 <= cm <= 99 assert 0 <= m <= 99 @@ -334,27 +1005,27 @@ def get_distance_code(distance, isSmallScene): assert distance_cm == km * 100000 + hm * 10000 + m * 100 + cm code = metersCode[m] - + if isSmallScene: - assert(hm == km == 0) + assert hm == km == 0 else: # large scenes if hm > 0 or km > 0: # hectometers - code += '1' + hectometersCode[hm] + code += "1" + hectometersCode[hm] while km > 0: # kilometers - code += '1' + kilometersCode[min(km, 10) - 1] + code += "1" + kilometersCode[min(km, 10) - 1] km = km - 10 - code += '0' + code += "0" else: - code += '0' - + code += "0" + # centimeters if cm > 0: - code += '1' + centimetersCode[cm] + code += "1" + centimetersCode[cm] else: - code += '0' + code += "0" return code @@ -365,54 +1036,111 @@ def get_absorption_code(absorption): index = round(absorption * 10.0) quantized_absorption = round(np.float32(absorption), 1) - update_quantization_error('absorption', quantized_absorption, absorption) + update_quantization_error("absorption", quantized_absorption, absorption) - return ['110', '100', '101', '0110', '0111', '111', '0100', '0101', '0010', '0011', '000' ][index] + return [ + "110", + "100", + "101", + "0110", + "0111", + "111", + "0100", + "0101", + "0010", + "0011", + "000", + ][index] # apply function to elements of list and concatenate the resulting strings def concatenate(function, data): - return ''.join([function(d) for d in data]) + return "".join([function(d) for d in data]) def test(): # exercise encoding functions over their supported ranges # save binary output to file so it can be compared against Matlab / C implementations - string = '' + string = "" # count or index encoding string += concatenate(get_count_or_index_code, [n for n in range(16 * 64)]) # duration encoding - string += concatenate(get_duration_code, [d / 1000 for d in range(30 * 1000)]) - string += concatenate(get_duration_code, [d / 10000 for d in range(30 * 1000)]) + string += concatenate(get_duration_code, [d / 1000 for d in range(30 * 1000)]) + string += concatenate(get_duration_code, [d / 10000 for d in range(30 * 1000)]) string += concatenate(get_duration_code, [d / 100000 for d in range(30 * 1000)]) # frequency encoding - string += concatenate(get_frequency_code, - [16 , 20 , 25 , 31.5 , 40 , 50 , 63 , 80 , 100 , 125 , - 160 , 200 , 250 , 315 , 400 , 500 , 630 , 800 , 1000 , 1250 , - 1600 , 2000 , 2500 , 3150 , 4000 , 5000 , 6300 , 8000, 10000, 12500, - 16000, 20000, 25000, 31500, 40000]) + string += concatenate( + get_frequency_code, + [ + 16, + 20, + 25, + 31.5, + 40, + 50, + 63, + 80, + 100, + 125, + 160, + 200, + 250, + 315, + 400, + 500, + 630, + 800, + 1000, + 1250, + 1600, + 2000, + 2500, + 3150, + 4000, + 5000, + 6300, + 8000, + 10000, + 12500, + 16000, + 20000, + 25000, + 31500, + 40000, + ], + ) # frequency hop encoding string += concatenate(get_frequency_hop_code, [index for index in range(7)]) # DSR encoding - string += concatenate(get_dsr_code, [math.pow(10, dsr / 10) for dsr in range(-150, -10 + 1)]) + string += concatenate( + get_dsr_code, [math.pow(10, dsr / 10) for dsr in range(-150, -10 + 1)] + ) # distance encoding - string += concatenate(lambda d : get_distance_code(d, False), [d for d in range(20 * 1000)]) - string += concatenate(lambda d : get_distance_code(d, False), [d / 10 for d in range(20 * 1000)]) - string += concatenate(lambda d : get_distance_code(d, False), [d / 100 for d in range(20 * 1000)]) - string += concatenate(lambda d : get_distance_code(d, True), [d / 100 for d in range(10 * 1000)]) + string += concatenate( + lambda d: get_distance_code(d, False), [d for d in range(20 * 1000)] + ) + string += concatenate( + lambda d: get_distance_code(d, False), [d / 10 for d in range(20 * 1000)] + ) + string += concatenate( + lambda d: get_distance_code(d, False), [d / 100 for d in range(20 * 1000)] + ) + string += concatenate( + lambda d: get_distance_code(d, True), [d / 100 for d in range(10 * 1000)] + ) # absorption encoding string += concatenate(get_absorption_code, [a / 100 for a in range(100 + 1)]) - data = bitarray(string, endian='big') + data = bitarray(string, endian="big") - file = open('test_python.dat', 'wb') + file = open("test_python.dat", "wb") data.tofile(file) file.close() @@ -421,93 +1149,272 @@ def generate_reverb_payload_equivalent_to_rend_config_renderer_cfg(): # based on config_renderer.cfg # note that because of encoding, resolution is lost and behaviour may not be bit-exact compared to .cfg file based values data = bitarray( - '1' # hasAcEnv (see IVAS acoustic environment payload syntax document) - + get_count_or_index_code(1) # fgdNrGrids + "1" # hasAcEnv (see IVAS acoustic environment payload syntax document) + + get_count_or_index_code(1) # fgdNrGrids + fgdMethod.Individual_Frequencies.value # fgdMethod - + get_count_or_index_code(31) # fgdNrBands - - + concatenate(get_frequency_code, # fgdCenterFreq - [ 20.0, 25.0, 31.5, 40.0, 50.0, 63.0, 80.0, 100.0, 125.0, 160.0, - 200.0, 250.0, 315.0, 400.0, 500.0, 630.0, 800.0, 1000.0, 1250.0, 1600.0, - 2000.0, 2500.0, 3150.0, 4000.0, 5000.0, 6300.0, 8000.0, 10000.0, 12500.0, 16000.0, - 20000.0 ]) - - + get_count_or_index_code(1) # AcousticEnvCount - + get_id_code(0) # ID - + get_count_or_index_code(0) # FreqGridID - + get_duration_code(0.1) # (input)Predelay - - + concatenate(get_duration_code, # RT60 - [ 1.3622, 1.4486, 1.3168, 1.5787, 1.4766, 1.3954, 1.2889, 1.3462, 1.0759, 1.0401, - 1.0970, 1.0850, 1.0910, 1.0404, 1.0499, 1.0699, 1.1028, 1.1714, 1.1027, 1.0666, - 1.0550, 1.0553, 1.0521, 1.0569, 1.0421, 0.97822, 0.80487, 0.75944, 0.71945, 0.61682, - 0.60031 ]) - - + concatenate(get_dsr_code, # DSR - [ 1.9952632e-08, 1.9952632e-08, 1.2589251e-08, 1.5848926e-08, 1.2589251e-08, 1.9952632e-08, 2.511887e-08, 3.9810708e-08, 1e-07, 1.9952633e-07, - 3.981071e-07, 6.3095763e-07, 7.943284e-07, 6.3095763e-07, 5.01187e-07, 5.01187e-07, 6.3095763e-07, 6.3095763e-07, 7.943284e-07, 6.3095763e-07, - 5.01187e-07, 6.3095763e-07, 6.3095763e-07, 6.3095763e-07, 5.01187e-07, 2.511887e-07, 1.2589251e-07, 1e-07, 6.309576e-08, 3.1622776e-08, - 2.511887e-08 ]) - + '0' # hasEarlyReflections - + '0' # hasDirectivity - , endian='big') - - file = open('rend_config_renderer.dat', 'wb') + + get_count_or_index_code(31) # fgdNrBands + + concatenate( + get_frequency_code, # fgdCenterFreq + [ + 20.0, + 25.0, + 31.5, + 40.0, + 50.0, + 63.0, + 80.0, + 100.0, + 125.0, + 160.0, + 200.0, + 250.0, + 315.0, + 400.0, + 500.0, + 630.0, + 800.0, + 1000.0, + 1250.0, + 1600.0, + 2000.0, + 2500.0, + 3150.0, + 4000.0, + 5000.0, + 6300.0, + 8000.0, + 10000.0, + 12500.0, + 16000.0, + 20000.0, + ], + ) + + get_count_or_index_code(1) # AcousticEnvCount + + get_id_code(0) # ID + + get_count_or_index_code(0) # FreqGridID + + get_duration_code(0.1) # (input)Predelay + + concatenate( + get_duration_code, # RT60 + [ + 1.3622, + 1.4486, + 1.3168, + 1.5787, + 1.4766, + 1.3954, + 1.2889, + 1.3462, + 1.0759, + 1.0401, + 1.0970, + 1.0850, + 1.0910, + 1.0404, + 1.0499, + 1.0699, + 1.1028, + 1.1714, + 1.1027, + 1.0666, + 1.0550, + 1.0553, + 1.0521, + 1.0569, + 1.0421, + 0.97822, + 0.80487, + 0.75944, + 0.71945, + 0.61682, + 0.60031, + ], + ) + + concatenate( + get_dsr_code, # DSR + [ + 1.9952632e-08, + 1.9952632e-08, + 1.2589251e-08, + 1.5848926e-08, + 1.2589251e-08, + 1.9952632e-08, + 2.511887e-08, + 3.9810708e-08, + 1e-07, + 1.9952633e-07, + 3.981071e-07, + 6.3095763e-07, + 7.943284e-07, + 6.3095763e-07, + 5.01187e-07, + 5.01187e-07, + 6.3095763e-07, + 6.3095763e-07, + 7.943284e-07, + 6.3095763e-07, + 5.01187e-07, + 6.3095763e-07, + 6.3095763e-07, + 6.3095763e-07, + 5.01187e-07, + 2.511887e-07, + 1.2589251e-07, + 1e-07, + 6.309576e-08, + 3.1622776e-08, + 2.511887e-08, + ], + ) + + "0" # hasEarlyReflections + + "0", # hasDirectivity + endian="big", + ) + + file = open("rend_config_renderer.dat", "wb") data.tofile(file) file.close() + def generate_reverb_payload_equivalent_to_rend_config_renderer_cfg_plus_early_reflections_no_listener_origin(): # based on config_renderer.cfg # note that because of encoding, resolution is lost and behaviour may not be bit-exact compared to .cfg file based values data = bitarray( - '1' # hasAcEnv - + get_count_or_index_code(2) # fgdNrGrids + "1" + get_count_or_index_code(2) # hasAcEnv # fgdNrGrids # frequency grid #1 + fgdMethod.Individual_Frequencies.value # fgdMethod - + get_count_or_index_code(1) # fgdNrBands - - + concatenate(get_frequency_code, # fgdCenterFreq - [ 10000.0 ]) - - # frequency grid #2 + + get_count_or_index_code(1) # fgdNrBands + + concatenate(get_frequency_code, [10000.0]) # fgdCenterFreq + # frequency grid #2 + fgdMethod.Individual_Frequencies.value # fgdMethod - + get_count_or_index_code(31) # fgdNrBands - - + concatenate(get_frequency_code, # fgdCenterFreq - [ 20.0, 25.0, 31.5, 40.0, 50.0, 63.0, 80.0, 100.0, 125.0, 160.0, - 200.0, 250.0, 315.0, 400.0, 500.0, 630.0, 800.0, 1000.0, 1250.0, 1600.0, - 2000.0, 2500.0, 3150.0, 4000.0, 5000.0, 6300.0, 8000.0, 10000.0, 12500.0, 16000.0, - 20000.0 ]) - - + get_count_or_index_code(1) # AcousticEnvCount - + get_id_code(0) # ID - + get_count_or_index_code(0) # FreqGridID - + get_duration_code(0.1) # (input)Predelay - - + concatenate(get_duration_code, # RT60 - [ 1.3622, 1.4486, 1.3168, 1.5787, 1.4766, 1.3954, 1.2889, 1.3462, 1.0759, 1.0401, - 1.0970, 1.0850, 1.0910, 1.0404, 1.0499, 1.0699, 1.1028, 1.1714, 1.1027, 1.0666, - 1.0550, 1.0553, 1.0521, 1.0569, 1.0421, 0.97822, 0.80487, 0.75944, 0.71945, 0.61682, - 0.60031 ]) - - + concatenate(get_dsr_code, # DSR - [ 1.9952632e-08, 1.9952632e-08, 1.2589251e-08, 1.5848926e-08, 1.2589251e-08, 1.9952632e-08, 2.511887e-08, 3.9810708e-08, 1e-07, 1.9952633e-07, - 3.981071e-07, 6.3095763e-07, 7.943284e-07, 6.3095763e-07, 5.01187e-07, 5.01187e-07, 6.3095763e-07, 6.3095763e-07, 7.943284e-07, 6.3095763e-07, - 5.01187e-07, 6.3095763e-07, 6.3095763e-07, 6.3095763e-07, 5.01187e-07, 2.511887e-07, 1.2589251e-07, 1e-07, 6.309576e-08, 3.1622776e-08, - 2.511887e-08 ]) - - + '1' # hasEarlyReflections - + concatenate(lambda d : get_distance_code(d, True), - [ 3.0, 4.0, 2.5 ]) # erSize (room dimensions) - + concatenate(get_absorption_code, # erAbsCoeff - [ 0.8, 0.8, 0.8, 0.8, 0.2, 0.6 ]) - + '0' # hasListenerOrigin - + '0' # lowComplexity - - + '0' # hasDirectivity - , endian='big') - - file = open('rend_config_renderer_cfg_plus_early_reflections_no_listener_origin.dat', 'wb') + + get_count_or_index_code(31) # fgdNrBands + + concatenate( + get_frequency_code, # fgdCenterFreq + [ + 20.0, + 25.0, + 31.5, + 40.0, + 50.0, + 63.0, + 80.0, + 100.0, + 125.0, + 160.0, + 200.0, + 250.0, + 315.0, + 400.0, + 500.0, + 630.0, + 800.0, + 1000.0, + 1250.0, + 1600.0, + 2000.0, + 2500.0, + 3150.0, + 4000.0, + 5000.0, + 6300.0, + 8000.0, + 10000.0, + 12500.0, + 16000.0, + 20000.0, + ], + ) + + get_count_or_index_code(1) # AcousticEnvCount + + get_id_code(0) # ID + + get_count_or_index_code(0) # FreqGridID + + get_duration_code(0.1) # (input)Predelay + + concatenate( + get_duration_code, # RT60 + [ + 1.3622, + 1.4486, + 1.3168, + 1.5787, + 1.4766, + 1.3954, + 1.2889, + 1.3462, + 1.0759, + 1.0401, + 1.0970, + 1.0850, + 1.0910, + 1.0404, + 1.0499, + 1.0699, + 1.1028, + 1.1714, + 1.1027, + 1.0666, + 1.0550, + 1.0553, + 1.0521, + 1.0569, + 1.0421, + 0.97822, + 0.80487, + 0.75944, + 0.71945, + 0.61682, + 0.60031, + ], + ) + + concatenate( + get_dsr_code, # DSR + [ + 1.9952632e-08, + 1.9952632e-08, + 1.2589251e-08, + 1.5848926e-08, + 1.2589251e-08, + 1.9952632e-08, + 2.511887e-08, + 3.9810708e-08, + 1e-07, + 1.9952633e-07, + 3.981071e-07, + 6.3095763e-07, + 7.943284e-07, + 6.3095763e-07, + 5.01187e-07, + 5.01187e-07, + 6.3095763e-07, + 6.3095763e-07, + 7.943284e-07, + 6.3095763e-07, + 5.01187e-07, + 6.3095763e-07, + 6.3095763e-07, + 6.3095763e-07, + 5.01187e-07, + 2.511887e-07, + 1.2589251e-07, + 1e-07, + 6.309576e-08, + 3.1622776e-08, + 2.511887e-08, + ], + ) + + "1" # hasEarlyReflections + + concatenate( + lambda d: get_distance_code(d, True), [3.0, 4.0, 2.5] + ) # erSize (room dimensions) + + concatenate( + get_absorption_code, [0.8, 0.8, 0.8, 0.8, 0.2, 0.6] # erAbsCoeff + ) + + "0" # hasListenerOrigin + + "0" # lowComplexity + + "0", # hasDirectivity + endian="big", + ) + + file = open( + "rend_config_renderer_cfg_plus_early_reflections_no_listener_origin.dat", "wb" + ) data.tofile(file) file.close() @@ -516,164 +1423,431 @@ def generate_reverb_payload_equivalent_to_rend_config_renderer_cfg_plus_early_re # based on config_renderer.cfg # note that because of encoding, resolution is lost and behaviour may not be bit-exact compared to .cfg file based values data = bitarray( - '1' # hasAcEnv - + get_count_or_index_code(2) # fgdNrGrids + "1" + get_count_or_index_code(2) # hasAcEnv # fgdNrGrids # frequency grid #1 + fgdMethod.Individual_Frequencies.value # fgdMethod - + get_count_or_index_code(1) # fgdNrBands - - + concatenate(get_frequency_code, # fgdCenterFreq - [ 10000.0 ]) - - # frequency grid #2 + + get_count_or_index_code(1) # fgdNrBands + + concatenate(get_frequency_code, [10000.0]) # fgdCenterFreq + # frequency grid #2 + fgdMethod.Individual_Frequencies.value # fgdMethod - + get_count_or_index_code(31) # fgdNrBands - - + concatenate(get_frequency_code, # fgdCenterFreq - [ 20.0, 25.0, 31.5, 40.0, 50.0, 63.0, 80.0, 100.0, 125.0, 160.0, - 200.0, 250.0, 315.0, 400.0, 500.0, 630.0, 800.0, 1000.0, 1250.0, 1600.0, - 2000.0, 2500.0, 3150.0, 4000.0, 5000.0, 6300.0, 8000.0, 10000.0, 12500.0, 16000.0, - 20000.0 ]) - - + get_count_or_index_code(1) # AcousticEnvCount - + get_id_code(0) # ID - + get_count_or_index_code(0) # FreqGridID - + get_duration_code(0.1) # (input)Predelay - - + concatenate(get_duration_code, # RT60 - [ 1.3622, 1.4486, 1.3168, 1.5787, 1.4766, 1.3954, 1.2889, 1.3462, 1.0759, 1.0401, - 1.0970, 1.0850, 1.0910, 1.0404, 1.0499, 1.0699, 1.1028, 1.1714, 1.1027, 1.0666, - 1.0550, 1.0553, 1.0521, 1.0569, 1.0421, 0.97822, 0.80487, 0.75944, 0.71945, 0.61682, - 0.60031 ]) - - + concatenate(get_dsr_code, # DSR - [ 1.9952632e-08, 1.9952632e-08, 1.2589251e-08, 1.5848926e-08, 1.2589251e-08, 1.9952632e-08, 2.511887e-08, 3.9810708e-08, 1e-07, 1.9952633e-07, - 3.981071e-07, 6.3095763e-07, 7.943284e-07, 6.3095763e-07, 5.01187e-07, 5.01187e-07, 6.3095763e-07, 6.3095763e-07, 7.943284e-07, 6.3095763e-07, - 5.01187e-07, 6.3095763e-07, 6.3095763e-07, 6.3095763e-07, 5.01187e-07, 2.511887e-07, 1.2589251e-07, 1e-07, 6.309576e-08, 3.1622776e-08, - 2.511887e-08 ]) - - + '1' # hasEarlyReflections - + concatenate(lambda code : get_distance_code(code, True), - [ 3.0, 4.0, 2.5 ]) # erSize (room dimensions) - + concatenate(get_absorption_code, # erAbsCoeff - [ 0.8, 0.8, 0.8, 0.8, 0.2, 0.6 ]) - - + '1' # hasListenerOrigin - + '1' # isPositiveX - + '0' # isPositiveY - + concatenate(lambda d : get_distance_code(d, True), - [ 0.5, 0.5, 1.5 ]) # erListenerOrigin (x, y, z) - + '1' # lowComplexity - + '0' # hasDirectivity - , endian='big') - - file = open('rend_config_renderer_cfg_plus_early_reflections_listener_origin.dat', 'wb') + + get_count_or_index_code(31) # fgdNrBands + + concatenate( + get_frequency_code, # fgdCenterFreq + [ + 20.0, + 25.0, + 31.5, + 40.0, + 50.0, + 63.0, + 80.0, + 100.0, + 125.0, + 160.0, + 200.0, + 250.0, + 315.0, + 400.0, + 500.0, + 630.0, + 800.0, + 1000.0, + 1250.0, + 1600.0, + 2000.0, + 2500.0, + 3150.0, + 4000.0, + 5000.0, + 6300.0, + 8000.0, + 10000.0, + 12500.0, + 16000.0, + 20000.0, + ], + ) + + get_count_or_index_code(1) # AcousticEnvCount + + get_id_code(0) # ID + + get_count_or_index_code(0) # FreqGridID + + get_duration_code(0.1) # (input)Predelay + + concatenate( + get_duration_code, # RT60 + [ + 1.3622, + 1.4486, + 1.3168, + 1.5787, + 1.4766, + 1.3954, + 1.2889, + 1.3462, + 1.0759, + 1.0401, + 1.0970, + 1.0850, + 1.0910, + 1.0404, + 1.0499, + 1.0699, + 1.1028, + 1.1714, + 1.1027, + 1.0666, + 1.0550, + 1.0553, + 1.0521, + 1.0569, + 1.0421, + 0.97822, + 0.80487, + 0.75944, + 0.71945, + 0.61682, + 0.60031, + ], + ) + + concatenate( + get_dsr_code, # DSR + [ + 1.9952632e-08, + 1.9952632e-08, + 1.2589251e-08, + 1.5848926e-08, + 1.2589251e-08, + 1.9952632e-08, + 2.511887e-08, + 3.9810708e-08, + 1e-07, + 1.9952633e-07, + 3.981071e-07, + 6.3095763e-07, + 7.943284e-07, + 6.3095763e-07, + 5.01187e-07, + 5.01187e-07, + 6.3095763e-07, + 6.3095763e-07, + 7.943284e-07, + 6.3095763e-07, + 5.01187e-07, + 6.3095763e-07, + 6.3095763e-07, + 6.3095763e-07, + 5.01187e-07, + 2.511887e-07, + 1.2589251e-07, + 1e-07, + 6.309576e-08, + 3.1622776e-08, + 2.511887e-08, + ], + ) + + "1" # hasEarlyReflections + + concatenate( + lambda code: get_distance_code(code, True), [3.0, 4.0, 2.5] + ) # erSize (room dimensions) + + concatenate( + get_absorption_code, [0.8, 0.8, 0.8, 0.8, 0.2, 0.6] # erAbsCoeff + ) + + "1" # hasListenerOrigin + + "1" # isPositiveX + + "0" # isPositiveY + + concatenate( + lambda d: get_distance_code(d, True), [0.5, 0.5, 1.5] + ) # erListenerOrigin (x, y, z) + + "1" # lowComplexity + + "0", # hasDirectivity + endian="big", + ) + + file = open( + "rend_config_renderer_cfg_plus_early_reflections_listener_origin.dat", "wb" + ) data.tofile(file) file.close() + def generate_reverb_payload_equivalent_to_rend_config_renderer_directivity_cfg(): # based on rend_config_renderer_directivity.cfg # note that because of encoding, resolution is lost and behaviour may not be bit-exact compared to .cfg file based values data = bitarray( - '1' # hasAcEnv - + get_count_or_index_code(1) # fgdNrGrids + "1" # hasAcEnv + + get_count_or_index_code(1) # fgdNrGrids + fgdMethod.Individual_Frequencies.value # fgdMethod - + get_count_or_index_code(31) # fgdNrBands - - + concatenate(get_frequency_code, # fgdCenterFreq - [ 20.0, 25.0, 31.5, 40.0, 50.0, 63.0, 80.0, 100.0, 125.0, 160.0, - 200.0, 250.0, 315.0, 400.0, 500.0, 630.0, 800.0, 1000.0, 1250.0, 1600.0, - 2000.0, 2500.0, 3150.0, 4000.0, 5000.0, 6300.0, 8000.0, 10000.0, 12500.0, 16000.0, - 20000.0 ]) - - + get_count_or_index_code(1) # AcousticEnvCount - + get_id_code(0) # ID - + get_count_or_index_code(0) # FreqGridID - + get_duration_code(0.1) # (input)Predelay - - + concatenate(get_duration_code, # RT60 - [ 1.3622, 1.4486, 1.3168, 1.5787, - 1.4766, 1.3954, 1.2889, 1.3462, - 1.0759, 1.0401, 1.0970, 1.0850, - 1.0910, 1.0404, 1.0499, 1.0699, - 1.1028, 1.1714, 1.1027, 1.0666, - 1.0550, 1.0553, 1.0521, 1.0569, - 1.0421, 0.97822, 0.80487, 0.75944, - 0.71945, 0.61682, 0.60031 ]) - - + concatenate(get_dsr_code, # DSR - [ 1.9952632e-08, 1.9952632e-08, 1.2589251e-08, 1.5848926e-08, 1.2589251e-08, 1.9952632e-08, 2.511887e-08, 3.9810708e-08, 1e-07, 1.9952633e-07, - 3.981071e-07, 6.3095763e-07, 7.943284e-07, 6.3095763e-07, 5.01187e-07, 5.01187e-07, 6.3095763e-07, 6.3095763e-07, 7.943284e-07, 6.3095763e-07, - 5.01187e-07, 6.3095763e-07, 6.3095763e-07, 6.3095763e-07, 5.01187e-07, 2.511887e-07, 1.2589251e-07, 1e-07, 6.309576e-08, 3.1622776e-08, - 2.511887e-08 ]) - - + '0' # hasEarlyReflections - + '1' # hasDirectivity - + get_id_code(1) # Number of directivity patterns - + get_id_code(0) # directivity ID + + get_count_or_index_code(31) # fgdNrBands + + concatenate( + get_frequency_code, # fgdCenterFreq + [ + 20.0, + 25.0, + 31.5, + 40.0, + 50.0, + 63.0, + 80.0, + 100.0, + 125.0, + 160.0, + 200.0, + 250.0, + 315.0, + 400.0, + 500.0, + 630.0, + 800.0, + 1000.0, + 1250.0, + 1600.0, + 2000.0, + 2500.0, + 3150.0, + 4000.0, + 5000.0, + 6300.0, + 8000.0, + 10000.0, + 12500.0, + 16000.0, + 20000.0, + ], + ) + + get_count_or_index_code(1) # AcousticEnvCount + + get_id_code(0) # ID + + get_count_or_index_code(0) # FreqGridID + + get_duration_code(0.1) # (input)Predelay + + concatenate( + get_duration_code, # RT60 + [ + 1.3622, + 1.4486, + 1.3168, + 1.5787, + 1.4766, + 1.3954, + 1.2889, + 1.3462, + 1.0759, + 1.0401, + 1.0970, + 1.0850, + 1.0910, + 1.0404, + 1.0499, + 1.0699, + 1.1028, + 1.1714, + 1.1027, + 1.0666, + 1.0550, + 1.0553, + 1.0521, + 1.0569, + 1.0421, + 0.97822, + 0.80487, + 0.75944, + 0.71945, + 0.61682, + 0.60031, + ], + ) + + concatenate( + get_dsr_code, # DSR + [ + 1.9952632e-08, + 1.9952632e-08, + 1.2589251e-08, + 1.5848926e-08, + 1.2589251e-08, + 1.9952632e-08, + 2.511887e-08, + 3.9810708e-08, + 1e-07, + 1.9952633e-07, + 3.981071e-07, + 6.3095763e-07, + 7.943284e-07, + 6.3095763e-07, + 5.01187e-07, + 5.01187e-07, + 6.3095763e-07, + 6.3095763e-07, + 7.943284e-07, + 6.3095763e-07, + 5.01187e-07, + 6.3095763e-07, + 6.3095763e-07, + 6.3095763e-07, + 5.01187e-07, + 2.511887e-07, + 1.2589251e-07, + 1e-07, + 6.309576e-08, + 3.1622776e-08, + 2.511887e-08, + ], + ) + + "0" # hasEarlyReflections + + "1" # hasDirectivity + + get_id_code(1) # Number of directivity patterns + + get_id_code(0) # directivity ID + get_angle_code(0.0) + get_angle_code(360.0) - + get_outer_attenuation_code(0.2512) - , endian='big') + + get_outer_attenuation_code(0.2512), + endian="big", + ) - file = open('rend_config_renderer_directivity.dat', 'wb') + file = open("rend_config_renderer_directivity.dat", "wb") data.tofile(file) file.close() + def generate_reverb_payload_equivalent_to_config_directivity_cfg(): # based on config_directivity_cfg.cfg # note that because of encoding, resolution is lost and behaviour may not be bit-exact compared to .cfg file based values data = bitarray( - '0' # hasAcEnv - + '1' # hasDirectivity - + get_id_code(1) # Number of directivity patterns - + get_id_code(0) # directivity ID + "0" # hasAcEnv + + "1" # hasDirectivity + + get_id_code(1) # Number of directivity patterns + + get_id_code(0) # directivity ID + get_angle_code(0.0) + get_angle_code(360.0) - + get_outer_attenuation_code(0.2512) - , endian='big') + + get_outer_attenuation_code(0.2512), + endian="big", + ) - file = open('config_directivity.dat', 'wb') + file = open("config_directivity.dat", "wb") data.tofile(file) file.close() + def generate_reverb_payload_equivalent_to_rend_config_hospital_patientroom_cfg(): # based on config_hospital_patientroom.cfg # note that because of encoding, resolution is lost and behaviour may not be bit-exact compared to .cfg file based values data = bitarray( - '1' # hasAcEnv - + get_count_or_index_code(1) # fgdNrGrids + "1" # hasAcEnv + + get_count_or_index_code(1) # fgdNrGrids + fgdMethod.Individual_Frequencies.value # fgdMethod - + get_count_or_index_code(31) # fgdNrBands - - - + concatenate(get_frequency_code, # fgdCenterFreq - [ 20.0, 25.0, 31.5, 40.0, 50.0, 63.0, 80.0, 100.0, 125.0, 160.0, - 200.0, 250.0, 315.0, 400.0, 500.0, 630.0, 800.0, 1000.0, 1250.0, 1600.0, - 2000.0, 2500.0, 3150.0, 4000.0, 5000.0, 6300.0, 8000.0, 10000.0, 12500.0, 16000.0, - 20000.0 ]) - - + get_count_or_index_code(1) # AcousticEnvCount - + get_id_code(0) # ID - + get_count_or_index_code(0) # FreqGridID - + get_duration_code(0.08163) # (input)Predelay - - + concatenate(get_duration_code, # RT60 - [ 0.81275, 0.61888, 0.45111, 0.34672, 0.46683, 0.53987, 0.61874, 0.70291, 0.66657, 0.73037, - 0.75090, 0.72470, 0.75486, 0.75857, 0.76844, 0.74999, 0.77622, 0.78227, 0.77441, 0.74688, - 0.73521, 0.73782, 0.71928, 0.71708, 0.71465, 0.60592, 0.52031, 0.51768, 0.52102, 0.37956, - 0.30786 ]) - - + concatenate(get_dsr_code, # DSR - [ 0.00019952621, 0.00019952621, 7.9432844e-05, 5.0118702e-05, 7.943284e-06, 6.3095763e-06, 6.3095763e-06, 7.943284e-06, 1e-05, 1e-05, - 7.943284e-06, 1e-05, 1e-05, 1e-05, 7.943284e-06, 1e-05, 1e-05, 7.943284e-06, 7.943284e-06, 6.3095763e-06, - 6.3095763e-06, 6.3095763e-06, 6.3095763e-06, 6.3095763e-06, 6.3095763e-06, 3.1622776e-06, 3.1622776e-06, 3.1622776e-06, 6.3095763e-07, 3.1622776e-07, - 3.1622776e-07 ]) - + '0' # hasEarlyReflections - + '0' # hasDirectivity - , endian='big') - - file = open('rend_config_hospital_patientroom.dat', 'wb') + + get_count_or_index_code(31) # fgdNrBands + + concatenate( + get_frequency_code, # fgdCenterFreq + [ + 20.0, + 25.0, + 31.5, + 40.0, + 50.0, + 63.0, + 80.0, + 100.0, + 125.0, + 160.0, + 200.0, + 250.0, + 315.0, + 400.0, + 500.0, + 630.0, + 800.0, + 1000.0, + 1250.0, + 1600.0, + 2000.0, + 2500.0, + 3150.0, + 4000.0, + 5000.0, + 6300.0, + 8000.0, + 10000.0, + 12500.0, + 16000.0, + 20000.0, + ], + ) + + get_count_or_index_code(1) # AcousticEnvCount + + get_id_code(0) # ID + + get_count_or_index_code(0) # FreqGridID + + get_duration_code(0.08163) # (input)Predelay + + concatenate( + get_duration_code, # RT60 + [ + 0.81275, + 0.61888, + 0.45111, + 0.34672, + 0.46683, + 0.53987, + 0.61874, + 0.70291, + 0.66657, + 0.73037, + 0.75090, + 0.72470, + 0.75486, + 0.75857, + 0.76844, + 0.74999, + 0.77622, + 0.78227, + 0.77441, + 0.74688, + 0.73521, + 0.73782, + 0.71928, + 0.71708, + 0.71465, + 0.60592, + 0.52031, + 0.51768, + 0.52102, + 0.37956, + 0.30786, + ], + ) + + concatenate( + get_dsr_code, # DSR + [ + 0.00019952621, + 0.00019952621, + 7.9432844e-05, + 5.0118702e-05, + 7.943284e-06, + 6.3095763e-06, + 6.3095763e-06, + 7.943284e-06, + 1e-05, + 1e-05, + 7.943284e-06, + 1e-05, + 1e-05, + 1e-05, + 7.943284e-06, + 1e-05, + 1e-05, + 7.943284e-06, + 7.943284e-06, + 6.3095763e-06, + 6.3095763e-06, + 6.3095763e-06, + 6.3095763e-06, + 6.3095763e-06, + 6.3095763e-06, + 3.1622776e-06, + 3.1622776e-06, + 3.1622776e-06, + 6.3095763e-07, + 3.1622776e-07, + 3.1622776e-07, + ], + ) + + "0" # hasEarlyReflections + + "0", # hasDirectivity + endian="big", + ) + + file = open("rend_config_hospital_patientroom.dat", "wb") data.tofile(file) file.close() @@ -682,39 +1856,128 @@ def generate_reverb_payload_equivalent_to_rend_config_recreation_cfg(): # based on config_recreation.cfg # note that because of encoding, resolution is lost and behaviour may not be bit-exact compared to .cfg file based values data = bitarray( - '1' # hasAcEnv - + get_count_or_index_code(1) # fgdNrGrids + "1" # hasAcEnv + + get_count_or_index_code(1) # fgdNrGrids + fgdMethod.Individual_Frequencies.value # fgdMethod - + get_count_or_index_code(31) # fgdNrBands - - - + concatenate(get_frequency_code, # fgdCenterFreq - [ 20.0, 25.0, 31.5, 40.0, 50.0, 63.0, 80.0, 100.0, 125.0, 160.0, - 200.0, 250.0, 315.0, 400.0, 500.0, 630.0, 800.0, 1000.0, 1250.0, 1600.0, - 2000.0, 2500.0, 3150.0, 4000.0, 5000.0, 6300.0, 8000.0, 10000.0, 12500.0, 16000.0, - 20000.0 ]) - - + get_count_or_index_code(1) # AcousticEnvCount - + get_id_code(0) # ID - + get_count_or_index_code(0) # FreqGridID - + get_duration_code(0.43031) # (input)Predelay - - + concatenate(get_duration_code, # RT60 - [ 4.51916, 4.89553, 4.83276, 5.00198, 5.34468, 5.76026, 6.36818, 6.95503, 7.27557, 7.62559, - 8.08892, 8.16002, 8.13900, 8.17919, 8.16280, 8.46226, 9.61806, 9.93048, 9.81353, 8.59340, - 8.38885, 8.36823, 6.51845, 3.76089, 3.75374, 3.57451, 1.28724, 1.22174, 1.22448, 1.71631, - 2.14343 ]) - - + concatenate(get_dsr_code, # DSR - [ 1e-06, 7.943284e-07, 1e-06, 1e-06, 1.5848925e-06, 1.9952631e-06, 3.1622776e-06, 3.9810707e-06, 6.3095763e-06, 7.943284e-06, - 1e-05, 7.943284e-06, 7.943284e-06, 7.943284e-06, 7.943284e-06, 7.943284e-06, 5.01187e-06, 5.01187e-06, 3.9810707e-06, 3.1622776e-06, - 3.1622776e-06, 2.511887e-06, 7.943284e-07, 6.3095763e-07, 6.3095763e-07, 5.01187e-08, 1.2589251e-08, 1.2589251e-08, 1.2589265e-09, 1.2589266e-11, - 3.981075e-12 ]) - + '0' # hasEarlyReflections - + '0' # hasDirectivity - , endian='big') - - file = open('rend_config_recreation.dat', 'wb') + + get_count_or_index_code(31) # fgdNrBands + + concatenate( + get_frequency_code, # fgdCenterFreq + [ + 20.0, + 25.0, + 31.5, + 40.0, + 50.0, + 63.0, + 80.0, + 100.0, + 125.0, + 160.0, + 200.0, + 250.0, + 315.0, + 400.0, + 500.0, + 630.0, + 800.0, + 1000.0, + 1250.0, + 1600.0, + 2000.0, + 2500.0, + 3150.0, + 4000.0, + 5000.0, + 6300.0, + 8000.0, + 10000.0, + 12500.0, + 16000.0, + 20000.0, + ], + ) + + get_count_or_index_code(1) # AcousticEnvCount + + get_id_code(0) # ID + + get_count_or_index_code(0) # FreqGridID + + get_duration_code(0.43031) # (input)Predelay + + concatenate( + get_duration_code, # RT60 + [ + 4.51916, + 4.89553, + 4.83276, + 5.00198, + 5.34468, + 5.76026, + 6.36818, + 6.95503, + 7.27557, + 7.62559, + 8.08892, + 8.16002, + 8.13900, + 8.17919, + 8.16280, + 8.46226, + 9.61806, + 9.93048, + 9.81353, + 8.59340, + 8.38885, + 8.36823, + 6.51845, + 3.76089, + 3.75374, + 3.57451, + 1.28724, + 1.22174, + 1.22448, + 1.71631, + 2.14343, + ], + ) + + concatenate( + get_dsr_code, # DSR + [ + 1e-06, + 7.943284e-07, + 1e-06, + 1e-06, + 1.5848925e-06, + 1.9952631e-06, + 3.1622776e-06, + 3.9810707e-06, + 6.3095763e-06, + 7.943284e-06, + 1e-05, + 7.943284e-06, + 7.943284e-06, + 7.943284e-06, + 7.943284e-06, + 7.943284e-06, + 5.01187e-06, + 5.01187e-06, + 3.9810707e-06, + 3.1622776e-06, + 3.1622776e-06, + 2.511887e-06, + 7.943284e-07, + 6.3095763e-07, + 6.3095763e-07, + 5.01187e-08, + 1.2589251e-08, + 1.2589251e-08, + 1.2589265e-09, + 1.2589266e-11, + 3.981075e-12, + ], + ) + + "0" # hasEarlyReflections + + "0", # hasDirectivity + endian="big", + ) + + file = open("rend_config_recreation.dat", "wb") data.tofile(file) file.close() @@ -723,56 +1986,120 @@ def generate_reverb_payload_ER_v0(): # based on config_renderer.cfg # note that because of encoding, resolution is lost and behaviour may not be bit-exact compared to .cfg file based values data = bitarray( - '1' # hasAcEnv - + get_count_or_index_code(1) # fgdNrGrids - # frequency grid + "1" + get_count_or_index_code(1) # hasAcEnv # fgdNrGrids + # frequency grid + fgdMethod.Individual_Frequencies.value # fgdMethod - + get_count_or_index_code(24) # fgdNrBands - - + concatenate(get_frequency_code, # fgdCenterFreq - [50.0, 63.0, 80.0, 100.0, - 125.0, 160.0, 200.0, 250.0, - 315.0, 400.0, 500.0, 630.0, - 800.0, 1000.0, 1250.0, 1600.0, - 2000.0, 2500.0, 3150.0, 4000.0, - 5000.0, 6300.0, 8000.0, 10000.0]) - - + get_count_or_index_code(1) # AcousticEnvCount - + get_id_code(0) # ID - + get_count_or_index_code(0) # FreqGridID - + get_duration_code(0.1) # (input)Predelay - - + concatenate(get_duration_code, # RT60 - [0.87, 0.66, 0.47, 0.41, - 0.32, 0.37, 0.28, 0.30, - 0.29, 0.29, 0.28, 0.30, - 0.31, 0.34, 0.34, 0.34, - 0.34, 0.33, 0.32, 0.29, - 0.28, 0.24, 0.24, 0.2]) - - + concatenate(get_dsr_code, # DSR - [2.511887e-07, 1e-07, 1.2589251e-07, 1e-07, - 5.01187e-08, 5.01187e-08, 7.9432844e-08, 1e-07, - 6.309576e-08, 5.01187e-08, 7.9432844e-08, 1e-07, - 5.01187e-08, 1e-07, 7.9432844e-08, 6.309576e-08, - 7.9432844e-08, 5.01187e-08, 6.309576e-08, 3.9810708e-08, - 3.9810708e-08, 2.511887e-08, 1.9952632e-08, 1.2589251e-08]) - - + '1' # hasEarlyReflections - + concatenate(lambda code : get_distance_code(code, True), - [ 2.0, 2.0, 3.0 ]) # room dimensions - + concatenate(get_absorption_code, # absorptionCode - [ 0.2, 0.1, 0.1, 0.1, 0.3, 0.1 ]) - + '1' # listener origin flag - + '1' # isPositiveX - + '1' # isPositiveY - + concatenate(lambda d : get_distance_code(d, True), - [ 0.0, 0.0, 1.5 ]) # listener origin (x, y, z) - + '1' # lowComplexity - + '0' # directivity - , endian='big') - - file = open('rend_config_ER_v0.dat', 'wb') + + get_count_or_index_code(24) # fgdNrBands + + concatenate( + get_frequency_code, # fgdCenterFreq + [ + 50.0, + 63.0, + 80.0, + 100.0, + 125.0, + 160.0, + 200.0, + 250.0, + 315.0, + 400.0, + 500.0, + 630.0, + 800.0, + 1000.0, + 1250.0, + 1600.0, + 2000.0, + 2500.0, + 3150.0, + 4000.0, + 5000.0, + 6300.0, + 8000.0, + 10000.0, + ], + ) + + get_count_or_index_code(1) # AcousticEnvCount + + get_id_code(0) # ID + + get_count_or_index_code(0) # FreqGridID + + get_duration_code(0.1) # (input)Predelay + + concatenate( + get_duration_code, # RT60 + [ + 0.87, + 0.66, + 0.47, + 0.41, + 0.32, + 0.37, + 0.28, + 0.30, + 0.29, + 0.29, + 0.28, + 0.30, + 0.31, + 0.34, + 0.34, + 0.34, + 0.34, + 0.33, + 0.32, + 0.29, + 0.28, + 0.24, + 0.24, + 0.2, + ], + ) + + concatenate( + get_dsr_code, # DSR + [ + 2.511887e-07, + 1e-07, + 1.2589251e-07, + 1e-07, + 5.01187e-08, + 5.01187e-08, + 7.9432844e-08, + 1e-07, + 6.309576e-08, + 5.01187e-08, + 7.9432844e-08, + 1e-07, + 5.01187e-08, + 1e-07, + 7.9432844e-08, + 6.309576e-08, + 7.9432844e-08, + 5.01187e-08, + 6.309576e-08, + 3.9810708e-08, + 3.9810708e-08, + 2.511887e-08, + 1.9952632e-08, + 1.2589251e-08, + ], + ) + + "1" # hasEarlyReflections + + concatenate( + lambda code: get_distance_code(code, True), [2.0, 2.0, 3.0] + ) # room dimensions + + concatenate( + get_absorption_code, [0.2, 0.1, 0.1, 0.1, 0.3, 0.1] # absorptionCode + ) + + "1" # listener origin flag + + "1" # isPositiveX + + "1" # isPositiveY + + concatenate( + lambda d: get_distance_code(d, True), [0.0, 0.0, 1.5] + ) # listener origin (x, y, z) + + "1" # lowComplexity + + "0", # directivity + endian="big", + ) + + file = open("rend_config_ER_v0.dat", "wb") data.tofile(file) file.close() @@ -781,109 +2108,237 @@ def generate_reverb_payload_ER_v1(): # based on config_renderer.cfg # note that because of encoding, resolution is lost and behaviour may not be bit-exact compared to .cfg file based values data = bitarray( - '1' # hasAcEnv - + get_count_or_index_code(1) # fgdNrGrids - # frequency grid + "1" + get_count_or_index_code(1) # hasAcEnv # fgdNrGrids + # frequency grid + fgdMethod.Individual_Frequencies.value # fgdMethod - + get_count_or_index_code(24) # fgdNrBands - - + concatenate(get_frequency_code, # fgdCenterFreq - [50.0, 63.0, 80.0, 100.0, - 125.0, 160.0, 200.0, 250.0, - 315.0, 400.0, 500.0, 630.0, - 800.0, 1000.0, 1250.0, 1600.0, - 2000.0, 2500.0, 3150.0, 4000.0, - 5000.0, 6300.0, 8000.0, 10000.0]) - - + get_count_or_index_code(1) # AcousticEnvCount - + get_id_code(0) # ID - + get_count_or_index_code(0) # FreqGridID - + get_duration_code(0.1) # (input)Predelay - - + concatenate(get_duration_code, # RT60 - [0.87, 0.66, 0.47, 0.41, - 0.32, 0.37, 0.28, 0.30, - 0.29, 0.29, 0.28, 0.30, - 0.31, 0.34, 0.34, 0.34, - 0.34, 0.33, 0.32, 0.29, - 0.28, 0.24, 0.24, 0.2]) - - + concatenate(get_dsr_code, # DSR - [2.511887e-07, 1e-07, 1.2589251e-07, 1e-07, - 5.01187e-08, 5.01187e-08, 7.9432844e-08, 1e-07, - 6.309576e-08, 5.01187e-08, 7.9432844e-08, 1e-07, - 5.01187e-08, 1e-07, 7.9432844e-08, 6.309576e-08, - 7.9432844e-08, 5.01187e-08, 6.309576e-08, 3.9810708e-08, - 3.9810708e-08, 2.511887e-08, 1.9952632e-08, 1.2589251e-08]) - - + '1' # hasEarlyReflections - + concatenate(lambda code : get_distance_code(code, True), - [ 3.0, 3.0, 4.0 ]) # room dimensions - + concatenate(get_absorption_code, # absorptionCode - [ 0.3, 0.2, 0.2, 0.2, 0.3, 0.1 ]) - + '0' # listener origin flag - + '0' # lowComplexity - + '0' # directivity - , endian='big') - - file = open('rend_config_ER_v1.dat', 'wb') + + get_count_or_index_code(24) # fgdNrBands + + concatenate( + get_frequency_code, # fgdCenterFreq + [ + 50.0, + 63.0, + 80.0, + 100.0, + 125.0, + 160.0, + 200.0, + 250.0, + 315.0, + 400.0, + 500.0, + 630.0, + 800.0, + 1000.0, + 1250.0, + 1600.0, + 2000.0, + 2500.0, + 3150.0, + 4000.0, + 5000.0, + 6300.0, + 8000.0, + 10000.0, + ], + ) + + get_count_or_index_code(1) # AcousticEnvCount + + get_id_code(0) # ID + + get_count_or_index_code(0) # FreqGridID + + get_duration_code(0.1) # (input)Predelay + + concatenate( + get_duration_code, # RT60 + [ + 0.87, + 0.66, + 0.47, + 0.41, + 0.32, + 0.37, + 0.28, + 0.30, + 0.29, + 0.29, + 0.28, + 0.30, + 0.31, + 0.34, + 0.34, + 0.34, + 0.34, + 0.33, + 0.32, + 0.29, + 0.28, + 0.24, + 0.24, + 0.2, + ], + ) + + concatenate( + get_dsr_code, # DSR + [ + 2.511887e-07, + 1e-07, + 1.2589251e-07, + 1e-07, + 5.01187e-08, + 5.01187e-08, + 7.9432844e-08, + 1e-07, + 6.309576e-08, + 5.01187e-08, + 7.9432844e-08, + 1e-07, + 5.01187e-08, + 1e-07, + 7.9432844e-08, + 6.309576e-08, + 7.9432844e-08, + 5.01187e-08, + 6.309576e-08, + 3.9810708e-08, + 3.9810708e-08, + 2.511887e-08, + 1.9952632e-08, + 1.2589251e-08, + ], + ) + + "1" # hasEarlyReflections + + concatenate( + lambda code: get_distance_code(code, True), [3.0, 3.0, 4.0] + ) # room dimensions + + concatenate( + get_absorption_code, [0.3, 0.2, 0.2, 0.2, 0.3, 0.1] # absorptionCode + ) + + "0" # listener origin flag + + "0" # lowComplexity + + "0", # directivity + endian="big", + ) + + file = open("rend_config_ER_v1.dat", "wb") data.tofile(file) file.close() + def generate_reverb_payload_ER_v2(): # based on config_renderer.cfg # note that because of encoding, resolution is lost and behaviour may not be bit-exact compared to .cfg file based values data = bitarray( - '1' # hasAcEnv - + get_count_or_index_code(1) # fgdNrGrids - # frequency grid + "1" + get_count_or_index_code(1) # hasAcEnv # fgdNrGrids + # frequency grid + fgdMethod.Individual_Frequencies.value # fgdMethod - + get_count_or_index_code(24) # fgdNrBands - - + concatenate(get_frequency_code, # fgdCenterFreq - [50.0, 63.0, 80.0, 100.0, - 125.0, 160.0, 200.0, 250.0, - 315.0, 400.0, 500.0, 630.0, - 800.0, 1000.0, 1250.0, 1600.0, - 2000.0, 2500.0, 3150.0, 4000.0, - 5000.0, 6300.0, 8000.0, 10000.0]) - - + get_count_or_index_code(1) # AcousticEnvCount - + get_id_code(0) # ID - + get_count_or_index_code(0) # FreqGridID - + get_duration_code(0.1) # (input)Predelay - - + concatenate(get_duration_code, # RT60 - [0.87, 0.66, 0.47, 0.41, - 0.32, 0.37, 0.28, 0.30, - 0.29, 0.29, 0.28, 0.30, - 0.31, 0.34, 0.34, 0.34, - 0.34, 0.33, 0.32, 0.29, - 0.28, 0.24, 0.24, 0.2]) - - + concatenate(get_dsr_code, # DSR - [2.511887e-07, 1e-07, 1.2589251e-07, 1e-07, - 5.01187e-08, 5.01187e-08, 7.9432844e-08, 1e-07, - 6.309576e-08, 5.01187e-08, 7.9432844e-08, 1e-07, - 5.01187e-08, 1e-07, 7.9432844e-08, 6.309576e-08, - 7.9432844e-08, 5.01187e-08, 6.309576e-08, 3.9810708e-08, - 3.9810708e-08, 2.511887e-08, 1.9952632e-08, 1.2589251e-08]) - - + '1' # hasEarlyReflections - + concatenate(lambda code : get_distance_code(code, True), - [ 3.0, 3.0, 4.0 ]) # room dimensions - + concatenate(get_absorption_code, # absorptionCode - [ 0.3, 0.2, 0.3, 0.4, 0.3, 0.4 ]) - + '1' # listener origin flag - + '1' # isPositiveX - + '0' # isPositiveY - + concatenate(lambda d : get_distance_code(d, True), - [ 0.5, 0.5, 1.5]) # listener origin (x, y, z) - + '0' # lowComplexity - + '0' # directivity - , endian='big') - - file = open('rend_config_ER_v2.dat', 'wb') + + get_count_or_index_code(24) # fgdNrBands + + concatenate( + get_frequency_code, # fgdCenterFreq + [ + 50.0, + 63.0, + 80.0, + 100.0, + 125.0, + 160.0, + 200.0, + 250.0, + 315.0, + 400.0, + 500.0, + 630.0, + 800.0, + 1000.0, + 1250.0, + 1600.0, + 2000.0, + 2500.0, + 3150.0, + 4000.0, + 5000.0, + 6300.0, + 8000.0, + 10000.0, + ], + ) + + get_count_or_index_code(1) # AcousticEnvCount + + get_id_code(0) # ID + + get_count_or_index_code(0) # FreqGridID + + get_duration_code(0.1) # (input)Predelay + + concatenate( + get_duration_code, # RT60 + [ + 0.87, + 0.66, + 0.47, + 0.41, + 0.32, + 0.37, + 0.28, + 0.30, + 0.29, + 0.29, + 0.28, + 0.30, + 0.31, + 0.34, + 0.34, + 0.34, + 0.34, + 0.33, + 0.32, + 0.29, + 0.28, + 0.24, + 0.24, + 0.2, + ], + ) + + concatenate( + get_dsr_code, # DSR + [ + 2.511887e-07, + 1e-07, + 1.2589251e-07, + 1e-07, + 5.01187e-08, + 5.01187e-08, + 7.9432844e-08, + 1e-07, + 6.309576e-08, + 5.01187e-08, + 7.9432844e-08, + 1e-07, + 5.01187e-08, + 1e-07, + 7.9432844e-08, + 6.309576e-08, + 7.9432844e-08, + 5.01187e-08, + 6.309576e-08, + 3.9810708e-08, + 3.9810708e-08, + 2.511887e-08, + 1.9952632e-08, + 1.2589251e-08, + ], + ) + + "1" # hasEarlyReflections + + concatenate( + lambda code: get_distance_code(code, True), [3.0, 3.0, 4.0] + ) # room dimensions + + concatenate( + get_absorption_code, [0.3, 0.2, 0.3, 0.4, 0.3, 0.4] # absorptionCode + ) + + "1" # listener origin flag + + "1" # isPositiveX + + "0" # isPositiveY + + concatenate( + lambda d: get_distance_code(d, True), [0.5, 0.5, 1.5] + ) # listener origin (x, y, z) + + "0" # lowComplexity + + "0", # directivity + endian="big", + ) + + file = open("rend_config_ER_v2.dat", "wb") data.tofile(file) file.close() @@ -892,74 +2347,138 @@ def generate_reverb_payload_ER_v3(): # based on config_renderer.cfg # note that because of encoding, resolution is lost and behaviour may not be bit-exact compared to .cfg file based values data = bitarray( - '1' # hasAcEnv - + get_count_or_index_code(1) # fgdNrGrids - # frequency grid + "1" + get_count_or_index_code(1) # hasAcEnv # fgdNrGrids + # frequency grid + fgdMethod.Individual_Frequencies.value # fgdMethod - + get_count_or_index_code(24) # fgdNrBands - - + concatenate(get_frequency_code, # fgdCenterFreq - [50.0, 63.0, 80.0, 100.0, - 125.0, 160.0, 200.0, 250.0, - 315.0, 400.0, 500.0, 630.0, - 800.0, 1000.0, 1250.0, 1600.0, - 2000.0, 2500.0, 3150.0, 4000.0, - 5000.0, 6300.0, 8000.0, 10000.0]) - - + get_count_or_index_code(1) # AcousticEnvCount - + get_id_code(0) # ID - + get_count_or_index_code(0) # FreqGridID - + get_duration_code(0.1) # (input)Predelay - - + concatenate(get_duration_code, # RT60 - [0.87, 0.66, 0.47, 0.41, - 0.32, 0.37, 0.28, 0.30, - 0.29, 0.29, 0.28, 0.30, - 0.31, 0.34, 0.34, 0.34, - 0.34, 0.33, 0.32, 0.29, - 0.28, 0.24, 0.24, 0.2]) - - + concatenate(get_dsr_code, # DSR - [2.511887e-07, 1e-07, 1.2589251e-07, 1e-07, - 5.01187e-08, 5.01187e-08, 7.9432844e-08, 1e-07, - 6.309576e-08, 5.01187e-08, 7.9432844e-08, 1e-07, - 5.01187e-08, 1e-07, 7.9432844e-08, 6.309576e-08, - 7.9432844e-08, 5.01187e-08, 6.309576e-08, 3.9810708e-08, - 3.9810708e-08, 2.511887e-08, 1.9952632e-08, 1.2589251e-08]) - - + '1' # hasEarlyReflections - + concatenate(lambda code : get_distance_code(code, True), - [4.0, 4.0, 5.0]) # room dimensions - + concatenate(get_absorption_code, # absorptionCode - [0.1, 0.2, 0.2, 0.2, 0.1, 0.1]) - + '1' # listener origin flag - + '0' # isPositiveX - + '1' # isPositiveY - + concatenate(lambda d : get_distance_code(d, True), - [ 1.0, 0.5, 1.5]) # listener origin (x, y, z) - + '1' # lowComplexity - + '0' # directivity - , endian='big') - - file = open('rend_config_ER_v3.dat', 'wb') + + get_count_or_index_code(24) # fgdNrBands + + concatenate( + get_frequency_code, # fgdCenterFreq + [ + 50.0, + 63.0, + 80.0, + 100.0, + 125.0, + 160.0, + 200.0, + 250.0, + 315.0, + 400.0, + 500.0, + 630.0, + 800.0, + 1000.0, + 1250.0, + 1600.0, + 2000.0, + 2500.0, + 3150.0, + 4000.0, + 5000.0, + 6300.0, + 8000.0, + 10000.0, + ], + ) + + get_count_or_index_code(1) # AcousticEnvCount + + get_id_code(0) # ID + + get_count_or_index_code(0) # FreqGridID + + get_duration_code(0.1) # (input)Predelay + + concatenate( + get_duration_code, # RT60 + [ + 0.87, + 0.66, + 0.47, + 0.41, + 0.32, + 0.37, + 0.28, + 0.30, + 0.29, + 0.29, + 0.28, + 0.30, + 0.31, + 0.34, + 0.34, + 0.34, + 0.34, + 0.33, + 0.32, + 0.29, + 0.28, + 0.24, + 0.24, + 0.2, + ], + ) + + concatenate( + get_dsr_code, # DSR + [ + 2.511887e-07, + 1e-07, + 1.2589251e-07, + 1e-07, + 5.01187e-08, + 5.01187e-08, + 7.9432844e-08, + 1e-07, + 6.309576e-08, + 5.01187e-08, + 7.9432844e-08, + 1e-07, + 5.01187e-08, + 1e-07, + 7.9432844e-08, + 6.309576e-08, + 7.9432844e-08, + 5.01187e-08, + 6.309576e-08, + 3.9810708e-08, + 3.9810708e-08, + 2.511887e-08, + 1.9952632e-08, + 1.2589251e-08, + ], + ) + + "1" # hasEarlyReflections + + concatenate( + lambda code: get_distance_code(code, True), [4.0, 4.0, 5.0] + ) # room dimensions + + concatenate( + get_absorption_code, [0.1, 0.2, 0.2, 0.2, 0.1, 0.1] # absorptionCode + ) + + "1" # listener origin flag + + "0" # isPositiveX + + "1" # isPositiveY + + concatenate( + lambda d: get_distance_code(d, True), [1.0, 0.5, 1.5] + ) # listener origin (x, y, z) + + "1" # lowComplexity + + "0", # directivity + endian="big", + ) + + file = open("rend_config_ER_v3.dat", "wb") data.tofile(file) file.close() if __name__ == "__main__": - #test() + # test() generate_reverb_payload_equivalent_to_rend_config_renderer_cfg() generate_reverb_payload_equivalent_to_rend_config_hospital_patientroom_cfg() generate_reverb_payload_equivalent_to_rend_config_recreation_cfg() generate_reverb_payload_equivalent_to_rend_config_renderer_directivity_cfg() generate_reverb_payload_equivalent_to_config_directivity_cfg() - + # generate_reverb_payload_aggressive_ER() - + generate_reverb_payload_ER_v0() generate_reverb_payload_ER_v1() generate_reverb_payload_ER_v2() generate_reverb_payload_ER_v3() # generate_reverb_payload_equivalent_to_rend_config_renderer_cfg_plus_early_reflections_no_listener_origin() - # generate_reverb_payload_equivalent_to_rend_config_renderer_cfg_plus_early_reflections_listener_origin() \ No newline at end of file + # generate_reverb_payload_equivalent_to_rend_config_renderer_cfg_plus_early_reflections_listener_origin() diff --git a/scripts/reverb/text_to_binary_payload.py b/scripts/reverb/text_to_binary_payload.py index b23b3a0c78..7eff404a7a 100644 --- a/scripts/reverb/text_to_binary_payload.py +++ b/scripts/reverb/text_to_binary_payload.py @@ -46,15 +46,16 @@ # -from bitarray import bitarray -from configparser import ConfigParser import ast +from configparser import ConfigParser + +from bitarray import bitarray from generate_acoustic_environments_metadata import * # convert text containing an option value to a Python value, if possible def eval_option(text): - text = text.replace(';', '') + text = text.replace(";", "") try: value = ast.literal_eval(text) except ValueError: @@ -63,8 +64,8 @@ def eval_option(text): def get_bool_code(b): - assert(isinstance(b, bool)) - return format(b, '01b') + assert isinstance(b, bool) + return format(b, "01b") def parse_reverb_text_configuration_and_generate_binary_payload(file): @@ -72,126 +73,185 @@ def parse_reverb_text_configuration_and_generate_binary_payload(file): # parse file config = ConfigParser() files_parsed = config.read(file) - assert len(files_parsed) == 1, 'file {} not successfully parsed'.format(file) + assert len(files_parsed) == 1, "file {} not successfully parsed".format(file) # collect dicts of frequency grid, acoustic environment and directivity sections - sections = { key : {} for key in ['roomAcoustics', 'frequencyGrid', 'acousticEnvironment', 'directivitySetting', 'directivityPattern']} + sections = { + key: {} + for key in [ + "roomAcoustics", + "frequencyGrid", + "acousticEnvironment", + "directivitySetting", + "directivityPattern", + ] + } for section_name in config.sections(): - if ':' in section_name: - section, index = section_name.split(':') - assert section in ['frequencyGrid', 'acousticEnvironment', 'directivityPattern'], f'unknown section name: {section}' + if ":" in section_name: + section, index = section_name.split(":") + assert section in [ + "frequencyGrid", + "acousticEnvironment", + "directivityPattern", + ], f"unknown section name: {section}" sections[section][index] = config[section_name] else: - assert section_name in ['roomAcoustics', 'directivitySetting'], f'unknown section name: {section_name}' + assert section_name in [ + "roomAcoustics", + "directivitySetting", + ], f"unknown section name: {section_name}" sections[section_name] = config[section_name] # parse room acoustics - if sections['roomAcoustics']: - frequencyGridCount = eval_option(sections['roomAcoustics']['frequencyGridCount']) - acousticEnvironmentCount = eval_option(sections['roomAcoustics']['acousticEnvironmentCount']) - assert frequencyGridCount == len(sections['frequencyGrid']) - assert acousticEnvironmentCount == len(sections['acousticEnvironment']) + if sections["roomAcoustics"]: + frequencyGridCount = eval_option( + sections["roomAcoustics"]["frequencyGridCount"] + ) + acousticEnvironmentCount = eval_option( + sections["roomAcoustics"]["acousticEnvironmentCount"] + ) + assert frequencyGridCount == len(sections["frequencyGrid"]) + assert acousticEnvironmentCount == len(sections["acousticEnvironment"]) - hasAcEnv = len(sections['roomAcoustics']) > 0 # hasAcEnv (see IVAS acoustic environment payload syntax document) + hasAcEnv = ( + len(sections["roomAcoustics"]) > 0 + ) # hasAcEnv (see IVAS acoustic environment payload syntax document) if hasAcEnv: - data = bitarray('1', endian='big') + data = bitarray("1", endian="big") else: - data = bitarray('0', endian='big') + data = bitarray("0", endian="big") if hasAcEnv: # parse frequency grids data += bitarray( - get_count_or_index_code(len(sections['frequencyGrid'])), # fgdNrGrids - endian='big') - for _, fg in sections['frequencyGrid'].items(): - method = eval_option(fg['method']) - if method == 'individualFrequencies': + get_count_or_index_code(len(sections["frequencyGrid"])), # fgdNrGrids + endian="big", + ) + for _, fg in sections["frequencyGrid"].items(): + method = eval_option(fg["method"]) + if method == "individualFrequencies": data += bitarray( - fgdMethod.Individual_Frequencies.value # fgdMethod - + get_count_or_index_code(len(eval_option(fg['frequencies']))) # fgdNrBands - + concatenate(get_frequency_code, eval_option(fg['frequencies']))) # fgdCenterFreq - elif method == 'startHopAmount': + fgdMethod.Individual_Frequencies.value # fgdMethod + + get_count_or_index_code( + len(eval_option(fg["frequencies"])) + ) # fgdNrBands + + concatenate(get_frequency_code, eval_option(fg["frequencies"])) + ) # fgdCenterFreq + elif method == "startHopAmount": data += bitarray( - fgdMethod.Start_Hop_Amount.value # fgdMethod - + get_count_or_index_code(eval_option(fg['nrBands'])) # fgdNrBands - + get_frequency_code(eval_option(fg['startFrequency'])) # fgdCenterFreq - + get_frequency_hop_code(eval_option(fg['frequencyHop']))) # frequencyHop - elif method == 'defaultBanding': + fgdMethod.Start_Hop_Amount.value # fgdMethod + + get_count_or_index_code(eval_option(fg["nrBands"])) # fgdNrBands + + get_frequency_code( + eval_option(fg["startFrequency"]) + ) # fgdCenterFreq + + get_frequency_hop_code(eval_option(fg["frequencyHop"])) + ) # frequencyHop + elif method == "defaultBanding": data += bitarray( - fgdMethod.Default_Banding.value # fgdMethod - + format(eval_option(fg['defaultGrid']), '04b') # fgdDefaultGrid - + get_bool_code('defaultGridOffset' in fg)) # fgdIsSubGrid - if 'defaultGridOffset' in fg: + fgdMethod.Default_Banding.value # fgdMethod + + format(eval_option(fg["defaultGrid"]), "04b") # fgdDefaultGrid + + get_bool_code("defaultGridOffset" in fg) + ) # fgdIsSubGrid + if "defaultGridOffset" in fg: data += bitarray( - format(eval_option(fg['defaultGridOffset']), '03b') # fgdDefaultGridOffset - + format(eval_option(fg['defaultGridNrBands']), '06b')) # fgdDefaultGridNrBands + format( + eval_option(fg["defaultGridOffset"]), "03b" + ) # fgdDefaultGridOffset + + format(eval_option(fg["defaultGridNrBands"]), "06b") + ) # fgdDefaultGridNrBands else: - assert False, 'unknow frequency grid method' + assert False, "unknow frequency grid method" # parse acoustic environments data += bitarray( - get_count_or_index_code(len(sections['acousticEnvironment']))) # revNrElements - for index, ae in sections['acousticEnvironment'].items(): + get_count_or_index_code(len(sections["acousticEnvironment"])) + ) # revNrElements + for index, ae in sections["acousticEnvironment"].items(): data += bitarray( - get_id_code(eval_option(index)) # revAcEnvID - + get_count_or_index_code(eval_option(ae['frequencyGridIndex'])) # revFreqGridIdx - + get_duration_code(eval_option(ae['predelay'])) # revPredelay - + concatenate(get_duration_code, eval_option(ae['rt60'])) # revRT60 - + concatenate(get_dsr_code, eval_option(ae['dsr'])) # revDSR - + get_bool_code('earlyReflectionsSize' in ae)) # hasEarlyReflections - if 'earlyReflectionsSize' in ae: - assert len(eval_option(ae['absorptionCoeffs'])) == 6, 'wrong number of absorption coefficients' + get_id_code(eval_option(index)) # revAcEnvID + + get_count_or_index_code( + eval_option(ae["frequencyGridIndex"]) + ) # revFreqGridIdx + + get_duration_code(eval_option(ae["predelay"])) # revPredelay + + concatenate(get_duration_code, eval_option(ae["rt60"])) # revRT60 + + concatenate(get_dsr_code, eval_option(ae["dsr"])) # revDSR + + get_bool_code("earlyReflectionsSize" in ae) + ) # hasEarlyReflections + if "earlyReflectionsSize" in ae: + assert ( + len(eval_option(ae["absorptionCoeffs"])) == 6 + ), "wrong number of absorption coefficients" data += bitarray( - concatenate(lambda d : get_distance_code(d, True), eval_option(ae['earlyReflectionsSize'])) # erSize - + concatenate(get_absorption_code, eval_option(ae['absorptionCoeffs'])) # erAbsCoeff - + get_bool_code('listenerOrigin' in ae)) # hasListenerOrigin - if 'listenerOrigin' in ae: - xyz = eval_option(ae['listenerOrigin']) - assert len(xyz) == 3, 'wrong number of listener origin coordinates' - assert xyz[2] >= 0, 'listener origin Z >= 0' + concatenate( + lambda d: get_distance_code(d, True), + eval_option(ae["earlyReflectionsSize"]), + ) # erSize + + concatenate( + get_absorption_code, eval_option(ae["absorptionCoeffs"]) + ) # erAbsCoeff + + get_bool_code("listenerOrigin" in ae) + ) # hasListenerOrigin + if "listenerOrigin" in ae: + xyz = eval_option(ae["listenerOrigin"]) + assert len(xyz) == 3, "wrong number of listener origin coordinates" + assert xyz[2] >= 0, "listener origin Z >= 0" data += bitarray( - get_bool_code(xyz[0] >= 0) # isPositiveX - - + get_bool_code(xyz[1] >= 0) # isPositiveY - + concatenate(lambda d : get_distance_code(d, True), [abs(v) for v in xyz])) # erListenerOrigin - lowComplexity = bool(eval_option(ae['lowComplexity'])) if 'lowComplexity' in ae else False - data += bitarray(get_bool_code(lowComplexity)) # lowComplexity - + get_bool_code(xyz[0] >= 0) # isPositiveX + + get_bool_code(xyz[1] >= 0) # isPositiveY + + concatenate( + lambda d: get_distance_code(d, True), [abs(v) for v in xyz] + ) + ) # erListenerOrigin + lowComplexity = ( + bool(eval_option(ae["lowComplexity"])) + if "lowComplexity" in ae + else False + ) + data += bitarray(get_bool_code(lowComplexity)) # lowComplexity # parse directivity settings - if sections['directivitySetting']: - directivityCount = eval_option(sections['directivitySetting']['directivityCount']) - assert directivityCount == len(sections['directivityPattern']) + if sections["directivitySetting"]: + directivityCount = eval_option( + sections["directivitySetting"]["directivityCount"] + ) + assert directivityCount == len(sections["directivityPattern"]) # parse directivity - hasDirectivity = len(sections['directivitySetting']) > 0 + hasDirectivity = len(sections["directivitySetting"]) > 0 data += get_bool_code(hasDirectivity) if hasDirectivity: - data += bitarray(get_id_code(len(sections['directivityPattern']))) - for index, dir_pattern in sections['directivityPattern'].items(): + data += bitarray(get_id_code(len(sections["directivityPattern"]))) + for index, dir_pattern in sections["directivityPattern"].items(): data += bitarray(get_id_code(eval_option(index))) - dir_values = eval_option(dir_pattern['directivity']) - data += bitarray(get_angle_code(dir_values[0]) # Directivity inner angle - + get_angle_code(dir_values[1]) # Directivity outer angle - + get_outer_attenuation_code(dir_values[2])) # Directivity outer attenuation + dir_values = eval_option(dir_pattern["directivity"]) + data += bitarray( + get_angle_code(dir_values[0]) # Directivity inner angle + + get_angle_code(dir_values[1]) # Directivity outer angle + + get_outer_attenuation_code(dir_values[2]) + ) # Directivity outer attenuation # generate binary file - data.tofile(open(file.split('.')[0] + '.dat', 'wb')) + data.tofile(open(file.split(".")[0] + ".dat", "wb")) if __name__ == "__main__": import argparse - parser = argparse.ArgumentParser(description='Reads a text-based configuration file and generates the equivalent binary payload file (.dat)') + + parser = argparse.ArgumentParser( + description="Reads a text-based configuration file and generates the equivalent binary payload file (.dat)" + ) parser.add_argument("configuration_file") args = parser.parse_args() parse_reverb_text_configuration_and_generate_binary_payload(args.configuration_file) - print("\nNote: the conversion algorithm uses quantization, which may lead to quantization errors.") + print( + "\nNote: the conversion algorithm uses quantization, which may lead to quantization errors." + ) # print maximum quantization errors exceeding float32 resolution epsilon = 2e-7 # slighly larger than float32 epsilon - text = '' + text = "" for name in max_quantization_error.keys(): if max_quantization_error[name] > epsilon: - text += '\n {:10s}: {:.1e}'.format(name, max_quantization_error[name]) + text += "\n {:10s}: {:.1e}".format(name, max_quantization_error[name]) if len(text) > 0: - print('Maximum relative quantization errors > {}:'.format(epsilon) + text) \ No newline at end of file + print("Maximum relative quantization errors > {}:".format(epsilon) + text) diff --git a/scripts/runIvasCodec.py b/scripts/runIvasCodec.py index 92fed75393..a4a4c1fef8 100755 --- a/scripts/runIvasCodec.py +++ b/scripts/runIvasCodec.py @@ -30,14 +30,14 @@ the United Nations Convention on Contracts on the International Sales of Goods. """ +import logging import os.path import platform -import sys -import logging import shutil +import sys -from pyivastest import IvasScriptsCommon, IvasModeRunner import pyivastest.constants as constants +from pyivastest import IvasModeRunner, IvasScriptsCommon bin_ext = "" if platform.system() == "Windows": @@ -83,7 +83,7 @@ class RunIvasCodec(IvasScriptsCommon.IvasScript): default=default_dec, ) self.parser.add_argument( - "--fail_log_dir", + "--fail_log_dir", help="Move logs of failed modes to dir (default none)", default=None, ) @@ -144,18 +144,17 @@ class RunIvasCodec(IvasScriptsCommon.IvasScript): self.logger.console(" Encoder: {}".format(bin_enc), logging.INFO) self.logger.console(" Decoder: {}".format(bin_dec), logging.INFO) - runner.run() self.logger.console(" ") - fail_log_dir=None + fail_log_dir = None if self.args["fail_log_dir"] is not None: fail_log_dir = os.path.realpath(self.args["fail_log_dir"]) - if not(os.path.exists(fail_log_dir)): + if not (os.path.exists(fail_log_dir)): os.makedirs(fail_log_dir) for r in runner.results: self.logger.console(r[0]) if fail_log_dir is not None: - shutil.copy(r[3],fail_log_dir) + shutil.copy(r[3], fail_log_dir) self.logger.console(" ") diff --git a/scripts/self_test.py b/scripts/self_test.py index 42b6ce935b..f3d204155b 100755 --- a/scripts/self_test.py +++ b/scripts/self_test.py @@ -31,28 +31,28 @@ """ -import re -import os -import urllib -from pyivastest import IvasScriptsCommon -from pyivastest.IvasSvnBuilder import * -from pyivastest.IvasModeRunner import * -from pyivastest.IvasModeAnalyzer import * -from pyivastest.IvasModeCollector import * -import pyivastest.ivas_svn as svn -import pyivastest.constants as constants +import errno +import multiprocessing import operator -import sys -import pyaudio3dtools +import os import platform -import numpy -import multiprocessing +import re +import shutil +import sys import tempfile +import urllib import urllib.parse -import shutil -import prepare_combined_format_inputs -import errno +import numpy +import prepare_combined_format_inputs +import pyaudio3dtools +import pyivastest.constants as constants +import pyivastest.ivas_svn as svn +from pyivastest import IvasScriptsCommon +from pyivastest.IvasModeAnalyzer import * +from pyivastest.IvasModeCollector import * +from pyivastest.IvasModeRunner import * +from pyivastest.IvasSvnBuilder import * BW_TO_SR = {"nb": 8, "wb": 16, "swb": 32, "fb": 48} SR_TO_BW = {"8": "nb", "16": "wb", "32": "swb", "48": "fb"} @@ -503,12 +503,14 @@ class SelfTest(IvasScriptsCommon.IvasScript): SNR_id.ljust(7, " "), snr_report_ref[snr_chan][SNR_id], snr_report_test[snr_chan][SNR_id], - "identical" - if snr_report_ref[snr_chan][SNR_id] - == snr_report_test[snr_chan][SNR_id] - else "not identical ({0:+.3f})".format( - snr_report_test[snr_chan][SNR_id] - - snr_report_ref[snr_chan][SNR_id] + ( + "identical" + if snr_report_ref[snr_chan][SNR_id] + == snr_report_test[snr_chan][SNR_id] + else "not identical ({0:+.3f})".format( + snr_report_test[snr_chan][SNR_id] + - snr_report_ref[snr_chan][SNR_id] + ) ), ) ) @@ -1002,10 +1004,14 @@ class SelfTest(IvasScriptsCommon.IvasScript): prepare_combined_format_inputs.main() if not os.path.exists(in_file): self.logger.error(f"Test vector {in_file} does not exist!") - raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), in_file) + raise FileNotFoundError( + errno.ENOENT, os.strerror(errno.ENOENT), in_file + ) else: self.logger.error(f"Test vector {in_file} does not exist!") - raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), in_file) + raise FileNotFoundError( + errno.ENOENT, os.strerror(errno.ENOENT), in_file + ) # handle intermediate processing steps, e.g. networksimulator, eid-xor, ... in_file = bs_enc_file @@ -1021,9 +1027,7 @@ class SelfTest(IvasScriptsCommon.IvasScript): proc_cmd[0] = os.path.join(TOOLS_DIR, proc_cmd[0]) - proc_cmd = [ - "{in_file}" if x == in_file else x for x in proc_cmd - ] + proc_cmd = ["{in_file}" if x == in_file else x for x in proc_cmd] if mode[1]: for cmdline_arg in proc_cmd[1:]: if cmdline_arg in mode[1][0]: @@ -1573,7 +1577,7 @@ class SelfTest(IvasScriptsCommon.IvasScript): "corrupt_test_conditions": {"cnt": 0, "conditions": []}, "diff_nsamples_conditions": {"cnt": 0, "conditions": []}, "detailedResults": [], - "failed_modes":[], + "failed_modes": [], } self.run_pesq = self.args["pesq"] failed_ref_conditions = {} @@ -1987,7 +1991,9 @@ class SelfTest(IvasScriptsCommon.IvasScript): self.logger.info("---------------------\n") for mode in run_dict.keys(): if mode in self.fail_results["failed_modes"]: - self.logger.info(f"[FAIL] {run_dict[mode]['cmd']['table_name']}") + self.logger.info( + f"[FAIL] {run_dict[mode]['cmd']['table_name']}" + ) else: self.logger.info(f"[OK] {run_dict[mode]['cmd']['table_name']}") diff --git a/scripts/split_rendering/lc3plus/split_rend_lc3plus_cmdlines.py b/scripts/split_rendering/lc3plus/split_rend_lc3plus_cmdlines.py index d328cc6759..033c25bb60 100755 --- a/scripts/split_rendering/lc3plus/split_rend_lc3plus_cmdlines.py +++ b/scripts/split_rendering/lc3plus/split_rend_lc3plus_cmdlines.py @@ -14,8 +14,12 @@ TEMP_DIR = "tmp" # Config values to iterate over ISM_CONFIGS_NUM_OBJECTS = [1, 2, 3, 4] IVAS_BITRATES = [128000] -PRE_HEAD_ROT_FILES = ["Workspace_msvc/trajectories/pre-renderer_pose_files/pre_yaw-20static.csv"] -POST_HEAD_ROT_FILES = ["Workspace_msvc/trajectories/post-renderer_pose_files/post_0static.csv"] +PRE_HEAD_ROT_FILES = [ + "Workspace_msvc/trajectories/pre-renderer_pose_files/pre_yaw-20static.csv" +] +POST_HEAD_ROT_FILES = [ + "Workspace_msvc/trajectories/post-renderer_pose_files/post_0static.csv" +] RENDER_CONFIG_FILES = [ ####################################################### # Alternative 2 - LC3plus with CLDFB pose correction @@ -43,7 +47,9 @@ def basename(file_path): # Full chain: IVAS_cod -> IVAS_dec -> IVAS_rend(post) -def full_chain(num_objects, ivas_bitrate, pre_head_rot_file, render_config_file, post_head_rot_file): +def full_chain( + num_objects, ivas_bitrate, pre_head_rot_file, render_config_file, post_head_rot_file +): bs_name = f"{TEMP_DIR}/ism{num_objects}_b{ivas_bitrate}_full_chain.g192" cod = [ ENC_PATH, @@ -56,9 +62,15 @@ def full_chain(num_objects, ivas_bitrate, pre_head_rot_file, render_config_file, bs_name, ] - render_config_infix = f"##{basename(render_config_file)}" if render_config_file else "" - split_bs_name = bs_name.replace(".g192", f"##{basename(pre_head_rot_file)}{render_config_infix}##split.bs") - render_config_args = ["-render_config", render_config_file] if render_config_file else [] + render_config_infix = ( + f"##{basename(render_config_file)}" if render_config_file else "" + ) + split_bs_name = bs_name.replace( + ".g192", f"##{basename(pre_head_rot_file)}{render_config_infix}##split.bs" + ) + render_config_args = ( + ["-render_config", render_config_file] if render_config_file else [] + ) dec = [ DEC_PATH, "-T", @@ -70,7 +82,9 @@ def full_chain(num_objects, ivas_bitrate, pre_head_rot_file, render_config_file, split_bs_name, ] - binaural_output_name = split_bs_name.replace(".bs", f"##{basename(post_head_rot_file)}##binaural.wav") + binaural_output_name = split_bs_name.replace( + ".bs", f"##{basename(post_head_rot_file)}##binaural.wav" + ) rend = [ REND_PATH, "-i", @@ -92,11 +106,13 @@ def full_chain(num_objects, ivas_bitrate, pre_head_rot_file, render_config_file, # Renderer chain: IVAS_rend(pre) -> IVAS_rend(post) def rend_chain(num_objects, pre_head_rot_file, render_config_file, post_head_rot_file): - render_config_infix = f"##{basename(render_config_file)}" if render_config_file else "" - split_bs_name = ( - f"{TEMP_DIR}/ism{num_objects}_rend_chain##{basename(pre_head_rot_file)}{render_config_infix}##split.bs" + render_config_infix = ( + f"##{basename(render_config_file)}" if render_config_file else "" + ) + split_bs_name = f"{TEMP_DIR}/ism{num_objects}_rend_chain##{basename(pre_head_rot_file)}{render_config_infix}##split.bs" + render_config_args = ( + ["-render_config", render_config_file] if render_config_file else [] ) - render_config_args = ["-render_config", render_config_file] if render_config_file else [] pre = [ REND_PATH, "-i", @@ -116,7 +132,9 @@ def rend_chain(num_objects, pre_head_rot_file, render_config_file, post_head_rot split_bs_name, ] - binaural_output_name = split_bs_name.replace(".bs", f"##{basename(post_head_rot_file)}##binaural.wav") + binaural_output_name = split_bs_name.replace( + ".bs", f"##{basename(post_head_rot_file)}##binaural.wav" + ) post = [ REND_PATH, "-i", diff --git a/scripts/strip_split_rendering.py b/scripts/strip_split_rendering.py index 0016a7fe4f..16382b189c 100644 --- a/scripts/strip_split_rendering.py +++ b/scripts/strip_split_rendering.py @@ -30,94 +30,94 @@ # the United Nations Convention on Contracts on the International Sales of Goods. # -import os import glob +import os # remove other split rendering files -sr_files_rend=[ - "lib_rend\\ivas_MSPred.c", - "lib_rend\\ivas_NoiseGen.c", - "lib_rend\\ivas_PerceptualModel.c", - "lib_rend\\ivas_PredDecoder.c", - "lib_rend\\ivas_PredEncoder.c", - "lib_rend\\ivas_RMSEnvGrouping.c", - "lib_rend\\ivas_lc3plus_common.c", - "lib_rend\\ivas_lc3plus_common.h", - "lib_rend\\ivas_lc3plus_dec.c", - "lib_rend\\ivas_lc3plus_dec.h", - "lib_rend\\ivas_lc3plus_enc.c", - "lib_rend\\ivas_lc3plus_enc.h", - "lib_rend\\ivas_lcld_decoder.c", - "lib_rend\\ivas_lcld_encoder.c", - "lib_rend\\ivas_lcld_prot.h", - "lib_rend\\ivas_lcld_rom_tables.c" - "lib_rend\\ivas_lcld_rom_tables.h" - "lib_rend\\ivas_splitRend_lcld_dec.c", - "lib_rend\\ivas_splitRend_lcld_enc.c", - "lib_rend\\ivas_splitRendererPLC.c", - "lib_rend\\ivas_splitRendererPost.c", - "lib_rend\\ivas_splitRendererPre.c", - "lib_rend\\ivas_splitRenderer_utils.c" +sr_files_rend = [ + "lib_rend\\ivas_MSPred.c", + "lib_rend\\ivas_NoiseGen.c", + "lib_rend\\ivas_PerceptualModel.c", + "lib_rend\\ivas_PredDecoder.c", + "lib_rend\\ivas_PredEncoder.c", + "lib_rend\\ivas_RMSEnvGrouping.c", + "lib_rend\\ivas_lc3plus_common.c", + "lib_rend\\ivas_lc3plus_common.h", + "lib_rend\\ivas_lc3plus_dec.c", + "lib_rend\\ivas_lc3plus_dec.h", + "lib_rend\\ivas_lc3plus_enc.c", + "lib_rend\\ivas_lc3plus_enc.h", + "lib_rend\\ivas_lcld_decoder.c", + "lib_rend\\ivas_lcld_encoder.c", + "lib_rend\\ivas_lcld_prot.h", + "lib_rend\\ivas_lcld_rom_tables.c" + "lib_rend\\ivas_lcld_rom_tables.h" + "lib_rend\\ivas_splitRend_lcld_dec.c", + "lib_rend\\ivas_splitRend_lcld_enc.c", + "lib_rend\\ivas_splitRendererPLC.c", + "lib_rend\\ivas_splitRendererPost.c", + "lib_rend\\ivas_splitRendererPre.c", + "lib_rend\\ivas_splitRenderer_utils.c", ] -sr_files_util=[ - "lib_util\\split_rend_bfi_file_reader.c", - "lib_util\\split_rend_bfi_file_reader.h", - "lib_util\\split_render_file_read_write.c", - "lib_util\\split_render_file_read_write.h" +sr_files_util = [ + "lib_util\\split_rend_bfi_file_reader.c", + "lib_util\\split_rend_bfi_file_reader.h", + "lib_util\\split_render_file_read_write.c", + "lib_util\\split_render_file_read_write.h", ] if __name__ == "__main__": - wsfile = '.\Workspace_msvc\Workspace_msvc.sln' - rendproj = '.\Workspace_msvc\lib_rend.vcxproj' - utilproj = '.\Workspace_msvc\lib_util.vcxproj' - lc3proj = '.\Workspace_msvc\lib_lc3plus.vcxproj' - + wsfile = ".\Workspace_msvc\Workspace_msvc.sln" + rendproj = ".\Workspace_msvc\lib_rend.vcxproj" + utilproj = ".\Workspace_msvc\lib_util.vcxproj" + lc3proj = ".\Workspace_msvc\lib_lc3plus.vcxproj" + # Remove lc3plus project os.remove(lc3proj) - + # Patch Workspace_msvc.sln - with open(wsfile,'r') as f: + with open(wsfile, "r") as f: lines = f.readlines() - with open(wsfile,'w') as f: + with open(wsfile, "w") as f: skip = 0 for line in lines: - if 'lib_lc3plus.vcxproj' in line: + if "lib_lc3plus.vcxproj" in line: skip = 1 else: if skip == 0: f.write(line) else: skip = skip - 1 - - # Patch lib_rend.vcxproj - with open(rendproj,'r') as f: + + # Patch lib_rend.vcxproj + with open(rendproj, "r") as f: lines = f.readlines() - with open(rendproj,'w') as f: + with open(rendproj, "w") as f: skip = 0 for line in lines: if any([x in line for x in sr_files_rend]): skip = 1 - if 'lib_lc3plus.vcxproj' in line: + if "lib_lc3plus.vcxproj" in line: skip = 4 - if skip == 0: + if skip == 0: f.write(line) else: skip = skip - 1 - - # Patch lib_util.vcxproj - with open(utilproj,'r') as f: + + # Patch lib_util.vcxproj + with open(utilproj, "r") as f: lines = f.readlines() - with open(utilproj,'w') as f: + with open(utilproj, "w") as f: for line in lines: if not any([x in line for x in sr_files_util]): f.write(line) - + # Remove include libraries - for proj in glob.glob('.\Workspace_msvc\*.vcxproj'): - with open(proj,'r') as f: + for proj in glob.glob(".\Workspace_msvc\*.vcxproj"): + with open(proj, "r") as f: lines = f.readlines() - with open(proj,'w') as f: + with open(proj, "w") as f: for line in lines: - f.write(line.replace("..\lib_lc3plus;","")) + f.write(line.replace("..\lib_lc3plus;", "")) diff --git a/tests/cmp_pcm.py b/tests/cmp_pcm.py index 9db7ccd39e..13a1c1ba5a 100755 --- a/tests/cmp_pcm.py +++ b/tests/cmp_pcm.py @@ -1,18 +1,18 @@ #!/usr/bin/env python3 +import argparse import os import sys -import argparse THIS_PATH = os.path.join(os.getcwd(), __file__) sys.path.append(os.path.join(os.path.dirname(THIS_PATH), "../scripts")) +import numpy as np import pyaudio3dtools import pyivastest -import numpy as np -def cmp_pcm(file1, file2, out_config, fs, get_mld = False, mld_lim = 0) -> (int, str): +def cmp_pcm(file1, file2, out_config, fs, get_mld=False, mld_lim=0) -> (int, str): """ Compare 2 PCM files for bitexactness """ @@ -34,7 +34,9 @@ def cmp_pcm(file1, file2, out_config, fs, get_mld = False, mld_lim = 0) -> (int, s1, _ = pyaudio3dtools.audiofile.readfile(file1, nchannels, fs, outdtype=np.int16) s2, _ = pyaudio3dtools.audiofile.readfile(file2, nchannels, fs, outdtype=np.int16) - nchannels = s1.shape[1] # In case of wav input, override the nchannels with the one from the wav header + nchannels = s1.shape[ + 1 + ] # In case of wav input, override the nchannels with the one from the wav header if s1.shape != s2.shape: print( @@ -43,7 +45,9 @@ def cmp_pcm(file1, file2, out_config, fs, get_mld = False, mld_lim = 0) -> (int, ) return 1, "FAIL: File lengths differ" - cmp_result = pyaudio3dtools.audioarray.compare(s1, s2, fs, per_frame=False, get_mld=get_mld) + cmp_result = pyaudio3dtools.audioarray.compare( + s1, s2, fs, per_frame=False, get_mld=get_mld + ) if cmp_result["bitexact"]: return 0, "SUCCESS: Files are bitexact" @@ -55,9 +59,9 @@ def cmp_pcm(file1, file2, out_config, fs, get_mld = False, mld_lim = 0) -> (int, if get_mld: mld_msg = f"MLD: {cmp_result['MLD']}" print(mld_msg) - if cmp_result['MLD'] <= mld_lim: + if cmp_result["MLD"] <= mld_lim: return 0, f"MLD: {cmp_result['MLD']} <= {mld_lim}" - else: + else: return 1, f"MLD: {cmp_result['MLD']} > {mld_lim}" return 1, "Non-BE" diff --git a/tests/codec_be_on_mr_nonselection/test_masa_enc_dec.py b/tests/codec_be_on_mr_nonselection/test_masa_enc_dec.py index da51049da3..8122074bc8 100644 --- a/tests/codec_be_on_mr_nonselection/test_masa_enc_dec.py +++ b/tests/codec_be_on_mr_nonselection/test_masa_enc_dec.py @@ -33,14 +33,15 @@ __doc__ = """ The outputs are compared with C generated references. """ -import os import errno -import pytest -from typing import Optional +import os from filecmp import cmp +from typing import Optional + +import pytest -from tests.conftest import EncoderFrontend, DecoderFrontend from tests.cmp_pcm import cmp_pcm +from tests.conftest import DecoderFrontend, EncoderFrontend # params # output_mode_list = ['MONO', 'STEREO', '5_1', '7_1', '5_1_2', '5_1_4', '7_1_4', 'FOA', 'HOA2', 'HOA3', 'BINAURAL', 'BINAURAL_ROOM', 'EXT'] @@ -203,17 +204,22 @@ def test_masa_enc_dec( # Compare audio outputs pcmcmp_res, reason = cmp_pcm( - dec_output_dut, dec_output_ref, output_mode, int(out_fs * 1000), get_mld=get_mld, mld_lim=get_mld_lim + dec_output_dut, + dec_output_ref, + output_mode, + int(out_fs * 1000), + get_mld=get_mld, + mld_lim=get_mld_lim, ) if get_mld: mld = 0 if "MLD" in reason: - mld = float(reason.split(':')[1].split()[0]) - record_property("MLD",mld) + mld = float(reason.split(":")[1].split()[0]) + record_property("MLD", mld) if get_mld and get_mld_lim > 0: if pcmcmp_res != 0: - pytest.fail(reason) + pytest.fail(reason) else: # Fail if compare fails compare result if metacmp_res == False and pcmcmp_res != 0: @@ -230,19 +236,24 @@ def test_masa_enc_dec( filecmp_res = cmp(dec_output_ref, dec_output_dut) if filecmp_res == False: cmp_result, reason = cmp_pcm( - dec_output_dut, dec_output_ref, output_mode, int(out_fs * 1000), get_mld=get_mld, mld_lim=get_mld_lim + dec_output_dut, + dec_output_ref, + output_mode, + int(out_fs * 1000), + get_mld=get_mld, + mld_lim=get_mld_lim, ) if get_mld: mld = 0 if "MLD" in reason: - mld = float(reason.split(':')[1].split()[0]) - record_property("MLD",mld) + mld = float(reason.split(":")[1].split()[0]) + record_property("MLD", mld) # Report compare result if cmp_result != 0: - pytest.fail(reason) + pytest.fail(reason) else: if get_mld: - record_property("MLD","0") + record_property("MLD", "0") print("Comparison bit exact") # remove_output( 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 34138c4b07..c020f84dfb 100644 --- a/tests/codec_be_on_mr_nonselection/test_param_file.py +++ b/tests/codec_be_on_mr_nonselection/test_param_file.py @@ -32,19 +32,20 @@ __doc__ = """ Execute tests specified via a parameter file. """ -import os -from pathlib import Path import errno -import platform import filecmp +import os +import platform +from pathlib import Path from subprocess import run + import pytest + from tests.cmp_pcm import cmp_pcm +from tests.conftest import DecoderFrontend, EncoderFrontend from tests.cut_pcm import cut_samples -from tests.conftest import EncoderFrontend, DecoderFrontend from tests.testconfig import PARAM_FILE - VALID_DEC_OUTPUT_CONF = [ "MONO", "STEREO", @@ -200,7 +201,7 @@ def test_param_file_tests( is_exist = os.path.exists(cut_file) if is_exist: os.remove(cut_file) - + # check for networkSimulator_g192 command line if sim_opts != "": sim_split = sim_opts.split() @@ -230,7 +231,7 @@ def test_param_file_tests( update_ref, rootdir, ) - + # check for eid-xor command line if eid_opts != "": eid_split = eid_opts.split() @@ -255,7 +256,7 @@ def test_param_file_tests( update_ref, rootdir, ) - + # evaluate decoder options dec_split = dec_opts.split() assert len(dec_split) >= 3 @@ -302,7 +303,6 @@ def test_param_file_tests( assert bitstream_file_dec == "bit" # in the parameter file, only "bit" is used as bitstream file name # -> re-use bitstream filename from encoder call - # the output file is not the real output filename # -> construct output filename @@ -321,21 +321,26 @@ def test_param_file_tests( update_ref, tracefile_dec, ) - + if update_ref in [0, 2]: dut_output_file = f"{dut_base_path}/param_file/dec/{output_file}" ref_output_file = f"{reference_path}/param_file/dec/{output_file}" fs = int(sampling_rate) * 1000 output_differs, reason = cmp_pcm( - dut_output_file, ref_output_file, output_config, fs, get_mld=get_mld, mld_lim=get_mld_lim + dut_output_file, + ref_output_file, + output_config, + fs, + get_mld=get_mld, + mld_lim=get_mld_lim, ) md_out_files = get_expected_md_files(ref_output_file, enc_split, output_config) if get_mld: mld = 0 if "MLD" in reason: - mld = float(reason.split(':')[1].split()[0]) - record_property("MLD",mld) + mld = float(reason.split(":")[1].split()[0]) + record_property("MLD", mld) metadata_differs = False for md_file in md_out_files: @@ -354,7 +359,7 @@ def test_param_file_tests( if get_mld and get_mld_lim > 0: if output_differs: - pytest.fail(reason) + pytest.fail(reason) else: if output_differs or metadata_differs: msg = "Difference between ref and dut in " @@ -378,7 +383,6 @@ def test_param_file_tests( os.remove(f"{dut_base_path}/param_file/enc/{testv_base}_{tag_str}.192") - def encode( dut_encoder_frontend, ref_encoder_frontend, @@ -490,7 +494,8 @@ def simulate( cmd_opts[2] = f"{dut_out_dir}/{netsim_outfile}" # dut_out_file cmd_opts[3] = f"{dut_out_dir}/{netsim_tracefile}" run(netsim + cmd_opts, check=False) - + + def error_insertion( reference_path, dut_base_path, @@ -501,7 +506,7 @@ def error_insertion( """ Call eid-xor to insert frame erasure on REF and/or DUT encoder output. """ - + # directories dut_out_dir = f"{dut_base_path}/param_file/enc" ref_out_dir = f"{reference_path}/param_file/enc" @@ -511,28 +516,21 @@ def error_insertion( ref_out_file = f"{ref_out_dir}/{eid_xor_outfile}" if platform.system() == "Windows": - eid_xor = [ - os.path.join( - rootdir, "scripts", "tools", "Win32", "eid-xor.exe" - ) - ] + eid_xor = [os.path.join(rootdir, "scripts", "tools", "Win32", "eid-xor.exe")] elif platform.system() in ["Linux", "Darwin"]: eid_xor = [ - os.path.join( - rootdir, "scripts", "tools", platform.system(), "eid-xor" - ) + os.path.join(rootdir, "scripts", "tools", platform.system(), "eid-xor") ] else: assert False, f"eid-xor not available for {platform.system()}" - if update_ref == 1 or update_ref == 2 and not os.path.exists(ref_out_file): # call eid-xor on REF encoder output cmd_opts = eid_opts_list cmd_opts[-3] = f"{ref_out_dir}/{eid_xor_infile}" cmd_opts[-1] = f"{ref_out_dir}/{eid_xor_outfile}" # ref_out_file run(eid_xor + cmd_opts, check=False) - + if update_ref in [0, 2]: # call eid-xor on DUT encoder output cmd_opts = eid_opts_list @@ -540,6 +538,7 @@ def error_insertion( cmd_opts[-1] = f"{dut_out_dir}/{eid_xor_outfile}" # ref_out_file run(eid_xor + cmd_opts, check=False) + def decode( decoder_frontend, ref_decoder_frontend, diff --git a/tests/codec_be_on_mr_nonselection/test_sba_bs_dec_plc.py b/tests/codec_be_on_mr_nonselection/test_sba_bs_dec_plc.py index 55c1e40a8f..a049c8453f 100644 --- a/tests/codec_be_on_mr_nonselection/test_sba_bs_dec_plc.py +++ b/tests/codec_be_on_mr_nonselection/test_sba_bs_dec_plc.py @@ -1,5 +1,4 @@ -__copyright__ = \ - """ +__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, @@ -29,27 +28,27 @@ __copyright__ = \ the United Nations Convention on Contracts on the International Sales of Goods. """ -__doc__ = \ - """ +__doc__ = """ Execute SBA decoder tests using different PLC patterns. """ -import os import errno +import os + import pytest from tests.cmp_pcm import cmp_pcm from tests.conftest import DecoderFrontend # params -tag_list = ['stvFOA'] -plc_patterns = ['PLperc12mblen5', 'PLperc40mblen50', 'PLperc42mblen2'] -dtx_set = ['0', '1'] -ivas_br_list = ['13200','16400','32000', '64000', '96000', '256000'] -sampling_rate_list = ['48', '32', '16'] +tag_list = ["stvFOA"] +plc_patterns = ["PLperc12mblen5", "PLperc40mblen50", "PLperc42mblen2"] +dtx_set = ["0", "1"] +ivas_br_list = ["13200", "16400", "32000", "64000", "96000", "256000"] +sampling_rate_list = ["48", "32", "16"] gain_list = [0, 1] -AbsTol = '0' +AbsTol = "0" def check_and_makedir(dir_path): @@ -93,17 +92,22 @@ def test_sba_plc_system( get_mld_lim, ): SID = 0 - if dtx == '1' and ivas_br not in ['13200','16400','24400','32000', '64000']: + if dtx == "1" and ivas_br not in ["13200", "16400", "24400", "32000", "64000"]: # skip high bitrates for DTX until DTX issue is resolved pytest.skip() - if ivas_br == '13200' or ivas_br == '16400': - if dtx == '1' and gain_flag == 0 and fs != '16' and plc_pattern == 'PLperc12mblen5': + if ivas_br == "13200" or ivas_br == "16400": + if ( + dtx == "1" + and gain_flag == 0 + and fs != "16" + and plc_pattern == "PLperc12mblen5" + ): SID = 1 else: pytest.skip() - if gain_flag == 1 and ivas_br not in ['13200','16400','24400','32000']: + if gain_flag == 1 and ivas_br not in ["13200", "16400", "24400", "32000"]: pytest.skip() - tag = tag + fs + 'c' + tag = tag + fs + "c" # dec sba_dec_plc( @@ -153,7 +157,7 @@ def sba_dec_plc( tag_out = f"{tag}_ivasbr{ivas_br[:-3]}k_DTX{dtx}" if gain_flag != -1: - tag_out += f'_Gain{gain_flag}' + tag_out += f"_Gain{gain_flag}" plc_tag_out = f"{tag_out}_{plc_pattern}" dut_out_dir = f"{dut_base_path}/sba_bs/raw" @@ -197,12 +201,19 @@ def sba_dec_plc( # -------------- compare cmd -------------- fs = int(sampling_rate) * 1000 - cmp_result, reason = cmp_pcm(dut_out_raw, ref_out_raw, output_config, fs, get_mld=get_mld, mld_lim=get_mld_lim) + cmp_result, reason = cmp_pcm( + dut_out_raw, + ref_out_raw, + output_config, + fs, + get_mld=get_mld, + mld_lim=get_mld_lim, + ) if get_mld: mld = 0 if "MLD" in reason: - mld = float(reason.split(':')[1].split()[0]) - record_property("MLD",mld) + mld = float(reason.split(":")[1].split()[0]) + record_property("MLD", mld) # report compare result if cmp_result != 0: diff --git a/tests/codec_be_on_mr_nonselection/test_sba_bs_enc.py b/tests/codec_be_on_mr_nonselection/test_sba_bs_enc.py index 00a6a54db1..4fdde6e9ae 100644 --- a/tests/codec_be_on_mr_nonselection/test_sba_bs_enc.py +++ b/tests/codec_be_on_mr_nonselection/test_sba_bs_enc.py @@ -33,14 +33,15 @@ __doc__ = """ The outputs are compared with C generated references. """ -import os import errno +import os + import pytest +from cut_bs import cut_from_start from tests.cmp_pcm import cmp_pcm +from tests.conftest import DecoderFrontend, EncoderFrontend from tests.cut_pcm import cut_samples -from tests.conftest import EncoderFrontend, DecoderFrontend -from cut_bs import cut_from_start # params @@ -190,10 +191,15 @@ def test_sba_enc_system( # skip high bitrates for DTX until DTX issue is resolved pytest.skip() if SID == 1: - if ivas_br not in ["13200", "16400", "64000"] or fs == "16" or gain_flag == 1 or dtx == "0": + if ( + ivas_br not in ["13200", "16400", "64000"] + or fs == "16" + or gain_flag == 1 + or dtx == "0" + ): pytest.skip() else: - if ivas_br in ["13200","16400"]: + if ivas_br in ["13200", "16400"]: pytest.skip() if ivas_br == "sw_24k4_256k.bin" and gain_flag != 1: pytest.skip() @@ -249,7 +255,7 @@ def test_sba_enc_system( gain_flag, keep_files, get_mld=get_mld, - get_mld_lim=get_mld_lim + get_mld_lim=get_mld_lim, ) @@ -685,12 +691,19 @@ def sba_dec( ) fs = int(sampling_rate) * 1000 - cmp_result, reason = cmp_pcm(dut_out_raw, ref_out_raw, output_config, fs, get_mld=get_mld, mld_lim=get_mld_lim ) + cmp_result, reason = cmp_pcm( + dut_out_raw, + ref_out_raw, + output_config, + fs, + get_mld=get_mld, + mld_lim=get_mld_lim, + ) if get_mld: mld = 0 if "MLD" in reason: - mld = float(reason.split(':')[1].split()[0]) - record_property("MLD",mld) + mld = float(reason.split(":")[1].split()[0]) + record_property("MLD", mld) # report compare result if cmp_result != 0: diff --git a/tests/codec_be_on_mr_selection/__init__.py b/tests/codec_be_on_mr_selection/__init__.py index c6cbd866ac..2ee63a30a5 100644 --- a/tests/codec_be_on_mr_selection/__init__.py +++ b/tests/codec_be_on_mr_selection/__init__.py @@ -28,14 +28,16 @@ accordance with the laws of the Federal Republic of Germany excluding its confli the United Nations Convention on Contracts on the International Sales of Goods. """ -import tempfile -import pytest -import os import filecmp -from pathlib import Path +import os import subprocess -from .constants import OUTPUT_MODES_AND_OPTIONS_FOR_EXPERIMENT, DTX_ON, FER_5PERC +import tempfile +from pathlib import Path + +import pytest + from ..testconfig import MD5_REF_DICT +from .constants import DTX_ON, FER_5PERC, OUTPUT_MODES_AND_OPTIONS_FOR_EXPERIMENT HERE = Path(__file__).parent # set environment variables in CI job @@ -95,7 +97,14 @@ def apply_error_pattern_on_bitstream( if in_bitstream == out_bitstream: in_bitstream = Path(tmpdir).joinpath(in_bitstream.name) - cmd = ["eid-xor", "-vbr", "-fer", str(in_bitstream), str(error_pattern), str(out_bitstream)] + cmd = [ + "eid-xor", + "-vbr", + "-fer", + str(in_bitstream), + str(error_pattern), + str(out_bitstream), + ] subprocess.run(cmd) diff --git a/tests/codec_be_on_mr_selection/constants.py b/tests/codec_be_on_mr_selection/constants.py index 4116ca73e7..8f01cf9332 100644 --- a/tests/codec_be_on_mr_selection/constants.py +++ b/tests/codec_be_on_mr_selection/constants.py @@ -29,8 +29,7 @@ the United Nations Convention on Contracts on the International Sales of Goods. """ from itertools import product -from typing import Union, List - +from typing import List, Union DTX_ON = "DTXon" DTX_OFF = "DTXoff" diff --git a/tests/codec_be_on_mr_selection/test_experiments.py b/tests/codec_be_on_mr_selection/test_experiments.py index 991b7350a6..35152955e9 100644 --- a/tests/codec_be_on_mr_selection/test_experiments.py +++ b/tests/codec_be_on_mr_selection/test_experiments.py @@ -29,13 +29,14 @@ the United Nations Convention on Contracts on the International Sales of Goods. """ import pytest + from . import run_check from .constants import ( - P800_CATEGORIES, + BS1534_MASA_PARAMS_UNIFIED, BS1534_N_FILES, - P800_PARAMS_UNIFIED, BS1534_PARAMS_UNIFIED, - BS1534_MASA_PARAMS_UNIFIED, + P800_CATEGORIES, + P800_PARAMS_UNIFIED, ) diff --git a/tests/conftest.py b/tests/conftest.py index d3d21aa903..221d61e63c 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -33,15 +33,17 @@ Pytest customization (configuration and fixtures) for the IVAS codec test suite. """ import logging -from pathlib import Path +import os import platform -from subprocess import run, TimeoutExpired, CalledProcessError, STDOUT +import tempfile import textwrap +from pathlib import Path +from subprocess import STDOUT, CalledProcessError, TimeoutExpired, run from typing import Optional, Union -import os -from tests import testconfig + import pytest -import tempfile + +from tests import testconfig logger = logging.getLogger(__name__) USE_LOGGER_FOR_DBG = False # current tests do not make use of the logger feature @@ -49,6 +51,7 @@ USE_LOGGER_FOR_DBG = False # current tests do not make use of the logger featur HERE = Path(__file__).parent SCRIPTS_DIR = str(HERE.parent.joinpath("scripts").absolute()) import sys + sys.path.append(SCRIPTS_DIR) import prepare_combined_format_inputs @@ -171,6 +174,7 @@ def pytest_addoption(parser): default="0", ) + @pytest.fixture(scope="session", autouse=True) def update_ref(request): """ @@ -181,6 +185,7 @@ def update_ref(request): """ return int(request.config.getoption("--update_ref")) + @pytest.fixture(scope="session", autouse=True) def create_combined_formats_testvectors(request): """ @@ -189,6 +194,7 @@ def create_combined_formats_testvectors(request): prepare_combined_format_inputs.main() + @pytest.fixture(scope="session", autouse=True) def get_mld(request): """ @@ -196,6 +202,7 @@ def get_mld(request): """ return request.config.option.mld + @pytest.fixture(scope="session", autouse=True) def get_mld_lim(request): """ @@ -203,6 +210,7 @@ def get_mld_lim(request): """ return float(request.config.getoption("--mld-lim")) + @pytest.fixture(scope="session") def keep_files(request) -> bool: """ @@ -445,7 +453,7 @@ class DecoderFrontend: command.extend(["-q"]) if plc_file is not None: - + system = platform.system() if system == "Windows": @@ -466,7 +474,7 @@ class DecoderFrontend: eid_command += [ str(input_bitstream_path), str(plc_file), - str(input_bitstream_path) + eid_output_suffix + str(input_bitstream_path) + eid_output_suffix, ] try: @@ -495,7 +503,9 @@ class DecoderFrontend: log_dbg_msg(f"{self._type} decoder command:\n{cmd_str}") try: - result = run(command, capture_output=True, check=False, timeout=self.timeout) + result = run( + command, capture_output=True, check=False, timeout=self.timeout + ) except TimeoutExpired: pytest.fail(f"{self._type} decoder run timed out after {self.timeout}s.") diff --git a/tests/create_short_testvectors.py b/tests/create_short_testvectors.py index a7c1b55212..0b8ee79c81 100755 --- a/tests/create_short_testvectors.py +++ b/tests/create_short_testvectors.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -__copyright__ = \ -""" +__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, @@ -31,13 +30,13 @@ accordance with the laws of the Federal Republic of Germany excluding its confli the United Nations Convention on Contracts on the International Sales of Goods. """ -__doc__ = \ -""" +__doc__ = """ Create short (5sec) testvectors. """ import sys from pathlib import Path + from cut_pcm import cut_samples HERE = Path(__file__).parent.resolve() @@ -49,17 +48,23 @@ CUT_LEN = "5.0" def create_short_testvectors(): - for fs in ['48', '32', '16']: + for fs in ["48", "32", "16"]: in_file = f"{TEST_VECTOR_DIR}/stvFOA{fs}c.wav" cut_gain = "1.0" cut_file = f"{TEST_VECTOR_DIR}/stvFOA{fs}c_cut.wav" - cut_samples(in_file, cut_file, NUM_CHANNELS, fs + "000", CUT_FROM, CUT_LEN, cut_gain) + cut_samples( + in_file, cut_file, NUM_CHANNELS, fs + "000", CUT_FROM, CUT_LEN, cut_gain + ) cut_gain = "16.0" cut_file = f"{TEST_VECTOR_DIR}/stvFOA{fs}c_cut_{cut_gain}.wav" - cut_samples(in_file, cut_file, NUM_CHANNELS, fs + "000", CUT_FROM, CUT_LEN, cut_gain) + cut_samples( + in_file, cut_file, NUM_CHANNELS, fs + "000", CUT_FROM, CUT_LEN, cut_gain + ) cut_gain = ".004" cut_file = f"{TEST_VECTOR_DIR}/stvFOA{fs}c_cut_{cut_gain}.wav" - cut_samples(in_file, cut_file, NUM_CHANNELS, fs + "000", CUT_FROM, CUT_LEN, cut_gain) + cut_samples( + in_file, cut_file, NUM_CHANNELS, fs + "000", CUT_FROM, CUT_LEN, cut_gain + ) if __name__ == "__main__": diff --git a/tests/cut_pcm.py b/tests/cut_pcm.py index 420dc9ce02..60bac699cb 100755 --- a/tests/cut_pcm.py +++ b/tests/cut_pcm.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -__copyright__ = \ -""" +__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, @@ -31,8 +30,7 @@ accordance with the laws of the Federal Republic of Germany excluding its confli the United Nations Convention on Contracts on the International Sales of Goods. """ -__doc__ = \ -""" +__doc__ = """ Script to cut samples from a 16-bit PCM file. USAGE : cut_pcm.py in_file_pcm out_file_pcm num_channels sample_rate start duration [gain] @@ -45,11 +43,12 @@ duration: duration in seconds gain: optional gain value to apply to the copied samples """ -import sys import platform -import numpy as np +import sys from pathlib import Path +import numpy as np + HERE = Path(__file__).parent.resolve() SCRIPTS_DIR = str(HERE.joinpath("../scripts").resolve()) sys.path.append(SCRIPTS_DIR) @@ -61,14 +60,19 @@ def usage(): return 1 -def cut_samples(in_file, out_file, num_channels, sample_rate, start, duration, gain="1.0"): +def cut_samples( + in_file, out_file, num_channels, sample_rate, start, duration, gain="1.0" +): """ Function to cut samples from an audio file (wav or pcm) """ # check for python >= 3.7 if sys.version_info[0] < 3 or sys.version_info[1] < 7: - sys.exit("This script is written for Python >= 3.7. Found: " + platform.python_version()) + sys.exit( + "This script is written for Python >= 3.7. Found: " + + platform.python_version() + ) # all input parameters are strings - convert some fs = int(sample_rate) @@ -87,10 +91,10 @@ def cut_samples(in_file, out_file, num_channels, sample_rate, start, duration, g + f" - input is too short ({num_in_samples})" ) - s_out = s[num_samples_to_skip:num_samples_to_skip + dur_samples, :] * gain_f + s_out = s[num_samples_to_skip : num_samples_to_skip + dur_samples, :] * gain_f audiofile.writefile(out_file, s_out, fs) - + def main(argv): if len(argv) < 7: diff --git a/tests/hrtf_binary_loading/constants.py b/tests/hrtf_binary_loading/constants.py index 1895443007..ab5ae13fe2 100644 --- a/tests/hrtf_binary_loading/constants.py +++ b/tests/hrtf_binary_loading/constants.py @@ -33,11 +33,7 @@ import re from pathlib import Path -from tests.renderer.constants import ( - OUTPUT_FORMATS_BINAURAL, - SCRIPTS_DIR, - TESTV_DIR, -) +from tests.renderer.constants import OUTPUT_FORMATS_BINAURAL, SCRIPTS_DIR, TESTV_DIR TESTS_DIR = Path(__file__).parent diff --git a/tests/hrtf_binary_loading/test_renderer_ROM_vs_file.py b/tests/hrtf_binary_loading/test_renderer_ROM_vs_file.py index a02b7b7c2d..5adcc5ae73 100644 --- a/tests/hrtf_binary_loading/test_renderer_ROM_vs_file.py +++ b/tests/hrtf_binary_loading/test_renderer_ROM_vs_file.py @@ -33,15 +33,14 @@ import pytest from tests.hrtf_binary_loading.utils import * - from tests.renderer.constants import ( - INPUT_FORMATS_AMBI, - INPUT_FORMATS_ISM, - INPUT_FORMATS_MC, - CUSTOM_LS_TO_TEST, CUSTOM_LAYOUT_DIR, + CUSTOM_LS_TO_TEST, FRAMING_TO_TEST, HR_TRAJECTORY_DIR, + INPUT_FORMATS_AMBI, + INPUT_FORMATS_ISM, + INPUT_FORMATS_MC, ) """ Ambisonics """ diff --git a/tests/hrtf_binary_loading/utils.py b/tests/hrtf_binary_loading/utils.py index 577ca2ed3f..3ce3702d8d 100644 --- a/tests/hrtf_binary_loading/utils.py +++ b/tests/hrtf_binary_loading/utils.py @@ -38,7 +38,7 @@ from typing import Dict, Optional import pytest from tests.renderer.compare_audio import compare_audio_arrays -from tests.renderer.utils import check_BE, run_cmd, test_info, run_renderer +from tests.renderer.utils import check_BE, run_cmd, run_renderer, test_info from .constants import * diff --git a/tests/prepare_pytests.py b/tests/prepare_pytests.py index b3cd5bf6ef..4cd6d07120 100755 --- a/tests/prepare_pytests.py +++ b/tests/prepare_pytests.py @@ -34,13 +34,13 @@ __doc__ = """ Script to prepare the pytest tests. """ -import os -import sys import argparse -import subprocess +import os import platform - +import subprocess +import sys from pathlib import Path + from create_short_testvectors import create_short_testvectors BIN_EXT = ".exe" if platform.system() == "Windows" else "" @@ -58,7 +58,10 @@ def main(argv): """ # check for python >= 3.7 if sys.version_info[0] < 3 or sys.version_info[1] < 7: - sys.exit("This script is written for Python >= 3.7. Found: " + platform.python_version()) + sys.exit( + "This script is written for Python >= 3.7. Found: " + + platform.python_version() + ) parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter) parser.add_argument( @@ -78,15 +81,21 @@ def main(argv): use_dut_binaries = False # check for DUT binaries - if not os.path.exists(DEFAULT_ENCODER_DUT) or not os.path.exists(DEFAULT_DECODER_DUT): + if not os.path.exists(DEFAULT_ENCODER_DUT) or not os.path.exists( + DEFAULT_DECODER_DUT + ): sys.exit( f"Need DUT binaries {DEFAULT_ENCODER_DUT} and {DEFAULT_DECODER_DUT}.\n" "Please create the binaries." ) # check for REF binaries - if not os.path.exists(DEFAULT_ENCODER_REF) or not os.path.exists(DEFAULT_DECODER_REF): - print(f"REF binaries {DEFAULT_ENCODER_REF} and {DEFAULT_DECODER_REF} not found.") + if not os.path.exists(DEFAULT_ENCODER_REF) or not os.path.exists( + DEFAULT_DECODER_REF + ): + print( + f"REF binaries {DEFAULT_ENCODER_REF} and {DEFAULT_DECODER_REF} not found." + ) print("DUT binaries will be used for reference generation.") use_dut_binaries = True @@ -98,7 +107,11 @@ def main(argv): else: base_cmd = ["python3", "-m", "pytest"] if args.param_file: - base_cmd += ["tests/codec_be_on_mr_nonselection/test_param_file.py", "--param_file", args.param_file] + base_cmd += [ + "tests/codec_be_on_mr_nonselection/test_param_file.py", + "--param_file", + args.param_file, + ] else: base_cmd += ["tests/codec_be_on_mr_nonselection"] base_cmd += [ diff --git a/tests/renderer/test_renderer.py b/tests/renderer/test_renderer.py index 27b6c73020..9718f710d8 100644 --- a/tests/renderer/test_renderer.py +++ b/tests/renderer/test_renderer.py @@ -42,19 +42,22 @@ from .utils import * ############################################################################## """ Ambisonics """ + @pytest.mark.create_ref @pytest.mark.parametrize("out_fmt", OUTPUT_FORMATS) @pytest.mark.parametrize("in_fmt", INPUT_FORMATS_AMBI) @pytest.mark.parametrize("frame_size", FRAMING_TO_TEST) -def test_ambisonics(record_property, test_info, in_fmt, out_fmt, frame_size, get_mld, get_mld_lim): +def test_ambisonics( + record_property, test_info, in_fmt, out_fmt, frame_size, get_mld, get_mld_lim +): run_renderer( - record_property, + record_property, test_info, in_fmt, out_fmt, frame_size=frame_size, - get_mld=get_mld, - mld_lim=get_mld_lim, + get_mld=get_mld, + mld_lim=get_mld_lim, ) @@ -62,15 +65,17 @@ def test_ambisonics(record_property, test_info, in_fmt, out_fmt, frame_size, get @pytest.mark.parametrize("out_fmt", OUTPUT_FORMATS_BINAURAL) @pytest.mark.parametrize("in_fmt", INPUT_FORMATS_AMBI) @pytest.mark.parametrize("frame_size", FRAMING_TO_TEST) -def test_ambisonics_binaural_static(record_property, test_info, in_fmt, out_fmt, frame_size, get_mld, get_mld_lim): +def test_ambisonics_binaural_static( + record_property, test_info, in_fmt, out_fmt, frame_size, get_mld, get_mld_lim +): run_renderer( - record_property, + record_property, test_info, in_fmt, out_fmt, frame_size=frame_size, - get_mld=get_mld, - mld_lim=get_mld_lim, + get_mld=get_mld, + mld_lim=get_mld_lim, ) @@ -80,17 +85,24 @@ def test_ambisonics_binaural_static(record_property, test_info, in_fmt, out_fmt, @pytest.mark.parametrize("in_fmt", INPUT_FORMATS_AMBI) @pytest.mark.parametrize("frame_size", FRAMING_TO_TEST) def test_ambisonics_binaural_headrotation( - record_property, test_info, in_fmt, out_fmt, trj_file, frame_size, get_mld, get_mld_lim + record_property, + test_info, + in_fmt, + out_fmt, + trj_file, + frame_size, + get_mld, + get_mld_lim, ): run_renderer( - record_property, + record_property, test_info, in_fmt, out_fmt, trj_file=HR_TRAJECTORY_DIR.joinpath(f"{trj_file}.csv"), frame_size=frame_size, - get_mld=get_mld, - mld_lim=get_mld_lim, + get_mld=get_mld, + mld_lim=get_mld_lim, ) @@ -101,15 +113,17 @@ def test_ambisonics_binaural_headrotation( @pytest.mark.parametrize("out_fmt", OUTPUT_FORMATS) @pytest.mark.parametrize("in_fmt", INPUT_FORMATS_MC) @pytest.mark.parametrize("frame_size", FRAMING_TO_TEST) -def test_multichannel(record_property, test_info, in_fmt, out_fmt, frame_size, get_mld, get_mld_lim): +def test_multichannel( + record_property, test_info, in_fmt, out_fmt, frame_size, get_mld, get_mld_lim +): run_renderer( - record_property, + record_property, test_info, in_fmt, out_fmt, frame_size=frame_size, - get_mld=get_mld, - mld_lim=get_mld_lim, + get_mld=get_mld, + mld_lim=get_mld_lim, ) @@ -117,18 +131,20 @@ def test_multichannel(record_property, test_info, in_fmt, out_fmt, frame_size, g @pytest.mark.parametrize("out_fmt", OUTPUT_FORMATS_BINAURAL) @pytest.mark.parametrize("in_fmt", INPUT_FORMATS_MC) @pytest.mark.parametrize("frame_size", FRAMING_TO_TEST) -def test_multichannel_binaural_static(record_property, test_info, in_fmt, out_fmt, frame_size, get_mld, get_mld_lim): +def test_multichannel_binaural_static( + record_property, test_info, in_fmt, out_fmt, frame_size, get_mld, get_mld_lim +): if in_fmt in ["MONO", "STEREO"]: pytest.skip("MONO or STEREO to Binaural rendering unsupported") run_renderer( - record_property, + record_property, test_info, in_fmt, out_fmt, frame_size=frame_size, - get_mld=get_mld, - mld_lim=get_mld_lim, + get_mld=get_mld, + mld_lim=get_mld_lim, ) @@ -138,7 +154,14 @@ def test_multichannel_binaural_static(record_property, test_info, in_fmt, out_fm @pytest.mark.parametrize("in_fmt", INPUT_FORMATS_MC) @pytest.mark.parametrize("frame_size", FRAMING_TO_TEST) def test_multichannel_binaural_headrotation( - record_property, test_info, in_fmt, out_fmt, trj_file, frame_size, get_mld, get_mld_lim + record_property, + test_info, + in_fmt, + out_fmt, + trj_file, + frame_size, + get_mld, + get_mld_lim, ): if in_fmt in ["MONO", "STEREO"]: pytest.skip("MONO or STEREO to Binaural rendering unsupported") @@ -150,7 +173,7 @@ def test_multichannel_binaural_headrotation( out_fmt, trj_file=HR_TRAJECTORY_DIR.joinpath(f"{trj_file}.csv"), frame_size=frame_size, - get_mld=get_mld, + get_mld=get_mld, mld_lim=get_mld_lim, ) @@ -162,7 +185,9 @@ def test_multichannel_binaural_headrotation( @pytest.mark.parametrize("out_fmt", OUTPUT_FORMATS) @pytest.mark.parametrize("in_fmt", INPUT_FORMATS_ISM) @pytest.mark.parametrize("frame_size", FRAMING_TO_TEST) -def test_ism(record_property, test_info, in_fmt, out_fmt, frame_size, get_mld, get_mld_lim): +def test_ism( + record_property, test_info, in_fmt, out_fmt, frame_size, get_mld, get_mld_lim +): run_renderer( record_property, test_info, @@ -170,7 +195,7 @@ def test_ism(record_property, test_info, in_fmt, out_fmt, frame_size, get_mld, g out_fmt, in_meta_files=FORMAT_TO_METADATA_FILES[in_fmt], frame_size=frame_size, - get_mld=get_mld, + get_mld=get_mld, mld_lim=get_mld_lim, ) @@ -179,21 +204,23 @@ def test_ism(record_property, test_info, in_fmt, out_fmt, frame_size, get_mld, g @pytest.mark.parametrize("out_fmt", OUTPUT_FORMATS_BINAURAL) @pytest.mark.parametrize("in_fmt", INPUT_FORMATS_ISM) @pytest.mark.parametrize("frame_size", FRAMING_TO_TEST) -def test_ism_binaural_static(record_property, test_info, in_fmt, out_fmt, frame_size, get_mld, get_mld_lim): +def test_ism_binaural_static( + record_property, test_info, in_fmt, out_fmt, frame_size, get_mld, get_mld_lim +): try: in_meta_files = FORMAT_TO_METADATA_FILES[in_fmt] except KeyError: in_meta_files = None run_renderer( - record_property, + record_property, test_info, in_fmt, out_fmt, in_meta_files=in_meta_files, frame_size=frame_size, - get_mld=get_mld, - mld_lim=get_mld_lim, + get_mld=get_mld, + mld_lim=get_mld_lim, ) @@ -202,22 +229,31 @@ def test_ism_binaural_static(record_property, test_info, in_fmt, out_fmt, frame_ @pytest.mark.parametrize("out_fmt", OUTPUT_FORMATS_BINAURAL) @pytest.mark.parametrize("in_fmt", INPUT_FORMATS_ISM) @pytest.mark.parametrize("frame_size", FRAMING_TO_TEST) -def test_ism_binaural_headrotation(record_property, test_info, in_fmt, out_fmt, trj_file, frame_size, get_mld, get_mld_lim): +def test_ism_binaural_headrotation( + record_property, + test_info, + in_fmt, + out_fmt, + trj_file, + frame_size, + get_mld, + get_mld_lim, +): try: in_meta_files = FORMAT_TO_METADATA_FILES[in_fmt] except KeyError: in_meta_files = None run_renderer( - record_property, + record_property, test_info, in_fmt, out_fmt, trj_file=HR_TRAJECTORY_DIR.joinpath(f"{trj_file}.csv"), in_meta_files=in_meta_files, frame_size=frame_size, - get_mld=get_mld, - mld_lim=get_mld_lim, + get_mld=get_mld, + mld_lim=get_mld_lim, ) @@ -228,16 +264,18 @@ def test_ism_binaural_headrotation(record_property, test_info, in_fmt, out_fmt, @pytest.mark.parametrize("out_fmt", OUTPUT_FORMATS) @pytest.mark.parametrize("in_fmt", INPUT_FORMATS_MASA) @pytest.mark.parametrize("frame_size", FRAMING_TO_TEST) -def test_masa(record_property, test_info, in_fmt, out_fmt, frame_size, get_mld, get_mld_lim): +def test_masa( + record_property, test_info, in_fmt, out_fmt, frame_size, get_mld, get_mld_lim +): run_renderer( - record_property, + record_property, test_info, in_fmt, out_fmt, in_meta_files=FORMAT_TO_METADATA_FILES[in_fmt], frame_size=frame_size, - get_mld=get_mld, - mld_lim=get_mld_lim, + get_mld=get_mld, + mld_lim=get_mld_lim, ) @@ -245,19 +283,21 @@ def test_masa(record_property, test_info, in_fmt, out_fmt, frame_size, get_mld, @pytest.mark.parametrize("out_fmt", OUTPUT_FORMATS_BINAURAL) @pytest.mark.parametrize("in_fmt", INPUT_FORMATS_MASA) @pytest.mark.parametrize("frame_size", FRAMING_TO_TEST) -def test_masa_binaural_static(record_property, test_info, in_fmt, out_fmt, frame_size, get_mld, get_mld_lim): +def test_masa_binaural_static( + record_property, test_info, in_fmt, out_fmt, frame_size, get_mld, get_mld_lim +): if out_fmt in ["BINAURAL_ROOM_IR", "BINAURAL_ROOM_REVERB"]: pytest.skip("Skipping binaural room outputs for MASA as unimplemented.") run_renderer( - record_property, + record_property, test_info, in_fmt, out_fmt, in_meta_files=FORMAT_TO_METADATA_FILES[in_fmt], frame_size=frame_size, - get_mld=get_mld, - mld_lim=get_mld_lim, + get_mld=get_mld, + mld_lim=get_mld_lim, ) @@ -266,20 +306,29 @@ def test_masa_binaural_static(record_property, test_info, in_fmt, out_fmt, frame @pytest.mark.parametrize("out_fmt", OUTPUT_FORMATS_BINAURAL) @pytest.mark.parametrize("in_fmt", INPUT_FORMATS_MASA) @pytest.mark.parametrize("frame_size", FRAMING_TO_TEST) -def test_masa_binaural_headrotation(record_property, test_info, in_fmt, out_fmt, trj_file, frame_size, get_mld, get_mld_lim): +def test_masa_binaural_headrotation( + record_property, + test_info, + in_fmt, + out_fmt, + trj_file, + frame_size, + get_mld, + get_mld_lim, +): if out_fmt in ["BINAURAL_ROOM_IR", "BINAURAL_ROOM_REVERB"]: pytest.skip("Skipping binaural room outputs for MASA as unimplemented.") run_renderer( - record_property, + record_property, test_info, in_fmt, out_fmt, trj_file=HR_TRAJECTORY_DIR.joinpath(f"{trj_file}.csv"), in_meta_files=FORMAT_TO_METADATA_FILES[in_fmt], frame_size=frame_size, - get_mld=get_mld, - mld_lim=get_mld_lim, + get_mld=get_mld, + mld_lim=get_mld_lim, ) @@ -287,13 +336,13 @@ def test_masa_binaural_headrotation(record_property, test_info, in_fmt, out_fmt, @pytest.mark.parametrize("in_fmt", METADATA_SCENES_TO_TEST_MASA_PREREND) def test_masa_prerend(record_property, test_info, in_fmt, get_mld, get_mld_lim): run_renderer( - record_property, + record_property, test_info, "META", "MASA2", metadata_input=TEST_VECTOR_DIR.joinpath(f"{in_fmt}.txt"), - get_mld=get_mld, - mld_lim=get_mld_lim, + get_mld=get_mld, + mld_lim=get_mld_lim, ) @@ -304,43 +353,49 @@ def test_masa_prerend(record_property, test_info, in_fmt, get_mld, get_mld_lim): @pytest.mark.parametrize("out_fmt", OUTPUT_FORMATS) @pytest.mark.parametrize("in_layout", CUSTOM_LS_TO_TEST) @pytest.mark.parametrize("frame_size", FRAMING_TO_TEST) -def test_custom_ls_input(record_property, test_info, in_layout, out_fmt, frame_size, get_mld, get_mld_lim): +def test_custom_ls_input( + record_property, test_info, in_layout, out_fmt, frame_size, get_mld, get_mld_lim +): run_renderer( - record_property, + record_property, test_info, CUSTOM_LAYOUT_DIR.joinpath(f"{in_layout}.txt"), out_fmt, frame_size=frame_size, - get_mld=get_mld, - mld_lim=get_mld_lim, + get_mld=get_mld, + mld_lim=get_mld_lim, ) @pytest.mark.create_ref @pytest.mark.parametrize("out_fmt", CUSTOM_LS_TO_TEST) @pytest.mark.parametrize("in_fmt", OUTPUT_FORMATS) -def test_custom_ls_output(record_property, test_info, in_fmt, out_fmt, get_mld, get_mld_lim): +def test_custom_ls_output( + record_property, test_info, in_fmt, out_fmt, get_mld, get_mld_lim +): run_renderer( - record_property, + record_property, test_info, in_fmt, CUSTOM_LAYOUT_DIR.joinpath(f"{out_fmt}.txt"), - get_mld=get_mld, - mld_lim=get_mld_lim, + get_mld=get_mld, + mld_lim=get_mld_lim, ) @pytest.mark.create_ref @pytest.mark.parametrize("out_fmt", CUSTOM_LS_TO_TEST) @pytest.mark.parametrize("in_fmt", CUSTOM_LS_TO_TEST) -def test_custom_ls_input_output(record_property, test_info, in_fmt, out_fmt, get_mld, get_mld_lim): +def test_custom_ls_input_output( + record_property, test_info, in_fmt, out_fmt, get_mld, get_mld_lim +): run_renderer( - record_property, + record_property, test_info, CUSTOM_LAYOUT_DIR.joinpath(f"{in_fmt}.txt"), CUSTOM_LAYOUT_DIR.joinpath(f"{out_fmt}.txt"), - get_mld=get_mld, - mld_lim=get_mld_lim, + get_mld=get_mld, + mld_lim=get_mld_lim, ) @@ -348,15 +403,17 @@ def test_custom_ls_input_output(record_property, test_info, in_fmt, out_fmt, get @pytest.mark.parametrize("out_fmt", OUTPUT_FORMATS_BINAURAL) @pytest.mark.parametrize("in_layout", CUSTOM_LS_TO_TEST) @pytest.mark.parametrize("frame_size", FRAMING_TO_TEST) -def test_custom_ls_input_binaural(record_property, test_info, in_layout, out_fmt, frame_size, get_mld, get_mld_lim): +def test_custom_ls_input_binaural( + record_property, test_info, in_layout, out_fmt, frame_size, get_mld, get_mld_lim +): run_renderer( - record_property, + record_property, test_info, CUSTOM_LAYOUT_DIR.joinpath(f"{in_layout}.txt"), out_fmt, frame_size=frame_size, - get_mld=get_mld, - mld_lim=get_mld_lim, + get_mld=get_mld, + mld_lim=get_mld_lim, ) @@ -366,17 +423,24 @@ def test_custom_ls_input_binaural(record_property, test_info, in_layout, out_fmt @pytest.mark.parametrize("in_layout", CUSTOM_LS_TO_TEST) @pytest.mark.parametrize("frame_size", FRAMING_TO_TEST) def test_custom_ls_input_binaural_headrotation( - record_property, test_info, in_layout, out_fmt, trj_file, frame_size, get_mld, get_mld_lim + record_property, + test_info, + in_layout, + out_fmt, + trj_file, + frame_size, + get_mld, + get_mld_lim, ): run_renderer( - record_property, + record_property, test_info, CUSTOM_LAYOUT_DIR.joinpath(f"{in_layout}.txt"), out_fmt, trj_file=HR_TRAJECTORY_DIR.joinpath(f"{trj_file}.csv"), frame_size=frame_size, - get_mld=get_mld, - mld_lim=get_mld_lim, + get_mld=get_mld, + mld_lim=get_mld_lim, ) @@ -387,16 +451,18 @@ def test_custom_ls_input_binaural_headrotation( @pytest.mark.parametrize("out_fmt", OUTPUT_FORMATS) @pytest.mark.parametrize("in_fmt", METADATA_SCENES_TO_TEST) @pytest.mark.parametrize("frame_size", FRAMING_TO_TEST) -def test_metadata(record_property, test_info, in_fmt, out_fmt, frame_size, get_mld, get_mld_lim): +def test_metadata( + record_property, test_info, in_fmt, out_fmt, frame_size, get_mld, get_mld_lim +): run_renderer( - record_property, + record_property, test_info, "META", out_fmt, metadata_input=TEST_VECTOR_DIR.joinpath(f"{in_fmt}.txt"), frame_size=frame_size, - get_mld=get_mld, - mld_lim=get_mld_lim, + get_mld=get_mld, + mld_lim=get_mld_lim, ) @@ -407,15 +473,17 @@ def test_metadata(record_property, test_info, in_fmt, out_fmt, frame_size, get_m @pytest.mark.parametrize("out_fmt", ["STEREO"]) @pytest.mark.parametrize("in_fmt", ["MONO"]) @pytest.mark.parametrize("non_diegetic_pan", ["0", "-30", "45", "90", "-90"]) -def test_non_diegetic_pan_static(record_property, test_info, in_fmt, out_fmt, non_diegetic_pan, get_mld, get_mld_lim): +def test_non_diegetic_pan_static( + record_property, test_info, in_fmt, out_fmt, non_diegetic_pan, get_mld, get_mld_lim +): run_renderer( - record_property, + record_property, test_info, in_fmt, out_fmt, non_diegetic_pan=non_diegetic_pan, - get_mld=get_mld, - mld_lim=get_mld_lim, + get_mld=get_mld, + mld_lim=get_mld_lim, ) @@ -423,15 +491,17 @@ def test_non_diegetic_pan_static(record_property, test_info, in_fmt, out_fmt, no @pytest.mark.parametrize("out_fmt", ["STEREO"]) @pytest.mark.parametrize("in_fmt", ["ISM1"]) @pytest.mark.parametrize("non_diegetic_pan", ["0", "-30", "45", "90", "-90"]) -def test_non_diegetic_pan_ism_static(record_property, test_info, in_fmt, out_fmt, non_diegetic_pan, get_mld, get_mld_lim): +def test_non_diegetic_pan_ism_static( + record_property, test_info, in_fmt, out_fmt, non_diegetic_pan, get_mld, get_mld_lim +): run_renderer( - record_property, + record_property, test_info, in_fmt, out_fmt, non_diegetic_pan=non_diegetic_pan, - get_mld=get_mld, - mld_lim=get_mld_lim, + get_mld=get_mld, + mld_lim=get_mld_lim, ) @@ -455,7 +525,7 @@ def test_ambisonics_binaural_headrotation_refrotzero( pytest.skip("OTR tests only run for smoke test") compare_renderer_args( - record_property, + record_property, test_info, in_fmt, out_fmt, @@ -477,12 +547,14 @@ def test_ambisonics_binaural_headrotation_refrotzero( # Note that reference rotation is supplied per 4 subframes; head rotation per subframe. @pytest.mark.parametrize("out_fmt", OUTPUT_FORMATS_BINAURAL) @pytest.mark.parametrize("in_fmt", INPUT_FORMATS_AMBI) -def test_ambisonics_binaural_headrotation_refrotequal(record_property, test_info, in_fmt, out_fmt, get_mld, get_mld_lim): +def test_ambisonics_binaural_headrotation_refrotequal( + record_property, test_info, in_fmt, out_fmt, get_mld, get_mld_lim +): if test_info.config.option.create_ref or test_info.config.option.create_cut: pytest.skip("OTR tests only run for smoke test") compare_renderer_args( - record_property, + record_property, test_info, in_fmt, out_fmt, @@ -516,7 +588,7 @@ def test_ambisonics_binaural_headrotation_refveczero( pytest.skip("OTR tests only run for smoke test") compare_renderer_args( - record_property, + record_property, test_info, in_fmt, out_fmt, @@ -539,7 +611,9 @@ def test_ambisonics_binaural_headrotation_refveczero( # looking-direction of the head rotation and therefore compensates it (OTR=REF_VEC) @pytest.mark.parametrize("out_fmt", OUTPUT_FORMATS_BINAURAL) @pytest.mark.parametrize("in_fmt", INPUT_FORMATS_AMBI) -def test_ambisonics_binaural_headrotation_refvecequal(record_property, test_info, in_fmt, out_fmt, get_mld, get_mld_lim): +def test_ambisonics_binaural_headrotation_refvecequal( + record_property, test_info, in_fmt, out_fmt, get_mld, get_mld_lim +): if test_info.config.option.create_ref or test_info.config.option.create_cut: pytest.skip("OTR tests only run for smoke test") @@ -548,7 +622,7 @@ def test_ambisonics_binaural_headrotation_refvecequal(record_property, test_info pytest.xfail("WIP : minor differences to be resolved") else: compare_renderer_args( - record_property, + record_property, test_info, in_fmt, out_fmt, @@ -574,7 +648,9 @@ def test_ambisonics_binaural_headrotation_refvecequal(record_property, test_info # in a way that produces the same acoustic output as the ref head rot trajectory (OTR=REF_VEC) @pytest.mark.parametrize("out_fmt", OUTPUT_FORMATS_BINAURAL) @pytest.mark.parametrize("in_fmt", INPUT_FORMATS_AMBI) -def test_ambisonics_binaural_headrotation_refvec_rotating(record_property, test_info, in_fmt, out_fmt, get_mld, get_mld_lim): +def test_ambisonics_binaural_headrotation_refvec_rotating( + record_property, test_info, in_fmt, out_fmt, get_mld, get_mld_lim +): if test_info.config.option.create_ref or test_info.config.option.create_cut: pytest.skip("OTR tests only run for smoke test") @@ -583,7 +659,7 @@ def test_ambisonics_binaural_headrotation_refvec_rotating(record_property, test_ pytest.xfail("WIP : minor differences to be resolved") else: compare_renderer_args( - record_property, + record_property, test_info, in_fmt, out_fmt, @@ -619,7 +695,7 @@ def test_ambisonics_binaural_headrotation_refvec_rotating_fixed_pos_offset( pytest.skip("OTR tests only run for smoke test") compare_renderer_args( - record_property, + record_property, test_info, in_fmt, out_fmt, @@ -654,7 +730,7 @@ def test_ambisonics_binaural_headrotation_refveclev_vs_refvec( pytest.skip("OTR tests only run for smoke test") compare_renderer_args( - record_property, + record_property, test_info, in_fmt, out_fmt, @@ -680,7 +756,9 @@ def test_ambisonics_binaural_headrotation_refveclev_vs_refvec( # in a way that produces the same acoustic output as the ref head rot trajectory (OTR=REF_VEC) @pytest.mark.parametrize("out_fmt", OUTPUT_FORMATS_BINAURAL) @pytest.mark.parametrize("in_fmt", INPUT_FORMATS_MC) -def test_multichannel_binaural_headrotation_refvec_rotating(record_property, test_info, in_fmt, out_fmt, get_mld, get_mld_lim): +def test_multichannel_binaural_headrotation_refvec_rotating( + record_property, test_info, in_fmt, out_fmt, get_mld, get_mld_lim +): if test_info.config.option.create_ref or test_info.config.option.create_cut: pytest.skip("OTR tests only run for smoke test") @@ -715,7 +793,9 @@ def test_multichannel_binaural_headrotation_refvec_rotating(record_property, tes # in a way that produces the same acoustic output as the ref head rot trajectory (OTR=REF_VEC) @pytest.mark.parametrize("out_fmt", OUTPUT_FORMATS_BINAURAL) @pytest.mark.parametrize("in_fmt", INPUT_FORMATS_ISM) -def test_ism_binaural_headrotation_refvec_rotating(record_property, test_info, in_fmt, out_fmt, get_mld, get_mld_lim): +def test_ism_binaural_headrotation_refvec_rotating( + record_property, test_info, in_fmt, out_fmt, get_mld, get_mld_lim +): if test_info.config.option.create_ref or test_info.config.option.create_cut: pytest.skip("OTR tests only run for smoke test") @@ -725,7 +805,7 @@ def test_ism_binaural_headrotation_refvec_rotating(record_property, test_info, i in_meta_files = None compare_renderer_args( - record_property, + record_property, test_info, in_fmt, out_fmt, diff --git a/tests/renderer/utils.py b/tests/renderer/utils.py index 2f83decc0f..82847599b3 100644 --- a/tests/renderer/utils.py +++ b/tests/renderer/utils.py @@ -110,8 +110,8 @@ def run_renderer( binary_suffix: str = "", frame_size: Optional[str] = "20ms", hrtf_file: Optional[str] = None, - get_mld = False, - mld_lim = 0, + get_mld=False, + mld_lim=0, ) -> str: # prepare arguments and filepaths if trj_file is not None: @@ -230,11 +230,18 @@ def run_renderer( out_file_ref = str(OUTPUT_PATH_REF.joinpath(out_file_stem)) if get_mld: - output_differs, reason = cmp_pcm(out_file, out_file_ref, out_fmt, ref_fs, get_mld=get_mld, mld_lim=get_mld_lim) + output_differs, reason = cmp_pcm( + out_file, + out_file_ref, + out_fmt, + ref_fs, + get_mld=get_mld, + mld_lim=get_mld_lim, + ) mld = 0 if "MLD" in reason: - mld = float(reason.split(':')[1].split()[0]) - record_property("MLD",mld) + mld = float(reason.split(":")[1].split()[0]) + record_property("MLD", mld) if output_differs: pytest.fail(f"Output differs: ({reason})") else: @@ -263,7 +270,7 @@ def compare_renderer_args( record_property, test_info, in_fmt, out_fmt, ref_kwargs: Dict, cut_kwargs: Dict ): out_file_ref = run_renderer( - record_property, + record_property, test_info, in_fmt, out_fmt, @@ -271,7 +278,7 @@ def compare_renderer_args( ) ref, ref_fs = readfile(out_file_ref) out_file_cut = run_renderer( - record_property, + record_property, test_info, in_fmt, out_fmt, diff --git a/tests/run_pytests.py b/tests/run_pytests.py index 6ef8d94676..ccac5e1436 100755 --- a/tests/run_pytests.py +++ b/tests/run_pytests.py @@ -37,11 +37,11 @@ Test prerequisites are checked for and check failures are reported. When prerequisites are met, the pytest test is executed. """ -import os -import sys import argparse -import subprocess +import os import platform +import subprocess +import sys from pathlib import Path BIN_EXT = ".exe" if platform.system() == "Windows" else "" @@ -57,7 +57,10 @@ def main(argv): """ # check for python >= 3.7 if sys.version_info[0] < 3 or sys.version_info[1] < 7: - sys.exit("This script is written for Python >= 3.7. Found: " + platform.python_version()) + sys.exit( + "This script is written for Python >= 3.7. Found: " + + platform.python_version() + ) parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter) parser.add_argument( @@ -81,7 +84,9 @@ def main(argv): ) # check for DUT binaries - if not os.path.exists(DEFAULT_ENCODER_DUT) or not os.path.exists(DEFAULT_DECODER_DUT): + if not os.path.exists(DEFAULT_ENCODER_DUT) or not os.path.exists( + DEFAULT_DECODER_DUT + ): sys.exit( f"Need DUT binaries {DEFAULT_ENCODER_DUT} and {DEFAULT_DECODER_DUT}.\n" "Please create the binaries." @@ -93,7 +98,11 @@ def main(argv): else: cmd = ["python3", "-m", "pytest"] if args.param_file: - cmd += ["tests/codec_be_on_mr_nonselection/test_param_file.py", "--param_file", args.param_file] + cmd += [ + "tests/codec_be_on_mr_nonselection/test_param_file.py", + "--param_file", + args.param_file, + ] else: cmd += ["tests/codec_be_on_mr_nonselection"] cmd += ["-n", args.numprocesses] diff --git a/tests/scale_pcm.py b/tests/scale_pcm.py index 9aef914da1..7b6d7f1ec7 100755 --- a/tests/scale_pcm.py +++ b/tests/scale_pcm.py @@ -1,17 +1,18 @@ #!/usr/bin/env python3 -import os -import sys import argparse +import os import pathlib +import sys THIS_PATH = os.path.join(os.getcwd(), __file__) sys.path.append(os.path.join(os.path.dirname(THIS_PATH), "../scripts")) +import concurrent.futures + +import numpy as np import pyaudio3dtools import pyivastest -import numpy as np -import concurrent.futures def scale_folder(folder, factor): @@ -20,14 +21,16 @@ def scale_folder(folder, factor): with concurrent.futures.ThreadPoolExecutor() as executor: executor.map(scale_file, files, files, [factor] * len(files)) -def scale_file(file1, file2, factor = 1.0) -> None: + +def scale_file(file1, file2, factor=1.0) -> None: """ Scale file1 to file2 """ s1, fs = pyaudio3dtools.audiofile.readfile(file1) - s2 = s1 * factor; + s2 = s1 * factor pyaudio3dtools.audiofile.writefile(file2, s2, fs) + if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument("folder", type=pathlib.Path) diff --git a/tests/test_26444.py b/tests/test_26444.py index 262e04b778..2d1771e6a0 100644 --- a/tests/test_26444.py +++ b/tests/test_26444.py @@ -32,21 +32,28 @@ __doc__ = """ Execute tests specified via a parameter file. """ -import os -from pathlib import Path import filecmp +import os import subprocess +from pathlib import Path + import pytest test_dict = {} -TEST_DIR = "evs_be_test" -scripts=["Readme_AMRWB_IO_dec.txt", "Readme_AMRWB_IO_enc.txt", "Readme_EVS_dec.txt","Readme_EVS_enc.txt", "Readme_JBM_dec.txt"] +TEST_DIR = "evs_be_test" +scripts = [ + "Readme_AMRWB_IO_dec.txt", + "Readme_AMRWB_IO_enc.txt", + "Readme_EVS_dec.txt", + "Readme_EVS_enc.txt", + "Readme_JBM_dec.txt", +] for s in scripts: with open(os.path.join(TEST_DIR, s), "r", encoding="UTF-8") as fp: tag = "" enc_opts = "" dec_opts = "" - diff_opts = "" + diff_opts = "" for line in fp.readlines(): if line.startswith("$ENC_BIN"): enc_opts = line @@ -54,15 +61,16 @@ for s in scripts: dec_opts = line if line.startswith("$DIFF_BIN"): diff_opts = line[9:] - tag = s + "--" + diff_opts.split()[1].split('/')[-1] + tag = s + "--" + diff_opts.split()[1].split("/")[-1] if tag in test_dict: print("non-unique tag found - ignoring new entry") - continue + continue test_dict[tag] = (enc_opts, dec_opts, diff_opts) tag = "" enc_opts = "" dec_opts = "" - diff_opts = "" + diff_opts = "" + @pytest.mark.parametrize("test_tag", list(test_dict.keys())) def test_evs_26444(test_tag): @@ -71,16 +79,16 @@ def test_evs_26444(test_tag): if enc_opts: enc_opts = enc_opts.replace("./", TEST_DIR + "/") - subprocess.run(["./IVAS_cod","-q"] + enc_opts.split()[1:]) + subprocess.run(["./IVAS_cod", "-q"] + enc_opts.split()[1:]) if dec_opts: dec_opts = dec_opts.replace("./", TEST_DIR + "/") - subprocess.run(["./IVAS_dec","-q"] + dec_opts.split()[1:]) - + subprocess.run(["./IVAS_dec", "-q"] + dec_opts.split()[1:]) + diff_opts = diff_opts.replace("./", TEST_DIR + "/") - if ';' in diff_opts: - cmd1, cmd2 = diff_opts.split(';') + if ";" in diff_opts: + cmd1, cmd2 = diff_opts.split(";") cmd1 = cmd1.split() - cmd2 = cmd2.split() + cmd2 = cmd2.split() result1 = filecmp.cmp(cmd1[0], cmd1[1]) result2 = filecmp.cmp(cmd2[2], cmd2[3]) else: @@ -89,6 +97,3 @@ def test_evs_26444(test_tag): result2 = True if not (result1 and result2): pytest.fail("Output differs") - - - \ No newline at end of file diff --git a/tests/test_param_file_ltv.py b/tests/test_param_file_ltv.py index bef9049be5..dd1831c517 100644 --- a/tests/test_param_file_ltv.py +++ b/tests/test_param_file_ltv.py @@ -32,17 +32,20 @@ __doc__ = """ Execute tests specified via a parameter file. """ -import os -from pathlib import Path import errno -import platform import filecmp +import os +import platform +from pathlib import Path from subprocess import run + import pytest + from tests.cmp_pcm import cmp_pcm +from tests.conftest import DecoderFrontend, EncoderFrontend from tests.cut_pcm import cut_samples -from tests.conftest import EncoderFrontend, DecoderFrontend -#from tests.testconfig import PARAM_FILE + +# from tests.testconfig import PARAM_FILE VALID_DEC_OUTPUT_CONF = [ @@ -201,7 +204,7 @@ def test_param_file_tests( is_exist = os.path.exists(cut_file) if is_exist: os.remove(cut_file) - + # check for networkSimulator_g192 command line if sim_opts != "": sim_split = sim_opts.split() @@ -231,7 +234,7 @@ def test_param_file_tests( update_ref, rootdir, ) - + # check for eid-xor command line if eid_opts != "": eid_split = eid_opts.split() @@ -256,7 +259,7 @@ def test_param_file_tests( update_ref, rootdir, ) - + # evaluate decoder options dec_split = dec_opts.split() assert len(dec_split) >= 3 @@ -303,7 +306,6 @@ def test_param_file_tests( assert bitstream_file_dec == "bit" # in the parameter file, only "bit" is used as bitstream file name # -> re-use bitstream filename from encoder call - # the output file is not the real output filename # -> construct output filename @@ -322,21 +324,26 @@ def test_param_file_tests( update_ref, tracefile_dec, ) - + if update_ref in [0, 2]: dut_output_file = f"{dut_base_path}/param_file/dec/{output_file}" ref_output_file = f"{reference_path}/param_file/dec/{output_file}" fs = int(sampling_rate) * 1000 output_differs, reason = cmp_pcm( - dut_output_file, ref_output_file, output_config, fs, get_mld=get_mld, mld_lim=get_mld_lim + dut_output_file, + ref_output_file, + output_config, + fs, + get_mld=get_mld, + mld_lim=get_mld_lim, ) md_out_files = get_expected_md_files(ref_output_file, enc_split, output_config) if get_mld: mld = 0 if "MLD" in reason: - mld = float(reason.split(':')[1].split()[0]) - record_property("MLD",mld) + mld = float(reason.split(":")[1].split()[0]) + record_property("MLD", mld) metadata_differs = False for md_file in md_out_files: @@ -375,7 +382,6 @@ def test_param_file_tests( os.remove(f"{dut_base_path}/param_file/enc/{testv_base}_{tag_str}.192") - def encode( dut_encoder_frontend, ref_encoder_frontend, @@ -487,7 +493,8 @@ def simulate( cmd_opts[2] = f"{dut_out_dir}/{netsim_outfile}" # dut_out_file cmd_opts[3] = f"{dut_out_dir}/{netsim_tracefile}" run(netsim + cmd_opts, check=False) - + + def error_insertion( reference_path, dut_base_path, @@ -498,7 +505,7 @@ def error_insertion( """ Call eid-xor to insert frame erasure on REF and/or DUT encoder output. """ - + # directories dut_out_dir = f"{dut_base_path}/param_file/enc" ref_out_dir = f"{reference_path}/param_file/enc" @@ -508,28 +515,21 @@ def error_insertion( ref_out_file = f"{ref_out_dir}/{eid_xor_outfile}" if platform.system() == "Windows": - eid_xor = [ - os.path.join( - rootdir, "scripts", "tools", "Win32", "eid-xor.exe" - ) - ] + eid_xor = [os.path.join(rootdir, "scripts", "tools", "Win32", "eid-xor.exe")] elif platform.system() in ["Linux", "Darwin"]: eid_xor = [ - os.path.join( - rootdir, "scripts", "tools", platform.system(), "eid-xor" - ) + os.path.join(rootdir, "scripts", "tools", platform.system(), "eid-xor") ] else: assert False, f"eid-xor not available for {platform.system()}" - if update_ref == 1 or update_ref == 2 and not os.path.exists(ref_out_file): # call eid-xor on REF encoder output cmd_opts = eid_opts_list cmd_opts[-3] = f"{ref_out_dir}/{eid_xor_infile}" cmd_opts[-1] = f"{ref_out_dir}/{eid_xor_outfile}" # ref_out_file run(eid_xor + cmd_opts, check=False) - + if update_ref in [0, 2]: # call eid-xor on DUT encoder output cmd_opts = eid_opts_list @@ -537,6 +537,7 @@ def error_insertion( cmd_opts[-1] = f"{dut_out_dir}/{eid_xor_outfile}" # ref_out_file run(eid_xor + cmd_opts, check=False) + def decode( decoder_frontend, ref_decoder_frontend, diff --git a/tests/testconfig.py b/tests/testconfig.py index 0c9cba4623..6a60c9de04 100644 --- a/tests/testconfig.py +++ b/tests/testconfig.py @@ -1,5 +1,4 @@ -__copyright__ = \ -""" +__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, @@ -29,11 +28,10 @@ accordance with the laws of the Federal Republic of Germany excluding its confli the United Nations Convention on Contracts on the International Sales of Goods. """ -__doc__ = \ -""" +__doc__ = """ To configure test modules. """ PARAM_FILE = "scripts/config/self_test.prm" -MD5_REF_DICT = dict() \ No newline at end of file +MD5_REF_DICT = dict() -- GitLab