LCOV - code coverage report
Current view: top level - lib_rend - ivas_td_ring_buffer.c (source / functions) Hit Total Coverage
Test: Coverage on main -- merged total coverage @ 9b04ec3cb36f5e8dc438cf854fa3e349998fa1e9 Lines: 83 87 95.4 %
Date: 2025-10-31 05:45:46 Functions: 10 10 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             : #include <assert.h>
      34             : #include <stdlib.h>
      35             : #include "ivas_error_utils.h"
      36             : #include "ivas_prot_rend.h"
      37             : #include "options.h"
      38             : #include "wmc_auto.h"
      39             : 
      40             : 
      41             : /*-----------------------------------------------------------------------*
      42             :  * Local function prototypes
      43             :  *-----------------------------------------------------------------------*/
      44             : 
      45    87323167 : static uint32_t ivas_td_ringbuf_total_size(
      46             :     TD_RINGBUF_HANDLE h )
      47             : {
      48    87323167 :     if ( h->is_full )
      49             :     {
      50      145806 :         return h->capacity;
      51             :     }
      52             : 
      53    87177361 :     if ( h->read_pos <= h->write_pos )
      54             :     {
      55    64687928 :         return h->write_pos - h->read_pos;
      56             :     }
      57             :     /* else wrap around */
      58    22489433 :     return h->write_pos + h->capacity - h->read_pos;
      59             : }
      60             : 
      61             : 
      62    43666785 : static int16_t ivas_td_ringbuf_has_space_for_num_samples(
      63             :     TD_RINGBUF_HANDLE h,
      64             :     const uint32_t num_samples )
      65             : {
      66    43666785 :     return (int16_t) ( ivas_td_ringbuf_total_size( h ) + num_samples <= h->capacity );
      67             : }
      68             : 
      69             : 
      70             : #ifdef FIX_1119_SPLIT_RENDERING_VOIP
      71      164849 : static void ivas_td_ringbuf_push_interleaved(
      72             :     TD_RINGBUF_HANDLE h,                    /* i/o: Ring buffer handle                                              */
      73             :     const float *data,                      /* i  : Input audio in interleaved channels layout                      */
      74             :     const uint32_t num_samples_per_channel, /* i  : Number of samples per channel to push                           */
      75             :     const uint16_t read_stride              /* i: : 1 for normal operation, 0 for reading from a single input value */
      76             : )
      77             : {
      78             :     uint32_t s, read_s;
      79             : 
      80      164849 :     assert( h != NULL );
      81      164849 :     assert( data != NULL );
      82      164849 :     assert( read_stride == 0 || read_stride == 1 );
      83      164849 :     assert( ivas_td_ringbuf_has_space_for_num_samples( h, num_samples_per_channel * h->num_channels ) );
      84             : 
      85   926556279 :     for ( s = 0, read_s = 0; s < num_samples_per_channel * h->num_channels; ++s, read_s += read_stride )
      86             :     {
      87   926391430 :         h->data[h->write_pos] = data[read_s];
      88   926391430 :         ++h->write_pos;
      89             : 
      90   926391430 :         if ( h->write_pos == h->capacity )
      91             :         {
      92      145806 :             h->write_pos = 0;
      93             :         }
      94             :     }
      95             : 
      96      164849 :     if ( h->read_pos == h->write_pos )
      97             :     {
      98      145806 :         h->is_full = 1;
      99             :     }
     100             : 
     101      164849 :     return;
     102             : }
     103             : #endif
     104             : 
     105             : 
     106             : /*-----------------------------------------------------------------------*
     107             :  * Global function definitions
     108             :  *-----------------------------------------------------------------------*/
     109             : 
     110             : /*---------------------------------------------------------------------*
     111             :  * ivas_TD_RINGBUF_Open()
     112             :  *
     113             :  * Allocate a ring buffer for TD data with the given capacity of TD samples per channel.
     114             :  *
     115             :  * May return IVAS_ERR_FAILED_ALLOC on failed allocation, or IVAS_ERR_OK otherwise.
     116             :  *---------------------------------------------------------------------*/
     117             : 
     118        9330 : ivas_error ivas_TD_RINGBUF_Open(
     119             :     TD_RINGBUF_HANDLE *ph,               /* i/o: Ring buffer handle                     */
     120             :     const uint32_t capacity_per_channel, /* i  : Number of samples stored per channel   */
     121             :     const uint16_t num_channels          /* i  : Number of channels                     */
     122             : )
     123             : {
     124             :     TD_RINGBUF_HANDLE h;
     125             :     uint32_t capacity;
     126             : 
     127        9330 :     capacity = capacity_per_channel * num_channels;
     128             : 
     129        9330 :     h = malloc( sizeof( TD_RINGBUF_DATA ) );
     130        9330 :     if ( h == NULL )
     131             :     {
     132           0 :         return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Failed to allocate memory for TD ring buffer\n" );
     133             :     }
     134        9330 :     h->data = NULL;
     135        9330 :     h->capacity = 0;
     136        9330 :     h->num_channels = num_channels;
     137        9330 :     h->write_pos = 0;
     138        9330 :     h->read_pos = 0;
     139        9330 :     h->is_full = 0;
     140        9330 :     *ph = h;
     141             : 
     142        9330 :     h->data = malloc( capacity * sizeof( float ) );
     143        9330 :     if ( h->data == NULL )
     144             :     {
     145           0 :         return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Failed to allocate memory for TD ring buffer\n" );
     146             :     }
     147        9330 :     h->capacity = capacity;
     148             : 
     149        9330 :     return IVAS_ERR_OK;
     150             : }
     151             : 
     152             : 
     153             : /*---------------------------------------------------------------------*
     154             :  * ivas_TD_RINGBUF_Close()
     155             :  *
     156             :  * Dellocate TD ring buffer. The given handle will be set to NULL.
     157             : 
     158             :  *---------------------------------------------------------------------*/
     159             : 
     160       99943 : void ivas_TD_RINGBUF_Close(
     161             :     TD_RINGBUF_HANDLE *ph /* i/o: Ring buffer handle */
     162             : )
     163             : {
     164             :     TD_RINGBUF_HANDLE h;
     165             : 
     166       99943 :     if ( ph == NULL )
     167             :     {
     168           0 :         return;
     169             :     }
     170       99943 :     h = *ph;
     171             : 
     172       99943 :     if ( h == NULL )
     173             :     {
     174       90613 :         return;
     175             :     }
     176             : 
     177        9330 :     if ( h->data != NULL )
     178             :     {
     179        9330 :         free( h->data );
     180             :     }
     181             : 
     182        9330 :     free( h );
     183        9330 :     *ph = NULL;
     184             : 
     185        9330 :     return;
     186             : }
     187             : 
     188             : 
     189             : #ifdef FIX_1119_SPLIT_RENDERING_VOIP
     190             : /*---------------------------------------------------------------------*
     191             :  * ivas_TD_RINGBUF_PushInterleaved()
     192             :  *
     193             :  * Push samples from a buffer with interleaved channel layout onto the back of the TD ring buffer.
     194             :  *---------------------------------------------------------------------*/
     195             : 
     196      156209 : void ivas_TD_RINGBUF_PushInterleaved(
     197             :     TD_RINGBUF_HANDLE h,                   /* i/o: Ring buffer handle                           */
     198             :     const float *data,                     /* i  : Input audio in interleaved channels layout   */
     199             :     const uint32_t num_samples_per_channel /* i  : Number of samples per channel to push        */
     200             : )
     201             : {
     202      156209 :     ivas_td_ringbuf_push_interleaved( h, data, num_samples_per_channel, 1 );
     203             : 
     204      156209 :     return;
     205             : }
     206             : 
     207             : 
     208             : /*---------------------------------------------------------------------*
     209             :  * ivas_TD_RINGBUF_PushChannels()
     210             :  *
     211             :  * Push samples from channel pointers onto the back of the TD ring buffer.
     212             :  *---------------------------------------------------------------------*/
     213             : 
     214    43501936 : void ivas_TD_RINGBUF_PushChannels(
     215             :     TD_RINGBUF_HANDLE h,                   /* i/o: Ring buffer handle                       */
     216             :     const float *p_channels[],             /* i  : Array of pointers to each input channel  */
     217             :     const uint32_t num_samples_per_channel /* i  : Number of samples per channel to push    */
     218             : )
     219             : #else
     220             : /*---------------------------------------------------------------------*
     221             :  * ivas_TD_RINGBUF_Push()
     222             :  *
     223             :  * Push samples onto the back of the TD ring buffer.
     224             :  * Returns total number of buffered samples (includes number of channels)
     225             :  *---------------------------------------------------------------------*/
     226             : 
     227             : void ivas_TD_RINGBUF_Push(
     228             :     TD_RINGBUF_HANDLE h,                   /* i/o: Ring buffer handle                       */
     229             :     const float *data,                     /* i  : Input data                               */
     230             :     const uint32_t num_samples_per_channel /* i  : Number of samples per channel to store   */
     231             : )
     232             : #endif
     233             : {
     234             :     uint32_t s;
     235             :     uint16_t c;
     236             : 
     237             : #ifdef FIX_1119_SPLIT_RENDERING_VOIP
     238    43501936 :     assert( h != NULL );
     239    43501936 :     assert( p_channels != NULL );
     240   189837416 :     for ( c = 0; c < h->num_channels; ++c )
     241             :     {
     242   146335480 :         assert( p_channels[c] != NULL );
     243             :     }
     244             : #endif
     245    43501936 :     assert( ivas_td_ringbuf_has_space_for_num_samples( h, num_samples_per_channel * h->num_channels ) );
     246             : 
     247 12777327536 :     for ( s = 0; s < num_samples_per_channel; ++s )
     248             :     {
     249 61051292800 :         for ( c = 0; c < h->num_channels; ++c )
     250             :         {
     251             : #ifdef FIX_1119_SPLIT_RENDERING_VOIP
     252 48317467200 :             h->data[h->write_pos] = p_channels[c][s];
     253             : #else
     254             :             h->data[h->write_pos] = *( data + c * num_samples_per_channel + s );
     255             : #endif
     256 48317467200 :             ++h->write_pos;
     257             : 
     258 48317467200 :             if ( h->write_pos == h->capacity )
     259             :             {
     260    17444141 :                 h->write_pos = 0;
     261             :             }
     262             :         }
     263             :     }
     264             : 
     265    43501936 :     if ( h->read_pos == h->write_pos )
     266             :     {
     267           0 :         h->is_full = 1;
     268             :     }
     269             : 
     270    43501936 :     return;
     271             : }
     272             : 
     273             : 
     274             : #ifdef FIX_1119_SPLIT_RENDERING_VOIP
     275             : /*---------------------------------------------------------------------*
     276             :  * ivas_TD_RINGBUF_PushConstant()
     277             :  *
     278             :  * Push samples with a constant value onto the back of the TD ring buffer.
     279             :  *---------------------------------------------------------------------*/
     280             : 
     281        8640 : void ivas_TD_RINGBUF_PushConstant(
     282             :     TD_RINGBUF_HANDLE h,                   /* i/o: Ring buffer handle                      */
     283             :     const float value,                     /* i  : Value to push                           */
     284             :     const uint32_t num_samples_per_channel /* i  : Number of samples per channel to push   */
     285             : )
     286             : {
     287        8640 :     ivas_td_ringbuf_push_interleaved( h, &value, num_samples_per_channel, 0 );
     288             : 
     289        8640 :     return;
     290             : }
     291             : #else
     292             : /*---------------------------------------------------------------------*
     293             :  * ivas_TD_RINGBUF_PushZeros()
     294             :  *
     295             :  * Push zero samples onto the back of the TD ring buffer.
     296             :  *---------------------------------------------------------------------*/
     297             : 
     298             : void ivas_TD_RINGBUF_PushZeros(
     299             :     TD_RINGBUF_HANDLE h,                   /* i/o: Ring buffer handle                   */
     300             :     const uint32_t num_samples_per_channel /* i  : Number of zeros per channel to store */
     301             : )
     302             : {
     303             :     uint32_t s;
     304             :     uint16_t c;
     305             : 
     306             :     assert( ivas_td_ringbuf_has_space_for_num_samples( h, num_samples_per_channel * h->num_channels ) );
     307             :     if ( !num_samples_per_channel )
     308             :     {
     309             :         return;
     310             :     }
     311             : 
     312             :     for ( s = 0; s < num_samples_per_channel; ++s )
     313             :     {
     314             :         for ( c = 0; c < h->num_channels; ++c )
     315             :         {
     316             :             h->data[h->write_pos] = 0.f;
     317             :             ++h->write_pos;
     318             : 
     319             :             if ( h->write_pos == h->capacity )
     320             :             {
     321             :                 h->write_pos = 0;
     322             :             }
     323             :         }
     324             :     }
     325             : 
     326             :     if ( h->read_pos == h->write_pos )
     327             :     {
     328             :         h->is_full = 1;
     329             :     }
     330             : 
     331             :     return;
     332             : }
     333             : #endif
     334             : 
     335             : 
     336             : #ifdef FIX_1119_SPLIT_RENDERING_VOIP
     337             : /*---------------------------------------------------------------------*
     338             :  * ivas_TD_RINGBUF_PopChannels()
     339             :  *
     340             :  * Pop samples from the front of the TD ring buffer to an array of channel pointers.
     341             :  *---------------------------------------------------------------------*/
     342             : 
     343    43647742 : void ivas_TD_RINGBUF_PopChannels(
     344             :     TD_RINGBUF_HANDLE h,                   /* i/o: Ring buffer handle                       */
     345             :     float *p_channels[],                   /* i  : Array of pointers to each output channel */
     346             :     const uint32_t num_samples_per_channel /* i  : Number of samples per channel to pop     */
     347             : )
     348             : #else
     349             : /*---------------------------------------------------------------------*
     350             :  * ivas_TD_RINGBUF_Pop()
     351             :  *
     352             :  * Pop samples from the front of the TD ring buffer.
     353             :  *---------------------------------------------------------------------*/
     354             : 
     355             : void ivas_TD_RINGBUF_Pop(
     356             :     TD_RINGBUF_HANDLE h,                   /* i/o: Ring buffer handle                           */
     357             :     float *data,                           /* i  : Output data                                  */
     358             :     const uint32_t num_samples_per_channel /* i  : Number of samples per channel to retrieve    */
     359             : )
     360             : #endif
     361             : {
     362             :     uint32_t s;
     363             :     uint16_t c;
     364             : 
     365             : #ifdef FIX_1119_SPLIT_RENDERING_VOIP
     366    43647742 :     assert( h != NULL );
     367    43647742 :     assert( p_channels != NULL );
     368   190974210 :     for ( c = 0; c < h->num_channels; ++c )
     369             :     {
     370   147326468 :         assert( p_channels[c] != NULL );
     371             :     }
     372             : #endif
     373    43647742 :     assert( ivas_td_ringbuf_total_size( h ) >= num_samples_per_channel * h->num_channels );
     374             : 
     375 12905467762 :     for ( s = 0; s < num_samples_per_channel; ++s )
     376             :     {
     377 62105678650 :         for ( c = 0; c < h->num_channels; ++c )
     378             :         {
     379             : #ifdef FIX_1119_SPLIT_RENDERING_VOIP
     380 49243858630 :             p_channels[c][s] = h->data[h->read_pos];
     381             : #else
     382             :             *( data + c * num_samples_per_channel + s ) = h->data[h->read_pos];
     383             : #endif
     384 49243858630 :             ++h->read_pos;
     385             : 
     386 49243858630 :             if ( h->read_pos == h->capacity )
     387             :             {
     388    17589947 :                 h->read_pos = 0;
     389             :             }
     390             :         }
     391             :     }
     392             : 
     393             : #ifdef FIX_1119_SPLIT_RENDERING_VOIP
     394    43647742 :     if ( num_samples_per_channel != 0 )
     395             :     {
     396    43647742 :         h->is_full = 0;
     397             :     }
     398             : #else
     399             :     if ( h->is_full )
     400             :     {
     401             :         h->is_full = 0;
     402             :     }
     403             : #endif
     404             : 
     405    43647742 :     return;
     406             : }
     407             : 
     408             : 
     409             : /*---------------------------------------------------------------------*
     410             :  * ivas_TD_RINGBUF_Size()
     411             :  *
     412             :  * Returns number of buffered samples per channel.
     413             :  *---------------------------------------------------------------------*/
     414             : 
     415        8640 : uint32_t ivas_TD_RINGBUF_Size(
     416             :     const TD_RINGBUF_HANDLE h /* i  : Ring buffer handle */
     417             : )
     418             : {
     419        8640 :     return ivas_td_ringbuf_total_size( h ) / (uint32_t) h->num_channels;
     420             : }

Generated by: LCOV version 1.14