diff --git a/examples/TEMPLATE.yml b/examples/TEMPLATE.yml index 21d2797d9671a6091ae810ac3dacf5cefde2ad31..91c7d36b685292427dd2c8756b7a6f02abc37cc7 100755 --- a/examples/TEMPLATE.yml +++ b/examples/TEMPLATE.yml @@ -77,12 +77,14 @@ input: ### Pre-processing step performed prior to core processing for all conditions ### If not defined, preprocessing step is skipped # preprocessing: - ### Linear gain factor to be applied before any other processing - # gain: 3.1622776602 ### 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" + ### Gain factor to be applied BEFORE any other processing (linear, or add dB suffix) + # gain_pre: 10 dB + ### Gain factor to be applied AFTER any other processing (linear, or add dB suffix) + # gain_post: 3.1622776602 ### Target sampling rate in Hz for resampling; default = null (no resampling) # fs: 16000 ### Target loudness in LKFS; default = null (no loudness change applied) @@ -321,8 +323,10 @@ postprocessing: fmt: "BINAURAL" ### REQUIRED: Target sampling rate in Hz for resampling fs: 48000 - ### Linear gain factor to be applied before any other processing - # gain: 0.316227766 + ### Gain factor to be applied BEFORE any other processing (linear, or add dB suffix) + # gain_pre: 10 dB + ### Gain factor to be applied AFTER any other processing (linear, or add dB suffix) + # gain_post: 3.1622776602 ### Low-pass cut-off frequency in Hz; default = null (no filtering) # lp_cutoff: 24000 ### 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 07598432ad173f8f3bd7dfb140e63a79e71e4610..c8f6b1703b2b259f1b4bfb7b1df194ac7888ef4a 100755 --- a/ivas_processing_scripts/audiotools/__init__.py +++ b/ivas_processing_scripts/audiotools/__init__.py @@ -51,6 +51,23 @@ def add_processing_args(group, input=True): p = "out" ps = "o" + # validation function(s) + def parse_gain(g: str) -> float: + g = g.strip() + try: + if g.lower().endswith("db"): + g = float(g[:-2].strip()) + g = 10 ** (g / 20) + else: + g = float(g) + + except ValueError: + raise argparse.ArgumentTypeError( + f"Invalid gain value '{g}' specified. Must be a number or a number suffixed with dB" + ) + + return g + group.add_argument( f"-{ps}", f"--{p}", @@ -93,6 +110,20 @@ def add_processing_args(group, input=True): help="Window the start/end of the signal by this amount in milliseconds (default = %(default)s)", default=None, ) + group.add_argument( + f"-{ps}gi", + f"--{p}_gain_pre", + type=parse_gain, + help="Apply the given pre-gain factor to the signal (suffix with dB to use nonlinear, e.g. '10 dB'), applied BEFORE other processing steps (default = %(default)s)", + default=None, + ) + group.add_argument( + f"-{ps}go", + f"--{p}_gain_post", + type=parse_gain, + help="Apply the given post-gain factor to the signal (suffix with dB to use nonlinear, e.g. '10 dB'), applied AFTER other processing steps (default = %(default)s)", + default=None, + ) group.add_argument( f"-{ps}t", f"--{p}_trim", @@ -114,13 +145,6 @@ def add_processing_args(group, input=True): help="Delay the signal by this amount in milliseconds (negative values advance, default = %(default)s)", default=None, ) - group.add_argument( - f"-{ps}g", - f"--{p}_gain", - type=float, - help="Apply the given linear gain factor to the signal, applied before other processing steps (default = %(default)s)", - default=None, - ) group.add_argument( f"-{ps}l", f"--{p}_loudness", @@ -256,6 +280,8 @@ def main(): ) elif args.input is not None: + # validate other arguments + if not args.out_fs: args.out_fs = args.in_fs diff --git a/ivas_processing_scripts/audiotools/convert/__init__.py b/ivas_processing_scripts/audiotools/convert/__init__.py index 300f672f50de1d7a58f39663c2397b010ef3febf..f1e56c430e53ad048e0d8b6c62d330bac611378c 100755 --- a/ivas_processing_scripts/audiotools/convert/__init__.py +++ b/ivas_processing_scripts/audiotools/convert/__init__.py @@ -190,7 +190,8 @@ def convert( in_cutoff: Optional[int] = None, in_mask: Optional[str] = None, in_window: Optional[list] = None, - in_gain: Optional[float] = None, + in_gain_pre: Optional[float] = None, + in_gain_post: Optional[float] = None, in_loudness: Optional[float] = None, in_loudness_fmt: Optional[str] = None, out_trim: Optional[list] = None, @@ -200,6 +201,8 @@ def convert( out_cutoff: Optional[int] = None, out_mask: Optional[str] = None, out_window: Optional[list] = None, + out_gain_pre: Optional[float] = None, + out_gain_post: Optional[float] = None, out_gain: Optional[float] = None, out_loudness: Optional[float] = None, out_loudness_fmt: Optional[str] = None, @@ -223,7 +226,8 @@ def convert( fc=in_cutoff, mask=in_mask, window=in_window, - gain=in_gain, + gain_pre=in_gain_pre, + gain_post=in_gain_post, loudness=in_loudness, loudness_fmt=in_loudness_fmt, spatial_distortion_amplitude=spatial_distortion_amplitude, @@ -244,7 +248,8 @@ def convert( fc=out_cutoff, mask=out_mask, window=out_window, - gain=out_gain, + gain_pre=out_gain_pre, + gain_post=out_gain_post, loudness=out_loudness, loudness_fmt=out_loudness_fmt, limit=limit, @@ -263,7 +268,8 @@ def process_audio( fc: Optional[int] = None, mask: Optional[str] = None, window: Optional[float] = None, - gain: Optional[float] = None, + gain_pre: Optional[float] = None, + gain_post: Optional[float] = None, loudness: Optional[float] = None, loudness_fmt: Optional[str] = None, limit: Optional[bool] = False, @@ -278,11 +284,11 @@ def process_audio( if fs is None: fs = x.fs - """gain""" - if gain is not None: + """pre-gain""" + if gain_pre is not None: if logger: - logger.debug(f"Applying linear gain factor of {gain}") - x.audio *= gain + logger.debug(f"Applying linear pre-gain factor of {gain_pre}") + x.audio *= gain_pre """delay audio""" if delay is not None: @@ -364,6 +370,12 @@ def process_audio( logger.debug("Applying limiter") audioarray.limiter(x.audio, x.fs) + """post-gain""" + if gain_post is not None: + if logger: + logger.debug(f"Applying linear pre-gain factor of {gain_post}") + x.audio *= gain_post + def format_conversion( input: audio.Audio, diff --git a/ivas_processing_scripts/processing/chains.py b/ivas_processing_scripts/processing/chains.py index bd315e0b7881c9875d0b15fe7e29ec7959e97ccb..111c920475a53082765291fd3a388d089c1d3774 100755 --- a/ivas_processing_scripts/processing/chains.py +++ b/ivas_processing_scripts/processing/chains.py @@ -137,10 +137,11 @@ def get_preprocessing(cfg: TestConfig) -> dict: "in_pad_noise": pre_cfg.get("pad_noise", False), "in_delay": pre_cfg.get("delay"), "in_window": pre_cfg.get("window"), - "in_gain": pre_cfg.get("gain"), "in_loudness": pre_cfg.get("loudness"), "in_loudness_fmt": pre_cfg.get("loudness_fmt", post_fmt), "in_mask": pre_cfg.get("mask", None), + "in_gain_pre": pre_cfg.get("gain_pre"), + "out_gain_post": pre_cfg.get("gain_post"), "multiprocessing": cfg.multiprocessing, } ) @@ -566,12 +567,11 @@ def get_processing_chain( { "in_fs": tmp_in_fs, "in_fmt": tmp_in_fmt, + "in_gain_pre": post_cfg.get("gain_pre"), + "out_gain_post": post_cfg.get("gain_post"), "out_fs": post_cfg.get("fs"), "out_fmt": post_fmt, "out_cutoff": tmp_lp_cutoff, - "in_gain": post_cfg.get( - "gain" - ), # should be in_gain here since we want to apply it before any conversion/rendering "bin_dataset": post_cfg.get("bin_dataset"), "bin_lfe_gain": post_cfg.get("bin_lfe_gain"), "limit": post_cfg.get("limit", True),