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 81053048 : static uint32_t ivas_td_ringbuf_total_size(
46 : TD_RINGBUF_HANDLE h )
47 : {
48 81053048 : if ( h->is_full )
49 : {
50 0 : return h->capacity;
51 : }
52 :
53 81053048 : if ( h->read_pos <= h->write_pos )
54 : {
55 60085668 : return h->write_pos - h->read_pos;
56 : }
57 : /* else wrap around */
58 20967380 : return h->write_pos + h->capacity - h->read_pos;
59 : }
60 :
61 :
62 40526524 : static int16_t ivas_td_ringbuf_has_space_for_num_samples(
63 : TD_RINGBUF_HANDLE h,
64 : const uint32_t num_samples )
65 : {
66 40526524 : return (int16_t) ( ivas_td_ringbuf_total_size( h ) + num_samples <= h->capacity );
67 : }
68 :
69 :
70 : #ifdef FIX_1119_SPLIT_RENDERING_VOIP
71 2792 : 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 2792 : assert( h != NULL );
81 2792 : assert( data != NULL );
82 2792 : assert( read_stride == 0 || read_stride == 1 );
83 2792 : assert( ivas_td_ringbuf_has_space_for_num_samples( h, num_samples_per_channel * h->num_channels ) );
84 :
85 333120 : for ( s = 0, read_s = 0; s < num_samples_per_channel * h->num_channels; ++s, read_s += read_stride )
86 : {
87 330328 : h->data[h->write_pos] = data[read_s];
88 330328 : ++h->write_pos;
89 :
90 330328 : if ( h->write_pos == h->capacity )
91 : {
92 0 : h->write_pos = 0;
93 : }
94 : }
95 :
96 2792 : if ( h->read_pos == h->write_pos )
97 : {
98 0 : h->is_full = 1;
99 : }
100 :
101 2792 : 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 2792 : 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 2792 : capacity = capacity_per_channel * num_channels;
128 :
129 2792 : h = malloc( sizeof( TD_RINGBUF_DATA ) );
130 2792 : if ( h == NULL )
131 : {
132 0 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Failed to allocate memory for TD ring buffer\n" );
133 : }
134 2792 : h->data = NULL;
135 2792 : h->capacity = 0;
136 2792 : h->num_channels = num_channels;
137 2792 : h->write_pos = 0;
138 2792 : h->read_pos = 0;
139 2792 : h->is_full = 0;
140 2792 : *ph = h;
141 :
142 2792 : h->data = malloc( capacity * sizeof( float ) );
143 2792 : 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 2792 : h->capacity = capacity;
148 :
149 2792 : 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 30849 : void ivas_TD_RINGBUF_Close(
161 : TD_RINGBUF_HANDLE *ph /* i/o: Ring buffer handle */
162 : )
163 : {
164 : TD_RINGBUF_HANDLE h;
165 :
166 30849 : if ( ph == NULL )
167 : {
168 0 : return;
169 : }
170 30849 : h = *ph;
171 :
172 30849 : if ( h == NULL )
173 : {
174 28057 : return;
175 : }
176 :
177 2792 : if ( h->data != NULL )
178 : {
179 2792 : free( h->data );
180 : }
181 :
182 2792 : free( h );
183 2792 : *ph = NULL;
184 :
185 2792 : 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 0 : 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 0 : ivas_td_ringbuf_push_interleaved( h, data, num_samples_per_channel, 1 );
203 :
204 0 : 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 40523732 : 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 40523732 : assert( h != NULL );
239 40523732 : assert( p_channels != NULL );
240 171459628 : for ( c = 0; c < h->num_channels; ++c )
241 : {
242 130935896 : assert( p_channels[c] != NULL );
243 : }
244 : #endif
245 40523732 : assert( ivas_td_ringbuf_has_space_for_num_samples( h, num_samples_per_channel * h->num_channels ) );
246 :
247 11839312532 : for ( s = 0; s < num_samples_per_channel; ++s )
248 : {
249 54878822400 : for ( c = 0; c < h->num_channels; ++c )
250 : {
251 : #ifdef FIX_1119_SPLIT_RENDERING_VOIP
252 43080033600 : 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 43080033600 : ++h->write_pos;
257 :
258 43080033600 : if ( h->write_pos == h->capacity )
259 : {
260 16156968 : h->write_pos = 0;
261 : }
262 : }
263 : }
264 :
265 40523732 : if ( h->read_pos == h->write_pos )
266 : {
267 0 : h->is_full = 1;
268 : }
269 :
270 40523732 : 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 2792 : 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 2792 : ivas_td_ringbuf_push_interleaved( h, &value, num_samples_per_channel, 0 );
288 :
289 2792 : 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 40523732 : 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 40523732 : assert( h != NULL );
367 40523732 : assert( p_channels != NULL );
368 171459628 : for ( c = 0; c < h->num_channels; ++c )
369 : {
370 130935896 : assert( p_channels[c] != NULL );
371 : }
372 : #endif
373 40523732 : assert( ivas_td_ringbuf_total_size( h ) >= num_samples_per_channel * h->num_channels );
374 :
375 11839637364 : for ( s = 0; s < num_samples_per_channel; ++s )
376 : {
377 54879477560 : for ( c = 0; c < h->num_channels; ++c )
378 : {
379 : #ifdef FIX_1119_SPLIT_RENDERING_VOIP
380 43080363928 : 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 43080363928 : ++h->read_pos;
385 :
386 43080363928 : if ( h->read_pos == h->capacity )
387 : {
388 16156968 : h->read_pos = 0;
389 : }
390 : }
391 : }
392 :
393 : #ifdef FIX_1119_SPLIT_RENDERING_VOIP
394 40523732 : if ( num_samples_per_channel != 0 )
395 : {
396 40523732 : h->is_full = 0;
397 : }
398 : #else
399 : if ( h->is_full )
400 : {
401 : h->is_full = 0;
402 : }
403 : #endif
404 :
405 40523732 : return;
406 : }
407 :
408 :
409 : /*---------------------------------------------------------------------*
410 : * ivas_TD_RINGBUF_Size()
411 : *
412 : * Returns number of buffered samples per channel.
413 : *---------------------------------------------------------------------*/
414 :
415 2792 : uint32_t ivas_TD_RINGBUF_Size(
416 : const TD_RINGBUF_HANDLE h /* i : Ring buffer handle */
417 : )
418 : {
419 2792 : return ivas_td_ringbuf_total_size( h ) / (uint32_t) h->num_channels;
420 : }
|