pjsip-pjproject/third_party/g7221/encode/sam2coef.c

272 lines
7.6 KiB
C

/******************************************************************************
**
** 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(const 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 *old_ptr;
const Word16 *new_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_nocheck(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 = itu_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 = itu_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_nocheck(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_nocheck(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_nocheck(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_nocheck(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);
}