package org.red5.app.sip.codecs.g729;
import org.red5.app.sip.BufferUtils;
public class Decoder {
float[] synth_buf = new float[ LD8KConstants.L_FRAME + LD8KConstants.M ]; // Synthesis
float[] Az_dec = new float[ 2 * LD8KConstants.MP1 ];
float[] pst_out = new float[ LD8KConstants.L_FRAME ]; // postfilter output
short[] serial = new short[ LD8KConstants.SERIAL_SIZE ]; // Serial stream
int[] parm = new int[ LD8KConstants.PRM_SIZE + 1 ]; // Synth parameters BFI
int synth;
int ptr_Az; // Decoded Az for post-filter
int voicing; // voicing for previous subframe
IntegerPointer t0_first = new IntegerPointer();
IntegerPointer sf_voic = new IntegerPointer( 0 ); // voicing for subframe
DecLD8K decLD = new DecLD8K();
PostFil postFil = new PostFil();
PostPro postPro = new PostPro();
public Decoder() {
for ( int i = 0; i < LD8KConstants.M; i++ ) {
synth_buf[ i ] = (float) 0.0;
}
synth = 0 + LD8KConstants.M;
decLD.init_decod_ld8k();
postFil.init_post_filter();
postPro.init_post_process();
voicing = 60;
}
public void decode( byte[] bufferIn, float[] bufferOut ) {
int inOffset = 0;
int outOffset = 0;
int steps = bufferIn.length / LD8KConstants.L_ENC_FRAME;
for ( int i = 0; i < steps; i++ ) {
byte[] tempBufferIn = new byte[ LD8KConstants.L_ENC_FRAME ];
float[] tempBufferOut = new float[ LD8KConstants.L_FRAME ];
// Encode bufferIn
BufferUtils.byteBufferIndexedCopy( tempBufferIn, 0, bufferIn, inOffset, LD8KConstants.L_ENC_FRAME );
tempBufferOut = process( tempBufferIn );
// Copy decoded data to bufferOut
BufferUtils.floatBufferIndexedCopy( bufferOut, outOffset, tempBufferOut, 0, LD8KConstants.L_FRAME );
inOffset += LD8KConstants.L_ENC_FRAME;
outOffset += LD8KConstants.L_FRAME;
}
}
/**
* Perform compression.
*
* @param input
* media
* @return compressed media.
*/
private float[] process( byte[] media ) {
serial = Bits.fromRealBits( media );
// serial = Util.byteArrayToShortArray(media);
Bits.bits2prm_ld8k( serial, 2, parm, 1 );
/*
* the hardware detects frame erasures by checking if all bits are set
* to zero
*/
parm[ 0 ] = 0; /* No frame erasure */
for ( int i = 2; i < LD8KConstants.SERIAL_SIZE; i++ ) {
if ( serial[ i ] == 0 ) {
parm[ 0 ] = 1; /* frame erased */
}
}
/* check parity and put 1 in parm[4] if parity error */
parm[ 4 ] = PParity.check_parity_pitch( parm[ 3 ], parm[ 4 ] );
decLD.decod_ld8k( parm, 0, voicing, synth_buf, synth, Az_dec, t0_first ); /* Decoder */
/* Post-filter and decision on voicing parameter */
voicing = 0;
ptr_Az = 0;// Az_dec;
for ( int i = 0; i < LD8KConstants.L_FRAME; i += LD8KConstants.L_SUBFR ) {
postFil.post( t0_first.value, synth_buf, synth + i, Az_dec, ptr_Az, pst_out, i, sf_voic );
if ( sf_voic.value != 0 ) {
voicing = sf_voic.value;
}
ptr_Az += LD8KConstants.MP1;
}
Util.copy( synth_buf, LD8KConstants.L_FRAME, synth_buf, 0, LD8KConstants.M );
postPro.post_process( pst_out, LD8KConstants.L_FRAME );
return pst_out;
}
}