LCOV - code coverage report
Current view: top level - lib_dec - jbm_jb4_circularbuffer.c (source / functions) Hit Total Coverage
Test: Coverage on main enc/dec/rend @ 3b2f07138c61dcf997bbf4165d0882f794b2995f Lines: 179 185 96.8 %
Date: 2025-05-03 01:55:50 Functions: 14 14 100.0 %

          Line data    Source code
       1             : /******************************************************************************************************
       2             : 
       3             :    (C) 2022-2025 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
       4             :    Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
       5             :    Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
       6             :    Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
       7             :    contributors to this repository. All Rights Reserved.
       8             : 
       9             :    This software is protected by copyright law and by international treaties.
      10             :    The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
      11             :    Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
      12             :    Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
      13             :    Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
      14             :    contributors to this repository retain full ownership rights in their respective contributions in
      15             :    the software. This notice grants no license of any kind, including but not limited to patent
      16             :    license, nor is any license granted by implication, estoppel or otherwise.
      17             : 
      18             :    Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
      19             :    contributions.
      20             : 
      21             :    This software is provided "AS IS", without any express or implied warranties. The software is in the
      22             :    development stage. It is intended exclusively for experts who have experience with such software and
      23             :    solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
      24             :    and fitness for a particular purpose are hereby disclaimed and excluded.
      25             : 
      26             :    Any dispute, controversy or claim arising under or in relation to providing this software shall be
      27             :    submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
      28             :    accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
      29             :    the United Nations Convention on Contracts on the International Sales of Goods.
      30             : 
      31             : *******************************************************************************************************/
      32             : 
      33             : /*====================================================================================
      34             :     EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
      35             :   ====================================================================================*/
      36             : 
      37             : #include <assert.h>
      38             : #include <stdint.h>
      39             : #include "options.h"
      40             : #include "string.h"
      41             : #include "prot_fx.h"
      42             : #include "wmc_auto.h"
      43             : /* local includes */
      44             : #include "jbm_jb4_circularbuffer.h"
      45             : 
      46             : 
      47             : /** Calculates percentile by selecting greatest elements.
      48             :  * This function partial sorts all given elements in the given buffer.
      49             :  * @param[in,out] elements ascending sorted buffer of selected greatest elements
      50             :  * @param[in,out] size size of elements buffer
      51             :  * @param[in]     capacity maximum number of elements to buffer
      52             :  * @param[in]     newElement element to insert in buffer IF great enough */
      53             : static void JB4_CIRCULARBUFFER_calcPercentile( JB4_CIRCULARBUFFER_ELEMENT *elements, UWord16 *size, const UWord16 capacity, JB4_CIRCULARBUFFER_ELEMENT newElement );
      54             : 
      55             : /** circular buffer (FIFO) with fixed capacity */
      56             : struct JB4_CIRCULARBUFFER
      57             : {
      58             :     /** elements of circular buffer */
      59             :     JB4_CIRCULARBUFFER_ELEMENT *data;
      60             :     /** maximum allowed number of elements plus one free element (to decide between full/empty buffer) */
      61             :     UWord16 capacity;
      62             :     /** position of next enque operation */
      63             :     UWord16 writePos;
      64             :     /** position of next deque operation */
      65             :     UWord16 readPos;
      66             : };
      67             : 
      68             : 
      69             : /* Creates a circular buffer (FIFO) */
      70         216 : ivas_error JB4_CIRCULARBUFFER_Create(
      71             :     JB4_CIRCULARBUFFER_HANDLE *ph )
      72             : {
      73             :     JB4_CIRCULARBUFFER_HANDLE h;
      74             : 
      75         216 :     IF( ( h = malloc( sizeof( struct JB4_CIRCULARBUFFER ) ) ) == NULL )
      76             :     {
      77           0 :         return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for JBM\n" ) );
      78             :     }
      79             : 
      80         216 :     h->data = NULL;
      81         216 :     h->capacity = 0;
      82         216 :     move16();
      83         216 :     h->writePos = 0;
      84         216 :     move16();
      85         216 :     h->readPos = 0;
      86         216 :     move16();
      87             : 
      88         216 :     *ph = h;
      89             : 
      90         216 :     return IVAS_ERR_OK;
      91             : }
      92             : 
      93             : 
      94             : /* Destroys the circular buffer (FIFO) */
      95         216 : void JB4_CIRCULARBUFFER_Destroy(
      96             :     JB4_CIRCULARBUFFER_HANDLE *ph )
      97             : {
      98             :     JB4_CIRCULARBUFFER_HANDLE h;
      99             : 
     100         216 :     IF( !ph )
     101             :     {
     102           0 :         return;
     103             :     }
     104         216 :     h = *ph;
     105         216 :     IF( !h )
     106             :     {
     107           0 :         return;
     108             :     }
     109             : 
     110         216 :     IF( h->data )
     111             :     {
     112         216 :         free( h->data );
     113             :     }
     114         216 :     free( h );
     115         216 :     *ph = NULL;
     116             : 
     117         216 :     return;
     118             : }
     119             : 
     120             : 
     121             : /* Initializes a circular buffer (FIFO) with a fixed maximum allowed number of elements */
     122         216 : Word16 JB4_CIRCULARBUFFER_Init(
     123             :     JB4_CIRCULARBUFFER_HANDLE h,
     124             :     UWord16 capacity )
     125             : {
     126             :     /* keep one element free to be able to decide between full/empty buffer */
     127         216 :     capacity = (UWord16) L_add( capacity, 1 );
     128             : 
     129         216 :     IF( ( h->data = malloc( capacity * sizeof( JB4_CIRCULARBUFFER_ELEMENT ) ) ) == NULL )
     130             :     {
     131           0 :         return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for JBM\n" ) );
     132             :     }
     133             : 
     134         216 :     h->capacity = capacity;
     135         216 :     move16();
     136         216 :     h->writePos = 0;
     137         216 :     move16();
     138         216 :     h->readPos = 0;
     139         216 :     move16();
     140             : 
     141         216 :     return IVAS_ERR_OK;
     142             : }
     143             : 
     144             : 
     145      139941 : Word16 JB4_CIRCULARBUFFER_Enque(
     146             :     JB4_CIRCULARBUFFER_HANDLE h,
     147             :     JB4_CIRCULARBUFFER_ELEMENT element )
     148             : {
     149      139941 :     IF( JB4_CIRCULARBUFFER_IsFull( h ) )
     150             :     {
     151           0 :         return -1;
     152             :     }
     153             : 
     154      139941 :     h->data[h->writePos] = element;
     155      139941 :     move32();
     156      139941 :     h->writePos = (UWord16) L_add( h->writePos, 1 );
     157      139941 :     move16();
     158      139941 :     if ( EQ_32( h->writePos, h->capacity ) )
     159             :     {
     160        1172 :         h->writePos = 0;
     161        1172 :         move16();
     162             :     }
     163             : 
     164      139941 :     return 0;
     165             : }
     166             : 
     167             : 
     168       99401 : Word16 JB4_CIRCULARBUFFER_Deque(
     169             :     JB4_CIRCULARBUFFER_HANDLE h,
     170             :     JB4_CIRCULARBUFFER_ELEMENT *pElement )
     171             : {
     172       99401 :     IF( JB4_CIRCULARBUFFER_IsEmpty( h ) )
     173             :     {
     174           0 :         return -1;
     175             :     }
     176             : 
     177       99401 :     *pElement = h->data[h->readPos];
     178       99401 :     move32();
     179       99401 :     h->readPos = (UWord16) L_add( h->readPos, 1 );
     180       99401 :     move16();
     181       99401 :     if ( EQ_32( h->readPos, h->capacity ) )
     182             :     {
     183        1009 :         h->readPos = 0;
     184        1009 :         move16();
     185             :     }
     186             : 
     187       99401 :     return 0;
     188             : }
     189             : 
     190             : 
     191             : /* Returns the first element. */
     192       83160 : JB4_CIRCULARBUFFER_ELEMENT JB4_CIRCULARBUFFER_Front(
     193             :     const JB4_CIRCULARBUFFER_HANDLE h )
     194             : {
     195             :     JB4_CIRCULARBUFFER_ELEMENT ret;
     196             : 
     197       83160 :     ret = h->data[h->readPos];
     198       83160 :     move32();
     199             : 
     200       83160 :     return ret;
     201             : }
     202             : 
     203             : /* Returns the last element. */
     204       52470 : JB4_CIRCULARBUFFER_ELEMENT JB4_CIRCULARBUFFER_Back(
     205             :     const JB4_CIRCULARBUFFER_HANDLE h )
     206             : {
     207             :     JB4_CIRCULARBUFFER_ELEMENT ret;
     208             : 
     209       52470 :     IF( h->writePos != 0U )
     210             :     {
     211       52056 :         ret = h->data[h->writePos - 1];
     212       52056 :         move32();
     213             :     }
     214             :     ELSE
     215             :     {
     216         414 :         ret = h->data[h->capacity - 1];
     217         414 :         move32();
     218             :     }
     219             : 
     220             : 
     221       52470 :     return ret;
     222             : }
     223             : 
     224             : 
     225      189219 : Word16 JB4_CIRCULARBUFFER_IsEmpty(
     226             :     const JB4_CIRCULARBUFFER_HANDLE h )
     227             : {
     228             :     Word16 ret;
     229             : 
     230      189219 :     IF( EQ_32( h->readPos, h->writePos ) )
     231             :     {
     232          54 :         ret = 1;
     233          54 :         move16();
     234             :     }
     235             :     ELSE
     236             :     {
     237      189165 :         ret = 0;
     238      189165 :         move16();
     239             :     }
     240             : 
     241      189219 :     return ret;
     242             : }
     243             : 
     244             : 
     245      192411 : Word16 JB4_CIRCULARBUFFER_IsFull(
     246             :     const JB4_CIRCULARBUFFER_HANDLE h )
     247             : {
     248             :     Word16 ret;
     249             : 
     250      192411 :     IF( EQ_32( ( L_add( h->writePos, 1 ) % h->capacity ), h->readPos ) )
     251             :     {
     252        6736 :         ret = 1;
     253        6736 :         move16();
     254             :     }
     255             :     ELSE
     256             :     {
     257      185675 :         ret = 0;
     258      185675 :         move16();
     259             :     }
     260             : 
     261      192411 :     return ret;
     262             : }
     263             : 
     264             : 
     265       36980 : UWord16 JB4_CIRCULARBUFFER_Size(
     266             :     const JB4_CIRCULARBUFFER_HANDLE h )
     267             : {
     268             :     UWord16 ret;
     269             : 
     270       36980 :     IF( LE_32( h->readPos, h->writePos ) )
     271             :     {
     272       13881 :         ret = (UWord16) L_sub( h->writePos, h->readPos );
     273       13881 :         move16();
     274             :     }
     275             :     ELSE
     276             :     {
     277             :         /* wrap around */
     278       23099 :         ret = (UWord16) L_add( h->writePos, L_sub( h->capacity, h->readPos ) );
     279       23099 :         move16();
     280             :     }
     281             : 
     282             : 
     283       36980 :     return ret;
     284             : }
     285             : 
     286             : 
     287             : /* Calculates statistics over all elements: min element */
     288       72295 : void JB4_CIRCULARBUFFER_Min(
     289             :     const JB4_CIRCULARBUFFER_HANDLE h,
     290             :     JB4_CIRCULARBUFFER_ELEMENT *pMin )
     291             : {
     292             :     UWord16 i;
     293             :     JB4_CIRCULARBUFFER_ELEMENT minEle;
     294             : 
     295             :     /* init output variable */
     296       72295 :     minEle = h->data[h->readPos];
     297       72295 :     move32();
     298             : 
     299       72295 :     IF( LE_32( h->readPos, h->writePos ) )
     300             :     {
     301             :         /* no wrap around */
     302             :         /* calc statistics for [readPos;writePos[ */
     303     7075156 :         FOR( i = h->readPos; i != h->writePos; ++i )
     304             :         {
     305     7041090 :             if ( LT_32( h->data[i], minEle ) )
     306             :             {
     307        3311 :                 minEle = h->data[i];
     308        3311 :                 move32();
     309             :             }
     310             :         }
     311             :     }
     312             :     ELSE
     313             :     {
     314             :         /* wrap around */
     315             :         /* calc statistics for [readPos;capacity[ */
     316     6010193 :         FOR( i = h->readPos; i != h->capacity; ++i )
     317             :         {
     318     5971964 :             if ( LT_32( h->data[i], minEle ) )
     319             :             {
     320       52029 :                 minEle = h->data[i];
     321       52029 :                 move32();
     322             :             }
     323             :         }
     324             :         /* calc statistics for [0;writePos[ */
     325     5331413 :         FOR( i = 0; i != h->writePos; ++i )
     326             :         {
     327     5293184 :             if ( LT_32( h->data[i], minEle ) )
     328             :             {
     329        1764 :                 minEle = h->data[i];
     330        1764 :                 move32();
     331             :             }
     332             :         }
     333             :     }
     334             : 
     335       72295 :     *pMin = minEle;
     336       72295 :     move32();
     337       72295 : }
     338             : 
     339             : 
     340             : /* Calculates statistics over all elements: max element */
     341       17469 : void JB4_CIRCULARBUFFER_Max(
     342             :     const JB4_CIRCULARBUFFER_HANDLE h,
     343             :     JB4_CIRCULARBUFFER_ELEMENT *pMax )
     344             : {
     345             :     UWord16 i;
     346             :     JB4_CIRCULARBUFFER_ELEMENT maxEle;
     347             : 
     348             :     /* init output variable */
     349       17469 :     maxEle = h->data[h->readPos];
     350       17469 :     move32();
     351       17469 :     IF( LE_32( h->readPos, h->writePos ) )
     352             :     {
     353             :         /* no wrap around */
     354             :         /* calc statistics for [readPos;writePos[ */
     355      635414 :         FOR( i = h->readPos; i != h->writePos; ++i )
     356             :         {
     357      629332 :             if ( GT_32( h->data[i], maxEle ) )
     358             :             {
     359       19792 :                 maxEle = h->data[i];
     360       19792 :                 move32();
     361             :             }
     362             :         }
     363             :     }
     364             :     ELSE
     365             :     {
     366             :         /* wrap around */
     367             :         /* calc statistics for [readPos;capacity[ */
     368     1123733 :         FOR( i = h->readPos; i != h->capacity; ++i )
     369             :         {
     370     1112346 :             if ( GT_32( h->data[i], maxEle ) )
     371             :             {
     372       15238 :                 maxEle = h->data[i];
     373       15238 :                 move32();
     374             :             }
     375             :         }
     376             :         /* calc statistics for [0;writePos[ */
     377      998333 :         FOR( i = 0; i != h->writePos; ++i )
     378             :         {
     379      986946 :             if ( GT_32( h->data[i], maxEle ) )
     380             :             {
     381        4904 :                 maxEle = h->data[i];
     382        4904 :                 move32();
     383             :             }
     384             :         }
     385             :     }
     386             : 
     387       17469 :     *pMax = maxEle;
     388       17469 :     move32();
     389             : 
     390       17469 :     return;
     391             : }
     392             : 
     393             : #define JBM_MAX_CIRCULAR_ELEMENTS 100
     394             : 
     395             : /* Calculates statistics over a considered fraction of all elements: min element and percentile */
     396       36872 : void JB4_CIRCULARBUFFER_MinAndPercentile(
     397             :     const JB4_CIRCULARBUFFER_HANDLE h,
     398             :     UWord16 nElementsToIgnore,
     399             :     JB4_CIRCULARBUFFER_ELEMENT *pMin,
     400             :     JB4_CIRCULARBUFFER_ELEMENT *pPercentile )
     401             : {
     402             :     UWord16 i;
     403             :     JB4_CIRCULARBUFFER_ELEMENT maxElements[JBM_MAX_CIRCULAR_ELEMENTS];
     404             :     UWord16 maxElementsSize;
     405             :     UWord16 maxElementsCapacity;
     406             :     JB4_CIRCULARBUFFER_ELEMENT minEle;
     407             : 
     408             :     /* init output variables */
     409       36872 :     minEle = h->data[h->readPos];
     410       36872 :     move32();
     411             :     /* To calculate the percentile, a number of elements with the highest values are collected in maxElements in
     412             :      * ascending sorted order. This array has a size of nElementsToIgnore plus one. This additional element is the
     413             :      * lowest of all maxElements, and is called the percentile of all elements. */
     414             : 
     415       36872 :     maxElementsSize = 0;
     416       36872 :     move16();
     417       36872 :     maxElementsCapacity = (UWord16) L_add( nElementsToIgnore, 1 );
     418       36872 :     move16();
     419       36872 :     assert( maxElementsCapacity <= JBM_MAX_CIRCULAR_ELEMENTS );
     420       36872 :     IF( LE_32( h->readPos, h->writePos ) )
     421             :     {
     422             :         /* no wrap around */
     423             :         /* calc statistics for [readPos;writePos[ */
     424     2615982 :         FOR( i = h->readPos; i != h->writePos; ++i )
     425             :         {
     426     2602209 :             if ( LT_32( h->data[i], minEle ) )
     427             :             {
     428        2361 :                 minEle = h->data[i];
     429        2361 :                 move32();
     430             :             }
     431     2602209 :             JB4_CIRCULARBUFFER_calcPercentile( maxElements, &maxElementsSize, maxElementsCapacity, h->data[i] );
     432             :         }
     433             :     }
     434             :     ELSE
     435             :     {
     436             :         /* wrap around */
     437             :         /* calc statistics for [readPos;capacity[ */
     438     2358625 :         FOR( i = h->readPos; i != h->capacity; ++i )
     439             :         {
     440     2335526 :             if ( LT_32( h->data[i], minEle ) )
     441             :             {
     442       30978 :                 minEle = h->data[i];
     443       30978 :                 move32();
     444             :             }
     445     2335526 :             JB4_CIRCULARBUFFER_calcPercentile( maxElements, &maxElementsSize, maxElementsCapacity, h->data[i] );
     446             :         }
     447             :         /* calc statistics for [0;writePos[ */
     448     2090637 :         FOR( i = 0; i != h->writePos; ++i )
     449             :         {
     450     2067538 :             if ( LT_32( h->data[i], minEle ) )
     451             :             {
     452        1764 :                 minEle = h->data[i];
     453        1764 :                 move32();
     454             :             }
     455     2067538 :             JB4_CIRCULARBUFFER_calcPercentile( maxElements, &maxElementsSize, maxElementsCapacity, h->data[i] );
     456             :         }
     457             :     }
     458             : 
     459       36872 :     *pPercentile = maxElements[0];
     460       36872 :     move32();
     461       36872 :     *pMin = minEle;
     462       36872 :     move32();
     463             : 
     464       36872 :     return;
     465             : }
     466             : 
     467             : 
     468             : /* Calculates percentile by selecting greatest elements. */
     469     7005273 : static void JB4_CIRCULARBUFFER_calcPercentile(
     470             :     JB4_CIRCULARBUFFER_ELEMENT *elements,
     471             :     UWord16 *size,
     472             :     const UWord16 capacity,
     473             :     JB4_CIRCULARBUFFER_ELEMENT newElement )
     474             : {
     475             :     UWord16 i, j;
     476             : 
     477             :     /* insert newElement IF elements buffer is not yet full */
     478     7005273 :     IF( LT_32( *size, capacity ) )
     479             :     {
     480      122928 :         FOR( i = 0; i != *size; ++i )
     481             :         {
     482       76500 :             IF( LE_32( newElement, elements[i] ) )
     483             :             {
     484             :                 /* insert newElement at index i */
     485      113638 :                 FOR( j = *size; j > i; --j )
     486             :                 {
     487       70868 :                     elements[j] = elements[j - 1];
     488       70868 :                     move32();
     489             :                 }
     490       42770 :                 elements[i] = newElement;
     491       42770 :                 move32();
     492       42770 :                 *size = (UWord16) L_add( *size, 1 );
     493       42770 :                 move16();
     494       42770 :                 return;
     495             :             }
     496             :         }
     497             :         /* newElement is maximum, just append it */
     498       46428 :         elements[*size] = newElement;
     499       46428 :         move32();
     500       46428 :         *size = (UWord16) L_add( *size, 1 );
     501       46428 :         move16();
     502       46428 :         return;
     503             :     }
     504             : 
     505             :     /* check IF newElement is too small to be inserted in elements buffer */
     506     6916075 :     IF( LE_32( newElement, elements[0] ) )
     507             :     {
     508     6751995 :         return;
     509             :     }
     510             : 
     511             :     /* select position to insert newElement to elements */
     512      277918 :     FOR( i = *size - 1; i != 0; --i )
     513             :     {
     514      209228 :         IF( GE_32( newElement, elements[i] ) )
     515             :         {
     516             :             /* insert newElement at index i */
     517      310556 :             FOR( j = 0; j < i; j++ )
     518             :             {
     519      215166 :                 elements[j] = elements[1 + j];
     520      215166 :                 move32();
     521             :             }
     522       95390 :             elements[i] = newElement;
     523       95390 :             move32();
     524       95390 :             return;
     525             :         }
     526             :     }
     527             :     /* newElement is just greater than first on in elements buffer */
     528       68690 :     elements[0] = newElement;
     529       68690 :     move32();
     530             : 
     531       68690 :     return;
     532             : }

Generated by: LCOV version 1.14