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

first version bitstream processing with error pattern

parent b3c889a2
Loading
Loading
Loading
Loading
Loading
+12 −6
Original line number Diff line number Diff line
@@ -94,14 +94,20 @@ input:
#################################################
### Bistream processing (transport simulation) done after encoding and before decoding
### e.g. frame error insertion or transport simulation for JBM testing
# tx:
# tx_jbm:
    ### REQUIRED: Path to network simulation binary
    # bs_proc_bin: ".../ivas_python_testscripts/networkSimulator_g192.exe"
    ### Path to error pattern (mandatory if no information for generating the error pattern is given)
    # error_pattern: ".../dly_error_profile.dat"
    ### options for the binary, possible placeholders are {error_pattern} for the error pattern,
    ### Path to delay error profile (mandatory if no information for generating the error pattern is given)
    # delay_error_profile: ".../dly_error_profile.dat"
    ### options for the binary, possible placeholders are {delay_error_profile} for the error pattern,
    ### {bitstream} for the bitstream to process and {bitstream_processed} for the processed bitstream
    # bs_proc_opts: [ "{error_pattern}",  "{bitstream}",  "{processed_bitstream}",  "{processed_bitstream}_tracefile_sim", "2", "0" ]
    # bs_proc_opts: [ "{delay_error_profile}",  "{bitstream}",  "{processed_bitstream}",  "{processed_bitstream}_tracefile_sim", "2", "0" ]
# tx_fer:
    ### REQUIRED: either error_pattern or error_rate
    ### Frame error pattern file
    # error_pattern: "path/pattern.192"
    ### Error rate in percent
    # error_rate: 5
    
################################################
### Configuration for conditions under test
+136 −0
Original line number Diff line number Diff line
@@ -31,26 +31,106 @@
#

from pathlib import Path
from typing import Union
from typing import Optional, Union

from ivas_processing_scripts.audiotools.wrappers.gen_patt import create_error_pattern
from ivas_processing_scripts.utils import find_binary, run


def eid_xor(
    error_pattern: Union[str, Path],
):
    # TODO
    in_bitstream: Union[str, Path],
    out_bitstream: Union[str, Path],
) -> None:
    """
    Wrapper for eid-xor binary to apply error patterns for the bitstream processing

    Parameters
    ----------
    error_pattern: Union[str, Path]
        Path to error pattern file
    in_bitstream: Union[str, Path]
        Path to input bitstream file
    out_bitstream: Union[str, Path]
        Output path for modified bitstream
    """

    # find binary
    binary = find_binary("eid-xor")

    # check for valid inputs
    if not Path(in_bitstream).is_file():
        raise ValueError(
            f"Input bitstream file {in_bitstream} for bitstream processing does not exist"
        )
    elif not Path(error_pattern).is_file():
        raise ValueError(
            f"Error pattern file {error_pattern} for bitstream processing does not exist"
        )

    # set up command line
    cmd = [
        str(binary),
        "-vbr",  # Enables variable bit rate operation
        "-fer",  # Error pattern is a frame erasure pattern
        in_bitstream,
        error_pattern,
        out_bitstream,
    ]

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

    return


def apply_error_pattern():
def create_and_apply_error_pattern(
    in_bitstream: Union[Path, str],
    out_bitstream: Union[Path, str],
    len_sig: int,
    error_pattern: Optional[Union[Path, str]] = None,
    error_rate: Optional[float] = None,
    preamble: Optional[int] = 0,
    fs: Optional[int] = 48000,
) -> None:
    """
    Function to create (or use existing) frame error pattern for bitstream processing

    Parameters
    ----------
    in_bitstream: Union[Path, str]
        Path of input bitstream
    out_bitstream: Union[Path, str]
        Path of output bitstream
    len_sig: int
        Length of signal in samples
    error_pattern: Optional[Union[Path, str]]
        Path to existing error pattern
    error_rate: float
        Error rate in percent
    preamble: Optional[int]
        Length of preamble
    fs: Optional[int]
        Sampling rate
    """

    if error_pattern is None:
        # create error pattern
        if error_rate is not None:
            error_pattern = in_bitstream.parent.joinpath("error_pattern").with_suffix(
                ".192"
            )
            create_error_pattern(len_sig, error_pattern, error_rate, preamble, fs)
        else:
            raise ValueError(
                "Either error pattern or error rate has to be specified for bitstream processing"
            )
    elif error_rate is not None:
        raise ValueError(
            "Error pattern and error rate are specified for bitstream processing. Can't use both"
        )

    # apply error pattern
    eid_xor(error_pattern, in_bitstream, out_bitstream)

    return
+163 −0
Original line number Diff line number Diff line
@@ -30,33 +30,134 @@
#  the United Nations Convention on Contracts on the International Sales of Goods.
#

import shutil
import warnings
from os import getcwd
from pathlib import Path
from ivas_processing_scripts.utils import find_binary, run
from tempfile import TemporaryDirectory
from typing import Optional, Union

from ivas_processing_scripts.audiotools.constants import IVAS_FRAME_LEN_MS
from ivas_processing_scripts.utils import find_binary, run

LIST_FER = [3, 5, 6, 10]
ERROR_PATTERNS_DIR = Path(__file__).parent.parent.parent.joinpath("error_patterns")


def gen_patt(
    len_sig: int,
    path_pattern: Union[Path, str],
    error_rate: float,
    start: Optional[int] = 0,
    fs: Optional[int] = 48000,
    working_dir: Optional[Union[Path, str]] = None,
) -> None:
    """
    Wrapper for gen-patt binary to create error patterns for the bitstream processing

    Parameters
    ----------
    len_sig: int
       Length of signal in samples
    path_pattern: Union[Path, str]
        Path of output pattern
    error_rate: float
        Error rate in percent
    start: Optional[int]
        Start sample of error pattern (length preamble)
    fs: Optional[int]
        Sampling rate
    working_dir: Optional[Union[Path, str]]
        Directory where binary should be called (sta file has to be in this dir if desired)
    """

    # check if multiple of frame length
    if len_sig % int(IVAS_FRAME_LEN_MS * fs // 1000):
        raise ValueError(
            "Signal length has to be integer multiple of frame length for bitstream processing"
        )
    if start % int(IVAS_FRAME_LEN_MS * fs // 1000):
        raise ValueError(
            "Preamble length has to be integer multiple of frame length for bitstream processing"
        )

    # find binary
    binary = find_binary("gen-patt")

def gen_patt():
    # TODO: call binary
    binary = find_binary("eid-xor")
    if working_dir is None:
        working_dir = getcwd()

    # set up command line
    cmd = [
        str(binary),
        "-tailstat",  # Statistics performed on the tail
        "-fer",  # Frame erasure mode using Gilbert model
        "-g192",  # Save error pattern in 16-bit G.192 format
        "-gamma",  # Correlation for BER|FER modes
        str(0),
        "-rate",
        str(error_rate / 100),
        "-tol",  # Max deviation of specified BER/FER/BFER
        str(0.001),
        "-reset",  # Reset EID state in between iteractions
        "-n",
        str(int(len_sig / int(IVAS_FRAME_LEN_MS * fs // 1000))),
        "-start",
        str(int(start / int(IVAS_FRAME_LEN_MS * fs // 1000)) + 1),
        path_pattern,
    ]

    # run command
    # result = run(cmd)
    run(cmd, cwd=working_dir)

    return


def create_error_pattern(
    len_sig: int,
    path_pattern: Union[Path, str],
    frame_error_rate: float,
    preamble: int,
):
    # TODO: copy sta files to cwd and call gen_patt
    # TODO: start after preamble (if preamble is int multiple of frame length)
    preamble: Optional[int] = 0,
    fs: Optional[int] = 48000,
) -> None:
    """
    Creates error pattern with desired frame error rate for bitstream processing
    For 3, 5, 6 and 10 percent FER the results are deterministic

    Parameters
    ----------
    len_sig: int
       Length of signal in samples
    path_pattern: Union[Path, str]
        Path of output pattern
    frame_error_rate: float
        Error rate in percent
    preamble: Optional[int]
        Length of preamble
    fs: Optional[int]
        Sampling rate
    """

    with TemporaryDirectory() as tmp_dir:
        tmp_dir = Path(tmp_dir)
        if frame_error_rate in LIST_FER:
            # copy sta file
        pass
            sta_file = ERROR_PATTERNS_DIR.joinpath(f"sta_{int(frame_error_rate)}")
            tmp_sta_file = tmp_dir.joinpath("sta")
            shutil.copyfile(sta_file, tmp_sta_file)

        else:
        warnings.warn(f"Frame error rate {frame_error_rate}% is not a default rate. Error pattern is random and not deterministic.")
            warnings.warn(
                f"Frame error rate {frame_error_rate}% is not a default rate. Error pattern is random and not deterministic."
            )

        gen_patt(
            len_sig=len_sig,
            error_rate=frame_error_rate,
            path_pattern=path_pattern,
            start=preamble,
            fs=fs,
            working_dir=tmp_dir,
        )

    return
Loading