/*
* @(#)JavaEncoder.java 1.9 02/08/21
*
* Copyright 1996-1998 by Sun Microsystems, Inc.,
* 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
* All rights reserved.
*
* This software is the confidential and proprietary information
* of Sun Microsystems, Inc. ("Confidential Information"). You
* shall not disclose such Confidential Information and shall use
* it only in accordance with the terms of the license agreement
* you entered into with Sun.
*/
package com.ibm.media.codec.audio.ima4;
import javax.media.*;
import javax.media.format.*;
import javax.media.format.*;
import com.sun.media.*;
public class JavaEncoder extends com.ibm.media.codec.audio.BufferedEncoder {
////////////////////////////////////////////////////////////////////////////
// Variables
////////////////////////////////////////////////////////////////////////////
// state of the ima4 decoder
private IMA4State ima4stateL,ima4stateR;
////////////////////////////////////////////////////////////////////////////
// Methods
public JavaEncoder() {
supportedInputFormats = new AudioFormat[] { new AudioFormat(
AudioFormat.LINEAR,
AudioFormat.NOT_SPECIFIED,
16,
AudioFormat.NOT_SPECIFIED,
AudioFormat.LITTLE_ENDIAN,
AudioFormat.SIGNED,
AudioFormat.NOT_SPECIFIED,
AudioFormat.NOT_SPECIFIED,
Format.byteArray
)};
defaultOutputFormats = new AudioFormat[] { new AudioFormat(AudioFormat.IMA4) };
PLUGIN_NAME="IMA4 Encoder";
historySize = 256; // worst case: stereo * 2 bytes/sample * 64 samples
}
protected Format[] getMatchingOutputFormats(Format in) {
AudioFormat af =(AudioFormat) in;
supportedOutputFormats = new AudioFormat[] {
new AudioFormat(
AudioFormat.IMA4,
af.getSampleRate(),
16,
af.getChannels(),
Format.NOT_SPECIFIED, //isBigEndian(),
Format.NOT_SPECIFIED, //isSigned());
34 * 8 * af.getChannels(),
AudioFormat.NOT_SPECIFIED,
Format.byteArray
) };
return supportedOutputFormats;
}
/** Initializes the codec. **/
public void open() {
ima4stateL=new IMA4State();
ima4stateR=new IMA4State();
}
/** Clean up **/
public void close() {
ima4stateL = null;
ima4stateR = null;
}
// reset IMA4 encoder state
public void codecReset() {
ima4stateL.index = 0;
ima4stateL.valprev = 0;
ima4stateR.index = 0;
ima4stateR.valprev = 0;
}
protected int calculateOutputSize(int inputSize) {
//System.out.println("output number "+inputSize+" => "+calculateFramesNumber(inputSize) * 34);
return calculateFramesNumber(inputSize) * 34 * 2;
}
protected int calculateFramesNumber(int inputSize) {
//System.out.println("frame number "+inputSize+" => "+inputSize / 128);
return inputSize / 128;
}
protected boolean codecProcess(byte[] inpData,int readPtr,
byte[] outData,int writePtr,
int inpLength,
int[] readBytes,int[] writeBytes,
int[] frameNumber,
int[] regions,int[] regiostypes) {
int inCount = 0;
int outCount = 0;
int channels=inputFormat.getChannels();
boolean isStereo = ( channels == 2);
int stride = isStereo ? 2 : 0;
final int frames = inpLength/(channels*128);
regions[0]=writePtr;
// IMA4 mono takes 64 little endian input stereo interleaved samples (256 bytes)
// and convert them to:
// LEFT: 2 bytes header followed by 32 bytes encoded data
// followed by:
// RIGHT: 2 bytes header followed by 32 bytes encoded data
// ima4stateL,R are stored between chunks encoding.
for (int frameCounter = 0; frameCounter<frames ; frameCounter++) {
//LEFT or mono
// validate index legality
if (ima4stateL.index>88) {
ima4stateL.index=88;
} else if (ima4stateL.index<0) {
ima4stateL.index=0;
}
ima4stateL.valprev &= 0xFFFFFF80 ; // synchronize state of encoder and decoder
int stateL = ima4stateL.valprev | ima4stateL.index;
// state is now prevVal(9 most significant bits- signed )::index (7 least significant bits- unsigned)
// note that state is sign extended !
// store state in big endian
outData[writePtr+(outCount++)]=(byte)(stateL>>8);
outData[writePtr+(outCount++)]=(byte)(stateL);
IMA4.encode(inpData,readPtr+inCount,outData,writePtr+outCount,64,ima4stateL,stride);
outCount += (64>>1);
//RIGHT
if (isStereo) {
// validate index legality
if (ima4stateR.index>88) {
ima4stateR.index=88;
} else if (ima4stateR.index<0) {
ima4stateR.index=0;
}
ima4stateR.valprev &= 0xFFFFFF80 ; // synchronize state of encoder and decoder
int stateR = ima4stateR.valprev | ima4stateR.index;
// state is now prevVal(9 most significant bits- signed )::index (7 least significant bits- unsigned)
// note that state is sign extended !
// store state in big endian
outData[writePtr+(outCount++)]=(byte)(stateR>>8);
outData[writePtr+(outCount++)]=(byte)(stateR);
IMA4.encode(inpData,readPtr+inCount+2,outData,writePtr+outCount,64,ima4stateR,stride);
outCount += (64>>1);
inCount += (64<<2);
} else {
inCount += (64<<1);
}
regions [frameCounter+1]= outCount + writePtr;
regionsTypes[frameCounter ]= 0;
// System.out.println(inCount+" "+outCount+" "+inpLength);
}
readBytes [0]=inCount;
writeBytes[0]=outCount;
frameNumber[0]=frames;
return true;
}
}
|