798 lines
18 KiB
C
Executable File
798 lines
18 KiB
C
Executable File
/*
|
|
* ===================================================================
|
|
* TS 26.104
|
|
* REL-5 V5.4.0 2004-03
|
|
* REL-6 V6.1.0 2004-03
|
|
* 3GPP AMR Floating-point Speech Codec
|
|
* ===================================================================
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* interf_enc.c
|
|
*
|
|
*
|
|
* Project:
|
|
* AMR Floating-Point Codec
|
|
*
|
|
* Contains:
|
|
* This module contains all the functions needed encoding 160
|
|
* 16-bit speech samples to AMR encoder parameters.
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* include files
|
|
*/
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <memory.h>
|
|
#include "sp_enc.h"
|
|
#include "interf_rom.h"
|
|
|
|
/*
|
|
* Declare structure types
|
|
*/
|
|
/* Declaration transmitted frame types */
|
|
enum TXFrameType { TX_SPEECH_GOOD = 0,
|
|
TX_SID_FIRST,
|
|
TX_SID_UPDATE,
|
|
TX_NO_DATA,
|
|
TX_SPEECH_DEGRADED,
|
|
TX_SPEECH_BAD,
|
|
TX_SID_BAD,
|
|
TX_ONSET,
|
|
TX_N_FRAMETYPES /* number of frame types */
|
|
};
|
|
|
|
/* Declaration of interface structure */
|
|
typedef struct
|
|
{
|
|
Word16 sid_update_counter; /* Number of frames since last SID */
|
|
Word16 sid_handover_debt; /* Number of extra SID_UPD frames to schedule */
|
|
Word32 dtx;
|
|
enum TXFrameType prev_ft; /* Type of the previous frame */
|
|
void *encoderState; /* Points encoder state structure */
|
|
} enc_interface_State;
|
|
|
|
|
|
#ifdef ETSI
|
|
/*
|
|
* Prm2Bits
|
|
*
|
|
*
|
|
* Parameters:
|
|
* value I: value to be converted to binary
|
|
* no_of_bits I: number of bits associated with value
|
|
* bitstream O: address where bits are written
|
|
*
|
|
* Function:
|
|
* Convert integer to binary and write the bits to the array.
|
|
* The most significant bits are written first.
|
|
* Returns:
|
|
* void
|
|
*/
|
|
static void Int2Bin( Word16 value, Word16 no_of_bits, Word16 *bitstream )
|
|
{
|
|
Word32 i, bit;
|
|
Word16 *pt_bitstream;
|
|
|
|
pt_bitstream = &bitstream[no_of_bits];
|
|
|
|
for ( i = 0; i < no_of_bits; i++ ) {
|
|
bit = value & 0x0001;
|
|
|
|
if ( bit == 0 ) {
|
|
* --pt_bitstream = 0;
|
|
}
|
|
else {
|
|
* --pt_bitstream = 1;
|
|
}
|
|
value = ( Word16 )( value >> 1 );
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* Prm2Bits
|
|
*
|
|
*
|
|
* Parameters:
|
|
* mode I: AMR mode
|
|
* prm I: analysis parameters
|
|
* bits O: serial bits
|
|
*
|
|
* Function:
|
|
* converts the encoder parameter vector into a vector of serial bits.
|
|
* Returns:
|
|
* void
|
|
*/
|
|
static void Prm2Bits( enum Mode mode, Word16 prm[], Word16 bits[] )
|
|
{
|
|
Word32 i;
|
|
|
|
switch ( mode ) {
|
|
case MR122:
|
|
for ( i = 0; i < PRMNO_MR122; i++ ) {
|
|
Int2Bin( prm[i], bitno_MR122[i], bits );
|
|
bits += bitno_MR122[i];
|
|
}
|
|
break;
|
|
|
|
case MR102:
|
|
for ( i = 0; i < PRMNO_MR102; i++ ) {
|
|
Int2Bin( prm[i], bitno_MR102[i], bits );
|
|
bits += bitno_MR102[i];
|
|
}
|
|
break;
|
|
|
|
case MR795:
|
|
for ( i = 0; i < PRMNO_MR795; i++ ) {
|
|
Int2Bin( prm[i], bitno_MR795[i], bits );
|
|
bits += bitno_MR795[i];
|
|
}
|
|
break;
|
|
|
|
case MR74:
|
|
for ( i = 0; i < PRMNO_MR74; i++ ) {
|
|
Int2Bin( prm[i], bitno_MR74[i], bits );
|
|
bits += bitno_MR74[i];
|
|
}
|
|
break;
|
|
|
|
case MR67:
|
|
for ( i = 0; i < PRMNO_MR67; i++ ) {
|
|
Int2Bin( prm[i], bitno_MR67[i], bits );
|
|
bits += bitno_MR67[i];
|
|
}
|
|
break;
|
|
|
|
case MR59:
|
|
for ( i = 0; i < PRMNO_MR59; i++ ) {
|
|
Int2Bin( prm[i], bitno_MR59[i], bits );
|
|
bits += bitno_MR59[i];
|
|
}
|
|
break;
|
|
|
|
case MR515:
|
|
for ( i = 0; i < PRMNO_MR515; i++ ) {
|
|
Int2Bin( prm[i], bitno_MR515[i], bits );
|
|
bits += bitno_MR515[i];
|
|
}
|
|
break;
|
|
|
|
case MR475:
|
|
for ( i = 0; i < PRMNO_MR475; i++ ) {
|
|
Int2Bin( prm[i], bitno_MR475[i], bits );
|
|
bits += bitno_MR475[i];
|
|
}
|
|
break;
|
|
|
|
case MRDTX:
|
|
for ( i = 0; i < PRMNO_MRDTX; i++ ) {
|
|
Int2Bin( prm[i], bitno_MRDTX[i], bits );
|
|
bits += bitno_MRDTX[i];
|
|
}
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
|
|
#else
|
|
|
|
#ifndef IF2
|
|
|
|
/*
|
|
* EncoderMMS
|
|
*
|
|
*
|
|
* Parameters:
|
|
* mode I: AMR mode
|
|
* param I: Encoder output parameters
|
|
* stream O: packed speech frame
|
|
* frame_type I: frame type (DTX)
|
|
* speech_mode I: speech mode (DTX)
|
|
*
|
|
* Function:
|
|
* Pack encoder output parameters to octet structure according
|
|
* importance table and AMR file storage format according to
|
|
* RFC 3267.
|
|
* Returns:
|
|
* number of octets
|
|
*/
|
|
static int EncoderMMS( enum Mode mode, Word16 *param, UWord8 *stream, enum
|
|
TXFrameType frame_type, enum Mode speech_mode )
|
|
{
|
|
Word32 j = 0, k;
|
|
Word16 *mask;
|
|
|
|
memset(stream, 0, block_size[mode]);
|
|
|
|
*stream = toc_byte[mode];
|
|
stream++;
|
|
|
|
if ( mode == 15 ) {
|
|
return 1;
|
|
}
|
|
else if ( mode == MRDTX ) {
|
|
mask = order_MRDTX;
|
|
|
|
for ( j = 1; j < 36; j++ ) {
|
|
if ( param[ * mask] & *( mask + 1 ) )
|
|
*stream += 0x01;
|
|
mask += 2;
|
|
|
|
if ( j % 8 )
|
|
*stream <<= 1;
|
|
else
|
|
stream++;
|
|
}
|
|
|
|
/* add SID type information */
|
|
if ( frame_type == TX_SID_UPDATE )
|
|
*stream += 0x01;
|
|
*stream <<= 3;
|
|
|
|
/* speech mode indication */
|
|
*stream += ( unsigned char )(speech_mode & 0x0007);
|
|
|
|
*stream <<= 1;
|
|
|
|
/* don't shift at the end of the function */
|
|
return 6;
|
|
}
|
|
else if ( mode == MR475 ) {
|
|
mask = order_MR475;
|
|
|
|
for ( j = 1; j < 96; j++ ) {
|
|
if ( param[ * mask] & *( mask + 1 ) )
|
|
*stream += 0x01;
|
|
mask += 2;
|
|
|
|
if ( j % 8 )
|
|
*stream <<= 1;
|
|
else
|
|
stream++;
|
|
}
|
|
}
|
|
else if ( mode == MR515 ) {
|
|
mask = order_MR515;
|
|
|
|
for ( j = 1; j < 104; j++ ) {
|
|
if ( param[ * mask] & *( mask + 1 ) )
|
|
*stream += 0x01;
|
|
mask += 2;
|
|
|
|
if ( j % 8 )
|
|
*stream <<= 1;
|
|
else
|
|
stream++;
|
|
}
|
|
}
|
|
else if ( mode == MR59 ) {
|
|
mask = order_MR59;
|
|
|
|
for ( j = 1; j < 119; j++ ) {
|
|
if ( param[ * mask] & *( mask + 1 ) )
|
|
*stream += 0x01;
|
|
mask += 2;
|
|
|
|
if ( j % 8 )
|
|
*stream <<= 1;
|
|
else
|
|
stream++;
|
|
}
|
|
}
|
|
else if ( mode == MR67 ) {
|
|
mask = order_MR67;
|
|
|
|
for ( j = 1; j < 135; j++ ) {
|
|
if ( param[ * mask] & *( mask + 1 ) )
|
|
*stream += 0x01;
|
|
mask += 2;
|
|
|
|
if ( j % 8 )
|
|
*stream <<= 1;
|
|
else
|
|
stream++;
|
|
}
|
|
}
|
|
else if ( mode == MR74 ) {
|
|
mask = order_MR74;
|
|
|
|
for ( j = 1; j < 149; j++ ) {
|
|
if ( param[ * mask] & *( mask + 1 ) )
|
|
*stream += 0x01;
|
|
mask += 2;
|
|
|
|
if ( j % 8 )
|
|
*stream <<= 1;
|
|
else
|
|
stream++;
|
|
}
|
|
}
|
|
else if ( mode == MR795 ) {
|
|
mask = order_MR795;
|
|
|
|
for ( j = 1; j < 160; j++ ) {
|
|
if ( param[ * mask] & *( mask + 1 ) )
|
|
*stream += 0x01;
|
|
mask += 2;
|
|
|
|
if ( j % 8 )
|
|
*stream <<= 1;
|
|
else
|
|
stream++;
|
|
}
|
|
}
|
|
else if ( mode == MR102 ) {
|
|
mask = order_MR102;
|
|
|
|
for ( j = 1; j < 205; j++ ) {
|
|
if ( param[ * mask] & *( mask + 1 ) )
|
|
*stream += 0x01;
|
|
mask += 2;
|
|
|
|
if ( j % 8 )
|
|
*stream <<= 1;
|
|
else
|
|
stream++;
|
|
}
|
|
}
|
|
else if ( mode == MR122 ) {
|
|
mask = order_MR122;
|
|
|
|
for ( j = 1; j < 245; j++ ) {
|
|
if ( param[ * mask] & *( mask + 1 ) )
|
|
*stream += 0x01;
|
|
mask += 2;
|
|
|
|
if ( j % 8 )
|
|
*stream <<= 1;
|
|
else
|
|
stream++;
|
|
}
|
|
}
|
|
|
|
/* shift remaining bits */
|
|
if ( k = j % 8 ) *stream <<= ( 8 - k );
|
|
return( (int)block_size[mode] );
|
|
}
|
|
|
|
#else
|
|
|
|
/*
|
|
* Encoder3GPP
|
|
*
|
|
*
|
|
* Parameters:
|
|
* mode I: AMR mode
|
|
* param I: Encoder output parameters
|
|
* stream O: packed speech frame
|
|
* frame_type I: frame type (DTX)
|
|
* speech_mode I: speech mode (DTX)
|
|
*
|
|
* Function:
|
|
* Pack encoder output parameters to octet structure according
|
|
* importance table.
|
|
* Returns:
|
|
* number of octets
|
|
*/
|
|
static int Encoder3GPP( enum Mode mode, Word16 *param, UWord8 *stream, enum
|
|
TXFrameType frame_type, enum Mode speech_mode )
|
|
{
|
|
Word32 j = 0;
|
|
Word16 *mask;
|
|
|
|
memset(stream, 0, block_size[mode]);
|
|
|
|
if ( mode == 15 ) {
|
|
*stream = 0xF;
|
|
return 1;
|
|
}
|
|
else if ( mode == MRDTX ) {
|
|
mask = order_MRDTX;
|
|
*stream = 0x40;
|
|
|
|
for ( j = 5; j < 40; j++ ) {
|
|
if ( param[ * mask] & *( mask + 1 ) )
|
|
*stream += 0x80;
|
|
mask += 2;
|
|
|
|
if ( j % 8 )
|
|
*stream >>= 1;
|
|
else
|
|
stream++;
|
|
}
|
|
|
|
/* add SID type information */
|
|
if ( frame_type == TX_SID_UPDATE )
|
|
*stream += 0x80;
|
|
stream++;
|
|
|
|
/* speech mode indication */
|
|
*stream = ( unsigned char )speech_mode;
|
|
|
|
/* don't shift at the end of the function */
|
|
return 6;
|
|
}
|
|
else if ( mode == MR475 ) {
|
|
mask = order_MR475;
|
|
*stream = 0;
|
|
|
|
for ( j = 5; j < 100; j++ ) {
|
|
if ( param[ * mask] & *( mask + 1 ) )
|
|
*stream += 0x80;
|
|
mask += 2;
|
|
|
|
if ( j % 8 )
|
|
*stream >>= 1;
|
|
else
|
|
stream++;
|
|
}
|
|
}
|
|
else if ( mode == MR515 ) {
|
|
mask = order_MR515;
|
|
*stream = 0x8;
|
|
|
|
for ( j = 5; j < 108; j++ ) {
|
|
if ( param[ * mask] & *( mask + 1 ) )
|
|
*stream += 0x80;
|
|
mask += 2;
|
|
|
|
if ( j % 8 )
|
|
*stream >>= 1;
|
|
else
|
|
stream++;
|
|
}
|
|
}
|
|
else if ( mode == MR59 ) {
|
|
mask = order_MR59;
|
|
*stream = 0x10;
|
|
|
|
for ( j = 5; j < 123; j++ ) {
|
|
if ( param[ * mask] & *( mask + 1 ) )
|
|
*stream += 0x80;
|
|
mask += 2;
|
|
|
|
if ( j % 8 )
|
|
*stream >>= 1;
|
|
else
|
|
stream++;
|
|
}
|
|
}
|
|
else if ( mode == MR67 ) {
|
|
mask = order_MR67;
|
|
*stream = 0x18;
|
|
|
|
for ( j = 5; j < 139; j++ ) {
|
|
if ( param[ * mask] & *( mask + 1 ) )
|
|
*stream += 0x80;
|
|
mask += 2;
|
|
|
|
if ( j % 8 )
|
|
*stream >>= 1;
|
|
else
|
|
stream++;
|
|
}
|
|
}
|
|
else if ( mode == MR74 ) {
|
|
mask = order_MR74;
|
|
*stream = 0x20;
|
|
|
|
for ( j = 5; j < 153; j++ ) {
|
|
if ( param[ * mask] & *( mask + 1 ) )
|
|
*stream += 0x80;
|
|
mask += 2;
|
|
|
|
if ( j % 8 )
|
|
*stream >>= 1;
|
|
else
|
|
stream++;
|
|
}
|
|
}
|
|
else if ( mode == MR795 ) {
|
|
mask = order_MR795;
|
|
*stream = 0x28;
|
|
|
|
for ( j = 5; j < 164; j++ ) {
|
|
if ( param[ * mask] & *( mask + 1 ) )
|
|
*stream += 0x80;
|
|
mask += 2;
|
|
|
|
if ( j % 8 )
|
|
*stream >>= 1;
|
|
else
|
|
stream++;
|
|
}
|
|
}
|
|
else if ( mode == MR102 ) {
|
|
mask = order_MR102;
|
|
*stream = 0x30;
|
|
|
|
for ( j = 5; j < 209; j++ ) {
|
|
if ( param[ * mask] & *( mask + 1 ) )
|
|
*stream += 0x80;
|
|
mask += 2;
|
|
|
|
if ( j % 8 )
|
|
*stream >>= 1;
|
|
else
|
|
stream++;
|
|
}
|
|
}
|
|
else if ( mode == MR122 ) {
|
|
mask = order_MR122;
|
|
*stream = 0x38;
|
|
|
|
for ( j = 5; j < 249; j++ ) {
|
|
if ( param[ * mask] & *( mask + 1 ) )
|
|
*stream += 0x80;
|
|
mask += 2;
|
|
|
|
if ( j % 8 )
|
|
*stream >>= 1;
|
|
else
|
|
stream++;
|
|
}
|
|
}
|
|
|
|
/* shift remaining bits */
|
|
*stream >>= ( 8 - j % 8 );
|
|
return( (int)block_size[mode] );
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
/*
|
|
* Sid_Sync_reset
|
|
*
|
|
*
|
|
* Parameters:
|
|
* st O: state structure
|
|
*
|
|
* Function:
|
|
* Initializes state memory
|
|
*
|
|
* Returns:
|
|
* void
|
|
*/
|
|
static void Sid_Sync_reset( enc_interface_State *st )
|
|
{
|
|
st->sid_update_counter = 3;
|
|
st->sid_handover_debt = 0;
|
|
st->prev_ft = TX_SPEECH_GOOD;
|
|
}
|
|
|
|
|
|
/*
|
|
* Encoder_Interface_Encode
|
|
*
|
|
*
|
|
* Parameters:
|
|
* st I: pointer to state structure
|
|
* mode I: Speech Mode
|
|
* speech I: Input speech
|
|
* serial O: Output octet structure 3GPP or
|
|
* ETSI serial stream
|
|
* force_speech I: Force speech in DTX
|
|
*
|
|
* Function:
|
|
* Encoding and packing one frame of speech
|
|
*
|
|
* Returns:
|
|
* number of octets
|
|
*/
|
|
int Encoder_Interface_Encode( void *st, enum Mode mode, Word16 *speech,
|
|
|
|
#ifndef ETSI
|
|
UWord8 *serial,
|
|
|
|
#else
|
|
Word16 *serial,
|
|
#endif
|
|
|
|
int force_speech )
|
|
{
|
|
Word16 prm[PRMNO_MR122]; /* speech parameters, max size */
|
|
const Word16 *homing; /* pointer to homing frame */
|
|
Word16 homing_size; /* frame size for homing frame */
|
|
|
|
|
|
enc_interface_State * s;
|
|
enum TXFrameType txFrameType; /* frame type */
|
|
|
|
int i, noHoming = 0;
|
|
|
|
|
|
/*
|
|
* used encoder mode,
|
|
* if used_mode == -1, force VAD on
|
|
*/
|
|
enum Mode used_mode = -force_speech;
|
|
|
|
|
|
s = ( enc_interface_State * )st;
|
|
|
|
/*
|
|
* Checks if all samples of the input frame matches the encoder
|
|
* homing frame pattern, which is 0x0008 for all samples.
|
|
*/
|
|
for ( i = 0; i < 160; i++ ) {
|
|
noHoming = speech[i] ^ 0x0008;
|
|
|
|
if ( noHoming )
|
|
break;
|
|
}
|
|
|
|
if (noHoming){
|
|
Speech_Encode_Frame( s->encoderState, mode, speech, prm, &used_mode );
|
|
}
|
|
else {
|
|
switch ( mode ) {
|
|
case MR122:
|
|
homing = dhf_MR122;
|
|
homing_size = 18;
|
|
break;
|
|
|
|
case MR102:
|
|
homing = dhf_MR102;
|
|
homing_size = 12;
|
|
break;
|
|
|
|
case MR795:
|
|
homing = dhf_MR795;
|
|
homing_size = 8;
|
|
break;
|
|
|
|
case MR74:
|
|
homing = dhf_MR74;
|
|
homing_size = 7;
|
|
break;
|
|
|
|
case MR67:
|
|
homing = dhf_MR67;
|
|
homing_size = 7;
|
|
break;
|
|
|
|
case MR59:
|
|
homing = dhf_MR59;
|
|
homing_size = 7;
|
|
break;
|
|
|
|
case MR515:
|
|
homing = dhf_MR515;
|
|
homing_size = 7;
|
|
break;
|
|
|
|
case MR475:
|
|
homing = dhf_MR475;
|
|
homing_size = 7;
|
|
break;
|
|
|
|
default:
|
|
homing = NULL;
|
|
homing_size = 0;
|
|
break;
|
|
}
|
|
for( i = 0; i < homing_size; i++){
|
|
prm[i] = homing[i];
|
|
}
|
|
/* rest of the parameters are zero */
|
|
memset(&prm[homing_size], 0, (PRMNO_MR122 - homing_size) << 1);
|
|
used_mode = mode;
|
|
}
|
|
if ( used_mode == MRDTX ) {
|
|
s->sid_update_counter--;
|
|
|
|
if ( s->prev_ft == TX_SPEECH_GOOD ) {
|
|
txFrameType = TX_SID_FIRST;
|
|
s->sid_update_counter = 3;
|
|
}
|
|
else {
|
|
/* TX_SID_UPDATE or TX_NO_DATA */
|
|
if ( ( s->sid_handover_debt > 0 ) && ( s->sid_update_counter > 2 ) ) {
|
|
/*
|
|
* ensure extra updates are properly delayed after
|
|
* a possible SID_FIRST
|
|
*/
|
|
txFrameType = TX_SID_UPDATE;
|
|
s->sid_handover_debt--;
|
|
}
|
|
else {
|
|
if ( s->sid_update_counter == 0 ) {
|
|
txFrameType = TX_SID_UPDATE;
|
|
s->sid_update_counter = 8;
|
|
}
|
|
else {
|
|
txFrameType = TX_NO_DATA;
|
|
used_mode = 15;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
s->sid_update_counter = 8;
|
|
txFrameType = TX_SPEECH_GOOD;
|
|
}
|
|
s->prev_ft = txFrameType;
|
|
|
|
if ( noHoming == 0 ) {
|
|
Speech_Encode_Frame_reset( s->encoderState, s->dtx );
|
|
Sid_Sync_reset( s );
|
|
}
|
|
|
|
#ifndef ETSI
|
|
#ifdef IF2
|
|
return Encoder3GPP( used_mode, prm, serial, txFrameType, mode );
|
|
|
|
#else
|
|
return EncoderMMS( used_mode, prm, serial, txFrameType, mode );
|
|
|
|
#endif
|
|
#else
|
|
|
|
Prm2Bits( used_mode, prm, &serial[1] );
|
|
serial[0] = ( Word16 )txFrameType;
|
|
serial[245] = ( Word16 )mode;
|
|
return 500;
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
* Encoder_Interface_init
|
|
*
|
|
*
|
|
* Parameters:
|
|
* dtx I: DTX flag
|
|
*
|
|
* Function:
|
|
* Allocates state memory and initializes state memory
|
|
*
|
|
* Returns:
|
|
* pointer to encoder interface structure
|
|
*/
|
|
void * Encoder_Interface_init( int dtx )
|
|
{
|
|
enc_interface_State * s;
|
|
|
|
/* allocate memory */
|
|
if ( ( s = ( enc_interface_State * ) malloc( sizeof( enc_interface_State ) ) ) ==
|
|
NULL ) {
|
|
fprintf( stderr, "Encoder_Interface_init: "
|
|
"can not malloc state structure\n" );
|
|
return NULL;
|
|
}
|
|
s->encoderState = Speech_Encode_Frame_init( dtx );
|
|
Sid_Sync_reset( s );
|
|
s->dtx = dtx;
|
|
return s;
|
|
}
|
|
|
|
|
|
/*
|
|
* DecoderInterfaceExit
|
|
*
|
|
*
|
|
* Parameters:
|
|
* state I: state structure
|
|
*
|
|
* Function:
|
|
* The memory used for state memory is freed
|
|
*
|
|
* Returns:
|
|
* Void
|
|
*/
|
|
void Encoder_Interface_exit( void *state )
|
|
{
|
|
enc_interface_State * s;
|
|
s = ( enc_interface_State * )state;
|
|
|
|
/* free memory */
|
|
Speech_Encode_Frame_exit( &s->encoderState );
|
|
free( s );
|
|
state = NULL;
|
|
}
|