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.h"
42 : #ifdef DEBUGGING
43 : #include "debug.h"
44 : #endif
45 : #include "wmc_auto.h"
46 : /* local includes */
47 : #include "jbm_jb4_circularbuffer.h"
48 :
49 :
50 : /** Calculates percentile by selecting greatest elements.
51 : * This function partial sorts all given elements in the given buffer.
52 : * @param[in,out] elements ascending sorted buffer of selected greatest elements
53 : * @param[in,out] size size of elements buffer
54 : * @param[in] capacity maximum number of elements to buffer
55 : * @param[in] newElement element to insert in buffer if great enough */
56 : static void JB4_CIRCULARBUFFER_calcPercentile( JB4_CIRCULARBUFFER_ELEMENT *elements, uint16_t *size, const uint16_t capacity, JB4_CIRCULARBUFFER_ELEMENT newElement );
57 :
58 : /** circular buffer (FIFO) with fixed capacity */
59 : struct JB4_CIRCULARBUFFER
60 : {
61 : /** elements of circular buffer */
62 : JB4_CIRCULARBUFFER_ELEMENT *data;
63 : /** maximum allowed number of elements plus one free element (to decide between full/empty buffer) */
64 : uint16_t capacity;
65 : /** position of next enque operation */
66 : uint16_t writePos;
67 : /** position of next deque operation */
68 : uint16_t readPos;
69 : };
70 :
71 :
72 : /* Creates a circular buffer (FIFO) */
73 840 : ivas_error JB4_CIRCULARBUFFER_Create(
74 : JB4_CIRCULARBUFFER_HANDLE *ph )
75 : {
76 : JB4_CIRCULARBUFFER_HANDLE h;
77 :
78 840 : if ( ( h = malloc( sizeof( struct JB4_CIRCULARBUFFER ) ) ) == NULL )
79 : {
80 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for JBM\n" ) );
81 : }
82 :
83 840 : h->data = NULL;
84 840 : h->capacity = 0;
85 840 : h->writePos = 0;
86 840 : h->readPos = 0;
87 :
88 840 : *ph = h;
89 :
90 840 : return IVAS_ERR_OK;
91 : }
92 :
93 :
94 : /* Destroys the circular buffer (FIFO) */
95 840 : void JB4_CIRCULARBUFFER_Destroy(
96 : JB4_CIRCULARBUFFER_HANDLE *ph )
97 : {
98 : JB4_CIRCULARBUFFER_HANDLE h;
99 :
100 840 : if ( !ph )
101 : {
102 0 : return;
103 : }
104 840 : h = *ph;
105 840 : if ( !h )
106 : {
107 0 : return;
108 : }
109 :
110 840 : if ( h->data )
111 : {
112 840 : free( h->data );
113 : }
114 840 : free( h );
115 840 : *ph = NULL;
116 :
117 840 : return;
118 : }
119 :
120 :
121 : /* Initializes a circular buffer (FIFO) with a fixed maximum allowed number of elements */
122 840 : int16_t JB4_CIRCULARBUFFER_Init(
123 : JB4_CIRCULARBUFFER_HANDLE h,
124 : uint16_t capacity )
125 : {
126 : /* keep one element free to be able to decide between full/empty buffer */
127 840 : ++capacity;
128 :
129 840 : 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 840 : h->capacity = capacity;
135 840 : h->writePos = 0;
136 840 : h->readPos = 0;
137 :
138 840 : return IVAS_ERR_OK;
139 : }
140 :
141 :
142 558318 : int16_t JB4_CIRCULARBUFFER_Enque(
143 : JB4_CIRCULARBUFFER_HANDLE h,
144 : JB4_CIRCULARBUFFER_ELEMENT element )
145 : {
146 558318 : if ( JB4_CIRCULARBUFFER_IsFull( h ) )
147 : {
148 0 : return -1;
149 : }
150 :
151 558318 : h->data[h->writePos] = element;
152 558318 : ++h->writePos;
153 558318 : if ( h->writePos == h->capacity )
154 : {
155 4692 : h->writePos = 0;
156 : }
157 :
158 558318 : return 0;
159 : }
160 :
161 :
162 402774 : int16_t JB4_CIRCULARBUFFER_Deque(
163 : JB4_CIRCULARBUFFER_HANDLE h,
164 : JB4_CIRCULARBUFFER_ELEMENT *pElement )
165 : {
166 402774 : if ( JB4_CIRCULARBUFFER_IsEmpty( h ) )
167 : {
168 0 : return -1;
169 : }
170 :
171 402774 : *pElement = h->data[h->readPos];
172 402774 : ++h->readPos;
173 402774 : if ( h->readPos == h->capacity )
174 : {
175 4071 : h->readPos = 0;
176 : }
177 :
178 402774 : return 0;
179 : }
180 :
181 :
182 : /* Returns the first element. */
183 336915 : JB4_CIRCULARBUFFER_ELEMENT JB4_CIRCULARBUFFER_Front(
184 : const JB4_CIRCULARBUFFER_HANDLE h )
185 : {
186 : JB4_CIRCULARBUFFER_ELEMENT ret;
187 :
188 336915 : ret = h->data[h->readPos];
189 :
190 336915 : return ret;
191 : }
192 :
193 : /* Returns the last element. */
194 209343 : JB4_CIRCULARBUFFER_ELEMENT JB4_CIRCULARBUFFER_Back(
195 : const JB4_CIRCULARBUFFER_HANDLE h )
196 : {
197 : JB4_CIRCULARBUFFER_ELEMENT ret;
198 :
199 209343 : if ( h->writePos != 0U )
200 : {
201 207684 : ret = h->data[h->writePos - 1];
202 : }
203 : else
204 : {
205 1659 : ret = h->data[h->capacity - 1];
206 : }
207 :
208 :
209 209343 : return ret;
210 : }
211 :
212 :
213 759804 : int16_t JB4_CIRCULARBUFFER_IsEmpty(
214 : const JB4_CIRCULARBUFFER_HANDLE h )
215 : {
216 : int16_t ret;
217 :
218 759804 : if ( h->readPos == h->writePos )
219 : {
220 210 : ret = 1;
221 : }
222 : else
223 : {
224 759594 : ret = 0;
225 : }
226 :
227 759804 : return ret;
228 : }
229 :
230 :
231 767661 : int16_t JB4_CIRCULARBUFFER_IsFull(
232 : const JB4_CIRCULARBUFFER_HANDLE h )
233 : {
234 : int16_t ret;
235 :
236 767661 : if ( ( ( h->writePos + 1 ) % h->capacity ) == h->readPos )
237 : {
238 23979 : ret = 1;
239 : }
240 : else
241 : {
242 743682 : ret = 0;
243 : }
244 :
245 767661 : return ret;
246 : }
247 :
248 :
249 146727 : uint16_t JB4_CIRCULARBUFFER_Size(
250 : const JB4_CIRCULARBUFFER_HANDLE h )
251 : {
252 : uint16_t ret;
253 :
254 146727 : if ( h->readPos <= h->writePos )
255 : {
256 52263 : ret = h->writePos - h->readPos;
257 : }
258 : else
259 : {
260 : /* wrap around */
261 94464 : ret = h->writePos + h->capacity - h->readPos;
262 : }
263 :
264 :
265 146727 : return ret;
266 : }
267 :
268 :
269 : /* Calculates statistics over all elements: min element */
270 287109 : void JB4_CIRCULARBUFFER_Min(
271 : const JB4_CIRCULARBUFFER_HANDLE h,
272 : JB4_CIRCULARBUFFER_ELEMENT *pMin )
273 : {
274 : uint16_t i;
275 : JB4_CIRCULARBUFFER_ELEMENT minEle;
276 :
277 : /* init output variable */
278 287109 : minEle = h->data[h->readPos];
279 :
280 287109 : if ( h->readPos <= h->writePos )
281 : {
282 : /* no wrap around */
283 : /* calc statistics for [readPos;writePos[ */
284 26624025 : for ( i = h->readPos; i != h->writePos; ++i )
285 : {
286 26495463 : if ( h->data[i] < minEle )
287 : {
288 13242 : minEle = h->data[i];
289 : }
290 : }
291 : }
292 : else
293 : {
294 : /* wrap around */
295 : /* calc statistics for [readPos;capacity[ */
296 25540014 : for ( i = h->readPos; i != h->capacity; ++i )
297 : {
298 25381467 : if ( h->data[i] < minEle )
299 : {
300 226500 : minEle = h->data[i];
301 : }
302 : }
303 : /* calc statistics for [0;writePos[ */
304 22766004 : for ( i = 0; i != h->writePos; ++i )
305 : {
306 22607457 : if ( h->data[i] < minEle )
307 : {
308 7629 : minEle = h->data[i];
309 : }
310 : }
311 : }
312 :
313 287109 : *pMin = minEle;
314 287109 : }
315 :
316 :
317 : /* Calculates statistics over all elements: max element */
318 69711 : void JB4_CIRCULARBUFFER_Max(
319 : const JB4_CIRCULARBUFFER_HANDLE h,
320 : JB4_CIRCULARBUFFER_ELEMENT *pMax )
321 : {
322 : uint16_t i;
323 : JB4_CIRCULARBUFFER_ELEMENT maxEle;
324 :
325 : /* init output variable */
326 69711 : maxEle = h->data[h->readPos];
327 69711 : if ( h->readPos <= h->writePos )
328 : {
329 : /* no wrap around */
330 : /* calc statistics for [readPos;writePos[ */
331 2413683 : for ( i = h->readPos; i != h->writePos; ++i )
332 : {
333 2390577 : if ( h->data[i] > maxEle )
334 : {
335 78327 : maxEle = h->data[i];
336 : }
337 : }
338 : }
339 : else
340 : {
341 : /* wrap around */
342 : /* calc statistics for [readPos;capacity[ */
343 4574217 : for ( i = h->readPos; i != h->capacity; ++i )
344 : {
345 4527612 : if ( h->data[i] > maxEle )
346 : {
347 64002 : maxEle = h->data[i];
348 : }
349 : }
350 : /* calc statistics for [0;writePos[ */
351 4165242 : for ( i = 0; i != h->writePos; ++i )
352 : {
353 4118637 : if ( h->data[i] > maxEle )
354 : {
355 23772 : maxEle = h->data[i];
356 : }
357 : }
358 : }
359 :
360 69711 : *pMax = maxEle;
361 :
362 69711 : return;
363 : }
364 :
365 : #define JBM_MAX_CIRCULAR_ELEMENTS 100
366 :
367 : /* Calculates statistics over a considered fraction of all elements: min element and percentile */
368 146307 : void JB4_CIRCULARBUFFER_MinAndPercentile(
369 : const JB4_CIRCULARBUFFER_HANDLE h,
370 : uint16_t nElementsToIgnore,
371 : JB4_CIRCULARBUFFER_ELEMENT *pMin,
372 : JB4_CIRCULARBUFFER_ELEMENT *pPercentile )
373 : {
374 : uint16_t i;
375 : JB4_CIRCULARBUFFER_ELEMENT maxElements[JBM_MAX_CIRCULAR_ELEMENTS];
376 : uint16_t maxElementsSize;
377 : uint16_t maxElementsCapacity;
378 : JB4_CIRCULARBUFFER_ELEMENT minEle;
379 :
380 : /* init output variables */
381 146307 : minEle = h->data[h->readPos];
382 :
383 : /* To calculate the percentile, a number of elements with the highest values are collected in maxElements in
384 : * ascending sorted order. This array has a size of nElementsToIgnore plus one. This additional element is the
385 : * lowest of all maxElements, and is called the percentile of all elements. */
386 :
387 146307 : maxElementsSize = 0;
388 146307 : maxElementsCapacity = nElementsToIgnore + 1;
389 146307 : assert( maxElementsCapacity <= JBM_MAX_CIRCULAR_ELEMENTS );
390 146307 : if ( h->readPos <= h->writePos )
391 : {
392 : /* no wrap around */
393 : /* calc statistics for [readPos;writePos[ */
394 9792357 : for ( i = h->readPos; i != h->writePos; ++i )
395 : {
396 9740514 : if ( h->data[i] < minEle )
397 : {
398 9402 : minEle = h->data[i];
399 : }
400 9740514 : JB4_CIRCULARBUFFER_calcPercentile( maxElements, &maxElementsSize, maxElementsCapacity, h->data[i] );
401 : }
402 : }
403 : else
404 : {
405 : /* wrap around */
406 : /* calc statistics for [readPos;capacity[ */
407 9953298 : for ( i = h->readPos; i != h->capacity; ++i )
408 : {
409 9858834 : if ( h->data[i] < minEle )
410 : {
411 131865 : minEle = h->data[i];
412 : }
413 9858834 : JB4_CIRCULARBUFFER_calcPercentile( maxElements, &maxElementsSize, maxElementsCapacity, h->data[i] );
414 : }
415 : /* calc statistics for [0;writePos[ */
416 8854773 : for ( i = 0; i != h->writePos; ++i )
417 : {
418 8760309 : if ( h->data[i] < minEle )
419 : {
420 7629 : minEle = h->data[i];
421 : }
422 8760309 : JB4_CIRCULARBUFFER_calcPercentile( maxElements, &maxElementsSize, maxElementsCapacity, h->data[i] );
423 : }
424 : }
425 :
426 146307 : *pPercentile = maxElements[0];
427 146307 : *pMin = minEle;
428 :
429 146307 : return;
430 : }
431 :
432 :
433 : /* Calculates percentile by selecting greatest elements. */
434 28359657 : static void JB4_CIRCULARBUFFER_calcPercentile(
435 : JB4_CIRCULARBUFFER_ELEMENT *elements,
436 : uint16_t *size,
437 : const uint16_t capacity,
438 : JB4_CIRCULARBUFFER_ELEMENT newElement )
439 : {
440 : uint16_t i, j;
441 :
442 : /* insert newElement if elements buffer is not yet full */
443 28359657 : if ( *size < capacity )
444 : {
445 489438 : for ( i = 0; i != *size; ++i )
446 : {
447 305019 : if ( newElement <= elements[i] )
448 : {
449 : /* insert newElement at index i */
450 453819 : for ( j = *size; j > i; --j )
451 : {
452 283113 : elements[j] = elements[j - 1];
453 : }
454 170706 : elements[i] = newElement;
455 170706 : ++*size;
456 170706 : return;
457 : }
458 : }
459 : /* newElement is maximum, just append it */
460 184419 : elements[*size] = newElement;
461 184419 : ++*size;
462 184419 : return;
463 : }
464 :
465 : /* check if newElement is too small to be inserted in elements buffer */
466 28004532 : if ( newElement <= elements[0] )
467 : {
468 27320190 : return;
469 : }
470 :
471 : /* select position to insert newElement to elements */
472 1164357 : for ( i = *size - 1; i != 0; --i )
473 : {
474 873756 : if ( newElement >= elements[i] )
475 : {
476 : /* insert newElement at index i */
477 1276929 : for ( j = 0; j < i; j++ )
478 : {
479 883188 : elements[j] = elements[1 + j];
480 : }
481 393741 : elements[i] = newElement;
482 393741 : return;
483 : }
484 : }
485 : /* newElement is just greater than first on in elements buffer */
486 290601 : elements[0] = newElement;
487 :
488 290601 : return;
489 : }
|