FileDocCategorySizeDatePackage
JavaDecoder_ms.javaAPI DocJMF 2.1.1e6439Mon May 12 12:21:02 BST 2003com.ibm.media.codec.audio.ima4

JavaDecoder_ms

public class JavaDecoder_ms extends AudioCodec

Fields Summary
private IMA4State
ima4state
Constructors Summary
public JavaDecoder_ms()

	supportedInputFormats = new AudioFormat[] { new AudioFormat(AudioFormat.IMA4_MS) };
        defaultOutputFormats  = new AudioFormat[] { new AudioFormat(AudioFormat.LINEAR) };
        PLUGIN_NAME="IMA4 MS Decoder";
    
Methods Summary
public voidclose()
Clean up

       ima4state = null;
    
private intdecodeJavaMSIMA4(byte[] inBuffer, byte[] outBuffer, int lenIn, int lenOut, int nChannels, int blockSize)

	switch (nChannels) {
	case 1: //mono
	    return decodeMSIMA4mono  (inBuffer,outBuffer,lenIn,lenOut,blockSize);
	case 2: //stereo
	    return decodeMSIMA4stereo(inBuffer,outBuffer,lenIn,lenOut,blockSize);
	default:
	    throw new RuntimeException("MSIMA4: Can only handle 1 or 2 channels\n");

	}
    
private intdecodeMSIMA4mono(byte[] inBuffer, byte[] outBuffer, int lenIn, int lenOut, int blockSize)

	int inCount  = 0;
	int outCount = 0;

	lenIn=( lenIn / blockSize) *  blockSize;

	while (inCount<lenIn) {
	    // MSDVI header is 2 bytes for previous value,
	    // 1 byte for index
	    // 1 byte spare
	    // note that previous value is also written to the output
	    int prevVal=  (inBuffer[inCount++] & 0xff);
	    prevVal |= (inBuffer[inCount++] << 8);


	    int index = (inBuffer[inCount++] & 0xff);

	    if (index>88)
		index=88;

	    inCount++;

	    outBuffer[outCount++] = (byte)(prevVal>>8);
	    outBuffer[outCount++] = (byte)(prevVal   );


	    ima4state.valprev=prevVal ;
	    ima4state.index=index;

	    IMA4.decode(inBuffer,inCount,outBuffer,outCount,(blockSize-4)<<1,ima4state,0);

	    inCount += blockSize-4;

	    outCount += (blockSize-4)<<2;
	}

	return outCount;

    
private intdecodeMSIMA4stereo(byte[] inBuffer, byte[] outBuffer, int lenIn, int lenOut, int blockSize)

	int inCount = 0;
	int outCount = 0;

        // MSDVI stereo format is a mess !
        // header left  (same as mono header)
        // header right (same as mono header)
        // 4 bytes left  (8 samples)
        // 4 bytes right (8 samples)
        // 4 bytes left  (8 samples)
        // 4 bytes right (8 samples)
        //    :      :      :
        //    :      :      :
        // 4 bytes left  (8 samples)
        // 4 bytes right (8 samples)

	lenIn=( lenIn / blockSize) *  blockSize;

	for (int i=0;i<outBuffer.length;i++)
	    outBuffer[i]=(byte)0;

	while (inCount<lenIn  ) {
	    int storedinCount = inCount;
	    int storedoutCount = outCount;
	    //LEFT
	    int prevValL=  (inBuffer[inCount++] & 0xff);
	    prevValL |= (inBuffer[inCount++] << 8);

	    int indexL = (inBuffer[inCount++] & 0xff);

	    if (indexL>88)
		indexL=88;

	    inCount++;

	    outBuffer[outCount++] = (byte)(prevValL>>8);
	    outBuffer[outCount++] = (byte)(prevValL   );

	    outCount += 2;
	    inCount += 4;

	    ima4state.valprev=prevValL;
	    ima4state.index=indexL;

	    for (int i=blockSize-8;i>0;i-=8) {
		IMA4.decode(inBuffer,inCount,outBuffer,outCount,8,ima4state,2);

		inCount +=8;
		outCount += 32;
	    }

	    //RIGHT
	    inCount  = storedinCount + 4;
	    outCount = storedoutCount + 2;


	    int prevValR=  (inBuffer[inCount++] & 0xff);
	    prevValR |= (inBuffer[inCount++] << 8);

	    int indexR = (inBuffer[inCount++] & 0xff);

	    if (indexR>88)
		indexR=88;

	    inCount++;

	    outBuffer[outCount++] = (byte)(prevValR>>8);
	    outBuffer[outCount++] = (byte)(prevValR   );
	    ima4state.valprev=prevValR;
	    ima4state.index=indexR;

	    outCount += 2;
	    inCount += 4;

	    for (int i=blockSize-8;i>0;i-=8) {
		IMA4.decode(inBuffer,inCount,outBuffer,outCount,8,ima4state,2);

		inCount +=8;
		outCount += 32;
	    }



	    inCount = storedinCount + blockSize;
	    outCount = storedoutCount +  ((blockSize-8)<<2) + 4;


	}



	return outCount;
    
public java.lang.Object[]getControls()

        if (controls==null) {
             controls=new Control[1];
             controls[0]=new SilenceSuppressionAdapter(this,false,false);
	}
        return (Object[])controls;
    
protected javax.media.Format[]getMatchingOutputFormats(javax.media.Format in)

      AudioFormat af =(AudioFormat) in;

      // sbd: check for correct frame size
      int fs=af.getFrameSizeInBits();
      int channels= af.getChannels();

      if ( ( fs % (8*4*channels) ) != 0 )
           return new Format[0];

      supportedOutputFormats = new AudioFormat[] {
                new AudioFormat(
                AudioFormat.LINEAR,
                af.getSampleRate(),
                16,
                af.getChannels(),
                AudioFormat.BIG_ENDIAN, //isBigEndian(),
                AudioFormat.SIGNED //isSigned());
                )
          };

        return  supportedOutputFormats;
    
public voidopen()
Initializes the codec.

       ima4state=new IMA4State();
    
public intprocess(javax.media.Buffer inputBuffer, javax.media.Buffer outputBuffer)
decode the buffer

      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);

      int blockSize=((AudioFormat)inputFormat).getFrameSizeInBits() >> 3;

		outLength = decodeJavaMSIMA4(inData, outData, inputBuffer.getLength(),
                                 outData.length, channels,blockSize );


      updateOutput(outputBuffer,outputFormat, outLength, 0);

	return BUFFER_PROCESSED_OK;