/* * @(#)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; } }