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 224 : ivas_error JB4_CIRCULARBUFFER_Create(
71 : JB4_CIRCULARBUFFER_HANDLE *ph )
72 : {
73 : JB4_CIRCULARBUFFER_HANDLE h;
74 :
75 224 : 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 224 : h->data = NULL;
81 224 : h->capacity = 0;
82 224 : move16();
83 224 : h->writePos = 0;
84 224 : move16();
85 224 : h->readPos = 0;
86 224 : move16();
87 :
88 224 : *ph = h;
89 :
90 224 : return IVAS_ERR_OK;
91 : }
92 :
93 :
94 : /* Destroys the circular buffer (FIFO) */
95 224 : void JB4_CIRCULARBUFFER_Destroy(
96 : JB4_CIRCULARBUFFER_HANDLE *ph )
97 : {
98 : JB4_CIRCULARBUFFER_HANDLE h;
99 :
100 224 : IF( !ph )
101 : {
102 0 : return;
103 : }
104 224 : h = *ph;
105 224 : IF( !h )
106 : {
107 0 : return;
108 : }
109 :
110 224 : IF( h->data )
111 : {
112 224 : free( h->data );
113 : }
114 224 : free( h );
115 224 : *ph = NULL;
116 :
117 224 : return;
118 : }
119 :
120 :
121 : /* Initializes a circular buffer (FIFO) with a fixed maximum allowed number of elements */
122 224 : 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 224 : capacity = (UWord16) L_add( capacity, 1 );
128 :
129 224 : 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 224 : h->capacity = capacity;
135 224 : move16();
136 224 : h->writePos = 0;
137 224 : move16();
138 224 : h->readPos = 0;
139 224 : move16();
140 :
141 224 : return IVAS_ERR_OK;
142 : }
143 :
144 :
145 141088 : Word16 JB4_CIRCULARBUFFER_Enque(
146 : JB4_CIRCULARBUFFER_HANDLE h,
147 : JB4_CIRCULARBUFFER_ELEMENT element )
148 : {
149 141088 : IF( JB4_CIRCULARBUFFER_IsFull( h ) )
150 : {
151 0 : return -1;
152 : }
153 :
154 141088 : h->data[h->writePos] = element;
155 141088 : move32();
156 141088 : h->writePos = (UWord16) L_add( h->writePos, 1 );
157 141088 : move16();
158 141088 : if ( EQ_32( h->writePos, h->capacity ) )
159 : {
160 1178 : h->writePos = 0;
161 1178 : move16();
162 : }
163 :
164 141088 : return 0;
165 : }
166 :
167 :
168 99689 : Word16 JB4_CIRCULARBUFFER_Deque(
169 : JB4_CIRCULARBUFFER_HANDLE h,
170 : JB4_CIRCULARBUFFER_ELEMENT *pElement )
171 : {
172 99689 : IF( JB4_CIRCULARBUFFER_IsEmpty( h ) )
173 : {
174 0 : return -1;
175 : }
176 :
177 99689 : *pElement = h->data[h->readPos];
178 99689 : move32();
179 99689 : h->readPos = (UWord16) L_add( h->readPos, 1 );
180 99689 : move16();
181 99689 : if ( EQ_32( h->readPos, h->capacity ) )
182 : {
183 1012 : h->readPos = 0;
184 1012 : move16();
185 : }
186 :
187 99689 : return 0;
188 : }
189 :
190 :
191 : /* Returns the first element. */
192 83639 : JB4_CIRCULARBUFFER_ELEMENT JB4_CIRCULARBUFFER_Front(
193 : const JB4_CIRCULARBUFFER_HANDLE h )
194 : {
195 : JB4_CIRCULARBUFFER_ELEMENT ret;
196 :
197 83639 : ret = h->data[h->readPos];
198 83639 : move32();
199 :
200 83639 : return ret;
201 : }
202 :
203 : /* Returns the last element. */
204 52901 : JB4_CIRCULARBUFFER_ELEMENT JB4_CIRCULARBUFFER_Back(
205 : const JB4_CIRCULARBUFFER_HANDLE h )
206 : {
207 : JB4_CIRCULARBUFFER_ELEMENT ret;
208 :
209 52901 : IF( h->writePos != 0U )
210 : {
211 52485 : ret = h->data[h->writePos - 1];
212 52485 : move32();
213 : }
214 : ELSE
215 : {
216 416 : ret = h->data[h->capacity - 1];
217 416 : move32();
218 : }
219 :
220 :
221 52901 : return ret;
222 : }
223 :
224 :
225 190204 : Word16 JB4_CIRCULARBUFFER_IsEmpty(
226 : const JB4_CIRCULARBUFFER_HANDLE h )
227 : {
228 : Word16 ret;
229 :
230 190204 : IF( EQ_32( h->readPos, h->writePos ) )
231 : {
232 56 : ret = 1;
233 56 : move16();
234 : }
235 : ELSE
236 : {
237 190148 : ret = 0;
238 190148 : move16();
239 : }
240 :
241 190204 : return ret;
242 : }
243 :
244 :
245 193989 : Word16 JB4_CIRCULARBUFFER_IsFull(
246 : const JB4_CIRCULARBUFFER_HANDLE h )
247 : {
248 : Word16 ret;
249 :
250 193989 : IF( EQ_32( ( L_add( h->writePos, 1 ) % h->capacity ), h->readPos ) )
251 : {
252 6784 : ret = 1;
253 6784 : move16();
254 : }
255 : ELSE
256 : {
257 187205 : ret = 0;
258 187205 : move16();
259 : }
260 :
261 193989 : return ret;
262 : }
263 :
264 :
265 37280 : UWord16 JB4_CIRCULARBUFFER_Size(
266 : const JB4_CIRCULARBUFFER_HANDLE h )
267 : {
268 : UWord16 ret;
269 :
270 37280 : IF( LE_32( h->readPos, h->writePos ) )
271 : {
272 14090 : ret = (UWord16) L_sub( h->writePos, h->readPos );
273 14090 : move16();
274 : }
275 : ELSE
276 : {
277 : /* wrap around */
278 23190 : ret = (UWord16) L_add( h->writePos, L_sub( h->capacity, h->readPos ) );
279 23190 : move16();
280 : }
281 :
282 :
283 37280 : return ret;
284 : }
285 :
286 :
287 : /* Calculates statistics over all elements: min element */
288 72844 : 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 72844 : minEle = h->data[h->readPos];
297 72844 : move32();
298 :
299 72844 : IF( LE_32( h->readPos, h->writePos ) )
300 : {
301 : /* no wrap around */
302 : /* calc statistics for [readPos;writePos[ */
303 7103815 : FOR( i = h->readPos; i != h->writePos; ++i )
304 : {
305 7069272 : if ( LT_32( h->data[i], minEle ) )
306 : {
307 3313 : minEle = h->data[i];
308 3313 : move32();
309 : }
310 : }
311 : }
312 : ELSE
313 : {
314 : /* wrap around */
315 : /* calc statistics for [readPos;capacity[ */
316 6007205 : FOR( i = h->readPos; i != h->capacity; ++i )
317 : {
318 5968904 : if ( LT_32( h->data[i], minEle ) )
319 : {
320 52123 : minEle = h->data[i];
321 52123 : move32();
322 : }
323 : }
324 : /* calc statistics for [0;writePos[ */
325 5321749 : FOR( i = 0; i != h->writePos; ++i )
326 : {
327 5283448 : if ( LT_32( h->data[i], minEle ) )
328 : {
329 1764 : minEle = h->data[i];
330 1764 : move32();
331 : }
332 : }
333 : }
334 :
335 72844 : *pMin = minEle;
336 72844 : move32();
337 72844 : }
338 :
339 :
340 : /* Calculates statistics over all elements: max element */
341 17615 : 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 17615 : maxEle = h->data[h->readPos];
350 17615 : move32();
351 17615 : IF( LE_32( h->readPos, h->writePos ) )
352 : {
353 : /* no wrap around */
354 : /* calc statistics for [readPos;writePos[ */
355 646291 : FOR( i = h->readPos; i != h->writePos; ++i )
356 : {
357 640063 : if ( GT_32( h->data[i], maxEle ) )
358 : {
359 20370 : maxEle = h->data[i];
360 20370 : 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 17615 : *pMax = maxEle;
388 17615 : move32();
389 :
390 17615 : 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 37168 : 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 37168 : minEle = h->data[h->readPos];
410 37168 : 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 37168 : maxElementsSize = 0;
416 37168 : move16();
417 37168 : maxElementsCapacity = (UWord16) L_add( nElementsToIgnore, 1 );
418 37168 : move16();
419 37168 : assert( maxElementsCapacity <= JBM_MAX_CIRCULAR_ELEMENTS );
420 37168 : IF( LE_32( h->readPos, h->writePos ) )
421 : {
422 : /* no wrap around */
423 : /* calc statistics for [readPos;writePos[ */
424 2628998 : FOR( i = h->readPos; i != h->writePos; ++i )
425 : {
426 2615020 : if ( LT_32( h->data[i], minEle ) )
427 : {
428 2362 : minEle = h->data[i];
429 2362 : move32();
430 : }
431 2615020 : JB4_CIRCULARBUFFER_calcPercentile( maxElements, &maxElementsSize, maxElementsCapacity, h->data[i] );
432 : }
433 : }
434 : ELSE
435 : {
436 : /* wrap around */
437 : /* calc statistics for [readPos;capacity[ */
438 2360779 : FOR( i = h->readPos; i != h->capacity; ++i )
439 : {
440 2337589 : if ( LT_32( h->data[i], minEle ) )
441 : {
442 31100 : minEle = h->data[i];
443 31100 : move32();
444 : }
445 2337589 : JB4_CIRCULARBUFFER_calcPercentile( maxElements, &maxElementsSize, maxElementsCapacity, h->data[i] );
446 : }
447 : /* calc statistics for [0;writePos[ */
448 2089162 : FOR( i = 0; i != h->writePos; ++i )
449 : {
450 2065972 : if ( LT_32( h->data[i], minEle ) )
451 : {
452 1764 : minEle = h->data[i];
453 1764 : move32();
454 : }
455 2065972 : JB4_CIRCULARBUFFER_calcPercentile( maxElements, &maxElementsSize, maxElementsCapacity, h->data[i] );
456 : }
457 : }
458 :
459 37168 : *pPercentile = maxElements[0];
460 37168 : move32();
461 37168 : *pMin = minEle;
462 37168 : move32();
463 :
464 37168 : return;
465 : }
466 :
467 :
468 : /* Calculates percentile by selecting greatest elements. */
469 7018581 : 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 7018581 : IF( LT_32( *size, capacity ) )
479 : {
480 123981 : FOR( i = 0; i != *size; ++i )
481 : {
482 77158 : IF( LE_32( newElement, elements[i] ) )
483 : {
484 : /* insert newElement at index i */
485 114520 : FOR( j = *size; j > i; --j )
486 : {
487 71414 : elements[j] = elements[j - 1];
488 71414 : move32();
489 : }
490 43106 : elements[i] = newElement;
491 43106 : move32();
492 43106 : *size = (UWord16) L_add( *size, 1 );
493 43106 : move16();
494 43106 : return;
495 : }
496 : }
497 : /* newElement is maximum, just append it */
498 46823 : elements[*size] = newElement;
499 46823 : move32();
500 46823 : *size = (UWord16) L_add( *size, 1 );
501 46823 : move16();
502 46823 : return;
503 : }
504 :
505 : /* check IF newElement is too small to be inserted in elements buffer */
506 6928652 : IF( LE_32( newElement, elements[0] ) )
507 : {
508 6763291 : return;
509 : }
510 :
511 : /* select position to insert newElement to elements */
512 280163 : FOR( i = *size - 1; i != 0; --i )
513 : {
514 211052 : IF( GE_32( newElement, elements[i] ) )
515 : {
516 : /* insert newElement at index i */
517 313398 : FOR( j = 0; j < i; j++ )
518 : {
519 217148 : elements[j] = elements[1 + j];
520 217148 : move32();
521 : }
522 96250 : elements[i] = newElement;
523 96250 : move32();
524 96250 : return;
525 : }
526 : }
527 : /* newElement is just greater than first on in elements buffer */
528 69111 : elements[0] = newElement;
529 69111 : move32();
530 :
531 69111 : return;
532 : }
|