package uk.co.mmscomputing.device.capi.sound;
import java.io.*;
public class PCMOutputStream extends FilterOutputStream{
/*
Convert mono PCM byte stream into ISDN 'raw' byte stream
PCM 8000.0 Hz, 16 bit, mono, SIGNED, little-endian
static AudioFormat pcmformat = new AudioFormat(8000,16,1,true,false);
*/
static private byte[] alawtable=new byte[65536];
static private byte[] ulawtable=new byte[65536];
private byte[] table=null;
public PCMOutputStream(OutputStream out, boolean useALaw)throws IOException{
super(out);
table=(useALaw)?alawtable:ulawtable;
}
public void write(int b)throws IOException{
throw new IOException(getClass().getName()+".write() :\n\tDo not support simple write(int b).");
}
public void write(byte[] b, int off, int len)throws IOException{
int sample;
len>>=1;
for(int i=0;i<len;i++){
sample = (b[off++]&0x00FF);
sample |= (b[off++]&0x00FF)<<8;
out.write(table[sample]);
}
}
/*
public void write(byte[] b, int off, int len)throws IOException{
byte[] outb;
int max,sample;
len>>=1;
outb=new byte[len];
for(int i=0;i<len;i++){
sample = (b[off++]&0x00FF);
sample |= (b[off++]&0x00FF)<<8;
outb[i]=table[sample];
}
out.write(outb);
}
*/
static{ // Build A-Law and mu-Law look up table.
byte[] inverse=new byte[256]; // swap bits 0x00->0x00, 0x01->0x80, 0x02->0x40 ... 0xFF->0xFF
int s=0;
for(int t=0;t<256;t++){
inverse[t]=(byte)s;
int u=256;
do{
u>>=1;
s^=u;
}while((s^u)>s);
}
ALawCompressor alawcompressor=new ALawCompressor();
uLawCompressor ulawcompressor=new uLawCompressor();
for(int sample=0;sample<65536;sample++){
alawtable[sample]=inverse[alawcompressor.compress((short)sample)&0x00FF];
ulawtable[sample]=inverse[ulawcompressor.compress((short)sample)&0x00FF];
}
}
}
/*
Mathematical Tools in Signal Processing with C++ and Java Simulations
by Willi-Hans Steeb
International School for Scientific Computing
*/
class ALawCompressor{
static final int cClip = 32635;
static final int[] ALawCompressTable ={
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
};
protected int compress(short sample){
int sign;
int exponent;
int mantissa;
int compressedByte;
sign = ((~sample) >> 8) & 0x80;
if(sign==0){ sample *= -1;}
if(sample > cClip){ sample = cClip; }
if(sample >= 256){
exponent = ALawCompressTable[(sample >> 8) & 0x007F];
mantissa = (sample >> (exponent + 3) ) & 0x0F;
compressedByte = 0x007F & ((exponent << 4) | mantissa);
}else{
compressedByte = 0x007F & (sample >> 4);
}
compressedByte ^= (sign ^ 0x55);
return compressedByte;
}
}
class uLawCompressor{
static final int cClip = 32635;
static final int cBias = 0x84;
int[] uLawCompressTable ={
0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
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,
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,
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
};
protected int compress(short sample){
int sign;
int exponent;
int mantissa;
int compressedByte;
sign = (sample >> 8) & 0x80;
if(sign!=0){ sample *= -1;}
if(sample > cClip){ sample = cClip; }
sample += cBias;
exponent = uLawCompressTable[(sample >> 7) & 0x00FF];
mantissa = (sample >> (exponent + 3)) & 0x0F;
compressedByte = ~(sign | (exponent << 4) | mantissa);
return compressedByte&0x000000FF;
}
}