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 864 : ivas_error JB4_CIRCULARBUFFER_Create(
74 : JB4_CIRCULARBUFFER_HANDLE *ph )
75 : {
76 : JB4_CIRCULARBUFFER_HANDLE h;
77 :
78 864 : 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 864 : h->data = NULL;
84 864 : h->capacity = 0;
85 864 : h->writePos = 0;
86 864 : h->readPos = 0;
87 :
88 864 : *ph = h;
89 :
90 864 : return IVAS_ERR_OK;
91 : }
92 :
93 :
94 : /* Destroys the circular buffer (FIFO) */
95 864 : void JB4_CIRCULARBUFFER_Destroy(
96 : JB4_CIRCULARBUFFER_HANDLE *ph )
97 : {
98 : JB4_CIRCULARBUFFER_HANDLE h;
99 :
100 864 : if ( !ph )
101 : {
102 0 : return;
103 : }
104 864 : h = *ph;
105 864 : if ( !h )
106 : {
107 0 : return;
108 : }
109 :
110 864 : if ( h->data )
111 : {
112 864 : free( h->data );
113 : }
114 864 : free( h );
115 864 : *ph = NULL;
116 :
117 864 : return;
118 : }
119 :
120 :
121 : /* Initializes a circular buffer (FIFO) with a fixed maximum allowed number of elements */
122 864 : 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 864 : ++capacity;
128 :
129 864 : 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 864 : h->capacity = capacity;
135 864 : h->writePos = 0;
136 864 : h->readPos = 0;
137 :
138 864 : return IVAS_ERR_OK;
139 : }
140 :
141 :
142 5844528 : int16_t JB4_CIRCULARBUFFER_Enque(
143 : JB4_CIRCULARBUFFER_HANDLE h,
144 : JB4_CIRCULARBUFFER_ELEMENT element )
145 : {
146 5844528 : if ( JB4_CIRCULARBUFFER_IsFull( h ) )
147 : {
148 0 : return -1;
149 : }
150 :
151 5844528 : h->data[h->writePos] = element;
152 5844528 : ++h->writePos;
153 5844528 : if ( h->writePos == h->capacity )
154 : {
155 54237 : h->writePos = 0;
156 : }
157 :
158 5844528 : return 0;
159 : }
160 :
161 :
162 5637498 : int16_t JB4_CIRCULARBUFFER_Deque(
163 : JB4_CIRCULARBUFFER_HANDLE h,
164 : JB4_CIRCULARBUFFER_ELEMENT *pElement )
165 : {
166 5637498 : if ( JB4_CIRCULARBUFFER_IsEmpty( h ) )
167 : {
168 0 : return -1;
169 : }
170 :
171 5637498 : *pElement = h->data[h->readPos];
172 5637498 : ++h->readPos;
173 5637498 : if ( h->readPos == h->capacity )
174 : {
175 53487 : h->readPos = 0;
176 : }
177 :
178 5637498 : return 0;
179 : }
180 :
181 :
182 : /* Returns the first element. */
183 3973803 : JB4_CIRCULARBUFFER_ELEMENT JB4_CIRCULARBUFFER_Front(
184 : const JB4_CIRCULARBUFFER_HANDLE h )
185 : {
186 : JB4_CIRCULARBUFFER_ELEMENT ret;
187 :
188 3973803 : ret = h->data[h->readPos];
189 :
190 3973803 : return ret;
191 : }
192 :
193 : /* Returns the last element. */
194 2191671 : JB4_CIRCULARBUFFER_ELEMENT JB4_CIRCULARBUFFER_Back(
195 : const JB4_CIRCULARBUFFER_HANDLE h )
196 : {
197 : JB4_CIRCULARBUFFER_ELEMENT ret;
198 :
199 2191671 : if ( h->writePos != 0U )
200 : {
201 2172402 : ret = h->data[h->writePos - 1];
202 : }
203 : else
204 : {
205 19269 : ret = h->data[h->capacity - 1];
206 : }
207 :
208 :
209 2191671 : return ret;
210 : }
211 :
212 :
213 9344674 : int16_t JB4_CIRCULARBUFFER_IsEmpty(
214 : const JB4_CIRCULARBUFFER_HANDLE h )
215 : {
216 : int16_t ret;
217 :
218 9344674 : if ( h->readPos == h->writePos )
219 : {
220 216 : ret = 1;
221 : }
222 : else
223 : {
224 9344458 : ret = 0;
225 : }
226 :
227 9344674 : return ret;
228 : }
229 :
230 :
231 8036199 : int16_t JB4_CIRCULARBUFFER_IsFull(
232 : const JB4_CIRCULARBUFFER_HANDLE h )
233 : {
234 : int16_t ret;
235 :
236 8036199 : if ( ( ( h->writePos + 1 ) % h->capacity ) == h->readPos )
237 : {
238 333828 : ret = 1;
239 : }
240 : else
241 : {
242 7702371 : ret = 0;
243 : }
244 :
245 8036199 : return ret;
246 : }
247 :
248 :
249 1513537 : uint16_t JB4_CIRCULARBUFFER_Size(
250 : const JB4_CIRCULARBUFFER_HANDLE h )
251 : {
252 : uint16_t ret;
253 :
254 1513537 : if ( h->readPos <= h->writePos )
255 : {
256 156904 : ret = h->writePos - h->readPos;
257 : }
258 : else
259 : {
260 : /* wrap around */
261 1356633 : ret = h->writePos + h->capacity - h->readPos;
262 : }
263 :
264 :
265 1513537 : return ret;
266 : }
267 :
268 :
269 : /* Calculates statistics over all elements: min element */
270 2976475 : 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 2976475 : minEle = h->data[h->readPos];
279 :
280 2976475 : if ( h->readPos <= h->writePos )
281 : {
282 : /* no wrap around */
283 : /* calc statistics for [readPos;writePos[ */
284 103071071 : for ( i = h->readPos; i != h->writePos; ++i )
285 : {
286 102723376 : if ( h->data[i] < minEle )
287 : {
288 226569 : minEle = h->data[i];
289 : }
290 : }
291 : }
292 : else
293 : {
294 : /* wrap around */
295 : /* calc statistics for [readPos;capacity[ */
296 483493431 : for ( i = h->readPos; i != h->capacity; ++i )
297 : {
298 480864651 : if ( h->data[i] < minEle )
299 : {
300 3503244 : minEle = h->data[i];
301 : }
302 : }
303 : /* calc statistics for [0;writePos[ */
304 470255793 : for ( i = 0; i != h->writePos; ++i )
305 : {
306 467627013 : if ( h->data[i] < minEle )
307 : {
308 94185 : minEle = h->data[i];
309 : }
310 : }
311 : }
312 :
313 2976475 : *pMin = minEle;
314 2976475 : }
315 :
316 :
317 : /* Calculates statistics over all elements: max element */
318 730485 : 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 730485 : maxEle = h->data[h->readPos];
327 730485 : if ( h->readPos <= h->writePos )
328 : {
329 : /* no wrap around */
330 : /* calc statistics for [readPos;writePos[ */
331 10128174 : for ( i = h->readPos; i != h->writePos; ++i )
332 : {
333 10062399 : if ( h->data[i] > maxEle )
334 : {
335 159312 : maxEle = h->data[i];
336 : }
337 : }
338 : }
339 : else
340 : {
341 : /* wrap around */
342 : /* calc statistics for [readPos;capacity[ */
343 63928737 : for ( i = h->readPos; i != h->capacity; ++i )
344 : {
345 63264027 : if ( h->data[i] > maxEle )
346 : {
347 643242 : maxEle = h->data[i];
348 : }
349 : }
350 : /* calc statistics for [0;writePos[ */
351 62943858 : for ( i = 0; i != h->writePos; ++i )
352 : {
353 62279148 : if ( h->data[i] > maxEle )
354 : {
355 376125 : maxEle = h->data[i];
356 : }
357 : }
358 : }
359 :
360 730485 : *pMax = maxEle;
361 :
362 730485 : 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 1513105 : 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 1513105 : 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 1513105 : maxElementsSize = 0;
388 1513105 : maxElementsCapacity = nElementsToIgnore + 1;
389 1513105 : assert( maxElementsCapacity <= JBM_MAX_CIRCULAR_ELEMENTS );
390 1513105 : if ( h->readPos <= h->writePos )
391 : {
392 : /* no wrap around */
393 : /* calc statistics for [readPos;writePos[ */
394 37953849 : for ( i = h->readPos; i != h->writePos; ++i )
395 : {
396 37797377 : if ( h->data[i] < minEle )
397 : {
398 120903 : minEle = h->data[i];
399 : }
400 37797377 : JB4_CIRCULARBUFFER_calcPercentile( maxElements, &maxElementsSize, maxElementsCapacity, h->data[i] );
401 : }
402 : }
403 : else
404 : {
405 : /* wrap around */
406 : /* calc statistics for [readPos;capacity[ */
407 179522238 : for ( i = h->readPos; i != h->capacity; ++i )
408 : {
409 178165605 : if ( h->data[i] < minEle )
410 : {
411 1775778 : minEle = h->data[i];
412 : }
413 178165605 : JB4_CIRCULARBUFFER_calcPercentile( maxElements, &maxElementsSize, maxElementsCapacity, h->data[i] );
414 : }
415 : /* calc statistics for [0;writePos[ */
416 174004221 : for ( i = 0; i != h->writePos; ++i )
417 : {
418 172647588 : if ( h->data[i] < minEle )
419 : {
420 81141 : minEle = h->data[i];
421 : }
422 172647588 : JB4_CIRCULARBUFFER_calcPercentile( maxElements, &maxElementsSize, maxElementsCapacity, h->data[i] );
423 : }
424 : }
425 :
426 1513105 : *pPercentile = maxElements[0];
427 1513105 : *pMin = minEle;
428 :
429 1513105 : return;
430 : }
431 :
432 :
433 : /* Calculates percentile by selecting greatest elements. */
434 388610570 : 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 388610570 : if ( *size < capacity )
444 : {
445 5067346 : for ( i = 0; i != *size; ++i )
446 : {
447 3179946 : if ( newElement <= elements[i] )
448 : {
449 : /* insert newElement at index i */
450 4835772 : for ( j = *size; j > i; --j )
451 : {
452 3018936 : elements[j] = elements[j - 1];
453 : }
454 1816836 : elements[i] = newElement;
455 1816836 : ++*size;
456 1816836 : return;
457 : }
458 : }
459 : /* newElement is maximum, just append it */
460 1887400 : elements[*size] = newElement;
461 1887400 : ++*size;
462 1887400 : return;
463 : }
464 :
465 : /* check if newElement is too small to be inserted in elements buffer */
466 384906334 : if ( newElement <= elements[0] )
467 : {
468 377439971 : return;
469 : }
470 :
471 : /* select position to insert newElement to elements */
472 12662366 : for ( i = *size - 1; i != 0; --i )
473 : {
474 9336693 : if ( newElement >= elements[i] )
475 : {
476 : /* insert newElement at index i */
477 13462218 : for ( j = 0; j < i; j++ )
478 : {
479 9321528 : elements[j] = elements[1 + j];
480 : }
481 4140690 : elements[i] = newElement;
482 4140690 : return;
483 : }
484 : }
485 : /* newElement is just greater than first on in elements buffer */
486 3325673 : elements[0] = newElement;
487 :
488 3325673 : return;
489 : }
|