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 : }
|