From 5f67ceef7c25e5b82cfabc725d73e52b130c9ac3 Mon Sep 17 00:00:00 2001 From: Markus Multrus Date: Sat, 29 Apr 2023 21:58:17 +0200 Subject: [PATCH 1/5] first implementation --- examples/TEMPLATE.yml | 4 +- .../audiotools/__init__.py | 8 +-- .../audiotools/constants.py | 1 + .../audiotools/convert/__init__.py | 26 ++++++---- .../audiotools/wrappers/filter.py | 52 +++++++++++++++++++ ivas_processing_scripts/constants.py | 2 +- ivas_processing_scripts/processing/chains.py | 4 +- .../processing/processing.py | 2 +- 8 files changed, 80 insertions(+), 19 deletions(-) diff --git a/examples/TEMPLATE.yml b/examples/TEMPLATE.yml index 47f6a195..460a863b 100755 --- a/examples/TEMPLATE.yml +++ b/examples/TEMPLATE.yml @@ -64,8 +64,8 @@ input: # preprocessing: ### Target format used in rendering from input format; default = null (no rendering) # fmt: "7_1_4" - ### Flag for application of 50Hz high-pass filter; default = false - # hp50: true + ### Define mask (HP50 or 20KBP) for input signal filtering; default = None + # mask: None ### Target sampling rate in Hz for resampling; default = null (no resampling) # fs: 16000 ### Target loudness in LKFS; default = null (no loudness change applied) diff --git a/ivas_processing_scripts/audiotools/__init__.py b/ivas_processing_scripts/audiotools/__init__.py index b7ceb7d1..8026f904 100755 --- a/ivas_processing_scripts/audiotools/__init__.py +++ b/ivas_processing_scripts/audiotools/__init__.py @@ -79,10 +79,10 @@ def add_processing_args(group, input=True): default=None, ) group.add_argument( - f"-{ps}hp", - f"--{p}_hp50", - help="Apply 50 Hz high-pass filtering (default = %(default)s)", - action="store_true", + f"-{ps}mk", + f"--{p}_mask", + help="Apply filtering with mask (default = %(default)s)", + default=None, ) group.add_argument( f"-{ps}w", diff --git a/ivas_processing_scripts/audiotools/constants.py b/ivas_processing_scripts/audiotools/constants.py index c3af9d29..f9f020c8 100755 --- a/ivas_processing_scripts/audiotools/constants.py +++ b/ivas_processing_scripts/audiotools/constants.py @@ -692,6 +692,7 @@ DELAY_COMPENSATION_FOR_FILTERING = { "down": 145, }, "MSIN": 92, + "20KBP": 200, "LP1p5": 322, "LP35": 232, "LP7": 117, diff --git a/ivas_processing_scripts/audiotools/convert/__init__.py b/ivas_processing_scripts/audiotools/convert/__init__.py index 024faa47..dbfaf463 100755 --- a/ivas_processing_scripts/audiotools/convert/__init__.py +++ b/ivas_processing_scripts/audiotools/convert/__init__.py @@ -44,6 +44,7 @@ from ivas_processing_scripts.audiotools.wrappers.bs1770 import loudness_norm from ivas_processing_scripts.audiotools.wrappers.esdru import esdru from ivas_processing_scripts.audiotools.wrappers.filter import ( hp50filter_itu, + kbp20filter_itu, lpfilter_itu, resample_itu, ) @@ -133,7 +134,7 @@ def convert( in_delay: Optional[float] = None, in_fs: Optional[int] = None, in_cutoff: Optional[int] = None, - in_hp50: Optional[bool] = None, + in_mask: Optional[str] = None, in_window: Optional[list] = None, in_loudness: Optional[float] = None, in_loudness_fmt: Optional[str] = None, @@ -142,7 +143,7 @@ def convert( out_delay: Optional[float] = None, out_fs: Optional[int] = None, out_cutoff: Optional[int] = None, - out_hp50: Optional[bool] = None, + out_mask: Optional[str] = None, out_window: Optional[list] = None, out_loudness: Optional[float] = None, out_loudness_fmt: Optional[str] = None, @@ -162,7 +163,7 @@ def convert( delay=in_delay, fs=in_fs, fc=in_cutoff, - hp50=in_hp50, + mask=in_mask, window=in_window, loudness=in_loudness, loudness_fmt=in_loudness_fmt, @@ -180,7 +181,7 @@ def convert( delay=out_delay, fs=out_fs, fc=out_cutoff, - hp50=out_hp50, + mask=out_mask, window=out_window, loudness=out_loudness, loudness_fmt=out_loudness_fmt, @@ -198,7 +199,7 @@ def process_audio( delay: Optional[float] = None, fs: Optional[int] = None, fc: Optional[int] = None, - hp50: Optional[bool] = False, + mask: Optional[str] = None, window: Optional[float] = None, loudness: Optional[float] = None, loudness_fmt: Optional[str] = None, @@ -232,11 +233,18 @@ def process_audio( logger.debug(f"Windowing audio with {window} ms Hann window") x.audio = audioarray.window(x.audio, x.fs, window) - """high-pass (50 Hz) filtering""" - if hp50: + """mask filtering""" + if mask is not None: if logger: - logger.debug("Applying 50 Hz high-pass filter using ITU STL filter") - x.audio = hp50filter_itu(x) + logger.debug("Applying mask filter using ITU STL filter") + if mask == "HP50": + x.audio = hp50filter_itu(x) +# elif mask == "20KBP": +# x.audio = kbp20filter_itu(x) +# else: +# raise ValueError( +# "Invalid mask filter defined" +# ) """resampling""" if x.fs != fs: diff --git a/ivas_processing_scripts/audiotools/wrappers/filter.py b/ivas_processing_scripts/audiotools/wrappers/filter.py index 9be95758..bfaa633d 100755 --- a/ivas_processing_scripts/audiotools/wrappers/filter.py +++ b/ivas_processing_scripts/audiotools/wrappers/filter.py @@ -291,6 +291,58 @@ def hp50filter_itu( return y +def kbp20filter_itu( + x: Audio, +) -> np.ndarray: + """ + 20Hz to 20kHz bandpass filter for multi-channel audio array + + Parameters + ---------- + x: Audio + Input audio + + Returns + ------- + y: np.ndarray + Output high-pass filtered array + """ + + # set filter type and check if sampling rate is supported + old_fs = None + tmp = copy(x) + if x.fs == 48000: + flt_type = "20KBP" + else: + # resample if samplingrate is not supported + warn( + f"Filter type 20KBP only supported for 48kHz samlingrate, not for {x.fs}Hz -> resampling" + ) + flt_type = "20KBP" + old_fs = x.fs + tmp.audio = resample_itu(tmp, 48000) + tmp.fs = 48000 + + # don't apply high-pass filtering to LFE channel + if isinstance(x, ChannelBasedAudio): + skip_channel = x.lfe_index + else: + skip_channel = None + + # apply filter + y = filter_itu(tmp, flt_type=flt_type, skip_channel=skip_channel) + + # delay compensation + y = delay_compensation(y, flt_type=flt_type, fs=tmp.fs) + + # reverse resampling + if old_fs: + tmp.audio = y + y = resample_itu(tmp, old_fs) + + return y + + def resample_itu( x: Audio, fs_new: int, diff --git a/ivas_processing_scripts/constants.py b/ivas_processing_scripts/constants.py index c2731016..fbadd523 100755 --- a/ivas_processing_scripts/constants.py +++ b/ivas_processing_scripts/constants.py @@ -63,7 +63,7 @@ DEFAULT_CONFIG = { "metadata_path": None, # postprocessing "postprocessing": { - "hp50": False, + "mask": None, "limit": False, }, } diff --git a/ivas_processing_scripts/processing/chains.py b/ivas_processing_scripts/processing/chains.py index 027ac447..64945dce 100755 --- a/ivas_processing_scripts/processing/chains.py +++ b/ivas_processing_scripts/processing/chains.py @@ -115,7 +115,7 @@ def get_preprocessing(cfg: TestConfig) -> dict: "in_window": pre_cfg.get("window"), "in_loudness": pre_cfg.get("loudness"), "in_loudness_fmt": pre_cfg.get("loudness_fmt"), - "in_hp50": pre_cfg.get("hp50", False), + "in_mask": pre_cfg.get("mask", None), "multiprocessing": cfg.multiprocessing, } ) @@ -163,7 +163,7 @@ def get_preprocessing_2(cfg: TestConfig) -> dict: "preamble": pre2_cfg.get("preamble", 0), "pad_noise_preamble": pre2_cfg.get("preamble_noise", False), "background_noise": background, - "in_hp50": pre2_cfg.get("hp50", False), + "in_mask": pre2_cfg.get("mask", None), "multiprocessing": cfg.multiprocessing, } ) diff --git a/ivas_processing_scripts/processing/processing.py b/ivas_processing_scripts/processing/processing.py index 0d2097fa..649aa882 100755 --- a/ivas_processing_scripts/processing/processing.py +++ b/ivas_processing_scripts/processing/processing.py @@ -477,7 +477,7 @@ def preprocess_background_noise(cfg): output=output_audio, in_fs=input_audio.fs, out_fs=out_fs, - in_hp50=cfg.pre.in_hp50, + in_mask=cfg.pre.in_mask, ) # save result in cfg -- GitLab From e604fdac92ad5edb141a829a5be9e0cb2418f629 Mon Sep 17 00:00:00 2001 From: Markus Multrus Date: Sat, 29 Apr 2023 22:31:28 +0200 Subject: [PATCH 2/5] introduce new function maskfilter_itu() where then the different filtering methods are called --- .../audiotools/convert/__init__.py | 12 ++------ .../audiotools/wrappers/filter.py | 30 +++++++++++++++++++ 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/ivas_processing_scripts/audiotools/convert/__init__.py b/ivas_processing_scripts/audiotools/convert/__init__.py index dbfaf463..bd527b61 100755 --- a/ivas_processing_scripts/audiotools/convert/__init__.py +++ b/ivas_processing_scripts/audiotools/convert/__init__.py @@ -43,8 +43,7 @@ from ivas_processing_scripts.audiotools.convert.scenebased import convert_sceneb from ivas_processing_scripts.audiotools.wrappers.bs1770 import loudness_norm from ivas_processing_scripts.audiotools.wrappers.esdru import esdru from ivas_processing_scripts.audiotools.wrappers.filter import ( - hp50filter_itu, - kbp20filter_itu, + maskfilter_itu, lpfilter_itu, resample_itu, ) @@ -237,14 +236,7 @@ def process_audio( if mask is not None: if logger: logger.debug("Applying mask filter using ITU STL filter") - if mask == "HP50": - x.audio = hp50filter_itu(x) -# elif mask == "20KBP": -# x.audio = kbp20filter_itu(x) -# else: -# raise ValueError( -# "Invalid mask filter defined" -# ) + x.audio = maskfilter_itu(x, mask) """resampling""" if x.fs != fs: diff --git a/ivas_processing_scripts/audiotools/wrappers/filter.py b/ivas_processing_scripts/audiotools/wrappers/filter.py index bfaa633d..edc6127e 100755 --- a/ivas_processing_scripts/audiotools/wrappers/filter.py +++ b/ivas_processing_scripts/audiotools/wrappers/filter.py @@ -343,6 +343,36 @@ def kbp20filter_itu( return y +def maskfilter_itu( + x: Audio, + mask: str, +) -> np.ndarray: + """ + mask filter for multi-channel audio array + + Parameters + ---------- + x: Audio + Input audio + + Returns + ------- + y: np.ndarray + Output high-pass filtered array + """ + + if mask == "HP50": + y = hp50filter_itu(x) + elif mask == "20KBP": + y = kbp20filter_itu(x) + else: + raise ValueError( + "Invalid mask filter defined" + ) + + return y + + def resample_itu( x: Audio, fs_new: int, -- GitLab From d54f3285f7ffc9723141f4fab3d9bbb099f45d83 Mon Sep 17 00:00:00 2001 From: Markus Multrus Date: Mon, 1 May 2023 12:27:19 +0200 Subject: [PATCH 3/5] apply formatting --- ivas_processing_scripts/audiotools/convert/__init__.py | 2 +- ivas_processing_scripts/audiotools/wrappers/filter.py | 4 +--- ivas_processing_scripts/audiotools/wrappers/gen_patt.py | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/ivas_processing_scripts/audiotools/convert/__init__.py b/ivas_processing_scripts/audiotools/convert/__init__.py index bd527b61..9698dd4f 100755 --- a/ivas_processing_scripts/audiotools/convert/__init__.py +++ b/ivas_processing_scripts/audiotools/convert/__init__.py @@ -43,8 +43,8 @@ from ivas_processing_scripts.audiotools.convert.scenebased import convert_sceneb from ivas_processing_scripts.audiotools.wrappers.bs1770 import loudness_norm from ivas_processing_scripts.audiotools.wrappers.esdru import esdru from ivas_processing_scripts.audiotools.wrappers.filter import ( - maskfilter_itu, lpfilter_itu, + maskfilter_itu, resample_itu, ) from ivas_processing_scripts.audiotools.wrappers.p50fbmnru import p50fbmnru diff --git a/ivas_processing_scripts/audiotools/wrappers/filter.py b/ivas_processing_scripts/audiotools/wrappers/filter.py index edc6127e..968665eb 100755 --- a/ivas_processing_scripts/audiotools/wrappers/filter.py +++ b/ivas_processing_scripts/audiotools/wrappers/filter.py @@ -366,9 +366,7 @@ def maskfilter_itu( elif mask == "20KBP": y = kbp20filter_itu(x) else: - raise ValueError( - "Invalid mask filter defined" - ) + raise ValueError("Invalid mask filter defined") return y diff --git a/ivas_processing_scripts/audiotools/wrappers/gen_patt.py b/ivas_processing_scripts/audiotools/wrappers/gen_patt.py index f801b07b..d8737ef4 100644 --- a/ivas_processing_scripts/audiotools/wrappers/gen_patt.py +++ b/ivas_processing_scripts/audiotools/wrappers/gen_patt.py @@ -138,7 +138,7 @@ def create_error_pattern( gen_patt(100, "ep.g192", 5, working_dir=tmp_dir_test) if not tmp_sta_file_test.exists(): raise RuntimeError( - "Used version of gen-patt was detected to be faulty (unable to write \"sta\"-file). See bin/README.md for details." + 'Used version of gen-patt was detected to be faulty (unable to write "sta"-file). See bin/README.md for details.' ) with TemporaryDirectory() as tmp_dir: -- GitLab From 4578ee8d60435dc1bc9029f08ed170c263b9a109 Mon Sep 17 00:00:00 2001 From: Markus Multrus Date: Tue, 2 May 2023 23:10:41 +0200 Subject: [PATCH 4/5] fix commandline options --- ivas_processing_scripts/audiotools/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ivas_processing_scripts/audiotools/__init__.py b/ivas_processing_scripts/audiotools/__init__.py index 8026f904..b4d7aa19 100755 --- a/ivas_processing_scripts/audiotools/__init__.py +++ b/ivas_processing_scripts/audiotools/__init__.py @@ -81,7 +81,8 @@ def add_processing_args(group, input=True): group.add_argument( f"-{ps}mk", f"--{p}_mask", - help="Apply filtering with mask (default = %(default)s)", + type=str, + help="Apply filtering with mask ((HP50, 20KBP or None; default = %(default)s)", default=None, ) group.add_argument( -- GitLab From 8da50732ada4c64465ac8a65fdf68a154d47250a Mon Sep 17 00:00:00 2001 From: Treffehn Date: Wed, 3 May 2023 12:08:03 +0200 Subject: [PATCH 5/5] some adjustment and documentation --- README.md | 4 ++-- examples/TEMPLATE.yml | 4 ++-- ivas_processing_scripts/audiotools/wrappers/filter.py | 10 ++++++---- tests/data/test_ISM.yml | 2 ++ tests/data/test_MC.yml | 2 ++ tests/data/test_SBA.yml | 6 +++--- 6 files changed, 17 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 07f1e541..b6efaa97 100755 --- a/README.md +++ b/README.md @@ -193,8 +193,8 @@ input: # preprocessing: ### Target format used in rendering from input format; default = null (no rendering) # fmt: "7_1_4" - ### Flag for application of 50Hz high-pass filter; default = false - # hp50: true + ### Define mask (HP50 or 20KBP) for input signal filtering; default = null + # mask: "HP50" ### Target sampling rate in Hz for resampling; default = null (no resampling) # fs: 16000 ### Target loudness in LKFS; default = null (no loudness change applied) diff --git a/examples/TEMPLATE.yml b/examples/TEMPLATE.yml index 460a863b..e29dcaef 100755 --- a/examples/TEMPLATE.yml +++ b/examples/TEMPLATE.yml @@ -64,8 +64,8 @@ input: # preprocessing: ### Target format used in rendering from input format; default = null (no rendering) # fmt: "7_1_4" - ### Define mask (HP50 or 20KBP) for input signal filtering; default = None - # mask: None + ### Define mask (HP50 or 20KBP) for input signal filtering; default = null + # mask: "HP50" ### Target sampling rate in Hz for resampling; default = null (no resampling) # fs: 16000 ### Target loudness in LKFS; default = null (no loudness change applied) diff --git a/ivas_processing_scripts/audiotools/wrappers/filter.py b/ivas_processing_scripts/audiotools/wrappers/filter.py index 968665eb..426a0f2c 100755 --- a/ivas_processing_scripts/audiotools/wrappers/filter.py +++ b/ivas_processing_scripts/audiotools/wrappers/filter.py @@ -305,7 +305,7 @@ def kbp20filter_itu( Returns ------- y: np.ndarray - Output high-pass filtered array + Output band-pass filtered array """ # set filter type and check if sampling rate is supported @@ -323,7 +323,7 @@ def kbp20filter_itu( tmp.audio = resample_itu(tmp, 48000) tmp.fs = 48000 - # don't apply high-pass filtering to LFE channel + # don't apply band-pass filtering to LFE channel if isinstance(x, ChannelBasedAudio): skip_channel = x.lfe_index else: @@ -348,17 +348,19 @@ def maskfilter_itu( mask: str, ) -> np.ndarray: """ - mask filter for multi-channel audio array + Mask filter for multi-channel audio array Parameters ---------- x: Audio Input audio + mask: str + Name of mask to be applied Returns ------- y: np.ndarray - Output high-pass filtered array + Output filtered array """ if mask == "HP50": diff --git a/tests/data/test_ISM.yml b/tests/data/test_ISM.yml index 6be2b377..8543d180 100644 --- a/tests/data/test_ISM.yml +++ b/tests/data/test_ISM.yml @@ -71,6 +71,8 @@ input: preprocessing: ### Target format used in rendering from input format; default = null (no rendering) # fmt: "7_1_4" + ### Define mask (HP50 or 20KBP) for input signal filtering; default = null + # mask: "HP50" ### Target sampling rate in Hz for resampling; default = null (no resampling) # fs: 16000 ### Target loudness in LKFS; default = null (no loudness change applied) diff --git a/tests/data/test_MC.yml b/tests/data/test_MC.yml index 81cb3446..414c2cdf 100644 --- a/tests/data/test_MC.yml +++ b/tests/data/test_MC.yml @@ -68,6 +68,8 @@ input: preprocessing: ### Target format used in rendering from input format; default = null (no rendering) fmt: "7_1_4" + ### Define mask (HP50 or 20KBP) for input signal filtering; default = null + # mask: "HP50" ### Target sampling rate in Hz for resampling; default = null (no resampling) fs: 16000 ### Target loudness in LKFS; default = null (no loudness change applied) diff --git a/tests/data/test_SBA.yml b/tests/data/test_SBA.yml index da243a21..2fc2adfe 100644 --- a/tests/data/test_SBA.yml +++ b/tests/data/test_SBA.yml @@ -65,11 +65,11 @@ input: ################################################ ### Pre-processing step performed prior to core processing for all conditions ### If not defined, preprocessing step is skipped -# preprocessing: +preprocessing: ### Target format used in rendering from input format; default = null (no rendering) # fmt: "7_1_4" - ### Flag for application of 50Hz high-pass filter; default = false - hp50: true + ### Define mask (HP50 or 20KBP) for input signal filtering; default = null + mask: "HP50" ### Target sampling rate in Hz for resampling; default = null (no resampling) # fs: 16000 ### Target loudness in LKFS; default = null (no loudness change applied) -- GitLab