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 @ 0c62f5312a76f89f3e6d6ab9a8d50516c9ab4059 Lines: 83 87 95.4 %
Date: 2025-12-17 10:49:08 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 <stdint.h>
      35             : #include <stdlib.h>
      36             : #include "ivas_error_utils.h"
      37             : #include "ivas_prot_rend.h"
      38             : #include "options.h"
      39             : #include "wmc_auto.h"
      40             : 
      41             : 
      42             : /*-----------------------------------------------------------------------*
      43             :  * Local function prototypes
      44             :  *-----------------------------------------------------------------------*/
      45             : 
      46             : /*---------------------------------------------------------------------*
      47             :  * ivas_td_ringbuf_total_size()
      48             :  *
      49             :  * Returns total number of buffered samples (including number of channels)
      50             :  *---------------------------------------------------------------------*/
      51             : 
      52   101318345 : static int32_t ivas_td_ringbuf_total_size(
      53             :     TD_RINGBUF_HANDLE h )
      54             : {
      55   101318345 :     if ( h->is_full )
      56             :     {
      57      145806 :         return h->capacity;
      58             :     }
      59             : 
      60   101172539 :     if ( h->read_pos <= h->write_pos )
      61             :     {
      62    74909305 :         return h->write_pos - h->read_pos;
      63             :     }
      64             :     /* else wrap around */
      65    26263234 :     return h->write_pos + h->capacity - h->read_pos;
      66             : }
      67             : 
      68             : 
      69    50664374 : static int16_t ivas_td_ringbuf_has_space_for_num_samples(
      70             :     TD_RINGBUF_HANDLE h,
      71             :     const int32_t num_samples )
      72             : {
      73    50664374 :     return (int16_t) ( ivas_td_ringbuf_total_size( h ) + num_samples <= h->capacity );
      74             : }
      75             : 
      76             : 
      77      166565 : static void ivas_td_ringbuf_push_interleaved(
      78             :     TD_RINGBUF_HANDLE h,                   /* i/o: Ring buffer handle                                              */
      79             :     const float *data,                     /* i  : Input audio in interleaved channels layout                      */
      80             :     const int16_t num_samples_per_channel, /* i  : Number of samples per channel to push                           */
      81             :     const int16_t read_stride              /* i: : 1 for normal operation, 0 for reading from a single input value */
      82             : )
      83             : {
      84             :     int32_t s, read_s;
      85             : 
      86      166565 :     assert( h != NULL );
      87      166565 :     assert( data != NULL );
      88      166565 :     assert( read_stride == 0 || read_stride == 1 );
      89      166565 :     assert( ivas_td_ringbuf_has_space_for_num_samples( h, (int32_t) num_samples_per_channel * h->num_channels ) );
      90             : 
      91   926803226 :     for ( s = 0, read_s = 0; s < (int32_t) num_samples_per_channel * h->num_channels; ++s, read_s += read_stride )
      92             :     {
      93   926636661 :         h->data[h->write_pos] = data[read_s];
      94   926636661 :         ++h->write_pos;
      95             : 
      96   926636661 :         if ( h->write_pos == h->capacity )
      97             :         {
      98      145806 :             h->write_pos = 0;
      99             :         }
     100             :     }
     101             : 
     102      166565 :     if ( h->read_pos == h->write_pos )
     103             :     {
     104      145806 :         h->is_full = 1;
     105             :     }
     106             : 
     107      166565 :     return;
     108             : }
     109             : 
     110             : 
     111             : /*-----------------------------------------------------------------------*
     112             :  * Global function definitions
     113             :  *-----------------------------------------------------------------------*/
     114             : 
     115             : /*---------------------------------------------------------------------*
     116             :  * ivas_TD_RINGBUF_Open()
     117             :  *
     118             :  * Allocates a ring buffer for TD data with the given capacity of TD samples per channel.
     119             :  *
     120             :  * May return IVAS_ERR_FAILED_ALLOC on failed allocation, or IVAS_ERR_OK otherwise.
     121             :  *---------------------------------------------------------------------*/
     122             : 
     123       11046 : ivas_error ivas_TD_RINGBUF_Open(
     124             :     TD_RINGBUF_HANDLE *ph,              /* i/o: Ring buffer handle                     */
     125             :     const int16_t capacity_per_channel, /* i  : Number of samples stored per channel   */
     126             :     const int16_t num_channels          /* i  : Number of channels                     */
     127             : )
     128             : {
     129             :     TD_RINGBUF_HANDLE h;
     130             :     int32_t capacity;
     131             : 
     132       11046 :     capacity = (int32_t) capacity_per_channel * num_channels;
     133             : 
     134       11046 :     h = malloc( sizeof( TD_RINGBUF_DATA ) );
     135       11046 :     if ( h == NULL )
     136             :     {
     137           0 :         return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Failed to allocate memory for TD ring buffer\n" );
     138             :     }
     139       11046 :     h->data = NULL;
     140       11046 :     h->capacity = 0;
     141       11046 :     h->num_channels = num_channels;
     142       11046 :     h->write_pos = 0;
     143       11046 :     h->read_pos = 0;
     144       11046 :     h->is_full = 0;
     145       11046 :     *ph = h;
     146             : 
     147       11046 :     h->data = malloc( capacity * sizeof( float ) );
     148       11046 :     if ( h->data == NULL )
     149             :     {
     150           0 :         return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Failed to allocate memory for TD ring buffer\n" );
     151             :     }
     152       11046 :     h->capacity = capacity;
     153             : 
     154       11046 :     return IVAS_ERR_OK;
     155             : }
     156             : 
     157             : 
     158             : /*---------------------------------------------------------------------*
     159             :  * ivas_TD_RINGBUF_Close()
     160             :  *
     161             :  * Dellocates TD ring buffer. The given handle will be set to NULL.
     162             :  *---------------------------------------------------------------------*/
     163             : 
     164      114762 : void ivas_TD_RINGBUF_Close(
     165             :     TD_RINGBUF_HANDLE *ph /* i/o: Ring buffer handle */
     166             : )
     167             : {
     168             :     TD_RINGBUF_HANDLE h;
     169             : 
     170      114762 :     if ( ph == NULL )
     171             :     {
     172           0 :         return;
     173             :     }
     174      114762 :     h = *ph;
     175             : 
     176      114762 :     if ( h == NULL )
     177             :     {
     178      103716 :         return;
     179             :     }
     180             : 
     181       11046 :     if ( h->data != NULL )
     182             :     {
     183       11046 :         free( h->data );
     184             :     }
     185             : 
     186       11046 :     free( h );
     187       11046 :     *ph = NULL;
     188             : 
     189       11046 :     return;
     190             : }
     191             : 
     192             : 
     193             : /*---------------------------------------------------------------------*
     194             :  * ivas_TD_RINGBUF_PushInterleaved()
     195             :  *
     196             :  * Pushes samples from a buffer with interleaved channel layout onto the back of the TD ring buffer.
     197             :  *---------------------------------------------------------------------*/
     198             : 
     199      156209 : void ivas_TD_RINGBUF_PushInterleaved(
     200             :     TD_RINGBUF_HANDLE h,                  /* i/o: Ring buffer handle                           */
     201             :     const float *data,                    /* i  : Input audio in interleaved channels layout   */
     202             :     const int16_t num_samples_per_channel /* i  : Number of samples per channel to push        */
     203             : )
     204             : {
     205      156209 :     ivas_td_ringbuf_push_interleaved( h, data, num_samples_per_channel, 1 );
     206             : 
     207      156209 :     return;
     208             : }
     209             : 
     210             : 
     211             : /*---------------------------------------------------------------------*
     212             :  * ivas_TD_RINGBUF_PushChannels()
     213             :  *
     214             :  * Pushes samples from channel pointers onto the back of the TD ring buffer.
     215             :  *---------------------------------------------------------------------*/
     216             : 
     217    50497809 : void ivas_TD_RINGBUF_PushChannels(
     218             :     TD_RINGBUF_HANDLE h,                  /* i/o: Ring buffer handle                       */
     219             :     const float *p_channels[],            /* i  : Array of pointers to each input channel  */
     220             :     const int16_t num_samples_per_channel /* i  : Number of samples per channel to push    */
     221             : )
     222             : {
     223             :     int32_t s;
     224             :     int16_t c;
     225             : 
     226    50497809 :     assert( h != NULL );
     227    50497809 :     assert( p_channels != NULL );
     228   208415079 :     for ( c = 0; c < h->num_channels; ++c )
     229             :     {
     230   157917270 :         assert( p_channels[c] != NULL );
     231             :     }
     232    50497809 :     assert( ivas_td_ringbuf_has_space_for_num_samples( h, (int32_t) num_samples_per_channel * h->num_channels ) );
     233             : 
     234 14672894929 :     for ( s = 0; s < num_samples_per_channel; ++s )
     235             :     {
     236 66340673920 :         for ( c = 0; c < h->num_channels; ++c )
     237             :         {
     238 51718276800 :             h->data[h->write_pos] = p_channels[c][s];
     239 51718276800 :             ++h->write_pos;
     240             : 
     241 51718276800 :             if ( h->write_pos == h->capacity )
     242             :             {
     243    20103784 :                 h->write_pos = 0;
     244             :             }
     245             :         }
     246             :     }
     247             : 
     248    50497809 :     if ( h->read_pos == h->write_pos )
     249             :     {
     250           0 :         h->is_full = 1;
     251             :     }
     252             : 
     253    50497809 :     return;
     254             : }
     255             : 
     256             : 
     257             : /*---------------------------------------------------------------------*
     258             :  * ivas_TD_RINGBUF_PushConstant()
     259             :  *
     260             :  * Pushes samples with a constant value onto the back of the TD ring buffer.
     261             :  *---------------------------------------------------------------------*/
     262             : 
     263       10356 : void ivas_TD_RINGBUF_PushConstant(
     264             :     TD_RINGBUF_HANDLE h,                  /* i/o: Ring buffer handle                      */
     265             :     const float value,                    /* i  : Value to push                           */
     266             :     const int16_t num_samples_per_channel /* i  : Number of samples per channel to push   */
     267             : )
     268             : {
     269       10356 :     ivas_td_ringbuf_push_interleaved( h, &value, num_samples_per_channel, 0 );
     270             : 
     271       10356 :     return;
     272             : }
     273             : 
     274             : 
     275             : /*---------------------------------------------------------------------*
     276             :  * ivas_TD_RINGBUF_PopChannels()
     277             :  *
     278             :  * Pops samples from the front of the TD ring buffer to an array of channel pointers.
     279             :  *---------------------------------------------------------------------*/
     280             : 
     281    50643615 : void ivas_TD_RINGBUF_PopChannels(
     282             :     TD_RINGBUF_HANDLE h,                  /* i/o: Ring buffer handle                       */
     283             :     float *p_channels[],                  /* i  : Array of pointers to each output channel */
     284             :     const int16_t num_samples_per_channel /* i  : Number of samples per channel to pop     */
     285             : )
     286             : {
     287             :     int32_t s;
     288             :     int16_t c;
     289             : 
     290    50643615 :     assert( h != NULL );
     291    50643615 :     assert( p_channels != NULL );
     292   209551873 :     for ( c = 0; c < h->num_channels; ++c )
     293             :     {
     294   158908258 :         assert( p_channels[c] != NULL );
     295             :     }
     296    50643615 :     assert( ivas_td_ringbuf_total_size( h ) >= (int32_t) num_samples_per_channel * h->num_channels );
     297             : 
     298 14801279330 :     for ( s = 0; s < num_samples_per_channel; ++s )
     299             :     {
     300 67395549176 :         for ( c = 0; c < h->num_channels; ++c )
     301             :         {
     302 52644913461 :             p_channels[c][s] = h->data[h->read_pos];
     303 52644913461 :             ++h->read_pos;
     304             : 
     305 52644913461 :             if ( h->read_pos == h->capacity )
     306             :             {
     307    20249590 :                 h->read_pos = 0;
     308             :             }
     309             :         }
     310             :     }
     311             : 
     312    50643615 :     if ( num_samples_per_channel != 0 )
     313             :     {
     314    50643615 :         h->is_full = 0;
     315             :     }
     316             : 
     317    50643615 :     return;
     318             : }
     319             : 
     320             : 
     321             : /*---------------------------------------------------------------------*
     322             :  * ivas_TD_RINGBUF_Size()
     323             :  *
     324             :  * Returns number of buffered samples per channel.
     325             :  *---------------------------------------------------------------------*/
     326             : 
     327       10356 : int16_t ivas_TD_RINGBUF_Size(
     328             :     const TD_RINGBUF_HANDLE h /* i  : Ring buffer handle */
     329             : )
     330             : {
     331       10356 :     return (int16_t) ( ivas_td_ringbuf_total_size( h ) / h->num_channels );
     332             : }

Generated by: LCOV version 1.14