/*
* Mobicents Media Gateway
*
* The source code contained in this file is in in the public domain.
* It can be used in any project or product without prior permission,
* license or royalty payments. There is NO WARRANTY OF ANY KIND,
* EXPRESS, IMPLIED OR STATUTORY, INCLUDING, WITHOUT LIMITATION,
* THE IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
* AND DATA ACCURACY. We do not warrant or make any representations
* regarding the use of the software or the results thereof, including
* but not limited to the correctness, accuracy, reliability or
* usefulness of the software.
*/
package org.mobicents.media.server.impl.dsp.audio.g711.alaw;
import org.mobicents.media.Buffer;
import org.mobicents.media.Format;
import org.mobicents.media.server.spi.dsp.Codec;
import org.mobicents.media.server.spi.dsp.SignalingProcessor;
/**
* Implements G.711 A-law compressor.
*
* @author Oleg Kulikov
*/
public class Encoder implements Codec {
private final static int cClip = 32635;
private static byte aLawCompressTable[] = new byte[]{
1, 1, 2, 2, 3, 3, 3, 3,
4, 4, 4, 4, 4, 4, 4, 4,
5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5,
6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6,
7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7
};
private byte[] temp = new byte[1200];
private SignalingProcessor dsp;
public void setProc(SignalingProcessor dsp) {
this.dsp = dsp;
}
/**
* (Non Java-doc)
*
* @see org.mobicents.media.server.impl.jmf.dsp.Codec#getSupportedFormat().
*/
public Format getSupportedInputFormat() {
return Codec.LINEAR_AUDIO;
}
/**
* (Non Java-doc)
*
* @see org.mobicents.media.server.impl.jmf.dsp.Codec#getSupportedFormats().
*/
public Format getSupportedOutputFormat() {
return Codec.PCMA;
}
/**
* (Non Java-doc)
*
* @see org.mobicents.media.server.impl.jmf.dsp.Codec#process(Buffer).
*/
public void process(Buffer buffer) {
int len = process((byte[]) buffer.getData(), buffer.getOffset(), buffer.getLength(), temp);
System.arraycopy(temp, 0, (byte[])buffer.getData(), 0, len);
buffer.setOffset(0);
buffer.setLength(len);
buffer.setFormat(PCMA);
}
private int process(byte[] src, int offset, int len, byte[] res) {
int j = offset;
int count = len / 2;
short sample = 0;
for (int i = 0; i < count; i++) {
sample = (short) (((src[j++] & 0xff) | (src[j++]) << 8));
res[i] = linearToALawSample(sample);
}
return count;
}
/**
* Perform compression using A-law.
*
* @param media the input uncompressed media
* @return the output compressed media.
*/
private byte[] process(byte[] media) {
byte[] compressed = new byte[media.length / 2];
int j = 0;
for (int i = 0; i < compressed.length; i++) {
short sample = (short) (((media[j++] & 0xff) | (media[j++]) << 8));
compressed[i] = linearToALawSample(sample);
}
return compressed;
}
/**
* Compress 16bit value to 8bit value
*
* @param sample 16-bit sample
* @return compressed 8-bit value.
*/
private byte linearToALawSample(short sample) {
int sign;
int exponent;
int mantissa;
int s;
sign = ((~sample) >> 8) & 0x80;
if (!(sign == 0x80)) {
sample = (short) -sample;
}
if (sample > cClip) {
sample = cClip;
}
if (sample >= 256) {
exponent = (int) aLawCompressTable[(sample >> 8) & 0x7F];
mantissa = (sample >> (exponent + 3)) & 0x0F;
s = (exponent << 4) | mantissa;
} else {
s = sample >> 4;
}
s ^= (sign ^ 0x55);
return (byte)s;
}
}