package org.mobicents.media.server.impl.dsp.audio.g729; import org.apache.log4j.Logger; import org.mobicents.media.Buffer; import org.mobicents.media.Format; import org.mobicents.media.server.impl.codec.g729.Bits; import org.mobicents.media.server.impl.codec.g729.DecLD8K; import org.mobicents.media.server.impl.codec.g729.LD8KConstants; import org.mobicents.media.server.impl.codec.g729.PParity; import org.mobicents.media.server.impl.codec.g729.IntegerPointer; import org.mobicents.media.server.impl.codec.g729.PostFil; import org.mobicents.media.server.impl.codec.g729.PostPro; import org.mobicents.media.server.impl.codec.g729.Util; import org.mobicents.media.server.spi.dsp.Codec; import org.mobicents.media.server.spi.dsp.SignalingProcessor; public class Decoder implements Codec { int frame = 0; CircularBuffer circular = new CircularBuffer(16000); float synth_buf[] = new float[LD8KConstants.L_FRAME + LD8KConstants.M]; /* Synthesis */ int synth; int parm[] = new int[LD8KConstants.PRM_SIZE + 1]; /* * Synthesis parameters + * BFI */ short serial[] = new short[LD8KConstants.SERIAL_SIZE]; /* Serial stream */ float Az_dec[] = new float[2 * LD8KConstants.MP1]; int ptr_Az; /* Decoded Az for post-filter */ IntegerPointer t0_first = new IntegerPointer(); float pst_out[] = new float[LD8KConstants.L_FRAME]; /* postfilter output */ int voicing; /* voicing for previous subframe */ IntegerPointer sf_voic = new IntegerPointer(0); /* voicing for subframe */ DecLD8K decLD = new DecLD8K(); PostFil postFil = new PostFil(); PostPro postPro = new PostPro(); private transient Logger logger = Logger.getLogger(Decoder.class); 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 Format getSupportedInputFormat() { return Codec.G729; } public Format getSupportedOutputFormat() { return Codec.LINEAR_AUDIO; } public Format[] getSupportedInputFormats(Format fmt) { Format[] formats = new Format[] { Codec.G729 }; return formats; } public Format[] getSupportedOutputFormats() { Format[] formats = new Format[] { Codec.LINEAR_AUDIO }; return formats; } public void process(Buffer buffer) { byte[] data = (byte[]) buffer.getData(); int offset = buffer.getOffset(); int length = buffer.getLength(); byte[] media = new byte[length - offset]; System.arraycopy(data, 0, media, 0, media.length); circular.addData(media); byte[] speechWindow = circular.getData(20); // Process two frames at time, 20ms byte[] resultBytes = null; if (speechWindow != null) { byte[] one = new byte[10]; byte[] two = new byte[10]; for (int q = 0; q < 10; q++) { one[q] = speechWindow[q]; two[q] = speechWindow[q + 10]; } one = process(one); two = process(two); if (one.length != two.length) throw new RuntimeException( "The two frames are not equal in size!"); resultBytes = new byte[one.length + two.length]; for (int q = 0; q < one.length; q++) { resultBytes[q] = one[q]; resultBytes[q + one.length] = two[q]; } } else resultBytes = new byte[0]; buffer.setData(resultBytes); buffer.setOffset(0); buffer.setFormat(Codec.LINEAR_AUDIO); buffer.setLength(resultBytes.length); } /** * Perform compression. * * @param input * media * @return compressed media. */ public byte[] process(byte[] media) { serial = Bits.fromRealBits(media); // serial = Util.byteArrayToShortArray(media); frame++; 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 Util.floatArrayToByteArray(pst_out, LD8KConstants.L_FRAME); } public void setProc(SignalingProcessor processor) { } }