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 6899761 : static int32_t ivas_td_ringbuf_total_size(
53 : TD_RINGBUF_HANDLE h )
54 : {
55 6899761 : if ( h->is_full )
56 : {
57 86531 : return h->capacity;
58 : }
59 :
60 6813230 : if ( h->read_pos <= h->write_pos )
61 : {
62 5091143 : return h->write_pos - h->read_pos;
63 : }
64 : /* else wrap around */
65 1722087 : return h->write_pos + h->capacity - h->read_pos;
66 : }
67 :
68 :
69 3452918 : static int16_t ivas_td_ringbuf_has_space_for_num_samples(
70 : TD_RINGBUF_HANDLE h,
71 : const int32_t num_samples )
72 : {
73 3452918 : return (int16_t) ( ivas_td_ringbuf_total_size( h ) + num_samples <= h->capacity );
74 : }
75 :
76 :
77 99210 : 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 99210 : assert( h != NULL );
87 99210 : assert( data != NULL );
88 99210 : assert( read_stride == 0 || read_stride == 1 );
89 99210 : assert( ivas_td_ringbuf_has_space_for_num_samples( h, (int32_t) num_samples_per_channel * h->num_channels ) );
90 :
91 568189336 : for ( s = 0, read_s = 0; s < (int32_t) num_samples_per_channel * h->num_channels; ++s, read_s += read_stride )
92 : {
93 568090126 : h->data[h->write_pos] = data[read_s];
94 568090126 : ++h->write_pos;
95 :
96 568090126 : if ( h->write_pos == h->capacity )
97 : {
98 86531 : h->write_pos = 0;
99 : }
100 : }
101 :
102 99210 : if ( h->read_pos == h->write_pos )
103 : {
104 86531 : h->is_full = 1;
105 : }
106 :
107 99210 : 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 7068 : 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 7068 : capacity = (int32_t) capacity_per_channel * num_channels;
133 :
134 7068 : h = malloc( sizeof( TD_RINGBUF_DATA ) );
135 7068 : if ( h == NULL )
136 : {
137 0 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Failed to allocate memory for TD ring buffer\n" );
138 : }
139 7068 : h->data = NULL;
140 7068 : h->capacity = 0;
141 7068 : h->num_channels = num_channels;
142 7068 : h->write_pos = 0;
143 7068 : h->read_pos = 0;
144 7068 : h->is_full = 0;
145 7068 : *ph = h;
146 :
147 7068 : h->data = malloc( capacity * sizeof( float ) );
148 7068 : 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 7068 : h->capacity = capacity;
153 :
154 7068 : 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 72942 : void ivas_TD_RINGBUF_Close(
165 : TD_RINGBUF_HANDLE *ph /* i/o: Ring buffer handle */
166 : )
167 : {
168 : TD_RINGBUF_HANDLE h;
169 :
170 72942 : if ( ph == NULL )
171 : {
172 0 : return;
173 : }
174 72942 : h = *ph;
175 :
176 72942 : if ( h == NULL )
177 : {
178 65874 : return;
179 : }
180 :
181 7068 : if ( h->data != NULL )
182 : {
183 7068 : free( h->data );
184 : }
185 :
186 7068 : free( h );
187 7068 : *ph = NULL;
188 :
189 7068 : 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 92606 : 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 92606 : ivas_td_ringbuf_push_interleaved( h, data, num_samples_per_channel, 1 );
206 :
207 92606 : 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 3353708 : 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 3353708 : assert( h != NULL );
227 3353708 : assert( p_channels != NULL );
228 19471568 : for ( c = 0; c < h->num_channels; ++c )
229 : {
230 16117860 : assert( p_channels[c] != NULL );
231 : }
232 3353708 : assert( ivas_td_ringbuf_has_space_for_num_samples( h, (int32_t) num_samples_per_channel * h->num_channels ) );
233 :
234 1041326508 : for ( s = 0; s < num_samples_per_channel; ++s )
235 : {
236 6485550400 : for ( c = 0; c < h->num_channels; ++c )
237 : {
238 5447577600 : h->data[h->write_pos] = p_channels[c][s];
239 5447577600 : ++h->write_pos;
240 :
241 5447577600 : if ( h->write_pos == h->capacity )
242 : {
243 1437155 : h->write_pos = 0;
244 : }
245 : }
246 : }
247 :
248 3353708 : if ( h->read_pos == h->write_pos )
249 : {
250 0 : h->is_full = 1;
251 : }
252 :
253 3353708 : 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 6604 : 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 6604 : ivas_td_ringbuf_push_interleaved( h, &value, num_samples_per_channel, 0 );
270 :
271 6604 : 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 3440239 : 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 3440239 : assert( h != NULL );
291 3440239 : assert( p_channels != NULL );
292 20164009 : for ( c = 0; c < h->num_channels; ++c )
293 : {
294 16723770 : assert( p_channels[c] != NULL );
295 : }
296 3440239 : assert( ivas_td_ringbuf_total_size( h ) >= (int32_t) num_samples_per_channel * h->num_channels );
297 :
298 1118087943 : for ( s = 0; s < num_samples_per_channel; ++s )
299 : {
300 7130315430 : for ( c = 0; c < h->num_channels; ++c )
301 : {
302 6015667726 : p_channels[c][s] = h->data[h->read_pos];
303 6015667726 : ++h->read_pos;
304 :
305 6015667726 : if ( h->read_pos == h->capacity )
306 : {
307 1523686 : h->read_pos = 0;
308 : }
309 : }
310 : }
311 :
312 3440239 : if ( num_samples_per_channel != 0 )
313 : {
314 3440239 : h->is_full = 0;
315 : }
316 :
317 3440239 : return;
318 : }
319 :
320 :
321 : /*---------------------------------------------------------------------*
322 : * ivas_TD_RINGBUF_Size()
323 : *
324 : * Returns number of buffered samples per channel.
325 : *---------------------------------------------------------------------*/
326 :
327 6604 : int16_t ivas_TD_RINGBUF_Size(
328 : const TD_RINGBUF_HANDLE h /* i : Ring buffer handle */
329 : )
330 : {
331 6604 : return (int16_t) ( ivas_td_ringbuf_total_size( h ) / h->num_channels );
332 : }
|