Commit 2a972eab authored by Lauros Pajunen's avatar Lauros Pajunen
Browse files

PI tests for audio focus

parent 116bacde
Loading
Loading
Loading
Loading
+16 −6
Original line number Diff line number Diff line
@@ -328,15 +328,20 @@ static void IVAS_RTP_LogPiData( FILE *f_piDataOut, PIDATA_TS *piData, uint32_t n
            break;
            case IVAS_PI_AUDIO_FOCUS_INDICATION:
            {
                fprintf( f_piDataOut, "{\n" );
                fprintf( f_piDataOut, "{" );
                if ( cur->data.focusIndication.availDirection )
                {
                    fprintf( f_piDataOut, "\t\t\t\"w\": %f,\n\t\t\t\"x\": %f,\n\t\t\t\"y\": %f,\n\t\t\t\"z\": %f \n\t\t\t",
                    fprintf( f_piDataOut, "\n\t\t\t\"direction\": {\n" );
                    fprintf( f_piDataOut, "\t\t\t\t\t\t\"w\": %f,\n\t\t\t\t\t\t\"x\": %f,\n\t\t\t\t\t\t\"y\": %f,\n\t\t\t\t\t\t\"z\": %f \n\t\t\t}",
                             cur->data.focusIndication.direction.w, cur->data.focusIndication.direction.x, cur->data.focusIndication.direction.y, cur->data.focusIndication.direction.z );
                    if ( cur->data.focusIndication.availLevel )
                    {
                        fprintf( f_piDataOut, "," );
                    }
                }
                if ( cur->data.focusIndication.availLevel )
                {
                    fprintf( f_piDataOut, "\t\t\t\"level\": %d", cur->data.focusIndication.flvl );
                    fprintf( f_piDataOut, "\n\t\t\t\"level\": %d", cur->data.focusIndication.flvl );
                }
                fprintf( f_piDataOut, "\n\t\t}" );
            }
@@ -355,15 +360,20 @@ static void IVAS_RTP_LogPiData( FILE *f_piDataOut, PIDATA_TS *piData, uint32_t n
            case IVAS_PI_RESERVED13:
            case IVAS_PI_AUDIO_FOCUS_REQUEST:
            {
                fprintf( f_piDataOut, "{\n" );
                fprintf( f_piDataOut, "{" );
                if ( cur->data.focusRequest.availDirection )
                {
                    fprintf( f_piDataOut, "\t\t\t\"w\": %f,\n\t\t\t\"x\": %f,\n\t\t\t\"y\": %f,\n\t\t\t\"z\": %f \n\t\t\t",
                    fprintf( f_piDataOut, "\n\t\t\t\"direction\": {\n" );
                    fprintf( f_piDataOut, "\t\t\t\t\t\t\"w\": %f,\n\t\t\t\t\t\t\"x\": %f,\n\t\t\t\t\t\t\"y\": %f,\n\t\t\t\t\t\t\"z\": %f \n\t\t\t}",
                             cur->data.focusRequest.direction.w, cur->data.focusRequest.direction.x, cur->data.focusRequest.direction.y, cur->data.focusRequest.direction.z );
                    if ( cur->data.focusRequest.availLevel )
                    {
                        fprintf( f_piDataOut, "," );
                    }
                }
                if ( cur->data.focusRequest.availLevel )
                {
                    fprintf( f_piDataOut, "\t\t\t\"level\": %d", cur->data.focusRequest.flvl );
                    fprintf( f_piDataOut, "\n\t\t\t\"level\": %d", cur->data.focusRequest.flvl );
                }
                fprintf( f_piDataOut, "\n\t\t}" );
            }
+31 −11
Original line number Diff line number Diff line
@@ -42,7 +42,7 @@ import json
import base64
import argparse
from pathlib import Path
from typing import cast
from typing import cast, Optional

NO_REQ="NO_REQ"

@@ -225,7 +225,6 @@ class AUDIO_FOCUS_LEVEL(int, Enum):
    AUDIO_FOCUS_LEVEL_DEFAULT = 14
    AUDIO_FOCUS_LEVEL_NO_PREFERENCE = 15


@dataclass
class RTPHDR:
    version: int = 2
@@ -363,11 +362,8 @@ class ACOUSTIC_ENVIRONMENT:

@dataclass
class AUDIO_FOCUS:
    w: float = 0.0
    x: float = 0.0
    y: float = 0.0
    z: float = 0.0
    level: AUDIO_FOCUS_LEVEL = AUDIO_FOCUS_LEVEL.AUDIO_FOCUS_LEVEL_DEFAULT
    direction: Optional[ORIENTATION] = None
    level: Optional[AUDIO_FOCUS_LEVEL] = None

@dataclass
class PIDATA:
@@ -599,6 +595,30 @@ def packAcousticEnv(bitstrm: BitStream, data: any):
                absCoeff = mapNearestIndex(absorptionCoeffValues, aenv.abscoeff[n])
                bitstrm.append(f'uint:2={absCoeff}')

def unpackAudioFocus(bitstrm: ConstBitStream, piSize: int) -> AUDIO_FOCUS:
    assert piSize == 1 or piSize == 8 or piSize == 9, "Incorrect PI Data Size for AUDIO_FOCUS"
    direction = None
    level = None
    if piSize == 1:
        level = bitstrm.read(4).uint
        _ = bitstrm.read(4)
    else:
        direction = unpackOrientation(bitstrm, 8)
        if piSize == 9:
            level = bitstrm.read(4).uint
            _ = bitstrm.read(4)

    return AUDIO_FOCUS(direction=direction, level=level)

def packAudioFocus(bitstrm: BitStream, data: any):
    assert type(data) == AUDIO_FOCUS, "Diegetic type PI Data expects a data of type AUDIO_FOCUS"
    auFocus = cast(AUDIO_FOCUS, data)
    if auFocus.direction is not None:
        packOrientations(bitstrm, [auFocus.direction])
    if auFocus.level is not None:
        bitstrm.append(f'uint:4={auFocus.level}')
        bitstrm.append(f'uint:4=0')


PIDataUnpacker = [
    unpackOrientation, # SCENE_ORIENTATION,
@@ -615,13 +635,13 @@ PIDataUnpacker = [
    unpackUnsupported, # ISM_DIRECTIVITY
    unpackDiegetic,    # DIEGETIC_TYPE
    unpackUnsupported, # RESERVED13
    unpackAudioFocusCommon, # AUDIO_FOCUS_INDICATION
    unpackAudioFocus,  # AUDIO_FOCUS_INDICATION
    unpackUnsupported, # RESERVED15
    unpackOrientation, # PLAYBACK_DEVICE_ORIENTATION
    unpackOrientation, # HEAD_ORIENTATION
    unpackPosition,    # LISTENER_POSITION
    unpackDAS,         # DYNAMIC_AUDIO_SUPPRESSION
    unpackAudioFocusCommon, # AUDIO_FOCUS_REQUEST
    unpackAudioFocus,  # AUDIO_FOCUS_REQUEST
    unpackUnsupported, # PI_LATENCY
    unpackUnsupported, # R_ISM_ID
    unpackUnsupported, # R_ISM_GAIN
@@ -650,13 +670,13 @@ PIDataPacker = [
    packUnsupported, # ISM_DIRECTIVITY
    packDiegetic,    # DIEGETIC_TYPE
    packUnsupported, # RESERVED13
    packUnsupported, # RESERVED14
    packAudioFocus,  # AUDIO_FOCUS_INDICATION
    packUnsupported, # RESERVED15
    packOrientation, # PLAYBACK_DEVICE_ORIENTATION
    packOrientation, # HEAD_ORIENTATION
    packPosition,    # LISTENER_POSITION
    packDAS,         # DYNAMIC_AUDIO_SUPPRESSION
    packOrientation, # AUDIO_FOCUS_DIRECTION
    packAudioFocus,  # AUDIO_FOCUS_DIRECTION
    packUnsupported, # PI_LATENCY
    packUnsupported, # R_ISM_ID
    packUnsupported, # R_ISM_GAIN
+36 −15
Original line number Diff line number Diff line
@@ -102,9 +102,14 @@ def test_rtp_bitstream_evs (
    )


@pytest.mark.parametrize("bitrate", [24400, 80000, 512000])
@pytest.mark.parametrize("bandwidth", ["WB", "SWB", "FB"])
@pytest.mark.parametrize("format", ["STEREO", "SBA", "MC", "MASA"])
#@pytest.mark.parametrize("bitrate", [24400, 80000, 512000])
#@pytest.mark.parametrize("bandwidth", ["WB", "SWB", "FB"])
#@pytest.mark.parametrize("format", ["STEREO", "SBA", "MC", "MASA"])
#@pytest.mark.parametrize("framesPerPacket", [8])

@pytest.mark.parametrize("bitrate", [24400])
@pytest.mark.parametrize("bandwidth", ["SWB"])
@pytest.mark.parametrize("format", ["MASA"])
@pytest.mark.parametrize("framesPerPacket", [8])
def test_rtp_bitstream_ivas_nodtx (
    test_info,
@@ -164,21 +169,24 @@ def generatePiData(startTs: int, endTs: int) -> dict:
    someDesc = lambda : AUDIO_DESCRIPTION(isSpeech=bool(random.getrandbits(1)), isMusic=bool(random.getrandbits(1)), isAmbiance=bool(random.getrandbits(1)), isEditable=bool(random.getrandbits(1)), isBinaural=bool(random.getrandbits(1)))
    someDAS = lambda : DYNAMIC_AUDIO_SUPPRESSION(preferSpeech=bool(random.getrandbits(1)), preferMusic=bool(random.getrandbits(1)), preferAmbiance=bool(random.getrandbits(1)), level=random.randint(0, 15))
    someDIG = lambda : DIEGETIC_TYPE(isDigetic=[ bool(random.getrandbits(1)) for _ in range(random.randint(1, 5)) ])
    someAFocus = lambda : AUDIO_FOCUS(w=2*random.random()-1.0, x=2*random.random()-1.0, y=2*random.random()-1.0, z=2*random.random()-1.0, level=random.randint(0, 15))
    someAuFocusDirLvl = lambda : AUDIO_FOCUS(ORIENTATION(w=2*random.random()-1.0, x=2*random.random()-1.0, y=2*random.random()-1.0, z=2*random.random()-1.0), level=AUDIO_FOCUS_LEVEL(random.randint(0, 15)))
    someAuFocusDir = lambda : AUDIO_FOCUS(ORIENTATION(w=2*random.random()-1.0, x=2*random.random()-1.0, y=2*random.random()-1.0, z=2*random.random()-1.0))
    someAuFocusLvl = lambda : AUDIO_FOCUS(level=AUDIO_FOCUS_LEVEL(random.randint(0, 15)))
    someAuFocusList = [someAuFocusDirLvl, someAuFocusDir, someAuFocusLvl]

    for ts in range(startTs, endTs, 320):
        pidata = dict()
        pidata["SCENE_ORIENTATION"] = someOrientation()
        pidata["DEVICE_ORIENTATION_COMPENSATED"] = someOrientation()
        pidata["DEVICE_ORIENTATION_UNCOMPENSATED"] = someOrientation()
        pidata["PLAYBACK_DEVICE_ORIENTATION"] = someOrientation()
        pidata["HEAD_ORIENTATION"] = someOrientation()
        pidata["AUDIO_FOCUS_REQUEST"] = someAFocus()
        pidata["LISTENER_POSITION"] = somePosition()
        pidata["DYNAMIC_AUDIO_SUPPRESSION"] = someDAS()
        pidata["AUDIO_DESCRIPTION"] = [someDesc() for n in range(random.randint(1, 5))]
        pidata["DIEGETIC_TYPE"] = someDIG()
        pidata["ACOUSTIC_ENVIRONMENT"] = ACOUSTIC_ENVIRONMENT(aeid=random.randint(0, 127))
        #pidata["SCENE_ORIENTATION"] = someOrientation()
        #pidata["DEVICE_ORIENTATION_COMPENSATED"] = someOrientation()
        #pidata["DEVICE_ORIENTATION_UNCOMPENSATED"] = someOrientation()
        #pidata["PLAYBACK_DEVICE_ORIENTATION"] = someOrientation()
        #pidata["HEAD_ORIENTATION"] = someOrientation()
        pidata["AUDIO_FOCUS_REQUEST"] = random.choice(someAuFocusList)()
        #pidata["LISTENER_POSITION"] = somePosition()
        #pidata["DYNAMIC_AUDIO_SUPPRESSION"] = someDAS()
        #pidata["AUDIO_DESCRIPTION"] = [someDesc() for n in range(random.randint(1, 5))]
        #pidata["DIEGETIC_TYPE"] = someDIG()
        #pidata["ACOUSTIC_ENVIRONMENT"] = ACOUSTIC_ENVIRONMENT(aeid=random.randint(0, 127))
        data[str(ts)] = pidata
    return data

@@ -225,6 +233,17 @@ def isEqualAcousticEnv(ref: ACOUSTIC_ENVIRONMENT, dut: ACOUSTIC_ENVIRONMENT):
    for r, d in zip(ref.rt60, dut.rt60):
        assert r == d, f"Acoustic Env PI Data mismatch in rt60 {r} != {d}"

def isEqualAudioFocus(ref: AUDIO_FOCUS, dut: AUDIO_FOCUS):
    if ref.direction is not None or dut.direction is not None:
        assert ref.direction is not None, "Audio Focus PI Data missing direction"
        assert dut.direction is not None, "Audio Focus PI Data missing direction"
    if ref.direction is not None and dut.direction is not None:
        assert abs(ref.direction.w - dut.direction.w) < 0.0001, "Audio Focus PI Data mismatch in direction w"
        assert abs(ref.direction.x - dut.direction.x) < 0.0001, "Audio Focus PI Data mismatch in direction x"
        assert abs(ref.direction.y - dut.direction.y) < 0.0001, "Audio Focus PI Data mismatch in direction y"
        assert abs(ref.direction.z - dut.direction.z) < 0.0001, "Audio Focus PI Data mismatch in direction z"
    assert ref.level == dut.level, "Audio Focus PI Data mismatch in level"

class CSVREADER:
    def __init__(self, csvFile: Path):
        self.rIdx = 0
@@ -448,6 +467,8 @@ def run_rtp_bitstream_tests (
                        isEqualDiegetic(DIEGETIC_TYPE(**decoded), data)
                    elif type(generatedPIData[ts][pitype]) == ACOUSTIC_ENVIRONMENT:
                        isEqualAcousticEnv(ACOUSTIC_ENVIRONMENT(**decoded), data)
                    if type(generatedPIData[ts][pitype]) == AUDIO_FOCUS:
                        isEqualAudioFocus(AUDIO_FOCUS(**decoded), data)
                    elif type(generatedPIData[ts][pitype]) == list:
                        for r, d in zip(generatedPIData[ts][pitype], decodedPiData[ts][pitype]):
                            isEqualAD(AUDIO_DESCRIPTION(**d), r)