summaryrefslogtreecommitdiff
path: root/third_party/g7221/common/common.c
blob: 94bcf79c3de83edd4c0338dcd1add7b47a0df44c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
/****************************************************************************************
**
**   ITU-T G.722.1 (2005-05) - Fixed point implementation for main body and Annex C
**   > Software Release 2.1 (2008-06)
**     (Simple repackaging; no change from 2005-05 Release 2.0 code)
**
**   © 2004 Polycom, Inc.
**
**	 All rights reserved.
**
****************************************************************************************/

/****************************************************************************************
  Filename:    common.c    

  Purpose:     Contains the functions used for both G.722.1 Annex C encoder and decoder
		
  Design Notes:

****************************************************************************************/
/****************************************************************************************
 Include files                                                           
****************************************************************************************/
#include "defs.h"
#include "huff_def.h"
#include "huff_tab.h"
#include "tables.h"
#include "count.h"

/****************************************************************************************
 Function:    categorize

 Syntax:      void categorize(Word16 number_of_available_bits,   
                              Word16 number_of_regions,
                              Word16 num_categorization_control_possibilities,
                              Word16 rms_index,                  
                              Word16 power_categories,           
                              Word16 category_balances)          

                  inputs:   number_of_regions
                            num_categorization_control_possibilities
                            number_of_available_bits
                            rms_index[MAX_NUMBER_OF_REGIONS]                              
                  
                  outputs:  power_categories[MAX_NUMBER_OF_REGIONS]                       
                            category_balances[MAX_NUM_CATEGORIZATION_CONTROL_POSSIBILITIES-1]

 Description: Computes a series of categorizations 

 WMOPS:     7kHz |    24kbit    |     32kbit
          -------|--------------|----------------
            AVG  |    0.14      |     0.14
          -------|--------------|----------------  
            MAX  |    0.15      |     0.15
          -------|--------------|---------------- 
   			
           14kHz |    24kbit    |     32kbit     |     48kbit
          -------|--------------|----------------|----------------
            AVG  |    0.42      |     0.45       |     0.48   
          -------|--------------|----------------|----------------
            MAX  |    0.47      |     0.52       |     0.52   
          -------|--------------|----------------|----------------

****************************************************************************************/
void categorize(Word16 number_of_available_bits,
		        Word16 number_of_regions,
		        Word16 num_categorization_control_possibilities,
		        Word16 *rms_index,
		        Word16 *power_categories,
		        Word16 *category_balances)
{
    
    Word16 offset;
    Word16 temp;
    Word16 frame_size;

    /* At higher bit rates, there is an increase for most categories in average bit
       consumption per region. We compensate for this by pretending we have fewer
       available bits. */
    test();
    if (number_of_regions == NUMBER_OF_REGIONS)
    {
        frame_size = DCT_LENGTH;
    }
    else
    {
        frame_size = MAX_DCT_LENGTH;
    }

    temp = sub(number_of_available_bits,frame_size);
    
    test();
    if (temp > 0)
    {
        number_of_available_bits = sub(number_of_available_bits,frame_size);
        number_of_available_bits = extract_l(L_mult0(number_of_available_bits,5));
        number_of_available_bits = shr_nocheck(number_of_available_bits,3);
        number_of_available_bits = add(number_of_available_bits,frame_size);
    }

    /* calculate the offset using the original category assignments */
    offset = calc_offset(rms_index,number_of_regions,number_of_available_bits);



    /* compute the power categories based on the uniform offset */
    compute_raw_pow_categories(power_categories,rms_index,number_of_regions,offset);
    
    
    /* adjust the category assignments */
    /* compute the new power categories and category balances */
    comp_powercat_and_catbalance(power_categories,category_balances,rms_index,number_of_available_bits,number_of_regions,num_categorization_control_possibilities,offset);

}
    
/***************************************************************************
 Function:    comp_powercat_and_catbalance

 Syntax:      void comp_powercat_and_catbalance(Word16 *power_categories,
                                                Word16 *category_balances,
                                                Word16 *rms_index,  
                                                Word16 number_of_available_bits,                                  
                                                Word16 number_of_regions,
                                                Word16 num_categorization_control_possibilities,
                                                Word16 offset)                                                    

                
                inputs:   *rms_index                              
                          number_of_available_bits                 
                          number_of_regions
                          num_categorization_control_possibilities
                          offset
                           
                outputs:  *power_categories  
                          *category_balances 
                
                
 Description: Computes the power_categories and the category balances

 WMOPS:     7kHz |    24kbit    |     32kbit
          -------|--------------|----------------
            AVG  |    0.10      |     0.10
          -------|--------------|----------------  
            MAX  |    0.11      |     0.11
          -------|--------------|---------------- 
				
           14kHz |    24kbit    |     32kbit     |     48kbit
          -------|--------------|----------------|----------------
            AVG  |    0.32      |     0.35       |     0.38   
          -------|--------------|----------------|----------------
            MAX  |    0.38      |     0.42       |     0.43   
          -------|--------------|----------------|----------------

***************************************************************************/
void comp_powercat_and_catbalance(Word16 *power_categories,
                                  Word16 *category_balances,
                                  Word16 *rms_index,
                                  Word16 number_of_available_bits,
                                  Word16 number_of_regions,
                                  Word16 num_categorization_control_possibilities,
								  Word16 offset)
{
    
    Word16 expected_number_of_code_bits;
    Word16 region;
    Word16 max_region;
    Word16 j;
    Word16 max_rate_categories[MAX_NUMBER_OF_REGIONS];
    Word16 min_rate_categories[MAX_NUMBER_OF_REGIONS];
    Word16 temp_category_balances[2*MAX_NUM_CATEGORIZATION_CONTROL_POSSIBILITIES];
    Word16 raw_max, raw_min;
    Word16 raw_max_index, raw_min_index;
    Word16 max_rate_pointer, min_rate_pointer;
    Word16 max, min;
    Word16 itemp0;
    Word16 itemp1;
    Word16 min_plus_max;
    Word16 two_x_number_of_available_bits;

    Word16 temp;

    expected_number_of_code_bits = 0;
    move16();

    for (region=0; region<number_of_regions; region++)
        expected_number_of_code_bits = add(expected_number_of_code_bits,expected_bits_table[power_categories[region]]);


    for (region=0; region<number_of_regions; region++) 
    {
        max_rate_categories[region] = power_categories[region];
        move16();
        
        min_rate_categories[region] = power_categories[region];
        move16();
    }
    
    max = expected_number_of_code_bits;
    move16();
    min = expected_number_of_code_bits;
    move16();
    max_rate_pointer = num_categorization_control_possibilities;
    move16();
    min_rate_pointer = num_categorization_control_possibilities;
    move16();
    
    for (j=0; j<num_categorization_control_possibilities-1; j++) 
    {
        min_plus_max = add(max,min);
        two_x_number_of_available_bits = shl_nocheck(number_of_available_bits,1);
        
        temp = sub(min_plus_max,two_x_number_of_available_bits);
        test();
        if (temp <= 0) 
        {
            raw_min = 99;
            move16();
            /* Search from lowest freq regions to highest for best */
            /* region to reassign to a higher bit rate category.   */
            for (region=0; region<number_of_regions; region++) 
            {
                test();
                if (max_rate_categories[region] > 0) 
                {
                    itemp0 = shl_nocheck(max_rate_categories[region],1);
                    itemp1 = sub(offset,rms_index[region]);
                    itemp0 = sub(itemp1,itemp0);
                    
                    temp = sub(itemp0,raw_min);
                    test();
                    if (temp < 0) 
                    {
                        raw_min = itemp0;
                        raw_min_index = region;
                    }
                }
            }
            max_rate_pointer = sub(max_rate_pointer,1);
            temp_category_balances[max_rate_pointer] = raw_min_index;
            move16();

        	max = sub(max,expected_bits_table[max_rate_categories[raw_min_index]]);
        	max_rate_categories[raw_min_index] = sub(max_rate_categories[raw_min_index],1);
        	move16();

            max = add(max,expected_bits_table[max_rate_categories[raw_min_index]]);
        }
        else 
        {
            raw_max = -99;
            move16();
            /* Search from highest freq regions to lowest for best region to reassign to
            a lower bit rate category. */
            max_region = sub(number_of_regions,1);
            for (region= max_region; region >= 0; region--) 
            {
                temp = sub(min_rate_categories[region],(NUM_CATEGORIES-1));
                test();
                if (temp < 0)
                {
                    itemp0 = shl_nocheck(min_rate_categories[region],1);
                    itemp1 = sub(offset,rms_index[region]);
                    itemp0 = sub(itemp1,itemp0);
                    
                    temp = sub(itemp0,raw_max);
                    test();
                    if (temp > 0) 
                    {
                        raw_max = itemp0;
                        move16();
                        raw_max_index = region;
                        move16();
                    }
                }
            }
            temp_category_balances[min_rate_pointer] = raw_max_index;
            move16();
            
            min_rate_pointer = add(min_rate_pointer,1);
            min = sub(min,expected_bits_table[min_rate_categories[raw_max_index]]);
            
            min_rate_categories[raw_max_index] = add(min_rate_categories[raw_max_index],1);
            move16();
            
            min = add(min,expected_bits_table[min_rate_categories[raw_max_index]]);
        }
    }
    
    for (region=0; region<number_of_regions; region++)
    {
        power_categories[region] = max_rate_categories[region];
        move16();
    }
    
    for (j=0; j<num_categorization_control_possibilities-1; j++)
    {
        category_balances[j] = temp_category_balances[max_rate_pointer++];
        move16();
    }

}
/***************************************************************************
 Function:    calc_offset

 Syntax:      offset=calc_offset(Word16 *rms_index,Word16 number_of_regions,Word16 available_bits)  

                input:  Word16 *rms_index
                        Word16 number_of_regions
                        Word16 available_bits
                        
                output: Word16 offset                        

 Description: Calculates the the category offset.  This is the shift required
              To get the most out of the number of available bits.  A binary 
              type search is used to find the offset.

 WMOPS:     7kHz |    24kbit    |     32kbit
          -------|--------------|----------------
            AVG  |    0.04      |     0.04
          -------|--------------|----------------  
            MAX  |    0.04      |     0.04
          -------|--------------|---------------- 

           14kHz |    24kbit    |     32kbit     |     48kbit
          -------|--------------|----------------|----------------
            AVG  |    0.08      |     0.08       |     0.08   
          -------|--------------|----------------|----------------
            MAX  |    0.09      |     0.09       |     0.09   
          -------|--------------|----------------|----------------

***************************************************************************/
Word16 calc_offset(Word16 *rms_index,Word16 number_of_regions,Word16 available_bits)    
{

    Word16 answer;
    Word16 delta;
    Word16 test_offset;
    Word16 region,j;
    Word16 power_cats[MAX_NUMBER_OF_REGIONS];
    Word16 bits;
    Word16 offset;
    Word16 temp;

    /* initialize vars */
    answer = -32;
    move16();
    delta = 32;
    move16();
    
    do 
    {
        test_offset = add(answer,delta);
        
        /* obtain a category for each region */
        /* using the test offset             */
        for (region=0; region<number_of_regions; region++) 
        {
            j = sub(test_offset,rms_index[region]);
            j = shr_nocheck(j,1);
            
            /* Ensure j is between 0 and NUM_CAT-1 */
            test();
            if (j < 0) 
            {
                j = 0;
                move16();
            }
            temp = sub(j,NUM_CATEGORIES-1);
            test();
            if (temp > 0) 
            {
                j = sub(NUM_CATEGORIES,1);
                move16();
            }
            power_cats[region] = j;
            move16();
        }
        bits = 0;
        move16();

        /* compute the number of bits that will be used given the cat assignments */
        for (region=0; region<number_of_regions; region++)
            bits = add(bits,expected_bits_table[power_cats[region]]);

        /* if (bits > available_bits - 32) then divide the offset region for the bin search */
        offset = sub(available_bits,32);
        temp = sub(bits,offset);
        test();
        if (temp >= 0)
        {
            answer = test_offset;
            move16();
        }
        delta = shr_nocheck(delta,1);
        test(); /* for the while loop */
    } while (delta > 0);

    return(answer);
}
/***************************************************************************
 Function:    compute_raw_pow_categories

 Syntax:      void compute_raw_pow_categories(Word16 *power_categories,
                                              Word16 *rms_index,
                                              Word16 number_of_regions,
                                              Word16 offset)
              inputs:  *rms_index
                       number_of_regions
                       offset
                    
              outputs: *power_categories                    



 Description: This function computes the power categories given the offset
              This is kind of redundant since they were already computed
              in calc_offset to determine the offset.

 WMOPS:          |    24kbit    |     32kbit
          -------|--------------|----------------
            AVG  |    0.01      |     0.01
          -------|--------------|----------------  
            MAX  |    0.01      |     0.01
          -------|--------------|---------------- 

           14kHz |    24kbit    |     32kbit     |     48kbit
          -------|--------------|----------------|----------------
            AVG  |    0.01      |     0.01       |     0.01   
          -------|--------------|----------------|----------------
            MAX  |    0.01      |     0.01       |     0.01   
          -------|--------------|----------------|----------------

***************************************************************************/
void compute_raw_pow_categories(Word16 *power_categories,Word16 *rms_index,Word16 number_of_regions,Word16 offset)
{
    Word16 region;
    Word16 j;
    Word16 temp;

    for (region=0; region<number_of_regions; region++) 
    {
        j = sub(offset,rms_index[region]);
        j = shr_nocheck(j,1);
        
        /* make sure j is between 0 and NUM_CAT-1 */
        test();
        if (j < 0) 
        {
            j = 0;
            move16();
        }
        temp = sub(j,(NUM_CATEGORIES-1));
        test();
        if (temp > 0) 
            j = sub(NUM_CATEGORIES,1);
        
        power_categories[region] = j;
        move16();
    }
}