/* * @(#)JavaDecoder.java 1.7 02/08/21 * * Copyright (c) 1996-2002 Sun Microsystems, Inc. All rights reserved. */ package com.ibm.media.codec.audio.ima4; import javax.media.*; import javax.media.format.*; import javax.media.format.*; import com.sun.media.*; import com.sun.media.controls.*; public class JavaDecoder extends com.ibm.media.codec.audio.AudioCodec { //////////////////////////////////////////////////////////////////////////// // Variables //////////////////////////////////////////////////////////////////////////// // state of the ima4 decoder private IMA4State ima4state; //////////////////////////////////////////////////////////////////////////// // Methods public JavaDecoder() { supportedInputFormats = new AudioFormat[] { new AudioFormat(AudioFormat.IMA4) }; defaultOutputFormats = new AudioFormat[] { new AudioFormat(AudioFormat.LINEAR) }; PLUGIN_NAME="IMA4 Decoder"; } protected Format[] getMatchingOutputFormats(Format in) { AudioFormat af =(AudioFormat) in; supportedOutputFormats = new AudioFormat[] { new AudioFormat( AudioFormat.LINEAR, af.getSampleRate(), 16, af.getChannels(), AudioFormat.BIG_ENDIAN, //isBigEndian(), AudioFormat.SIGNED //isSigned()); ) }; return supportedOutputFormats; } /** Initializes the codec. **/ public void open() { ima4state=new IMA4State(); } /** Clean up **/ public void close() { ima4state = null; } /** decode the buffer **/ public int process(Buffer inputBuffer, Buffer outputBuffer) { int outLength; if (!checkInputBuffer(inputBuffer) ) { return BUFFER_PROCESSED_FAILED; } if (isEOM(inputBuffer) ) { propagateEOM(outputBuffer); return BUFFER_PROCESSED_OK; } int channels = ((AudioFormat)outputFormat).getChannels(); byte[] inData =(byte[]) inputBuffer.getData(); byte[] outData = validateByteArraySize(outputBuffer, inData.length * 4); outLength = decodeJavaIMA4(inData, outData, inputBuffer.getLength(), outData.length, channels); updateOutput(outputBuffer,outputFormat, outLength, 0); return BUFFER_PROCESSED_OK; } // java decoding methods // /////////////////////////// /** IMA4 decoding: sends the buffer to either decodeIMA4mono or decodeIMA4stereo **/ int decodeJavaIMA4(byte[] inData, byte[] outData, int lenIn, int lenOut,int nChannels){ switch (nChannels) { case 1: //mono return decodeIMA4mono (inData,outData,lenIn,lenOut,0x20); // 0x20 is IMA4 chunk size case 2: //stereo return decodeIMA4stereo(inData,outData,lenIn,lenOut,0x20); default: throw new RuntimeException("IMA4: Can only handle 1 or 2 channels\n"); } } /** decode IMA4 mono packet **/ private int decodeIMA4mono(byte[] inData, byte[] outData, int lenIn, int lenOut,int blockSize){ int inCount = 0; int outCount = 0; // IMA4 mono chunk format is 2 bytes header followed by 32 bytes encoded data lenIn = (lenIn / (blockSize+2) ) * (blockSize+2); while (inCount<lenIn) { int state = (inData[inCount++] << 8); state |= (inData[inCount++] & 0xff); // state is now prevVal(9 most significant bits- signed )::index (7 least significant bits- unsigned) int index = state & 0x7F; if (index>88) index=88; ima4state.valprev=state & 0xFFFFFF80 ; ima4state.index=index; IMA4.decode(inData,inCount,outData,outCount,blockSize<<1,ima4state,0); inCount += blockSize; outCount += blockSize<<2; } return outCount; } /** decode IMA4 stereo packet **/ private int decodeIMA4stereo(byte[] inData, byte[] outData, int lenIn, int lenOut,int blockSize){ int inCount = 0; int outCount = 0; // System.out.println( lenIn); lenIn = (lenIn / 2 /(blockSize+2) ) * (blockSize+2)*2; // IMA4 stereo chunk format is left IMA4 mono chunk followed by right IMA4 mono chunk while (inCount<lenIn) { //LEFT int stateL = (inData[inCount++] << 8); stateL |= (inData[inCount++] & 0xff); int indexL = stateL & 0x7F; if (indexL>88) indexL=88; ima4state.valprev=stateL & 0xFFFFFF80 ; ima4state.index=indexL; IMA4.decode(inData,inCount,outData,outCount,blockSize<<1,ima4state,2); inCount += blockSize; //RIGHT int stateR = (inData[inCount++] << 8); stateR |= (inData[inCount++] & 0xff); int indexR = stateR & 0x7F; if (indexR>88) indexR=88; ima4state.valprev=stateR & 0xFFFFFF80 ; ima4state.index=indexR; IMA4.decode(inData, inCount, outData, outCount+2, blockSize<<1, ima4state, 2); //loop counters inCount += blockSize; outCount += blockSize<<3; } return outCount; } public java.lang.Object[] getControls() { if (controls==null) { controls=new Control[1]; controls[0]=new SilenceSuppressionAdapter(this,false,false); } return (Object[])controls; } }