Commit 95be5475 authored by Anika Treffehn's avatar Anika Treffehn
Browse files

Merge branch '69-support-for-external-renderer-missing' into 'main'

Resolve "Support for external renderer missing"

See merge request !142
parents dd3ac143 58f6b77c
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -554,6 +554,11 @@ The configuration of the IVAS condition is similar to the EVS condition. However
In addition to that, the encoder and decoder take some additional arguments defined by the key `opts`.
For the decoder an output format can be set. If this argument is not defined the format specified in postprocessing is used.

### IVAS External Renderer

The key `ivas_rend` can be added in each condition to apply the IVAS_rend external renderer after the condition (e.g. after encoding and decoding for `ivas`) but previous to the 
postprocessing.

---

## Supported audio formats
+16 −0
Original line number Diff line number Diff line
@@ -175,6 +175,14 @@ conditions_to_generate:
      type: ref
      ### optional low-pass cut-off frequency in Hz; default = null
      # out_fc: 22500
      ### optional use of IVAS_rend (can be used in all conditions)
      # ivas_rend:
        ### Path to renderer binary; default search for IVAS_rend in bin folder (primary) and PATH (secondary)
        # bin: ~/git/ivas-codec/IVAS_rend
        ### Additional commandline options; default = null
        # opts: []
        ### Renderer output format; default = postprocessing fmt
        # fmt: "BINAURAL"
  c02:
      ### REQUIRED: type of condition
      type: lp3k5
@@ -218,6 +226,14 @@ conditions_to_generate:
          # fs: 48000
          ### Additional commandline options; default = null
          # opts: ["-q", "-no_delay_cmp"]
      ### optional use of IVAS_rend (can be used in all conditions)
      # ivas_rend:
        ### Path to renderer binary; default search for IVAS_rend in bin folder (primary) and PATH (secondary)
        # bin: ~/git/ivas-codec/IVAS_rend
        ### Additional commandline options; default = null
        # opts: []
        ### Renderer output format; default = postprocessing fmt
        # fmt: "BINAURAL"
      ### Bitstream options
      # tx:
          ### For possible arguments see overall bitstream modification
+20 −1
Original line number Diff line number Diff line
@@ -39,7 +39,7 @@ from ivas_processing_scripts.audiotools.audioarray import trim
from ivas_processing_scripts.audiotools.audiofile import read, write
from ivas_processing_scripts.processing.config import TestConfig
from ivas_processing_scripts.processing.evs import EVS
from ivas_processing_scripts.processing.ivas import IVAS
from ivas_processing_scripts.processing.ivas import IVAS, IVAS_rend
from ivas_processing_scripts.processing.postprocessing import Postprocessing
from ivas_processing_scripts.processing.preprocessing import Preprocessing
from ivas_processing_scripts.processing.preprocessing_2 import Preprocessing2
@@ -450,6 +450,25 @@ def get_processing_chain(
    else:
        raise SystemExit(f"Unknown condition {condition}!")

    # add optional IVAS_rend rendering step after each condition
    if cond_cfg.get("ivas_rend", -1) != -1:
        rend_cfg = cond_cfg["ivas_rend"]
        chain["processes"].append(
            IVAS_rend(
                {
                    "in_fmt": tmp_in_fmt,
                    "in_fs": tmp_in_fs,
                    "out_fmt": rend_cfg.get("fmt", tmp_out_fmt),
                    "bin": get_abs_path(rend_cfg.get("bin", None)),
                    "opts": rend_cfg.get("opts"),
                    "use_windows_codec_binaries": cfg.use_windows_codec_binaries,
                }
            )
        )
        # update values to reflect renderer output
        tmp_in_fs = rend_cfg.get("fs", tmp_in_fs)
        tmp_in_fmt = rend_cfg.get("fmt", tmp_out_fmt)

    # add postprocessing step based on condition
    post_fmt = post_cfg.get("fmt")
    if isinstance(post_fmt, list):
+17 −0
Original line number Diff line number Diff line
@@ -79,6 +79,17 @@ def get_default_config_for_codecs(codec_name: str, ext_with_dot: str = "") -> di
    return cfg


def get_default_config_for_renderer(codec_name: str, ext_with_dot: str = "") -> dict:
    rend_bin = f"{codec_name}_rend{ext_with_dot}"

    cfg = {
        "ivas_rend": {
            "bin": find_binary(rend_bin, raise_error=False),
        },
    }
    return cfg


class TestConfig:
    # avoid confusion with pytest tests due to naming
    __test__ = False
@@ -244,6 +255,12 @@ class TestConfig:
                        f"The following key must be specified for ESDRU: {REQUIRED_KEYS_ESDRU}"
                    )

            if cond_cfg.get("ivas_rend", -1) != -1:
                merged_cfg = get_default_config_for_renderer("IVAS", codec_bin_extension)
                merge_dicts(merged_cfg, cond_cfg)
                cfg["conditions_to_generate"][cond_name] = merged_cfg


    def _validate_merged_config(self, cfg: dict):
        # if not on windows, but "use_windows_codec_binaries" is given, assure that wine is there
        if (
+36 −32
Original line number Diff line number Diff line
@@ -110,9 +110,8 @@ class IVAS(Processing):
        # set defaults in case input and output sampling rates were not specified
        if not self.in_fs:
            if in_file.suffix in [".pcm", ".raw"]:
                self.in_fs = 48000
                raise ValueError("Sampling rate has to be specified for headerless files!")
            elif in_file.suffix == ".txt":
                # TODO
                raise NotImplementedError(".txt file support is WIP!")
            else:
                self.in_fs = parse_wave_header(in_file)["fs"]
@@ -366,11 +365,24 @@ class IVAS_rend(Processing):
        self.name = "ivas_rend"
        self.in_fmt = audio.fromtype(self.in_fmt)
        self.out_fmt = audio.fromtype(self.out_fmt)
        if not hasattr(self, "opts"):
            self.dec_opts = None
        self._use_wine = (
                platform.system() == "Linux" and self.use_windows_codec_binaries
        )

    def _validate(self):
        need_exe_suffix = (
                platform.system() == "Windows" or self.use_windows_codec_binaries
        )
        if not Path(self.bin).exists():
            if need_exe_suffix and (
                    self.bin and Path(self.bin).with_suffix(".exe").exists()
            ):
                self.bin = Path(self.bin).with_suffix(".exe")
            else:
                raise FileNotFoundError(
                f"The IVAS renderer binary was not found at the given path: {self.cod_bin}"
                    "The IVAS renderer binary was not found! Please check the configuration."
                )

    def process(
@@ -380,46 +392,38 @@ class IVAS_rend(Processing):
        in_meta,
        logger: Optional[logging.Logger] = None,
    ) -> None:
        # set defaults in case input and output sampling rates were not specified
        logger.debug(f"IVAS rend configuration : {self.__dict__}")
        logger.debug(f"IVAS rend {in_file.absolute()} -> {out_file.absolute()}")

        # set defaults in case input sampling rate is not specified
        if not self.in_fs:
            if in_file.suffix in [".pcm", ".raw"]:
                self.in_fs = 48000
                raise ValueError("Sampling rate has to be specified for headerless files!")
            elif in_file.suffix == ".txt":
                # TODO
                raise NotImplementedError(".txt file support is WIP!")
            else:
                self.in_fs = parse_wave_header(in_file)["fs"]

        if not self.out_fs:
            self.out_fs = self.in_fs

        raise NotImplementedError("IVAS Renderer support is WIP!")
                self.in_fs = parse_wave_header(str(in_file))["fs"]

        cmd = [self.bin]

        if self.fs:
            cmd.extend(["-fs", str(self.fs // 1000)])

        if self.metadata:
            cmd.append("-im")
            cmd.extend([str(f) for f in self.metadata])

        if self.trajectory:
            cmd.extend(["-tf", str(self.trajectory)])
        if self._use_wine:
            cmd.insert(0, "wine")

        cmd.extend(
            [
                "-q",
                "-i",
                str(in_file),
                "-if",
                str(self.in_fmt.name),
                "-o",
                str(out_file),
                "-of",
                str(self.out_fmt.name),
                "-fs", str(self.in_fs // 1000),
                "-i", str(in_file),
                "-if", self.in_fmt.name,
                "-o", str(out_file),
                "-of", self.out_fmt.name,
            ]
        )

        if in_meta:
            cmd.append("-im")
            cmd.extend([str(f) for f in in_meta])

        if self.opts:
            cmd.extend(self.opts)

        run(cmd, logger=logger)