Commit ece769a3 authored by Anika Treffehn's avatar Anika Treffehn
Browse files

Merge branch 'loudness_info' into 'main'

Loudness info

See merge request !48
parents 0105e07f cfdf9531
Loading
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -513,7 +513,7 @@ The following additional executables are needed for the different processing ste

| Processing step                                 | Executable            | Where to find                                                                                               |
|-------------------------------------------------|-----------------------|-------------------------------------------------------------------------------------------------------------|
| Loudness measurement and adjustment             | bs1770demo            | https://github.com/openitu/STL                                                                              |
| Loudness measurement and adjustment             | bs1770demo            | https://github.com/ErikNorvell-Ericsson/STL (Note branch)                                                                             |
| MNRU                                            | p50fbmnru             | https://github.com/openitu/STL                                                                              |
| ESDRU                                           | esdru                 | https://github.com/openitu/STL                                                                              |
| Frame error pattern application                 | eid-xor               | https://github.com/openitu/STL                                                                              |
+1 −1
Original line number Diff line number Diff line
@@ -70,7 +70,7 @@ def logging_init(args, cfg):
        cfg.output_path.joinpath(f"{cfg.name}{LOGGER_SUFFIX}"), mode="w"
    )
    file_handler.setFormatter(logging.Formatter(LOGGER_FORMAT, datefmt=LOGGER_DATEFMT))
    file_handler.setLevel(logging.DEBUG if args.debug else logging.INFO)
    file_handler.setLevel(logging.DEBUG)
    logger.addHandler(file_handler)

    logger.info(f"Processing test configuration file {args.config}")
+1 −1
Original line number Diff line number Diff line
@@ -253,7 +253,7 @@ def process_audio(
            logger.debug(
                f"Applying loudness adjustment to {loudness} LKFS for format {loudness_fmt} using ITU STL bs1770demo"
            )
        x.audio = loudness_norm(x, loudness, loudness_fmt)
        x.audio = loudness_norm(x, loudness, loudness_fmt, logger=logger)

    """low-pass filtering"""
    if fc is not None:
+67 −38
Original line number Diff line number Diff line
@@ -47,9 +47,6 @@ from ivas_processing_scripts.audiotools.wrappers.filter import resample_itu
from ivas_processing_scripts.constants import DEFAULT_CONFIG_BINARIES
from ivas_processing_scripts.utils import find_binary, get_devnull, run

logger = logging.getLogger("__main__")
logger.setLevel(logging.DEBUG)


def bs1770demo(
    input: audio.Audio,
@@ -65,6 +62,8 @@ def bs1770demo(
        Input audio
    target_loudness: Optional[float]
        Desired loudness in LKFS
    rms: Optional[bool]
        Flag for using rms argument in bs1770demo tool (for low level signals)

    Returns
    -------
@@ -85,8 +84,6 @@ def bs1770demo(
        binary = find_binary("bs1770demo")

    # checking if the new binary (with '-rms') is used
    with TemporaryDirectory() as tmp_dir_test:
        tmp_dir_test = Path(tmp_dir_test)
    result = sp.run(str(binary), shell=True, stdout=sp.PIPE, stderr=sp.PIPE)
    result_stdout = result.stdout.decode("utf-8")
    if "-rms" not in result_stdout:
@@ -146,8 +143,9 @@ def bs1770demo(
        # using rms if true
        if rms:
            cmd.insert(1, "-rms")

        # run command
        result = run(cmd, logger=logger)
        result = run(cmd)

        # parse output
        # we are looking for the (floating-point) number after the search string - '( )' around the number denotes the first group
@@ -174,10 +172,12 @@ def get_loudness(
    ----------
    input : Audio
        Input audio
    target_loudness: float
    target_loudness: Optional[float]
        Desired loudness in LKFS
    loudness_format: str
    loudness_format: Optional[str]
        Loudness format to render to for loudness computation (default input format if possible)
    rms: Optional[bool]
        Flag for using rms argument in bs1770demo tool (for low level signals)

    Returns
    -------
@@ -212,10 +212,7 @@ def get_loudness(
        convert.format_conversion(input, tmp)
    else:
        tmp.audio = input.audio
    if rms:
        return bs1770demo(tmp, target_loudness, rms=True)
    else:
        return bs1770demo(tmp, target_loudness)
    return bs1770demo(tmp, target_loudness, rms)


def loudness_norm(
@@ -223,6 +220,8 @@ def loudness_norm(
    target_loudness: Optional[float] = -26,
    loudness_format: Optional[str] = None,
    rms: Optional[bool] = False,
    logger: Optional[logging.Logger] = None,
    file_name_logging: Optional[Union[str, Path]] = None,
) -> np.ndarray:
    """
    Iterative loudness normalization using ITU-R BS.1770-4
@@ -237,6 +236,12 @@ def loudness_norm(
        Desired loudness level in LKFS
    loudness_format: Optional[str]
        Loudness format to render to for loudness computation (default input format)
    rms: Optional[bool]
        Flag for using rms argument in bs1770demo tool (for low level signals)
    logger: Optional[logging.Logger]
        Logger to log loudness information
    file_name_logging: Optional[Union[str, Path]]
        Name of processed file for logging information

    Returns
    -------
@@ -244,42 +249,56 @@ def loudness_norm(
        Normalized audio
    """

    # repeat until convergence of loudness
    measured_loudness = np.inf
    scale_factor = 1
    num_iter = 1
    scaled_input = copy.deepcopy(input)

    while np.abs(measured_loudness - target_loudness) > 0.5 and num_iter < 10:
        measured_loudness, scale_factor_new = get_loudness(
            input,
            target_loudness,
            loudness_format,
            rms=rms,
    # save loudness before and after scaling for the logger info
    loudness_before, scale_factor_new = get_loudness(
        scaled_input, target_loudness, loudness_format, rms
    )

    # repeat until convergence of loudness
    while np.abs(measured_loudness - target_loudness) > 0.5 and num_iter < 10:
        # scale input
        input.audio *= scale_factor_new
        scaled_input.audio *= scale_factor_new

        # update scale factor
        scale_factor *= scale_factor_new
        # measure loudness and get scaling factor
        measured_loudness, scale_factor_new = get_loudness(
            scaled_input, target_loudness, loudness_format, rms
        )

        num_iter += 1

    loudness_after = measured_loudness

    # log loudness before and after adjustment
    if logger:
        if file_name_logging:
            logger.debug(
                f"File {file_name_logging} loudness; before: {loudness_before}, after: {loudness_after}"
            )
        else:
            logger.debug(
                f"Loudness; before: {loudness_before}, after: {loudness_after}"
            )

    if num_iter >= 10:
        warn(
            f"Loudness did not converge to desired value, stopping at: {measured_loudness:.2f}"
            f"Loudness did not converge to desired value, stopping at: {loudness_after:.2f}"
        )

    return input.audio
    return scaled_input.audio


def scale_files(
    file_list: list[list[Union[Path, str]]],
    fmt: str,
    loudness: float,
    loudness_format: Optional[str] = None,
    fs: Optional[int] = 48000,
    in_meta: Optional[list] = None,
    rms: Optional[bool] = False,
    logger: Optional[logging.Logger] = None,
) -> None:
    """
    Scales audio files to desired loudness
@@ -292,15 +311,22 @@ def scale_files(
        Audio format of files in list
    loudness: float
        Desired loudness level in LKFS/dBov
    loudness_format: Optional[str]
        Format for loudness measurement
    fs: Optional[int]
        Sampling rate
    in_meta: Optional[list]
        Metadata for ISM with same structure as file_list but one layer more
        for the list of metadata for one file
    logger: Optional[logging.Logger]
        Logger to log loudness information
    """

    if fmt.startswith("ISM") and in_meta:
    if fmt.startswith("ISM"):
        if in_meta:
            meta_bool = True
        else:
            raise ValueError("No metadata available for loudness measurement")
    else:
        in_meta = copy.copy(file_list)
        meta_bool = False
@@ -314,10 +340,13 @@ def scale_files(
                audio_obj = audio.fromfile(fmt, file, fs)

            # adjust loudness
            if rms:
                scaled_audio = loudness_norm(audio_obj, loudness, rms=True)
            else:
                scaled_audio = loudness_norm(audio_obj, loudness)
            scaled_audio = loudness_norm(
                audio_obj,
                loudness,
                loudness_format,
                logger=logger,
                file_name_logging=file,
            )

            # write into file
            write(file, scaled_audio, audio_obj.fs)
+2 −2
Original line number Diff line number Diff line
@@ -3,7 +3,7 @@ Necessary additional executables:

| Processing step                                 | Executable            | Where to find                                                                                               |
|-------------------------------------------------|-----------------------|-------------------------------------------------------------------------------------------------------------|
| Loudness measurement and adjustment             | bs1770demo            | https://github.com/openitu/STL                                                                              |
| Loudness measurement and adjustment             | bs1770demo            | https://github.com/ErikNorvell-Ericsson/STL (Note branch)                                                   |
| MNRU                                            | p50fbmnru             | https://github.com/openitu/STL                                                                              |
| ESDRU                                           | esdru                 | https://github.com/openitu/STL                                                                              |
| Frame error pattern application                 | eid-xor               | https://github.com/openitu/STL                                                                              |
Loading