diff options
author | Nanang Izzuddin <nanang@teluu.com> | 2009-04-01 12:05:34 +0000 |
---|---|---|
committer | Nanang Izzuddin <nanang@teluu.com> | 2009-04-01 12:05:34 +0000 |
commit | d35a8221a34a562a88bdb7c947a7018080539c59 (patch) | |
tree | aa5a5abd2d4421426668329a193d079d2d0b293d /third_party/g7221/encode | |
parent | 5c2400ce2b6ca229272457be1ff383df1d9c6139 (diff) |
Ticket #774:
- Initial source of G.722.1/Annex C integration.
- Disabled some "odd" modes of L16 codec (11kHz & 22kHz mono & stereo) while releasing some payload types.
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@2563 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'third_party/g7221/encode')
-rw-r--r-- | third_party/g7221/encode/dct4_a.c | 352 | ||||
-rw-r--r-- | third_party/g7221/encode/dct4_a.h | 728 | ||||
-rw-r--r-- | third_party/g7221/encode/encoder.c | 1125 | ||||
-rw-r--r-- | third_party/g7221/encode/sam2coef.c | 270 |
4 files changed, 2475 insertions, 0 deletions
diff --git a/third_party/g7221/encode/dct4_a.c b/third_party/g7221/encode/dct4_a.c new file mode 100644 index 00000000..24f4f5e0 --- /dev/null +++ b/third_party/g7221/encode/dct4_a.c @@ -0,0 +1,352 @@ +/********************************************************************************* +** 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: dct_type_iv_a.c +* +* Purpose: Discrete Cosine Transform, Type IV used for MLT +* +* The basis functions are +* +* cos(PI*(t+0.5)*(k+0.5)/block_length) +* +* for time t and basis function number k. Due to the symmetry of the expression +* in t and k, it is clear that the forward and inverse transforms are the same. +* +*********************************************************************************/ + +/********************************************************************************* + Include files +*********************************************************************************/ +#include "defs.h" +#include "count.h" +#include "dct4_a.h" + +/********************************************************************************* + External variable declarations +*********************************************************************************/ +extern Word16 anal_bias[DCT_LENGTH]; +extern Word16 dct_core_a[DCT_LENGTH_DIV_32][DCT_LENGTH_DIV_32]; +extern cos_msin_t a_cos_msin_2 [DCT_LENGTH_DIV_32]; +extern cos_msin_t a_cos_msin_4 [DCT_LENGTH_DIV_16]; +extern cos_msin_t a_cos_msin_8 [DCT_LENGTH_DIV_8]; +extern cos_msin_t a_cos_msin_16[DCT_LENGTH_DIV_4]; +extern cos_msin_t a_cos_msin_32[DCT_LENGTH_DIV_2]; +extern cos_msin_t a_cos_msin_64[DCT_LENGTH]; +extern cos_msin_t *a_cos_msin_table[]; + +/********************************************************************************* + Function: dct_type_iv_a + + Syntax: void dct_type_iv_a (input, output, dct_length) + Word16 input[], output[], dct_length; + + Description: Discrete Cosine Transform, Type IV used for MLT + + Design Notes: + + WMOPS: | 24kbit | 32kbit + -------|--------------|---------------- + AVG | 1.14 | 1.14 + -------|--------------|---------------- + MAX | 1.14 | 1.14 + -------|--------------|---------------- + + 14kHz | 24kbit | 32kbit | 48kbit + -------|--------------|----------------|---------------- + AVG | 2.57 | 2.57 | 2.57 + -------|--------------|----------------|---------------- + MAX | 2.57 | 2.57 | 2.57 + -------|--------------|----------------|---------------- + +*********************************************************************************/ + +void dct_type_iv_a (Word16 *input,Word16 *output,Word16 dct_length) +{ + Word16 buffer_a[MAX_DCT_LENGTH], buffer_b[MAX_DCT_LENGTH], buffer_c[MAX_DCT_LENGTH]; + Word16 *in_ptr, *in_ptr_low, *in_ptr_high, *next_in_base; + Word16 *out_ptr_low, *out_ptr_high, *next_out_base; + Word16 *out_buffer, *in_buffer, *buffer_swap; + Word16 in_val_low, in_val_high; + Word16 out_val_low, out_val_high; + Word16 in_low_even, in_low_odd; + Word16 in_high_even, in_high_odd; + Word16 out_low_even, out_low_odd; + Word16 out_high_even, out_high_odd; + Word16 *pair_ptr; + Word16 cos_even, cos_odd, msin_even, msin_odd; + Word16 neg_cos_odd; + Word16 neg_msin_even; + Word32 sum; + Word16 set_span, set_count, set_count_log, pairs_left, sets_left; + Word16 i,k; + Word16 index; + cos_msin_t **table_ptr_ptr, *cos_msin_ptr; + + Word16 temp; + Word32 acca; + + Word16 dct_length_log; + + + /*++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ + /* Do the sum/difference butterflies, the first part of */ + /* converting one N-point transform into N/2 two-point */ + /* transforms, where N = 1 << DCT_LENGTH_LOG. = 64/128 */ + /*++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ + test(); + if (dct_length==DCT_LENGTH) + { + dct_length_log = DCT_LENGTH_LOG; + + /* Add bias offsets */ + for (i=0;i<dct_length;i++) + { + input[i] = add(input[i],anal_bias[i]); + move16(); + } + } + else + dct_length_log = MAX_DCT_LENGTH_LOG; + + index = 0L; + move16(); + + in_buffer = input; + move16(); + + out_buffer = buffer_a; + move16(); + + temp = sub(dct_length_log,2); + for (set_count_log=0;set_count_log<=temp;set_count_log++) + { + + /*===========================================================*/ + /* Initialization for the loop over sets at the current size */ + /*===========================================================*/ + + /* set_span = 1 << (DCT_LENGTH_LOG - set_count_log); */ + set_span = shr(dct_length,set_count_log); + + set_count = shl(1,set_count_log); + + in_ptr = in_buffer; + move16(); + + next_out_base = out_buffer; + move16(); + + /*=====================================*/ + /* Loop over all the sets of this size */ + /*=====================================*/ + + for (sets_left=set_count;sets_left>0;sets_left--) + { + + /*||||||||||||||||||||||||||||||||||||||||||||*/ + /* Set up output pointers for the current set */ + /*||||||||||||||||||||||||||||||||||||||||||||*/ + + out_ptr_low = next_out_base; + next_out_base = next_out_base + set_span; + out_ptr_high = next_out_base; + + /*||||||||||||||||||||||||||||||||||||||||||||||||||*/ + /* Loop over all the butterflies in the current set */ + /*||||||||||||||||||||||||||||||||||||||||||||||||||*/ + + do + { + in_val_low = *in_ptr++; + in_val_high = *in_ptr++; + acca = L_add(in_val_low,in_val_high); + acca = L_shr(acca,1); + out_val_low = extract_l(acca); + + acca = L_sub(in_val_low,in_val_high); + acca = L_shr(acca,1); + out_val_high = extract_l(acca); + + *out_ptr_low++ = out_val_low; + *--out_ptr_high = out_val_high; + + test(); + } while (out_ptr_low < out_ptr_high); + + } /* End of loop over sets of the current size */ + + /*============================================================*/ + /* Decide which buffers to use as input and output next time. */ + /* Except for the first time (when the input buffer is the */ + /* subroutine input) we just alternate the local buffers. */ + /*============================================================*/ + + in_buffer = out_buffer; + move16(); + if (out_buffer == buffer_a) + out_buffer = buffer_b; + else + out_buffer = buffer_a; + index = add(index,1); + + } /* End of loop over set sizes */ + + + /*++++++++++++++++++++++++++++++++*/ + /* Do N/2 two-point transforms, */ + /* where N = 1 << DCT_LENGTH_LOG */ + /*++++++++++++++++++++++++++++++++*/ + + pair_ptr = in_buffer; + move16(); + + buffer_swap = buffer_c; + move16(); + + temp = sub(dct_length_log,1); + temp = shl(1,temp); + + for (pairs_left=temp; pairs_left > 0; pairs_left--) + { + for ( k=0; k<CORE_SIZE; k++ ) + { + sum=0L; + move32(); + for ( i=0; i<CORE_SIZE; i++ ) + { + sum = L_mac(sum, pair_ptr[i],dct_core_a[i][k]); + } + buffer_swap[k] = round(sum); + } + /* address arithmetic */ + pair_ptr += CORE_SIZE; + buffer_swap += CORE_SIZE; + } + + for (i=0;i<dct_length;i++) + { + in_buffer[i] = buffer_c[i]; + move16(); + } + + table_ptr_ptr = a_cos_msin_table; + + /*++++++++++++++++++++++++++++++*/ + /* Perform rotation butterflies */ + /*++++++++++++++++++++++++++++++*/ + temp = sub(dct_length_log,2); + for (set_count_log = temp; set_count_log >= 0; set_count_log--) + { + /*===========================================================*/ + /* Initialization for the loop over sets at the current size */ + /*===========================================================*/ + /* set_span = 1 << (DCT_LENGTH_LOG - set_count_log); */ + set_span = shr(dct_length,set_count_log); + + set_count = shl(1,set_count_log); + next_in_base = in_buffer; + move16(); + + test(); + if (set_count_log == 0) + { + next_out_base = output; + } + else + { + next_out_base = out_buffer; + } + + + /*=====================================*/ + /* Loop over all the sets of this size */ + /*=====================================*/ + for (sets_left = set_count; sets_left > 0;sets_left--) + { + /*|||||||||||||||||||||||||||||||||||||||||*/ + /* Set up the pointers for the current set */ + /*|||||||||||||||||||||||||||||||||||||||||*/ + in_ptr_low = next_in_base; + move16(); + temp = shr(set_span,1); + + /* address arithmetic */ + in_ptr_high = in_ptr_low + temp; + next_in_base += set_span; + out_ptr_low = next_out_base; + next_out_base += set_span; + out_ptr_high = next_out_base; + cos_msin_ptr = *table_ptr_ptr; + + /*||||||||||||||||||||||||||||||||||||||||||||||||||||||*/ + /* Loop over all the butterfly pairs in the current set */ + /*||||||||||||||||||||||||||||||||||||||||||||||||||||||*/ + + do + { + /* address arithmetic */ + in_low_even = *in_ptr_low++; + in_low_odd = *in_ptr_low++; + in_high_even = *in_ptr_high++; + in_high_odd = *in_ptr_high++; + cos_even = cos_msin_ptr[0].cosine; + move16(); + msin_even = cos_msin_ptr[0].minus_sine; + move16(); + cos_odd = cos_msin_ptr[1].cosine; + move16(); + msin_odd = cos_msin_ptr[1].minus_sine; + move16(); + cos_msin_ptr += 2; + + sum = 0L; + sum=L_mac(sum,cos_even,in_low_even); + neg_msin_even = negate(msin_even); + sum=L_mac(sum,neg_msin_even,in_high_even); + out_low_even = round(sum); + + sum = 0L; + sum=L_mac(sum,msin_even,in_low_even); + sum=L_mac(sum,cos_even,in_high_even); + out_high_even= round(sum); + + sum = 0L; + sum=L_mac(sum,cos_odd,in_low_odd); + sum=L_mac(sum,msin_odd,in_high_odd); + out_low_odd= round(sum); + + sum = 0L; + sum=L_mac(sum,msin_odd,in_low_odd); + neg_cos_odd = negate(cos_odd); + sum=L_mac(sum,neg_cos_odd,in_high_odd); + out_high_odd= round(sum); + + *out_ptr_low++ = out_low_even; + *--out_ptr_high = out_high_even; + *out_ptr_low++ = out_low_odd; + *--out_ptr_high = out_high_odd; + test(); + } while (out_ptr_low < out_ptr_high); + + } /* End of loop over sets of the current size */ + + /*=============================================*/ + /* Swap input and output buffers for next time */ + /*=============================================*/ + + buffer_swap = in_buffer; + in_buffer = out_buffer; + out_buffer = buffer_swap; + table_ptr_ptr++; + } +} + diff --git a/third_party/g7221/encode/dct4_a.h b/third_party/g7221/encode/dct4_a.h new file mode 100644 index 00000000..74f3d939 --- /dev/null +++ b/third_party/g7221/encode/dct4_a.h @@ -0,0 +1,728 @@ +/**************************************************************************** +** +** 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: dct4_a.h + + Purpose: Contains tables used by dct4_a.c + + Design Notes: + +****************************************************************************/ + +/*************************************************************************** + Include files +***************************************************************************/ +#include <stdio.h> +#include <math.h> + +typedef struct +{ + Word16 cosine; + Word16 minus_sine; +} cos_msin_t; + +cos_msin_t a_cos_msin_2[10] = { + { 29805 , -1171 } , + { 29621 , -3506 } , + { 29255 , -5819 } , + { 28708 , -8097 } , + { 27984 , -10324 } , + { 27088 , -12488 } , + { 26025 , -14575 } , + { 24801 , -16572 } , + { 23425 , -18466 } , + { 21903 , -20247 } + }; +cos_msin_t a_cos_msin_4[20] = { + { 29822 , -586 } , + { 29776 , -1756 } , + { 29684 , -2924 } , + { 29547 , -4087 } , + { 29364 , -5244 } , + { 29135 , -6392 } , + { 28862 , -7531 } , + { 28544 , -8659 } , + { 28182 , -9773 } , + { 27776 , -10871 } , + { 27328 , -11954 } , + { 26838 , -13017 } , + { 26306 , -14061 } , + { 25734 , -15083 } , + { 25122 , -16081 } , + { 24471 , -17055 } , + { 23783 , -18003 } , + { 23057 , -18923 } , + { 22297 , -19813 } , + { 21502 , -20673 } + }; +cos_msin_t a_cos_msin_8[40] = { + { 29827 , -293 } , + { 29815 , -878 } , + { 29792 , -1464 } , + { 29758 , -2048 } , + { 29712 , -2632 } , + { 29654 , -3215 } , + { 29586 , -3797 } , + { 29505 , -4377 } , + { 29414 , -4955 } , + { 29311 , -5532 } , + { 29196 , -6106 } , + { 29071 , -6678 } , + { 28934 , -7248 } , + { 28786 , -7814 } , + { 28627 , -8378 } , + { 28457 , -8938 } , + { 28276 , -9495 } , + { 28084 , -10049 } , + { 27882 , -10598 } , + { 27668 , -11144 } , + { 27444 , -11685 } , + { 27209 , -12221 } , + { 26964 , -12753 } , + { 26709 , -13280 } , + { 26443 , -13802 } , + { 26167 , -14318 } , + { 25881 , -14829 } , + { 25584 , -15335 } , + { 25278 , -15834 } , + { 24963 , -16327 } , + { 24637 , -16814 } , + { 24302 , -17295 } , + { 23958 , -17769 } , + { 23605 , -18236 } , + { 23242 , -18695 } , + { 22871 , -19148 } , + { 22490 , -19594 } , + { 22101 , -20031 } , + { 21704 , -20461 } , + { 21298 , -20884 } + }; +cos_msin_t a_cos_msin_16[80] = { + { 29828 , -146 } , + { 29825 , -439 } , + { 29819 , -732 } , + { 29811 , -1025 } , + { 29799 , -1317 } , + { 29785 , -1610 } , + { 29767 , -1902 } , + { 29747 , -2194 } , + { 29724 , -2486 } , + { 29698 , -2778 } , + { 29670 , -3069 } , + { 29638 , -3360 } , + { 29604 , -3651 } , + { 29567 , -3942 } , + { 29526 , -4232 } , + { 29483 , -4521 } , + { 29438 , -4811 } , + { 29389 , -5099 } , + { 29338 , -5388 } , + { 29283 , -5676 } , + { 29226 , -5963 } , + { 29166 , -6249 } , + { 29103 , -6535 } , + { 29038 , -6821 } , + { 28969 , -7106 } , + { 28898 , -7390 } , + { 28824 , -7673 } , + { 28748 , -7956 } , + { 28668 , -8237 } , + { 28586 , -8518 } , + { 28501 , -8799 } , + { 28413 , -9078 } , + { 28323 , -9357 } , + { 28229 , -9634 } , + { 28133 , -9911 } , + { 28035 , -10187 } , + { 27933 , -10461 } , + { 27829 , -10735 } , + { 27723 , -11008 } , + { 27613 , -11279 } , + { 27501 , -11550 } , + { 27387 , -11819 } , + { 27269 , -12088 } , + { 27149 , -12355 } , + { 27027 , -12621 } , + { 26901 , -12885 } , + { 26774 , -13149 } , + { 26643 , -13411 } , + { 26510 , -13672 } , + { 26375 , -13932 } , + { 26237 , -14190 } , + { 26096 , -14447 } , + { 25953 , -14702 } , + { 25807 , -14956 } , + { 25659 , -15209 } , + { 25509 , -15460 } , + { 25356 , -15710 } , + { 25200 , -15958 } , + { 25043 , -16205 } , + { 24882 , -16450 } , + { 24720 , -16693 } , + { 24554 , -16935 } , + { 24387 , -17175 } , + { 24217 , -17414 } , + { 24045 , -17651 } , + { 23871 , -17886 } , + { 23694 , -18119 } , + { 23515 , -18351 } , + { 23334 , -18581 } , + { 23150 , -18809 } , + { 22964 , -19036 } , + { 22776 , -19260 } , + { 22586 , -19483 } , + { 22394 , -19704 } , + { 22199 , -19923 } , + { 22003 , -20140 } , + { 21804 , -20355 } , + { 21603 , -20568 } , + { 21400 , -20779 } , + { 21195 , -20988 } + }; +cos_msin_t a_cos_msin_32[160]= { + { 29828 , -73 } , + { 29827 , -220 } , + { 29826 , -366 } , + { 29824 , -512 } , + { 29821 , -659 } , + { 29817 , -805 } , + { 29813 , -952 } , + { 29808 , -1098 } , + { 29802 , -1244 } , + { 29796 , -1390 } , + { 29789 , -1537 } , + { 29781 , -1683 } , + { 29772 , -1829 } , + { 29763 , -1975 } , + { 29753 , -2121 } , + { 29742 , -2267 } , + { 29730 , -2413 } , + { 29718 , -2559 } , + { 29705 , -2705 } , + { 29692 , -2851 } , + { 29677 , -2997 } , + { 29662 , -3142 } , + { 29646 , -3288 } , + { 29630 , -3433 } , + { 29613 , -3579 } , + { 29595 , -3724 } , + { 29576 , -3869 } , + { 29557 , -4014 } , + { 29537 , -4159 } , + { 29516 , -4304 } , + { 29494 , -4449 } , + { 29472 , -4594 } , + { 29449 , -4738 } , + { 29426 , -4883 } , + { 29401 , -5027 } , + { 29376 , -5172 } , + { 29351 , -5316 } , + { 29324 , -5460 } , + { 29297 , -5604 } , + { 29269 , -5747 } , + { 29241 , -5891 } , + { 29211 , -6034 } , + { 29181 , -6178 } , + { 29151 , -6321 } , + { 29119 , -6464 } , + { 29087 , -6607 } , + { 29054 , -6749 } , + { 29021 , -6892 } , + { 28987 , -7034 } , + { 28952 , -7177 } , + { 28916 , -7319 } , + { 28880 , -7460 } , + { 28843 , -7602 } , + { 28805 , -7744 } , + { 28767 , -7885 } , + { 28728 , -8026 } , + { 28688 , -8167 } , + { 28648 , -8308 } , + { 28607 , -8448 } , + { 28565 , -8589 } , + { 28522 , -8729 } , + { 28479 , -8869 } , + { 28435 , -9008 } , + { 28391 , -9148 } , + { 28346 , -9287 } , + { 28300 , -9426 } , + { 28253 , -9565 } , + { 28206 , -9703 } , + { 28158 , -9842 } , + { 28109 , -9980 } , + { 28060 , -10118 } , + { 28010 , -10255 } , + { 27959 , -10393 } , + { 27908 , -10530 } , + { 27856 , -10667 } , + { 27803 , -10803 } , + { 27750 , -10940 } , + { 27696 , -11076 } , + { 27641 , -11212 } , + { 27586 , -11347 } , + { 27529 , -11482 } , + { 27473 , -11617 } , + { 27415 , -11752 } , + { 27357 , -11886 } , + { 27299 , -12021 } , + { 27239 , -12154 } , + { 27179 , -12288 } , + { 27119 , -12421 } , + { 27057 , -12554 } , + { 26996 , -12687 } , + { 26933 , -12819 } , + { 26870 , -12951 } , + { 26806 , -13083 } , + { 26741 , -13215 } , + { 26676 , -13346 } , + { 26610 , -13476 } , + { 26544 , -13607 } , + { 26477 , -13737 } , + { 26409 , -13867 } , + { 26340 , -13996 } , + { 26271 , -14125 } , + { 26202 , -14254 } , + { 26132 , -14383 } , + { 26061 , -14511 } , + { 25989 , -14638 } , + { 25917 , -14766 } , + { 25844 , -14893 } , + { 25771 , -15020 } , + { 25697 , -15146 } , + { 25622 , -15272 } , + { 25547 , -15397 } , + { 25471 , -15523 } , + { 25394 , -15648 } , + { 25317 , -15772 } , + { 25239 , -15896 } , + { 25161 , -16020 } , + { 25082 , -16143 } , + { 25003 , -16266 } , + { 24923 , -16389 } , + { 24842 , -16511 } , + { 24760 , -16632 } , + { 24678 , -16754 } , + { 24596 , -16875 } , + { 24513 , -16995 } , + { 24429 , -17115 } , + { 24345 , -17235 } , + { 24260 , -17354 } , + { 24174 , -17473 } , + { 24088 , -17592 } , + { 24002 , -17710 } , + { 23914 , -17827 } , + { 23827 , -17945 } , + { 23738 , -18061 } , + { 23649 , -18178 } , + { 23560 , -18293 } , + { 23470 , -18409 } , + { 23379 , -18524 } , + { 23288 , -18638 } , + { 23196 , -18752 } , + { 23104 , -18866 } , + { 23011 , -18979 } , + { 22917 , -19092 } , + { 22824 , -19204 } , + { 22729 , -19316 } , + { 22634 , -19427 } , + { 22538 , -19538 } , + { 22442 , -19649 } , + { 22345 , -19759 } , + { 22248 , -19868 } , + { 22150 , -19977 } , + { 22052 , -20086 } , + { 21953 , -20194 } , + { 21854 , -20301 } , + { 21754 , -20408 } , + { 21653 , -20515 } , + { 21552 , -20621 } , + { 21451 , -20726 } , + { 21349 , -20831 } , + { 21246 , -20936 } , + { 21143 , -21040 } + }; +cos_msin_t a_cos_msin_64[320] = { +{29827, -34}, +{29827, -106}, +{29827, -177}, +{29827, -249}, +{29826, -320}, +{29825, -392}, +{29824, -463}, +{29823, -535}, +{29821, -606}, +{29819, -678}, +{29818, -750}, +{29816, -821}, +{29814, -893}, +{29812, -964}, +{29809, -1035}, +{29807, -1106}, +{29804, -1177}, +{29801, -1249}, +{29797, -1320}, +{29795, -1392}, +{29791, -1463}, +{29787, -1535}, +{29784, -1606}, +{29780, -1678}, +{29776, -1749}, +{29771, -1820}, +{29767, -1892}, +{29763, -1963}, +{29758, -2035}, +{29753, -2106}, +{29748, -2177}, +{29742, -2249}, +{29737, -2320}, +{29731, -2391}, +{29726, -2462}, +{29719, -2534}, +{29713, -2605}, +{29707, -2676}, +{29701, -2747}, +{29694, -2819}, +{29686, -2890}, +{29680, -2961}, +{29673, -3032}, +{29665, -3103}, +{29658, -3174}, +{29650, -3245}, +{29643, -3316}, +{29635, -3387}, +{29626, -3459}, +{29618, -3529}, +{29610, -3600}, +{29601, -3671}, +{29592, -3742}, +{29583, -3813}, +{29574, -3884}, +{29564, -3955}, +{29554, -4026}, +{29544, -4097}, +{29535, -4167}, +{29525, -4238}, +{29514, -4309}, +{29504, -4380}, +{29493, -4450}, +{29483, -4521}, +{29472, -4591}, +{29461, -4662}, +{29450, -4733}, +{29439, -4803}, +{29427, -4874}, +{29415, -4944}, +{29403, -5015}, +{29391, -5085}, +{29379, -5155}, +{29366, -5226}, +{29353, -5296}, +{29341, -5367}, +{29328, -5438}, +{29314, -5508}, +{29301, -5578}, +{29289, -5648}, +{29274, -5718}, +{29260, -5788}, +{29247, -5858}, +{29232, -5928}, +{29218, -5998}, +{29204, -6068}, +{29188, -6139}, +{29175, -6209}, +{29159, -6279}, +{29145, -6348}, +{29128, -6418}, +{29114, -6488}, +{29097, -6557}, +{29082, -6627}, +{29066, -6697}, +{29050, -6767}, +{29034, -6837}, +{29017, -6906}, +{29001, -6975}, +{28984, -7045}, +{28966, -7114}, +{28950, -7184}, +{28933, -7254}, +{28915, -7323}, +{28897, -7392}, +{28880, -7461}, +{28862, -7530}, +{28843, -7600}, +{28825, -7669}, +{28807, -7738}, +{28788, -7806}, +{28769, -7875}, +{28751, -7944}, +{28732, -8014}, +{28712, -8082}, +{28692, -8151}, +{28672, -8219}, +{28653, -8289}, +{28633, -8357}, +{28613, -8425}, +{28593, -8494}, +{28572, -8563}, +{28551, -8632}, +{28531, -8700}, +{28510, -8768}, +{28488, -8837}, +{28468, -8905}, +{28447, -8973}, +{28425, -9041}, +{28403, -9109}, +{28381, -9177}, +{28359, -9245}, +{28336, -9313}, +{28315, -9381}, +{28292, -9448}, +{28269, -9517}, +{28246, -9584}, +{28223, -9652}, +{28200, -9720}, +{28176, -9787}, +{28153, -9854}, +{28129, -9922}, +{28105, -9990}, +{28082, -10056}, +{28057, -10124}, +{28032, -10191}, +{28009, -10258}, +{27984, -10326}, +{27959, -10392}, +{27934, -10460}, +{27909, -10526}, +{27883, -10593}, +{27858, -10661}, +{27832, -10727}, +{27807, -10794}, +{27780, -10860}, +{27754, -10927}, +{27728, -10993}, +{27701, -11059}, +{27676, -11126}, +{27648, -11192}, +{27622, -11259}, +{27595, -11324}, +{27567, -11391}, +{27540, -11456}, +{27512, -11523}, +{27484, -11588}, +{27456, -11655}, +{27429, -11720}, +{27401, -11786}, +{27372, -11852}, +{27344, -11917}, +{27315, -11982}, +{27286, -12049}, +{27257, -12114}, +{27229, -12179}, +{27199, -12244}, +{27169, -12309}, +{27140, -12375}, +{27110, -12439}, +{27080, -12505}, +{27050, -12570}, +{27019, -12634}, +{26990, -12699}, +{26958, -12764}, +{26928, -12828}, +{26897, -12892}, +{26866, -12956}, +{26835, -13021}, +{26804, -13086}, +{26773, -13149}, +{26741, -13214}, +{26709, -13278}, +{26677, -13342}, +{26645, -13406}, +{26613, -13470}, +{26581, -13534}, +{26549, -13597}, +{26515, -13661}, +{26483, -13725}, +{26450, -13788}, +{26417, -13851}, +{26384, -13915}, +{26350, -13978}, +{26316, -14041}, +{26283, -14103}, +{26248, -14166}, +{26215, -14229}, +{26180, -14292}, +{26146, -14355}, +{26112, -14417}, +{26077, -14480}, +{26042, -14543}, +{26008, -14605}, +{25972, -14667}, +{25937, -14730}, +{25901, -14792}, +{25866, -14854}, +{25830, -14916}, +{25794, -14977}, +{25759, -15039}, +{25723, -15101}, +{25687, -15162}, +{25650, -15224}, +{25613, -15286}, +{25577, -15347}, +{25540, -15408}, +{25503, -15470}, +{25465, -15531}, +{25428, -15592}, +{25391, -15653}, +{25353, -15714}, +{25315, -15774}, +{25277, -15834}, +{25240, -15895}, +{25201, -15956}, +{25162, -16016}, +{25124, -16076}, +{25086, -16136}, +{25047, -16196}, +{25008, -16256}, +{24969, -16316}, +{24930, -16375}, +{24891, -16436}, +{24851, -16496}, +{24811, -16555}, +{24772, -16615}, +{24732, -16674}, +{24692, -16732}, +{24652, -16791}, +{24612, -16852}, +{24572, -16911}, +{24531, -16969}, +{24490, -17027}, +{24449, -17086}, +{24408, -17145}, +{24367, -17203}, +{24325, -17261}, +{24284, -17320}, +{24242, -17379}, +{24200, -17436}, +{24158, -17494}, +{24116, -17552}, +{24075, -17610}, +{24032, -17668}, +{23990, -17725}, +{23947, -17782}, +{23904, -17840}, +{23862, -17897}, +{23819, -17954}, +{23775, -18011}, +{23732, -18068}, +{23689, -18125}, +{23645, -18181}, +{23602, -18238}, +{23558, -18294}, +{23514, -18351}, +{23470, -18407}, +{23426, -18464}, +{23381, -18520}, +{23337, -18576}, +{23293, -18632}, +{23248, -18688}, +{23202, -18743}, +{23158, -18799}, +{23112, -18854}, +{23068, -18910}, +{23022, -18964}, +{22977, -19020}, +{22931, -19074}, +{22885, -19129}, +{22839, -19185}, +{22793, -19239}, +{22747, -19294}, +{22700, -19348}, +{22655, -19403}, +{22607, -19457}, +{22561, -19511}, +{22514, -19565}, +{22467, -19619}, +{22421, -19673}, +{22373, -19726}, +{22326, -19780}, +{22279, -19834}, +{22230, -19887}, +{22183, -19940}, +{22135, -19993}, +{22087, -20047}, +{22039, -20099}, +{21991, -20152}, +{21942, -20205}, +{21894, -20257}, +{21845, -20309}, +{21797, -20362}, +{21748, -20413}, +{21699, -20466}, +{21650, -20518}, +{21601, -20570}, +{21551, -20621}, +{21502, -20674} +}; + +cos_msin_t *a_cos_msin_table[] = {a_cos_msin_2, a_cos_msin_4, + a_cos_msin_8, a_cos_msin_16, + a_cos_msin_32,a_cos_msin_64 + }; + +Word16 dct_core_a[10][10] = { + +{ 10453, 10196, 9688, 8941, 7973, 6810, 5479, 4013, 2448, 823 }, +{ 10196, 7973, 4013, -823, -5479, -8941, -10453, -9688, -6810, -2448 }, +{ 9688 , 4013, -4013, -9688, -9688, -4013, 4013, 9688, 9688, 4013 }, +{ 8941 , -823, -9688, -7973, 2448, 10196, 6810, -4013, -10453, -5479 }, +{ 7973 , -5479, -9688, 2448, 10453, 823, -10196, -4013, 8941, 6810 }, +{ 6810 , -8941, -4013, 10196, 823, -10453, 2448, 9688, -5479, -7973 }, +{ 5479 , -10453, 4013, 6810, -10196, 2448, 7973, -9688, 823, 8941 }, +{ 4013 , -9688, 9688, -4013, -4013, 9688, -9688, 4013, 4013, -9688 }, +{ 2448 , -6810, 9688, -10453, 8941, -5479, 823, 4013, -7973, 10196 }, +{ 823 , -2448, 4013, -5479, 6810, -7973, 8941, -9688, 10196, -10453 }}; + +Word16 anal_bias[320] = { + 1, 1, 3, 1, 4, 1, 3, -2, 4, 3, + 4, 1, 3, 0, 2, -3, 0, 0, 2, 2, + 4, 1, 1, -5, 4, 1, 2, -1, 0, -1, + 1, -2, 0, 2, 2, 2, 4, 1, 3, 0, + 5, 3, 2, 0, 3, 0, 1, -4, 1, 1, + 2, 0, 4, 0, 1, -4, 6, 1, 3, -1, + 1, 0, 0, -4, 1, 1, 3, 1, 3, 2, + 4, -2, 4, 3, 5, 1, 3, 0, 1, -3, + 1, 1, 2, 0, 4, 1, 2, -4, 4, 2, + 2, -1, 1, -1, 1, -4, 0, 0, 3, 0, + 5, 2, 3, -1, 6, 2, 5, 0, 4, 0, + 1, -3, 1, 0, 3, 0, 4, 0, 1, -3, + 4, 1, 3, -1, 1, -2, 1, -4, 0, 1, + 2, 1, 3, 2, 2, -2, 4, 3, 3, 0, + 3, 0, 0, -2, 1, 0, 2, 0, 5, -1, + 1, -3, 4, 2, 2, 0, 2, -3, 1, -4, + -1, 1, 2, 2, 4, 1, 3, -1, 5, 2, + 2, 0, 3, -1, 2, -3, 0, 1, 2, 2, + 4, 0, 1, -5, 5, 1, 3, 0, 2, -1, + 0, -2, 1, 2, 2, 2, 4, 1, 0, 0, + 4, 2, 4, 1, 4, -1, 1, -4, 0, 1, + 3, 1, 5, 1, 1, -2, 4, 0, 2, 0, + 2, -1, 0, -2, 0, 1, 1, 1, 4, 2, + 3, -2, 5, 4, 4, 0, 3, 0, 3, -4, + 1, 2, 2, 0, 4, 1, 0, -3, 4, 2, + 3, -1, 1, -1, 1, -4, 0, 2, 3, 1, + 4, 1, 3, 0, 3, 3, 4, 1, 2, 0, + 1, -3, 2, 2, 2, 1, 5, 0, 1, -4, + 4, 1, 3, -2, 3, -1, 0, -2, 0, 2, + 2, 0, 5, 1, 4, -1, 4, 3, 4, 1, + 3, 0, 1, -4, 2, 0, 3, 1, 5, 0, + 1, -5, 5, 2, 2, 0, 0, 0, 0, -4}; + diff --git a/third_party/g7221/encode/encoder.c b/third_party/g7221/encode/encoder.c new file mode 100644 index 00000000..0ec8cf85 --- /dev/null +++ b/third_party/g7221/encode/encoder.c @@ -0,0 +1,1125 @@ +/*************************************************************************** +** +** 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: encoder.c + + Purpose: Contains files used to implement the G.722.1 Annex C encoder + + Design Notes: + +***************************************************************************/ + +/*************************************************************************** + Include files +***************************************************************************/ + +#include <stdio.h> +#include <math.h> +#include "defs.h" +#include "huff_def.h" +#include "tables.h" +#include "count.h" + +/*************************************************************************** + Function: encoder + + Syntax: void encoder(Word16 number_of_available_bits, + Word16 number_of_regions, + Word16 mlt_coefs, + Word16 mag_shift, + Word16 out_words) + + inputs: number_of_available_bits + number_of_regions + mag_shift + mlt_coefs[DCT_LENGTH] + + outputs: out_words[MAX_BITS_PER_FRAME/16] + + + Description: Encodes the mlt coefs into out_words using G.722.1 Annex C + + + WMOPS: 7kHz | 24kbit | 32kbit + -------|--------------|---------------- + AVG | 0.93 | 1.04 + -------|--------------|---------------- + MAX | 1.20 | 1.28 + -------|--------------|---------------- + + 14kHz | 24kbit | 32kbit | 48kbit + -------|--------------|----------------|---------------- + AVG | 1.39 | 1.71 | 2.01 + -------|--------------|----------------|---------------- + MAX | 2.00 | 2.30 | 2.52 + -------|--------------|----------------|---------------- + +***************************************************************************/ + +void encoder(Word16 number_of_available_bits, + Word16 number_of_regions, + Word16 *mlt_coefs, + Word16 mag_shift, + Word16 *out_words) +{ + + Word16 num_categorization_control_bits; + Word16 num_categorization_control_possibilities; + Word16 number_of_bits_per_frame; + Word16 number_of_envelope_bits; + Word16 categorization_control; + Word16 region; + Word16 absolute_region_power_index[MAX_NUMBER_OF_REGIONS]; + Word16 power_categories[MAX_NUMBER_OF_REGIONS]; + Word16 category_balances[MAX_NUM_CATEGORIZATION_CONTROL_POSSIBILITIES-1]; + Word16 drp_num_bits[MAX_NUMBER_OF_REGIONS+1]; + UWord16 drp_code_bits[MAX_NUMBER_OF_REGIONS+1]; + Word16 region_mlt_bit_counts[MAX_NUMBER_OF_REGIONS]; + UWord32 region_mlt_bits[4*MAX_NUMBER_OF_REGIONS]; + Word16 mag_shift_offset; + + Word16 temp; + + /* initialize variables */ + test(); + if (number_of_regions == NUMBER_OF_REGIONS) + { + num_categorization_control_bits = NUM_CATEGORIZATION_CONTROL_BITS; + move16(); + num_categorization_control_possibilities = NUM_CATEGORIZATION_CONTROL_POSSIBILITIES; + move16(); + } + else + { + num_categorization_control_bits = MAX_NUM_CATEGORIZATION_CONTROL_BITS; + move16(); + num_categorization_control_possibilities = MAX_NUM_CATEGORIZATION_CONTROL_POSSIBILITIES; + move16(); + } + + number_of_bits_per_frame = number_of_available_bits; + move16(); + + for (region=0; region<number_of_regions; region++) + { + region_mlt_bit_counts[region] = 0; + move16(); + } + + /* Estimate power envelope. */ + number_of_envelope_bits = compute_region_powers(mlt_coefs, + mag_shift, + drp_num_bits, + drp_code_bits, + absolute_region_power_index, + number_of_regions); + + /* Adjust number of available bits based on power envelope estimate */ + temp = sub(number_of_available_bits,number_of_envelope_bits); + number_of_available_bits = sub(temp,num_categorization_control_bits); + + /* get categorizations */ + categorize(number_of_available_bits, + number_of_regions, + num_categorization_control_possibilities, + absolute_region_power_index, + power_categories, + category_balances); + + /* Adjust absolute_region_category_index[] for mag_shift. + This assumes that REGION_POWER_STEPSIZE_DB is defined + to be exactly 3.010299957 or 20.0 times log base 10 + of square root of 2. */ + temp = shl(mag_shift,1); + mag_shift_offset = add(temp,REGION_POWER_TABLE_NUM_NEGATIVES); + + for (region=0; region<number_of_regions; region++) + { + absolute_region_power_index[region] = add(absolute_region_power_index[region],mag_shift_offset); + move16(); + } + + /* adjust the absolute power region index based on the mlt coefs */ + adjust_abs_region_power_index(absolute_region_power_index,mlt_coefs,number_of_regions); + + + /* quantize and code the mlt coefficients based on categorizations */ + vector_quantize_mlts(number_of_available_bits, + number_of_regions, + num_categorization_control_possibilities, + mlt_coefs, + absolute_region_power_index, + power_categories, + category_balances, + &categorization_control, + region_mlt_bit_counts, + region_mlt_bits); + + /* stuff bits into words */ + bits_to_words(region_mlt_bits, + region_mlt_bit_counts, + drp_num_bits, + drp_code_bits, + out_words, + categorization_control, + number_of_regions, + num_categorization_control_bits, + number_of_bits_per_frame); + +} + +/*************************************************************************** + Function: bits_to_words + + Syntax: bits_to_words(UWord32 *region_mlt_bits, + Word16 *region_mlt_bit_counts, + Word16 *drp_num_bits, + UWord16 *drp_code_bits, + Word16 *out_words, + Word16 categorization_control, + Word16 number_of_regions, + Word16 num_categorization_control_bits, + Word16 number_of_bits_per_frame) + + + Description: Stuffs the bits into words for output + + WMOPS: 7kHz | 24kbit | 32kbit + -------|--------------|---------------- + AVG | 0.09 | 0.12 + -------|--------------|---------------- + MAX | 0.10 | 0.13 + -------|--------------|---------------- + + 14kHz | 24kbit | 32kbit | 48kbit + -------|--------------|----------------|---------------- + AVG | 0.12 | 0.15 | 0.19 + -------|--------------|----------------|---------------- + MAX | 0.14 | 0.17 | 0.21 + -------|--------------|----------------|---------------- + +***************************************************************************/ +void bits_to_words(UWord32 *region_mlt_bits, + Word16 *region_mlt_bit_counts, + Word16 *drp_num_bits, + UWord16 *drp_code_bits, + Word16 *out_words, + Word16 categorization_control, + Word16 number_of_regions, + Word16 num_categorization_control_bits, + Word16 number_of_bits_per_frame) +{ + Word16 out_word_index = 0; + Word16 j; + Word16 region; + Word16 out_word; + Word16 region_bit_count; + Word16 current_word_bits_left; + UWord16 slice; + Word16 out_word_bits_free = 16; + UWord32 *in_word_ptr; + UWord32 current_word; + + Word32 acca; + Word32 accb; + Word16 temp; + + /* First set up the categorization control bits to look like one more set of region power bits. */ + out_word = 0; + move16(); + + drp_num_bits[number_of_regions] = num_categorization_control_bits; + move16(); + + drp_code_bits[number_of_regions] = (UWord16)categorization_control; + move16(); + + /* These code bits are right justified. */ + for (region=0; region <= number_of_regions; region++) + { + current_word_bits_left = drp_num_bits[region]; + move16(); + + current_word = (UWord32)drp_code_bits[region]; + move16(); + + j = sub(current_word_bits_left,out_word_bits_free); + + test(); + if (j >= 0) + { + temp = extract_l(L_shr(current_word,j)); + out_word = add(out_word,temp); + + out_words[out_word_index++] = out_word; + move16(); + + out_word_bits_free = 16; + move16(); + + out_word_bits_free = sub(out_word_bits_free,j); + + acca = (current_word << out_word_bits_free); + out_word = extract_l(acca); + } + else + { + j = negate(j); + + acca = (current_word << j); + accb = L_deposit_l(out_word); + acca = L_add(accb,acca); + out_word = extract_l(acca); + + out_word_bits_free = sub(out_word_bits_free,current_word_bits_left); + } + } + + /* These code bits are left justified. */ + + for (region=0;region<number_of_regions; region++) + { + accb = L_deposit_l(out_word_index); + accb = L_shl(accb,4); + accb = L_sub(accb,number_of_bits_per_frame); + test(); + if(accb < 0) + { + temp = shl(region,2); + in_word_ptr = ®ion_mlt_bits[temp]; + region_bit_count = region_mlt_bit_counts[region]; + move16(); + + temp = sub(32,region_bit_count); + test(); + if(temp > 0) + current_word_bits_left = region_bit_count; + else + current_word_bits_left = 32; + + current_word = *in_word_ptr++; + + acca = L_deposit_l(out_word_index); + acca = L_shl(acca,4); + acca = L_sub(acca,number_of_bits_per_frame); + + /* from while loop */ + test(); + test(); + logic16(); + while ((region_bit_count > 0) && (acca < 0)) + { + /* from while loop */ + test(); + test(); + logic16(); + + temp = sub(current_word_bits_left,out_word_bits_free); + test(); + if (temp >= 0) + { + temp = sub(32,out_word_bits_free); + accb = LU_shr(current_word,temp); + slice = (UWord16)extract_l(accb); + + out_word = add(out_word,slice); + + test(); + current_word <<= out_word_bits_free; + + current_word_bits_left = sub(current_word_bits_left,out_word_bits_free); + out_words[out_word_index++] = extract_l(out_word); + move16(); + + out_word = 0; + move16(); + + out_word_bits_free = 16; + move16(); + } + else + { + temp = sub(32,current_word_bits_left); + accb = LU_shr(current_word,temp); + slice = (UWord16)extract_l(accb); + + temp = sub(out_word_bits_free,current_word_bits_left); + test(); + accb = slice << temp; + acca = L_deposit_l(out_word); + acca = L_add(acca,accb); + out_word = extract_l(acca); + out_word_bits_free = sub(out_word_bits_free,current_word_bits_left); + + current_word_bits_left = 0; + move16(); + } + + test(); + if (current_word_bits_left == 0) + { + current_word = *in_word_ptr++; + region_bit_count = sub(region_bit_count,32); + + /* current_word_bits_left = MIN(32,region_bit_count); */ + temp = sub(32,region_bit_count); + test(); + if(temp > 0) + current_word_bits_left = region_bit_count; + else + current_word_bits_left = 32; + + } + acca = L_deposit_l(out_word_index); + acca = L_shl(acca,4); + acca = L_sub(acca,number_of_bits_per_frame); + } + accb = L_deposit_l(out_word_index); + accb = L_shl(accb,4); + accb = L_sub(accb,number_of_bits_per_frame); + } + } + + /* Fill out with 1's. */ + + test(); + while (acca < 0) + { + test(); + current_word = 0x0000ffff; + move32(); + + temp = sub(16,out_word_bits_free); + acca = LU_shr(current_word,temp); + slice = (UWord16)extract_l(acca); + + out_word = add(out_word,slice); + out_words[out_word_index++] = out_word; + move16(); + + out_word = 0; + move16(); + + out_word_bits_free = 16; + move16(); + + acca = L_deposit_l(out_word_index); + acca = L_shl(acca,4); + acca = L_sub(acca,number_of_bits_per_frame); + } +} +/*************************************************************************** + Function: adjust_abs_region_power_index + + Syntax: adjust_abs_region_power_index(Word16 *absolute_region_power_index, + Word16 *mlt_coefs, + Word16 number_of_regions) + + inputs: *mlt_coefs + *absolute_region_power_index + number_of_regions + + outputs: *absolute_region_power_index + + Description: Adjusts the absolute power index + + + WMOPS: 7kHz | 24kbit | 32kbit + -------|--------------|---------------- + AVG | 0.03 | 0.03 + -------|--------------|---------------- + MAX | 0.12 | 0.12 + -------|--------------|---------------- + + 14kHz | 24kbit | 32kbit | 48kbit + -------|--------------|----------------|---------------- + AVG | 0.03 | 0.03 | 0.03 + -------|--------------|----------------|---------------- + MAX | 0.14 | 0.14 | 0.14 + -------|--------------|----------------|---------------- + +***************************************************************************/ +void adjust_abs_region_power_index(Word16 *absolute_region_power_index,Word16 *mlt_coefs,Word16 number_of_regions) +{ + Word16 n,i; + Word16 region; + Word16 *raw_mlt_ptr; + + Word32 acca; + Word16 temp; + + for (region=0; region<number_of_regions; region++) + { + n = sub(absolute_region_power_index[region],39); + n = shr(n,1); + + test(); + if (n > 0) + { + temp = extract_l(L_mult0(region,REGION_SIZE)); + + raw_mlt_ptr = &mlt_coefs[temp]; + + for (i=0; i<REGION_SIZE; i++) + { + acca = L_shl(*raw_mlt_ptr,16); + acca = L_add(acca,32768L); + acca = L_shr(acca,n); + acca = L_shr(acca,16); + *raw_mlt_ptr++ = extract_l(acca); + } + + temp = shl(n,1); + temp = sub(absolute_region_power_index[region],temp); + absolute_region_power_index[region] = temp; + move16(); + } + } +} + +/*************************************************************************** + Function: compute_region_powers + + Syntax: Word16 compute_region_powers(Word16 *mlt_coefs, + Word16 mag_shift, + Word16 *drp_num_bits, + UWord16 *drp_code_bits, + Word16 *absolute_region_power_index, + Word16 number_of_regions) + mlt_coefs[DCT_LENGTH]; + mag_shift; + drp_num_bits[MAX_NUMBER_OF_REGIONS]; + drp_code_bits[MAX_NUMBER_OF_REGIONS]; + absolute_region_power_index[MAX_NUMBER_OF_REGIONS]; + number_of_regions; + + Description: Computes the power for each of the regions + + + WMOPS: 7kHz | 24kbit | 32kbit + -------|--------------|---------------- + AVG | 0.09 | 0.09 + -------|--------------|---------------- + MAX | 0.13 | 0.13 + -------|--------------|---------------- + + 14kHz | 24kbit | 32kbit | 48kbit + -------|--------------|----------------|---------------- + AVG | 0.20 | 0.20 | 0.20 + -------|--------------|----------------|---------------- + MAX | 0.29 | 0.29 | 0.29 + -------|--------------|----------------|---------------- + +***************************************************************************/ + +Word16 compute_region_powers(Word16 *mlt_coefs, + Word16 mag_shift, + Word16 *drp_num_bits, + UWord16 *drp_code_bits, + Word16 *absolute_region_power_index, + Word16 number_of_regions) +{ + + Word16 *input_ptr; + Word32 long_accumulator; + Word16 itemp1; + Word16 power_shift; + Word16 region; + Word16 j; + Word16 differential_region_power_index[MAX_NUMBER_OF_REGIONS]; + Word16 number_of_bits; + + Word32 acca; + Word16 temp; + Word16 temp1; + Word16 temp2; + + + input_ptr = mlt_coefs; + for (region=0; region<number_of_regions; region++) + { + long_accumulator = L_deposit_l(0); + + for (j=0; j<REGION_SIZE; j++) + { + itemp1 = *input_ptr++; + move16(); + long_accumulator = L_mac0(long_accumulator,itemp1,itemp1); + } + + power_shift = 0; + move16(); + + acca = (long_accumulator & 0x7fff0000L); + logic32(); + + test(); + while (acca > 0) + { + test(); + long_accumulator = L_shr(long_accumulator,1); + + acca = (long_accumulator & 0x7fff0000L); + logic32(); + + power_shift = add(power_shift,1); + } + + acca = L_sub(long_accumulator,32767); + + temp = add(power_shift,15); + test(); + test(); + logic16(); + while ((acca <= 0) && (temp >= 0)) + { + test(); + test(); + logic16(); + + long_accumulator = L_shl(long_accumulator,1); + acca = L_sub(long_accumulator,32767); + power_shift--; + temp = add(power_shift,15); + } + long_accumulator = L_shr(long_accumulator,1); + /* 28963 corresponds to square root of 2 times REGION_SIZE(20). */ + acca = L_sub(long_accumulator,28963); + + test(); + if (acca >= 0) + power_shift = add(power_shift,1); + + acca = L_deposit_l(mag_shift); + acca = L_shl(acca,1); + acca = L_sub(power_shift,acca); + acca = L_add(35,acca); + acca = L_sub(acca,REGION_POWER_TABLE_NUM_NEGATIVES); + absolute_region_power_index[region] = extract_l(acca); + } + + + /* Before we differentially encode the quantized region powers, adjust upward the + valleys to make sure all the peaks can be accurately represented. */ + temp = sub(number_of_regions,2); + + for (region = temp; region >= 0; region--) + { + temp1 = sub(absolute_region_power_index[region+1],DRP_DIFF_MAX); + temp2 = sub(absolute_region_power_index[region],temp1); + test(); + if (temp2 < 0) + { + absolute_region_power_index[region] = temp1; + move16(); + } + } + + /* The MLT is currently scaled too low by the factor + ENCODER_SCALE_FACTOR(=18318)/32768 * (1./sqrt(160). + This is the ninth power of 1 over the square root of 2. + So later we will add ESF_ADJUSTMENT_TO_RMS_INDEX (now 9) + to drp_code_bits[0]. */ + + /* drp_code_bits[0] can range from 1 to 31. 0 will be used only as an escape sequence. */ + temp1 = sub(1,ESF_ADJUSTMENT_TO_RMS_INDEX); + temp2 = sub(absolute_region_power_index[0],temp1); + test(); + if (temp2 < 0) + { + absolute_region_power_index[0] = temp1; + move16(); + } + + temp1 = sub(31,ESF_ADJUSTMENT_TO_RMS_INDEX); + + /* + * The next line was corrected in Release 1.2 + */ + + temp2 = sub(absolute_region_power_index[0], temp1); + test(); + if (temp2 > 0) + { + absolute_region_power_index[0] = temp1; + move16(); + } + + differential_region_power_index[0] = absolute_region_power_index[0]; + move16(); + + number_of_bits = 5; + move16(); + + drp_num_bits[0] = 5; + move16(); + + drp_code_bits[0] = (UWord16)add(absolute_region_power_index[0],ESF_ADJUSTMENT_TO_RMS_INDEX); + move16(); + + /* Lower limit the absolute region power indices to -8 and upper limit them to 31. Such extremes + may be mathematically impossible anyway.*/ + for (region=1; region<number_of_regions; region++) + { + temp1 = sub(-8,ESF_ADJUSTMENT_TO_RMS_INDEX); + temp2 = sub(absolute_region_power_index[region],temp1); + test(); + if (temp2 < 0) + { + absolute_region_power_index[region] = temp1; + move16(); + } + + temp1 = sub(31,ESF_ADJUSTMENT_TO_RMS_INDEX); + temp2 = sub(absolute_region_power_index[region],temp1); + test(); + if (temp2 > 0) + { + absolute_region_power_index[region] = temp1; + move16(); + } + } + + for (region=1; region<number_of_regions; region++) + { + j = sub(absolute_region_power_index[region],absolute_region_power_index[region-1]); + temp = sub(j,DRP_DIFF_MIN); + test(); + if (temp < 0) + { + j = DRP_DIFF_MIN; + } + j = sub(j,DRP_DIFF_MIN); + move16(); + differential_region_power_index[region] = j; + move16(); + + temp = add(absolute_region_power_index[region-1],differential_region_power_index[region]); + temp = add(temp,DRP_DIFF_MIN); + absolute_region_power_index[region] = temp; + move16(); + + number_of_bits = add(number_of_bits,differential_region_power_bits[region][j]); + drp_num_bits[region] = differential_region_power_bits[region][j]; + move16(); + drp_code_bits[region] = differential_region_power_codes[region][j]; + move16(); + } + + return (number_of_bits); +} + +/*************************************************************************** + Function: vector_quantize_mlts + + Syntax: void vector_quantize_mlts(number_of_available_bits, + number_of_regions, + num_categorization_control_possibilities, + mlt_coefs, + absolute_region_power_index, + power_categories, + category_balances, + p_categorization_control, + region_mlt_bit_counts, + region_mlt_bits) + + Word16 number_of_available_bits; + Word16 number_of_regions; + Word16 num_categorization_control_possibilities; + Word16 mlt_coefs[DCT_LENGTH]; + Word16 absolute_region_power_index[MAX_NUMBER_OF_REGIONS]; + Word16 power_categories[MAX_NUMBER_OF_REGIONS]; + Word16 category_balances[MAX_NUM_CATEGORIZATION_CONTROL_POSSIBILITIES-1]; + Word16 *p_categorization_control; + Word16 region_mlt_bit_counts[MAX_NUMBER_OF_REGIONS]; + Word32 region_mlt_bits[4*MAX_NUMBER_OF_REGIONS]; + + Description: Scalar quantized vector Huffman coding (SQVH) + + + WMOPS: 7kHz | 24kbit | 32kbit + -------|--------------|---------------- + AVG | 0.57 | 0.65 + -------|--------------|---------------- + MAX | 0.78 | 0.83 + -------|--------------|---------------- + + 14kHz | 24kbit | 32kbit | 48kbit + -------|--------------|----------------|---------------- + AVG | 0.62 | 0.90 | 1.11 + -------|--------------|----------------|---------------- + MAX | 1.16 | 1.39 | 1.54 + -------|--------------|----------------|---------------- + +***************************************************************************/ + +void vector_quantize_mlts(Word16 number_of_available_bits, + Word16 number_of_regions, + Word16 num_categorization_control_possibilities, + Word16 *mlt_coefs, + Word16 *absolute_region_power_index, + Word16 *power_categories, + Word16 *category_balances, + Word16 *p_categorization_control, + Word16 *region_mlt_bit_counts, + UWord32 *region_mlt_bits) +{ + + Word16 *raw_mlt_ptr; + Word16 region; + Word16 category; + Word16 total_mlt_bits = 0; + + Word16 temp; + Word16 temp1; + Word16 temp2; + + /* Start in the middle of the categorization control range. */ + temp = shr(num_categorization_control_possibilities,1); + temp = sub(temp,1); + for (*p_categorization_control = 0; *p_categorization_control < temp; (*p_categorization_control)++) + { + region = category_balances[*p_categorization_control]; + move16(); + power_categories[region] = add(power_categories[region],1); + move16(); + } + + for (region=0; region<number_of_regions; region++) + { + category = power_categories[region]; + move16(); + temp = extract_l(L_mult0(region,REGION_SIZE)); + raw_mlt_ptr = &mlt_coefs[temp]; + move16(); + temp = sub(category,(NUM_CATEGORIES-1)); + test(); + if (temp < 0) + { + region_mlt_bit_counts[region] = + vector_huffman(category, absolute_region_power_index[region],raw_mlt_ptr, + ®ion_mlt_bits[shl(region,2)]); + } + else + { + region_mlt_bit_counts[region] = 0; + move16(); + } + total_mlt_bits = add(total_mlt_bits,region_mlt_bit_counts[region]); + } + + + /* If too few bits... */ + temp = sub(total_mlt_bits,number_of_available_bits); + test(); + test(); + logic16(); + while ((temp < 0) && (*p_categorization_control > 0)) + { + test(); + test(); + logic16(); + (*p_categorization_control)--; + region = category_balances[*p_categorization_control]; + move16(); + + power_categories[region] = sub(power_categories[region],1); + move16(); + + total_mlt_bits = sub(total_mlt_bits,region_mlt_bit_counts[region]); + category = power_categories[region]; + move16(); + + raw_mlt_ptr = &mlt_coefs[region*REGION_SIZE]; + move16(); + + temp = sub(category,(NUM_CATEGORIES-1)); + test(); + if (temp < 0) + { + region_mlt_bit_counts[region] = + vector_huffman(category, absolute_region_power_index[region],raw_mlt_ptr, + ®ion_mlt_bits[shl(region,2)]); + } + else + { + region_mlt_bit_counts[region] = 0; + move16(); + } + total_mlt_bits = add(total_mlt_bits,region_mlt_bit_counts[region]); + temp = sub(total_mlt_bits,number_of_available_bits); + } + + /* If too many bits... */ + /* Set up for while loop test */ + temp1 = sub(total_mlt_bits,number_of_available_bits); + temp2 = sub(*p_categorization_control,sub(num_categorization_control_possibilities,1)); + test(); + test(); + logic16(); + + while ((temp1 > 0) && (temp2 < 0)) + { + /* operations for while contitions */ + test(); + test(); + logic16(); + + region = category_balances[*p_categorization_control]; + move16(); + + power_categories[region] = add(power_categories[region],1); + move16(); + + total_mlt_bits = sub(total_mlt_bits,region_mlt_bit_counts[region]); + category = power_categories[region]; + move16(); + + temp = extract_l(L_mult0(region,REGION_SIZE)); + raw_mlt_ptr = &mlt_coefs[temp]; + move16(); + + temp = sub(category,(NUM_CATEGORIES-1)); + test(); + if (temp < 0) + { + region_mlt_bit_counts[region] = + vector_huffman(category, absolute_region_power_index[region],raw_mlt_ptr, + ®ion_mlt_bits[shl(region,2)]); + } + else + { + region_mlt_bit_counts[region] = 0; + move16(); + } + total_mlt_bits = add(total_mlt_bits,region_mlt_bit_counts[region]); + (*p_categorization_control)++; + + temp1 = sub(total_mlt_bits,number_of_available_bits); + temp2 = sub(*p_categorization_control,sub(num_categorization_control_possibilities,1)); + } +} + +/*************************************************************************** + Function: vector_huffman + + Syntax: Word16 vector_huffman(Word16 category, + Word16 power_index, + Word16 *raw_mlt_ptr, + UWord32 *word_ptr) + + inputs: Word16 category + Word16 power_index + Word16 *raw_mlt_ptr + + outputs: number_of_region_bits + *word_ptr + + + Description: Huffman encoding for each region based on category and power_index + + WMOPS: 7kHz | 24kbit | 32kbit + -------|--------------|---------------- + AVG | 0.03 | 0.03 + -------|--------------|---------------- + MAX | 0.04 | 0.04 + -------|--------------|---------------- + + 14kHz | 24kbit | 32kbit | 48kbit + -------|--------------|----------------|---------------- + AVG | 0.03 | 0.03 | 0.03 + -------|--------------|----------------|---------------- + MAX | 0.04 | 0.04 | 0.04 + -------|--------------|----------------|---------------- + +***************************************************************************/ +Word16 vector_huffman(Word16 category, + Word16 power_index, + Word16 *raw_mlt_ptr, + UWord32 *word_ptr) +{ + + + Word16 inv_of_step_size_times_std_dev; + Word16 j,n; + Word16 k; + Word16 number_of_region_bits; + Word16 number_of_non_zero; + Word16 vec_dim; + Word16 num_vecs; + Word16 kmax, kmax_plus_one; + Word16 index,signs_index; + Word16 *bitcount_table_ptr; + UWord16 *code_table_ptr; + Word32 code_bits; + Word16 number_of_code_bits; + UWord32 current_word; + Word16 current_word_bits_free; + + Word32 acca; + Word32 accb; + Word16 temp; + + Word16 mytemp; /* new variable in Release 1.2 */ + Word16 myacca; /* new variable in Release 1.2 */ + + + /* initialize variables */ + vec_dim = vector_dimension[category]; + move16(); + + num_vecs = number_of_vectors[category]; + move16(); + + kmax = max_bin[category]; + move16(); + + kmax_plus_one = add(kmax,1); + move16(); + + current_word = 0L; + move16(); + + current_word_bits_free = 32; + move16(); + + number_of_region_bits = 0; + move16(); + + /* set up table pointers */ + bitcount_table_ptr = (Word16 *)table_of_bitcount_tables[category]; + code_table_ptr = (UWord16 *) table_of_code_tables[category]; + + /* compute inverse of step size * standard deviation */ + acca = L_mult(step_size_inverse_table[category],standard_deviation_inverse_table[power_index]); + acca = L_shr(acca,1); + acca = L_add(acca,4096); + acca = L_shr(acca,13); + + /* + * The next two lines are new to Release 1.2 + */ + + mytemp = acca & 0x3; + acca = L_shr(acca,2); + + inv_of_step_size_times_std_dev = extract_l(acca); + + + for (n=0; n<num_vecs; n++) + { + index = 0; + move16(); + + signs_index = 0; + move16(); + + number_of_non_zero = 0; + move16(); + + for (j=0; j<vec_dim; j++) + { + k = abs_s(*raw_mlt_ptr); + + acca = L_mult(k,inv_of_step_size_times_std_dev); + acca = L_shr(acca,1); + + /* + * The next four lines are new to Release 1.2 + */ + + myacca = (Word16)L_mult(k,mytemp); + myacca = (Word16)L_shr(myacca,1); + myacca = (Word16)L_add(myacca,int_dead_zone_low_bits[category]); + myacca = (Word16)L_shr(myacca,2); + + acca = L_add(acca,int_dead_zone[category]); + + /* + * The next two lines are new to Release 1.2 + */ + + acca = L_add(acca,myacca); + acca = L_shr(acca,13); + + k = extract_l(acca); + + test(); + if (k != 0) + { + number_of_non_zero = add(number_of_non_zero,1); + signs_index = shl(signs_index,1); + + test(); + if (*raw_mlt_ptr > 0) + { + signs_index = add(signs_index,1); + } + + temp = sub(k,kmax); + test(); + if (temp > 0) + { + k = kmax; + move16(); + } + } + acca = L_shr(L_mult(index,(kmax_plus_one)),1); + index = extract_l(acca); + index = add(index,k); + raw_mlt_ptr++; + } + + code_bits = *(code_table_ptr+index); + number_of_code_bits = add((*(bitcount_table_ptr+index)),number_of_non_zero); + number_of_region_bits = add(number_of_region_bits,number_of_code_bits); + + acca = code_bits << number_of_non_zero; + accb = L_deposit_l(signs_index); + acca = L_add(acca,accb); + code_bits = acca; + move32(); + + /* msb of codebits is transmitted first. */ + j = sub(current_word_bits_free,number_of_code_bits); + test(); + if (j >= 0) + { + test(); + acca = code_bits << j; + current_word = L_add(current_word,acca); + current_word_bits_free = j; + move16(); + } + else + { + j = negate(j); + acca = L_shr(code_bits,j); + current_word = L_add(current_word,acca); + + *word_ptr++ = current_word; + move16(); + + current_word_bits_free = sub(32,j); + test(); + current_word = code_bits << current_word_bits_free; + } + } + + *word_ptr++ = current_word; + move16(); + + return (number_of_region_bits); +} + + diff --git a/third_party/g7221/encode/sam2coef.c b/third_party/g7221/encode/sam2coef.c new file mode 100644 index 00000000..08ee0e11 --- /dev/null +++ b/third_party/g7221/encode/sam2coef.c @@ -0,0 +1,270 @@ +/****************************************************************************** +** +** 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: samples_to_rmlt_coefs.c +* +* Purpose: Convert Samples to Reversed MLT (Modulated Lapped Transform) +* Coefficients +* +* The "Reversed MLT" is an overlapped block transform which uses +* even symmetry * on the left, odd symmetry on the right and a +* Type IV DCT as the block transform. * It is thus similar to a +* MLT which uses odd symmetry on the left, even symmetry * on the +* right and a Type IV DST as the block transform. In fact, it is +* equivalent * to reversing the order of the samples, performing +* an MLT and then negating all * the even-numbered coefficients. +* +******************************************************************************/ + +/*************************************************************************** + Include files +***************************************************************************/ +#include "defs.h" +#include "tables.h" +#include "count.h" + +/*************************************************************************** + Function: samples_to_rmlt_coefs + + Syntax: Word16 samples_to_rmlt_coefs(new_samples, + old_samples, + coefs, + dct_length) + Word16 *new_samples; + Word16 *old_samples; + Word16 *coefs; + Word16 dct_length; + + Description: Convert samples to MLT coefficients + + Design Notes: + + WMOPS: 7kHz | 24kbit | 32kbit + -------|--------------|---------------- + AVG | 1.40 | 1.40 + -------|--------------|---------------- + MAX | 1.40 | 1.40 + -------|--------------|---------------- + + 14kHz | 24kbit | 32kbit | 48kbit + -------|--------------|----------------|---------------- + AVG | 3.07 | 3.07 | 3.07 + -------|--------------|----------------|---------------- + MAX | 3.10 | 3.10 | 3.10 + -------|--------------|----------------|---------------- + +***************************************************************************/ + +Word16 samples_to_rmlt_coefs(Word16 *new_samples,Word16 *old_samples,Word16 *coefs,Word16 dct_length) +{ + + Word16 index, vals_left,mag_shift,n; + Word16 windowed_data[MAX_DCT_LENGTH]; + Word16 *new_ptr, *old_ptr, *sam_low, *sam_high; + Word16 *win_low, *win_high; + Word16 *dst_ptr; + Word16 neg_win_low; + Word16 samp_high; + Word16 half_dct_size; + + Word32 acca; + Word32 accb; + Word16 temp; + Word16 temp1; + Word16 temp2; + Word16 temp5; + + half_dct_size = shr(dct_length,1); + + /*++++++++++++++++++++++++++++++++++++++++++++*/ + /* Get the first half of the windowed samples */ + /*++++++++++++++++++++++++++++++++++++++++++++*/ + + dst_ptr = windowed_data; + move16(); + + /* address arithmetic */ + test(); + if (dct_length==DCT_LENGTH) + { + win_high = samples_to_rmlt_window + half_dct_size; + } + else + { + win_high = max_samples_to_rmlt_window + half_dct_size; + } + + win_low = win_high; + move16(); + + /* address arithmetic */ + sam_high = old_samples + half_dct_size; + + sam_low = sam_high; + move16(); + + for (vals_left = half_dct_size;vals_left > 0;vals_left--) + { + acca = 0L; + move32(); + + acca = L_mac(acca,*--win_low, *--sam_low); + acca = L_mac(acca,*win_high++, *sam_high++); + temp = round(acca); + + *dst_ptr++ = temp; + move16(); + } + + /*+++++++++++++++++++++++++++++++++++++++++++++*/ + /* Get the second half of the windowed samples */ + /*+++++++++++++++++++++++++++++++++++++++++++++*/ + + sam_low = new_samples; + move16(); + + /* address arithmetic */ + sam_high = new_samples + dct_length; + + for (vals_left = half_dct_size; vals_left > 0; vals_left--) + { + acca = 0L; + move32(); + + acca = L_mac(acca,*--win_high, *sam_low++); + neg_win_low = negate(*win_low++); + samp_high = *--sam_high; + acca = L_mac(acca, neg_win_low, samp_high); + temp = round(acca); + + *dst_ptr++=temp; + move16(); + } + + /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ + /* Save the new samples for next time, when they will be the old samples */ + /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ + + new_ptr = new_samples; + move16(); + + old_ptr = old_samples; + move16(); + + for (vals_left = dct_length;vals_left > 0;vals_left--) + { + *old_ptr++ = *new_ptr++; + move16(); + } + + /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ + /* Calculate how many bits to shift up the input to the DCT. */ + /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ + + temp1=0; + move16(); + + for(index=0;index<dct_length;index++) + { + temp2 = abs_s(windowed_data[index]); + temp = sub(temp2,temp1); + test(); + if(temp > 0) + { + move16(); + temp1 = temp2; + } + } + + mag_shift=0; + move16(); + + temp = sub(temp1,14000); + test(); + if (temp >= 0) + { + mag_shift = 0; + move16(); + } + else + { + temp = sub(temp1,438); + test(); + if(temp < 0) + temp = add(temp1,1); + else + { + temp = temp1; + move16(); + } + accb = L_mult(temp,9587); + acca = L_shr(accb,20); + temp5 = extract_l(acca); + temp = norm_s(temp5); + test(); + if (temp == 0) + { + mag_shift = 9; + move16(); + } + else + mag_shift = sub(temp,6); + + } + + acca = 0L; + move32(); + for(index=0; index<dct_length; index++) + { + temp = abs_s( windowed_data[index]); + acca = L_add(acca,temp); + } + + acca = L_shr(acca,7); + + test(); + if (temp1 < acca) + { + mag_shift = sub(mag_shift,1); + } + + test(); + if (mag_shift > 0) + { + for(index=0;index<dct_length;index++) + { + windowed_data[index] = shl(windowed_data[index],mag_shift); + } + } + else + { + test(); + if (mag_shift < 0) + { + n = negate(mag_shift); + for(index=0;index<dct_length;index++) + { + windowed_data[index] = shr(windowed_data[index],n); + move16(); + } + } + } + + /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ + /* Perform a Type IV DCT on the windowed data to get the coefficients */ + /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ + + dct_type_iv_a(windowed_data, coefs, dct_length); + + return(mag_shift); +} |