Loading .gitlab-ci.yml +5 −3 Original line number Diff line number Diff line Loading @@ -1012,11 +1012,13 @@ voip-be-on-merge-request: - .test-job-linux-needs-testv-dir - .rules-merge-request stage: test needs: ["build-codec-linux-make", "codec-smoke-test"] needs: ["build-codec-linux-make"] timeout: "10 minutes" script: - *print-common-info - bash ci/ivas_voip_be_test.sh - make clean - make -j - python3 -m pytest tests/test_be_for_jbm_neutral_dly_profile.py clang-format-check: extends: Loading Loading @@ -2205,7 +2207,7 @@ coverage-test-on-main-scheduled: - python3 -m pytest $TESTS_DIR_CODEC_BE_ON_MR/test_param_file.py -v -n auto --update_ref 1 -m create_ref --param_file scripts/config/self_test_evs.prm --ref_encoder_path ./IVAS_cod --ref_decoder_path ./IVAS_dec - bash ci/smoke_test.sh coverage - python3 -m pytest $TESTS_DIR_CODEC_BE_ON_MR/test_param_file.py -v -n auto --update_ref 1 -m create_ref --param_file scripts/config/self_test_ltv.prm --ref_encoder_path ./IVAS_cod --ref_decoder_path ./IVAS_dec - bash ci/ivas_voip_be_test.sh coverage - python3 -m pytest tests/test_be_for_jbm_neutral_dly_profile.py - lcov -c -d obj -o coverage.info # remove apps and lib_util files from coverage - lcov -r coverage.info "*apps*" -o coverage.info Loading ci/ivas_voip_be_test.shdeleted 100755 → 0 +0 −145 Original line number Diff line number Diff line #! /usr/bin/bash # (C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, # Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., # Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, # Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other # contributors to this repository. All Rights Reserved. # This software is protected by copyright law and by international treaties. # The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, # Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., # Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, # Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other # contributors to this repository retain full ownership rights in their respective contributions in # the software. This notice grants no license of any kind, including but not limited to patent # license, nor is any license granted by implication, estoppel or otherwise. # Contributors are required to enter into the IVAS codec Public Collaboration agreement before making # contributions. # This software is provided "AS IS", without any express or implied warranties. The software is in the # development stage. It is intended exclusively for experts who have experience with such software and # solely for the purpose of inspection. All implied warranties of non-infringement, merchantability # and fitness for a particular purpose are hereby disclaimed and excluded. # Any dispute, controversy or claim arising under or in relation to providing this software shall be # submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in # accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and # the United Nations Convention on Contracts on the International Sales of Goods. function usage { echo echo "Usage:" echo " ivas_voip_be_test.sh [MODE]" echo echo " MODE - test (default) or coverage" exit } if [ ! -d "lib_com" ]; then echo "not in root directory! - please run in IVAS root" exit 1 fi if [ -z "$1" ] || [ "$1" == "test" ]; then WORKERS="" BUILD=1 COVERAGE=0 elif [ "$1" == "coverage" ]; then WORKERS="-t 1" BUILD=0 COVERAGE=1 else usage fi if [ $BUILD -eq 1 ];then make clean make all -j fi # Configuration modes=('HOA3_b128_wb_cbr' 'MC_7_1_b96_fb_cbr' 'ISM2_b48_fb_cbr') output_formats=('STEREO' 'FOA' '7_1' 'HOA3') limit_input_to_x_seconds=30 verbosity_cmd="-z console" cfg=./scripts/config/ci_linux.json dly_profile=./scripts/dly_error_profiles/dly_error_profile_0.dat output_dir_default="out" output_dir_voip="out_voip" # Run the same modes in VoIP and non-VoIP mode with a neutral delay profile ./scripts/runIvasCodec.py $verbosity_cmd -p $cfg $WORKERS -U $limit_input_to_x_seconds -m "${modes[@]}" --oc "${output_formats[@]}" -o $output_dir_default | tee voip_be_test_output.txt ./scripts/runIvasCodec.py $verbosity_cmd -p $cfg $WORKERS -U $limit_input_to_x_seconds -m "${modes[@]}" --oc "${output_formats[@]}" -o $output_dir_voip -J "$dly_profile" | tee -a voip_be_test_output.txt # Check if Python scripts above failed. They return status 0 even when running a mode fails, so we have to parse log file if grep -iq failed voip_be_test_output.txt ; then echo "Run errors in runIvasCodec.py" exit 1 fi if [ $COVERAGE -eq 1 ];then # Coverage analysis requires only running the codec and may exit before the comparison part exit 0 fi # Set up Python path python_audio_module_path=$(pwd)/scripts export PYTHONPATH=$python_audio_module_path:$PYTHONPATH python_audiofile_script_path=$python_audio_module_path/pyaudio3dtools/audiofile.py # Trim JBM delay from VoIP output files output_dir_voip_dec="$output_dir_voip"/dec output_dir_voip_dec_trimmed="$output_dir_voip"/dec_trimmed if [[ ! -d $output_dir_voip_dec_trimmed ]]; then mkdir $output_dir_voip_dec_trimmed fi for cut in "$output_dir_voip_dec"/*.wav; do output_path=${cut/$output_dir_voip_dec/$output_dir_voip_dec_trimmed} output_path=${output_path/".wav"/".raw"} python3 "$python_audiofile_script_path" pre-trim 60 "$cut" "$output_path" | tee -a voip_be_test_output.txt done # Convert non-VoIP output from wav to pcm (comparison script doesn't support wav) output_dir_default_dec="$output_dir_default"/dec output_dir_default_dec_pcm="$output_dir_default"/dec_pcm if [[ ! -d $output_dir_default_dec_pcm ]]; then mkdir $output_dir_default_dec_pcm fi for ref in "$output_dir_default_dec"/*.wav; do output_path=${ref/$output_dir_default_dec/$output_dir_default_dec_pcm} output_path=${output_path/".wav"/".raw"} python3 "$python_audiofile_script_path" convert "$ref" "$output_path" | tee -a voip_be_test_output.txt done # Assert BE between non-VoIP and VoIP modes all_be=1 cmp_tool_path=$(pwd)/tests/cmp_pcm.py for ref in "$output_dir_default_dec_pcm"/*; do cut=${ref/$output_dir_default_dec_pcm/$output_dir_voip_dec_trimmed} cut=${cut/".dec."/"_jbm_dly_error_profile_0_dat.dec."} # Print paths of compared files, since the script doesn't do it printf "\nComparing %s and %s\n" "$ref" "$cut" | tee -a voip_be_test_output.txt printout=$($cmp_tool_path "$ref" "$cut") if [ $? -ne 0 ]; then all_be=0 fi printf "%s\n" "$printout" | tee -a voip_be_test_output.txt done if [ $all_be -eq 1 ]; then printf "\n\nAll tested conditions are bit-exact\n" | tee -a voip_be_test_output.txt else printf "\n\nBitexactness problems found!\n" | tee -a voip_be_test_output.txt exit 1; fi scripts/batch_comp_audio.py +26 −7 Original line number Diff line number Diff line Loading @@ -49,16 +49,21 @@ SEG_SNR_EXPR = r"Seg. SNR\s+=(.+)dB" DIFF_EXPR = r"Max Diff\s+=\s+(\d+)" DIFF_STR = { "CompAudio": "{label} Max. diff (PCM) for file {f}: {diff}", "pyaudio3dtools": "{label} Max. diff (PCM) for file {f}: {diff}", "mld": "{label} MLD diff for file {f}: {diff}", } def main(args): tool = args.tool if shutil.which(tool) is None: if tool != "pyaudio3dtools" and shutil.which(tool) is None: print(f"{tool} not in PATH - abort.") sys.exit(-1) test_offset_ms = args.test_offset_ms if tool != "pyaudio3dtools": test_offset_ms = 0 num_files_diff = 0 with OutFileManager(args.out_file) as out_file: Loading @@ -77,7 +82,7 @@ def main(args): # if only one thread is passed, do everything in the main thread # to allow for meaningful debugging if needed for f in common_files: compare_files(f, fol1, fol2, outputs, tool) compare_files(f, fol1, fol2, outputs, tool, test_offset_ms) else: with concurrent.futures.ThreadPoolExecutor( max_workers=args.num_threads Loading @@ -89,6 +94,7 @@ def main(args): repeat(fol2), repeat(outputs), repeat(tool), repeat(test_offset_ms) ) if args.sort: Loading @@ -98,7 +104,7 @@ def main(args): # write csv header if out_file is not None: if tool == "CompAudio": if tool == "CompAudio" or tool == "pyaudio3dtools": out_file.write("filename,diff\n") elif tool == "mld": out_file.write("filename,mld\n") Loading @@ -106,7 +112,7 @@ def main(args): for f, tool_output in out.items(): if tool == "CompAudio": diff, snr, gain, seg_snr = tool_output elif tool == "mld": elif tool == "mld" or tool == "pyaudio3dtools": diff = tool_output if diff > 0: Loading @@ -133,8 +139,10 @@ def main(args): else: print("All files are bitexact") return num_files_diff def compare_files(f, fol1, fol2, outputs_dict, tool): def compare_files(f, fol1, fol2, outputs_dict, tool, test_offset_ms): """ Compare file f in both folders fol1 and fol2 using the given tool and store the parsed difference in outputs_dict. Loading @@ -155,6 +163,11 @@ def compare_files(f, fol1, fol2, outputs_dict, tool): s2, fs2 = readfile(f2, outdtype="int16") cmp_result = compare(s1, s2, fs1, per_frame=False, get_mld=True) tool_output = cmp_result["MLD"] elif tool == "pyaudio3dtools": s1, fs1 = readfile(f1, outdtype="int16") s2, fs2 = readfile(f2, outdtype="int16") cmp_result = compare(s1, s2, fs1, per_frame=False, test_start_offset_ms=test_offset_ms) tool_output = cmp_result["max_abs_diff"] with threading.Lock(): outputs_dict.update({f: tool_output}) Loading Loading @@ -284,10 +297,16 @@ if __name__ == "__main__": ) parser.add_argument( "--tool", choices=["mld", "CompAudio"], choices=["mld", "CompAudio", "pyaudio3dtools"], default="CompAudio", help="Compare tool to run", ) parser.add_argument( "--test_offset_ms", type=int, default=0, help="Offset in miliseconds that is ignored at the start of the files in folder2 (only used if tool=pyaudio3dtools)" ) args = parser.parse_args() main(args) sys.exit(main(args)) scripts/pyaudio3dtools/audioarray.py +12 −0 Original line number Diff line number Diff line Loading @@ -237,6 +237,7 @@ def compare( ssnr_thresh_low: float = -np.inf, ssnr_thresh_high: float = np.inf, apply_thresholds_to_ref_only: bool = False, test_start_offset_ms: int = 0, ) -> dict: """Compare two audio arrays Loading Loading @@ -264,12 +265,23 @@ def compare( Set to True to only apply the threshold comparison for the reference signal for whether to include a segment in the ssnr computation. Use this to align behaviour with the MPEG-D conformance specification. test_start_offset_ms: (non-negative) int offset in miliseconds for test signal. If > 0, the corresponding number of samples will be removed from the test array like so: test = test[sample_offset:, :]. Returns ------- result: dict Comparison results """ if test_start_offset_ms < 0: raise ValueError( f"Test_start_offset_ms has to be non-negative, but {test_start_offset_ms} was given." ) test_start_offset_samples = int(fs * test_start_offset_ms / 1000) test = test[test_start_offset_samples:, :] framesize = fs // 50 diff = abs(test - ref) max_diff = int(diff.max()) Loading scripts/pyaudio3dtools/audiofile.py +20 −0 Original line number Diff line number Diff line Loading @@ -780,5 +780,25 @@ if __name__ == "__main__": parser_convert.add_argument("output_file") parser_convert.set_defaults(func=convert_wrapper) def compare_wrapper(compare_args): if not compare_args.ref_file.endswith(".wav") or not compare_args.test_file.endswith(".wav"): print("Convert currently only supported with WAV file input") exit(-1) s1, fs1 = readfile(compare_args.ref_file, outdtype="int16") s2, fs2 = readfile(compare_args.test_file, outdtype="int16") if fs1 != fs2: print("Can only compare signals of same sampling rate") exit(-1) cmp_result = audioarray.compare(s1, s2, fs1, per_frame=False, test_start_offset_ms=compare_args.test_start_offset_ms) exit(cmp_result["max_abs_diff"]) parser_compare = subparsers.add_parser("compare", help="Compare two wav files for bitexactness") parser_compare.add_argument("ref_file") parser_compare.add_argument("test_file") parser_compare.add_argument("test_start_offset_ms", default=0, type=int) parser_compare.set_defaults(func=compare_wrapper) args = parser.parse_args() args.func(args) Loading
.gitlab-ci.yml +5 −3 Original line number Diff line number Diff line Loading @@ -1012,11 +1012,13 @@ voip-be-on-merge-request: - .test-job-linux-needs-testv-dir - .rules-merge-request stage: test needs: ["build-codec-linux-make", "codec-smoke-test"] needs: ["build-codec-linux-make"] timeout: "10 minutes" script: - *print-common-info - bash ci/ivas_voip_be_test.sh - make clean - make -j - python3 -m pytest tests/test_be_for_jbm_neutral_dly_profile.py clang-format-check: extends: Loading Loading @@ -2205,7 +2207,7 @@ coverage-test-on-main-scheduled: - python3 -m pytest $TESTS_DIR_CODEC_BE_ON_MR/test_param_file.py -v -n auto --update_ref 1 -m create_ref --param_file scripts/config/self_test_evs.prm --ref_encoder_path ./IVAS_cod --ref_decoder_path ./IVAS_dec - bash ci/smoke_test.sh coverage - python3 -m pytest $TESTS_DIR_CODEC_BE_ON_MR/test_param_file.py -v -n auto --update_ref 1 -m create_ref --param_file scripts/config/self_test_ltv.prm --ref_encoder_path ./IVAS_cod --ref_decoder_path ./IVAS_dec - bash ci/ivas_voip_be_test.sh coverage - python3 -m pytest tests/test_be_for_jbm_neutral_dly_profile.py - lcov -c -d obj -o coverage.info # remove apps and lib_util files from coverage - lcov -r coverage.info "*apps*" -o coverage.info Loading
ci/ivas_voip_be_test.shdeleted 100755 → 0 +0 −145 Original line number Diff line number Diff line #! /usr/bin/bash # (C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, # Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., # Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, # Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other # contributors to this repository. All Rights Reserved. # This software is protected by copyright law and by international treaties. # The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, # Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., # Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, # Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other # contributors to this repository retain full ownership rights in their respective contributions in # the software. This notice grants no license of any kind, including but not limited to patent # license, nor is any license granted by implication, estoppel or otherwise. # Contributors are required to enter into the IVAS codec Public Collaboration agreement before making # contributions. # This software is provided "AS IS", without any express or implied warranties. The software is in the # development stage. It is intended exclusively for experts who have experience with such software and # solely for the purpose of inspection. All implied warranties of non-infringement, merchantability # and fitness for a particular purpose are hereby disclaimed and excluded. # Any dispute, controversy or claim arising under or in relation to providing this software shall be # submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in # accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and # the United Nations Convention on Contracts on the International Sales of Goods. function usage { echo echo "Usage:" echo " ivas_voip_be_test.sh [MODE]" echo echo " MODE - test (default) or coverage" exit } if [ ! -d "lib_com" ]; then echo "not in root directory! - please run in IVAS root" exit 1 fi if [ -z "$1" ] || [ "$1" == "test" ]; then WORKERS="" BUILD=1 COVERAGE=0 elif [ "$1" == "coverage" ]; then WORKERS="-t 1" BUILD=0 COVERAGE=1 else usage fi if [ $BUILD -eq 1 ];then make clean make all -j fi # Configuration modes=('HOA3_b128_wb_cbr' 'MC_7_1_b96_fb_cbr' 'ISM2_b48_fb_cbr') output_formats=('STEREO' 'FOA' '7_1' 'HOA3') limit_input_to_x_seconds=30 verbosity_cmd="-z console" cfg=./scripts/config/ci_linux.json dly_profile=./scripts/dly_error_profiles/dly_error_profile_0.dat output_dir_default="out" output_dir_voip="out_voip" # Run the same modes in VoIP and non-VoIP mode with a neutral delay profile ./scripts/runIvasCodec.py $verbosity_cmd -p $cfg $WORKERS -U $limit_input_to_x_seconds -m "${modes[@]}" --oc "${output_formats[@]}" -o $output_dir_default | tee voip_be_test_output.txt ./scripts/runIvasCodec.py $verbosity_cmd -p $cfg $WORKERS -U $limit_input_to_x_seconds -m "${modes[@]}" --oc "${output_formats[@]}" -o $output_dir_voip -J "$dly_profile" | tee -a voip_be_test_output.txt # Check if Python scripts above failed. They return status 0 even when running a mode fails, so we have to parse log file if grep -iq failed voip_be_test_output.txt ; then echo "Run errors in runIvasCodec.py" exit 1 fi if [ $COVERAGE -eq 1 ];then # Coverage analysis requires only running the codec and may exit before the comparison part exit 0 fi # Set up Python path python_audio_module_path=$(pwd)/scripts export PYTHONPATH=$python_audio_module_path:$PYTHONPATH python_audiofile_script_path=$python_audio_module_path/pyaudio3dtools/audiofile.py # Trim JBM delay from VoIP output files output_dir_voip_dec="$output_dir_voip"/dec output_dir_voip_dec_trimmed="$output_dir_voip"/dec_trimmed if [[ ! -d $output_dir_voip_dec_trimmed ]]; then mkdir $output_dir_voip_dec_trimmed fi for cut in "$output_dir_voip_dec"/*.wav; do output_path=${cut/$output_dir_voip_dec/$output_dir_voip_dec_trimmed} output_path=${output_path/".wav"/".raw"} python3 "$python_audiofile_script_path" pre-trim 60 "$cut" "$output_path" | tee -a voip_be_test_output.txt done # Convert non-VoIP output from wav to pcm (comparison script doesn't support wav) output_dir_default_dec="$output_dir_default"/dec output_dir_default_dec_pcm="$output_dir_default"/dec_pcm if [[ ! -d $output_dir_default_dec_pcm ]]; then mkdir $output_dir_default_dec_pcm fi for ref in "$output_dir_default_dec"/*.wav; do output_path=${ref/$output_dir_default_dec/$output_dir_default_dec_pcm} output_path=${output_path/".wav"/".raw"} python3 "$python_audiofile_script_path" convert "$ref" "$output_path" | tee -a voip_be_test_output.txt done # Assert BE between non-VoIP and VoIP modes all_be=1 cmp_tool_path=$(pwd)/tests/cmp_pcm.py for ref in "$output_dir_default_dec_pcm"/*; do cut=${ref/$output_dir_default_dec_pcm/$output_dir_voip_dec_trimmed} cut=${cut/".dec."/"_jbm_dly_error_profile_0_dat.dec."} # Print paths of compared files, since the script doesn't do it printf "\nComparing %s and %s\n" "$ref" "$cut" | tee -a voip_be_test_output.txt printout=$($cmp_tool_path "$ref" "$cut") if [ $? -ne 0 ]; then all_be=0 fi printf "%s\n" "$printout" | tee -a voip_be_test_output.txt done if [ $all_be -eq 1 ]; then printf "\n\nAll tested conditions are bit-exact\n" | tee -a voip_be_test_output.txt else printf "\n\nBitexactness problems found!\n" | tee -a voip_be_test_output.txt exit 1; fi
scripts/batch_comp_audio.py +26 −7 Original line number Diff line number Diff line Loading @@ -49,16 +49,21 @@ SEG_SNR_EXPR = r"Seg. SNR\s+=(.+)dB" DIFF_EXPR = r"Max Diff\s+=\s+(\d+)" DIFF_STR = { "CompAudio": "{label} Max. diff (PCM) for file {f}: {diff}", "pyaudio3dtools": "{label} Max. diff (PCM) for file {f}: {diff}", "mld": "{label} MLD diff for file {f}: {diff}", } def main(args): tool = args.tool if shutil.which(tool) is None: if tool != "pyaudio3dtools" and shutil.which(tool) is None: print(f"{tool} not in PATH - abort.") sys.exit(-1) test_offset_ms = args.test_offset_ms if tool != "pyaudio3dtools": test_offset_ms = 0 num_files_diff = 0 with OutFileManager(args.out_file) as out_file: Loading @@ -77,7 +82,7 @@ def main(args): # if only one thread is passed, do everything in the main thread # to allow for meaningful debugging if needed for f in common_files: compare_files(f, fol1, fol2, outputs, tool) compare_files(f, fol1, fol2, outputs, tool, test_offset_ms) else: with concurrent.futures.ThreadPoolExecutor( max_workers=args.num_threads Loading @@ -89,6 +94,7 @@ def main(args): repeat(fol2), repeat(outputs), repeat(tool), repeat(test_offset_ms) ) if args.sort: Loading @@ -98,7 +104,7 @@ def main(args): # write csv header if out_file is not None: if tool == "CompAudio": if tool == "CompAudio" or tool == "pyaudio3dtools": out_file.write("filename,diff\n") elif tool == "mld": out_file.write("filename,mld\n") Loading @@ -106,7 +112,7 @@ def main(args): for f, tool_output in out.items(): if tool == "CompAudio": diff, snr, gain, seg_snr = tool_output elif tool == "mld": elif tool == "mld" or tool == "pyaudio3dtools": diff = tool_output if diff > 0: Loading @@ -133,8 +139,10 @@ def main(args): else: print("All files are bitexact") return num_files_diff def compare_files(f, fol1, fol2, outputs_dict, tool): def compare_files(f, fol1, fol2, outputs_dict, tool, test_offset_ms): """ Compare file f in both folders fol1 and fol2 using the given tool and store the parsed difference in outputs_dict. Loading @@ -155,6 +163,11 @@ def compare_files(f, fol1, fol2, outputs_dict, tool): s2, fs2 = readfile(f2, outdtype="int16") cmp_result = compare(s1, s2, fs1, per_frame=False, get_mld=True) tool_output = cmp_result["MLD"] elif tool == "pyaudio3dtools": s1, fs1 = readfile(f1, outdtype="int16") s2, fs2 = readfile(f2, outdtype="int16") cmp_result = compare(s1, s2, fs1, per_frame=False, test_start_offset_ms=test_offset_ms) tool_output = cmp_result["max_abs_diff"] with threading.Lock(): outputs_dict.update({f: tool_output}) Loading Loading @@ -284,10 +297,16 @@ if __name__ == "__main__": ) parser.add_argument( "--tool", choices=["mld", "CompAudio"], choices=["mld", "CompAudio", "pyaudio3dtools"], default="CompAudio", help="Compare tool to run", ) parser.add_argument( "--test_offset_ms", type=int, default=0, help="Offset in miliseconds that is ignored at the start of the files in folder2 (only used if tool=pyaudio3dtools)" ) args = parser.parse_args() main(args) sys.exit(main(args))
scripts/pyaudio3dtools/audioarray.py +12 −0 Original line number Diff line number Diff line Loading @@ -237,6 +237,7 @@ def compare( ssnr_thresh_low: float = -np.inf, ssnr_thresh_high: float = np.inf, apply_thresholds_to_ref_only: bool = False, test_start_offset_ms: int = 0, ) -> dict: """Compare two audio arrays Loading Loading @@ -264,12 +265,23 @@ def compare( Set to True to only apply the threshold comparison for the reference signal for whether to include a segment in the ssnr computation. Use this to align behaviour with the MPEG-D conformance specification. test_start_offset_ms: (non-negative) int offset in miliseconds for test signal. If > 0, the corresponding number of samples will be removed from the test array like so: test = test[sample_offset:, :]. Returns ------- result: dict Comparison results """ if test_start_offset_ms < 0: raise ValueError( f"Test_start_offset_ms has to be non-negative, but {test_start_offset_ms} was given." ) test_start_offset_samples = int(fs * test_start_offset_ms / 1000) test = test[test_start_offset_samples:, :] framesize = fs // 50 diff = abs(test - ref) max_diff = int(diff.max()) Loading
scripts/pyaudio3dtools/audiofile.py +20 −0 Original line number Diff line number Diff line Loading @@ -780,5 +780,25 @@ if __name__ == "__main__": parser_convert.add_argument("output_file") parser_convert.set_defaults(func=convert_wrapper) def compare_wrapper(compare_args): if not compare_args.ref_file.endswith(".wav") or not compare_args.test_file.endswith(".wav"): print("Convert currently only supported with WAV file input") exit(-1) s1, fs1 = readfile(compare_args.ref_file, outdtype="int16") s2, fs2 = readfile(compare_args.test_file, outdtype="int16") if fs1 != fs2: print("Can only compare signals of same sampling rate") exit(-1) cmp_result = audioarray.compare(s1, s2, fs1, per_frame=False, test_start_offset_ms=compare_args.test_start_offset_ms) exit(cmp_result["max_abs_diff"]) parser_compare = subparsers.add_parser("compare", help="Compare two wav files for bitexactness") parser_compare.add_argument("ref_file") parser_compare.add_argument("test_file") parser_compare.add_argument("test_start_offset_ms", default=0, type=int) parser_compare.set_defaults(func=compare_wrapper) args = parser.parse_args() args.func(args)