📄 pcm2pcmconversionprovider.java
字号:
case BIG_ENDIAN32: return "BIG_ENDIAN32"; case LITTLE_ENDIAN32: return "LITTLE_ENDIAN32"; } return "unknown"; } private static String conversionType2Str(int conversionType) { switch (conversionType) { case CONVERT_NOT_POSSIBLE: return "CONVERT_NOT_POSSIBLE"; case CONVERT_SIGN: return "CONVERT_SIGN"; case CONVERT_BYTE_ORDER16: return "CONVERT_BYTE_ORDER16"; case CONVERT_BYTE_ORDER24: return "CONVERT_BYTE_ORDER24"; case CONVERT_BYTE_ORDER32: return "CONVERT_BYTE_ORDER32"; case CONVERT_16LTO8S: return "CONVERT_16LTO8S"; case CONVERT_16LTO8U: return "CONVERT_16LTO8U"; case CONVERT_16BTO8S: return "CONVERT_16BTO8S"; case CONVERT_16BTO8U: return "CONVERT_16BTO8U"; case CONVERT_8STO16L: return "CONVERT_8STO16L"; case CONVERT_8STO16B: return "CONVERT_8STO16B"; case CONVERT_8UTO16L: return "CONVERT_8UTO16L"; case CONVERT_8UTO16B: return "CONVERT_8UTO16B"; case CONVERT_ONLY_EXPAND_CHANNELS: return "CONVERT_ONLY_EXPAND_CHANNELS"; case CONVERT_FLOAT: return "CONVERT_FLOAT"; case CONVERT_NONE: return "CONVERT_NONE"; } return "unknown"; } /** * PCM2PCMStream * Provides direct conversion of some selected formats and rxpanding of channels. */ class PCM2PCMStream extends TSynchronousFilteredAudioInputStream { private int conversionType; private int sourceType; private int targetType; private boolean needExpandChannels; private boolean needMixDown; private AudioFormat intermediateFloatBufferFormat; private FloatSampleBuffer floatBuffer=null; public PCM2PCMStream(AudioInputStream sourceStream, AudioFormat targetFormat, int sourceType, int targetType, int conversionType) { // transform the targetFormat so that // FrameRate, and SampleRate match the sourceFormat super (sourceStream, new AudioFormat( targetFormat.getEncoding(), sourceStream.getFormat().getSampleRate(), targetFormat.getSampleSizeInBits(), targetFormat.getChannels(), targetFormat.getChannels()*targetFormat.getSampleSizeInBits()/8, sourceStream.getFormat().getFrameRate(), targetFormat.isBigEndian())); if (TDebug.TraceAudioConverter) { TDebug.out("PCM2PCMStream: constructor. ConversionType=" +conversionType2Str(conversionType)); } this.conversionType=conversionType; this.sourceType=sourceType; this.targetType=targetType; needExpandChannels=sourceStream.getFormat().getChannels()<targetFormat.getChannels(); needMixDown=sourceStream.getFormat().getChannels()>targetFormat.getChannels(); // some sanity tests. These can be dropped when this converter has been tested enough... if (needMixDown && conversionType!=CONVERT_FLOAT) { throw new IllegalArgumentException( "PCM2PCMStream: MixDown only possible with CONVERT_FLOAT"); } if (needMixDown && targetFormat.getChannels()!=1) { throw new IllegalArgumentException( "PCM2PCMStream: MixDown only possible with target channel count=1"); } if (needExpandChannels && sourceStream.getFormat().getChannels()!=1) { throw new IllegalArgumentException( "PCM2PCMStream: Expanding channels only possible with source channel count=1"); } // end sanity if (conversionType==CONVERT_FLOAT) { int floatChannels=needExpandChannels?1:targetFormat.getChannels(); intermediateFloatBufferFormat=new AudioFormat( targetFormat.getEncoding(), sourceStream.getFormat().getSampleRate(), targetFormat.getSampleSizeInBits(), floatChannels, floatChannels*targetFormat.getSampleSizeInBits()/8, sourceStream.getFormat().getFrameRate(), targetFormat.isBigEndian()); // with floatBuffer we need to copy anyway, so enable in-place conversion enableConvertInPlace(); } if (!needExpandChannels && (conversionType==CONVERT_SIGN || conversionType==CONVERT_BYTE_ORDER16 || conversionType==CONVERT_BYTE_ORDER24 || conversionType==CONVERT_BYTE_ORDER32)) { enableConvertInPlace(); } } // these functions only treat the highbyte of 16bit samples // obsolete: is handled with FloatBuffer because of dithering private void do16BTO8S(byte[] inBuffer, int inCounter, byte[] outBuffer, int outByteOffset, int sampleCount) { for (; sampleCount>0; sampleCount--, inCounter++) { outBuffer[outByteOffset++]=inBuffer[inCounter++]; } } // obsolete: is handled with FloatBuffer because of dithering private void do16BTO8U(byte[] inBuffer, int inCounter, byte[] outBuffer, int outByteOffset, int sampleCount) { for (; sampleCount>0; sampleCount--, inCounter++) { outBuffer[outByteOffset++]=(byte)(inBuffer[inCounter++]+128); } } private void do8STO16L(byte[] inBuffer, byte[] outBuffer, int outByteOffset, int sampleCount) { for (int inCounter=0; sampleCount>0; sampleCount--) { outBuffer[outByteOffset++]=0; outBuffer[outByteOffset++]=inBuffer[inCounter++]; } } private void do8UTO16L(byte[] inBuffer, byte[] outBuffer, int outByteOffset, int sampleCount) { for (int inCounter=0; sampleCount>0; sampleCount--) { outBuffer[outByteOffset++]=0; outBuffer[outByteOffset++]=(byte)(inBuffer[inCounter++]+128); } } private void do8STO16B(byte[] inBuffer, byte[] outBuffer, int outByteOffset, int sampleCount) { for (int inCounter=0; sampleCount>0; sampleCount--) { outBuffer[outByteOffset++]=inBuffer[inCounter++]; outBuffer[outByteOffset++]=0; } } private void do8UTO16B(byte[] inBuffer, byte[] outBuffer, int outByteOffset, int sampleCount) { for (int inCounter=0; sampleCount>0; sampleCount--) { outBuffer[outByteOffset++]=(byte)(inBuffer[inCounter++]+128); outBuffer[outByteOffset++]=0; } } // copies the channels: in the buffer there is only one channel private void expandChannels(byte[] buffer, int offset, int frameCount, int bytesPerFrame, int channels) { int inOffset=offset+bytesPerFrame*frameCount; int outOffset=offset+bytesPerFrame*channels*frameCount; switch (bytesPerFrame) { case 1: if (channels==2) { for (;frameCount>0; frameCount--) { buffer[--outOffset]=buffer[--inOffset]; buffer[--outOffset]=buffer[inOffset]; } } else { for (;frameCount>0; frameCount--) { inOffset--; for (int channel=0; channel<channels; channel++) { buffer[--outOffset]=buffer[inOffset]; } } } break; case 2: if (channels==2) { for (;frameCount>0; frameCount--) { buffer[--outOffset]=buffer[--inOffset]; buffer[--outOffset]=buffer[inOffset-1]; buffer[--outOffset]=buffer[inOffset]; buffer[--outOffset]=buffer[--inOffset]; } } else { for (;frameCount>0; frameCount--) { inOffset--; for (int channel=0; channel<channels; channel++) { buffer[--outOffset]=buffer[inOffset]; buffer[--outOffset]=buffer[inOffset-1]; } inOffset--; } } break; default: for (;frameCount>0; frameCount--) { for (int channel=0; channel<channels; channel++) { for (int by=1; by<=bytesPerFrame; by++) { buffer[--outOffset]=buffer[inOffset-by]; } } inOffset-=bytesPerFrame; } break; } } private void doFloatConversion(FloatSampleBuffer buffer, boolean expandChannels) { if (needMixDown) { buffer.mixDownChannels(); } if (expandChannels) { buffer.expandChannel(getFormat().getChannels()); } } private void doFloatConversion(byte[] inBuffer, int inByteOffset, byte[] outBuffer, int outByteOffset, int sampleCount) { int byteCount=sampleCount*(getOriginalStream().getFormat().getSampleSizeInBits()/8); if (floatBuffer==null) { floatBuffer=new FloatSampleBuffer(); } floatBuffer.initFromByteArray(inBuffer, inByteOffset, byteCount, getOriginalStream().getFormat()); doFloatConversion(floatBuffer, false); // expansion is done on byte array floatBuffer.convertToByteArray(outBuffer, outByteOffset, intermediateFloatBufferFormat); } protected int convert(byte[] inBuffer, byte[] outBuffer, int outByteOffset, int inFrameCount) { int sampleCount=inFrameCount*getOriginalStream().getFormat().getChannels(); switch (conversionType) { case CONVERT_SIGN: TConversionTool.convertSign8( inBuffer, 0, outBuffer, outByteOffset, sampleCount); break; case CONVERT_BYTE_ORDER16: TConversionTool.swapOrder16( inBuffer, 0, outBuffer, outByteOffset, sampleCount); break; case CONVERT_BYTE_ORDER24: TConversionTool.swapOrder24( inBuffer, 0, outBuffer, outByteOffset, sampleCount); break; case CONVERT_BYTE_ORDER32: TConversionTool.swapOrder32( inBuffer, 0, outBuffer, outByteOffset, sampleCount); break; case CONVERT_16LTO8S: do16BTO8S(inBuffer, 1, outBuffer, outByteOffset, sampleCount); break; case CONVERT_16LTO8U: do16BTO8U(inBuffer, 1, outBuffer, outByteOffset, sampleCount); break; case CONVERT_16BTO8S: do16BTO8S(inBuffer, 0, outBuffer, outByteOffset, sampleCount); break; case CONVERT_16BTO8U: do16BTO8U(inBuffer, 0, outBuffer, outByteOffset, sampleCount); break; case CONVERT_8STO16L: do8STO16L(inBuffer, outBuffer, outByteOffset, sampleCount); break; case CONVERT_8STO16B: do8STO16B(inBuffer, outBuffer, outByteOffset, sampleCount); break; case CONVERT_8UTO16L: do8UTO16L(inBuffer, outBuffer, outByteOffset, sampleCount); break; case CONVERT_8UTO16B: do8UTO16B(inBuffer, outBuffer, outByteOffset, sampleCount); break; case CONVERT_ONLY_EXPAND_CHANNELS: // implicit: channelCount in inBuffer=1 System.arraycopy(inBuffer, 0, outBuffer, outByteOffset, inFrameCount*getOriginalStream().getFormat().getFrameSize()); break; case CONVERT_FLOAT: doFloatConversion(inBuffer, 0, outBuffer, outByteOffset, sampleCount); break; default: throw new RuntimeException( "PCM2PCMStream: Call to convert with unknown conversionType."); } if (needExpandChannels) { expandChannels(outBuffer, outByteOffset, inFrameCount, getFormat().getSampleSizeInBits()/8, getFormat().getChannels()); } return inFrameCount; } protected void convertInPlace(byte[] buffer, int byteOffset, int frameCount) { int sampleCount=frameCount*getOriginalStream().getFormat().getChannels(); switch (conversionType) { case CONVERT_SIGN: TConversionTool.convertSign8(buffer, byteOffset, sampleCount); break; case CONVERT_BYTE_ORDER16: TConversionTool.swapOrder16(buffer, byteOffset, sampleCount); break; case CONVERT_BYTE_ORDER24: TConversionTool.swapOrder24(buffer, byteOffset, sampleCount); break; case CONVERT_BYTE_ORDER32: TConversionTool.swapOrder32(buffer, byteOffset, sampleCount); break; case CONVERT_FLOAT: doFloatConversion(buffer, byteOffset, buffer, byteOffset, sampleCount); if (needExpandChannels) { expandChannels(buffer, byteOffset, frameCount, getFormat().getSampleSizeInBits()/8, getFormat().getChannels()); } break; default: throw new RuntimeException( "PCM2PCMStream: Call to convertInPlace, but it cannot convert in place."); } } }}/*** PCM2PCMFormatConversionProvider.java ***/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -