📄 floatsamplebuffer.java
字号:
float[] newChannel=null; if (physSize>virtSize) { // there are hidden channels. Try to use one. for (int ch=virtSize; ch<physSize; ch++) { float[] thisChannel=(float[]) channels.get(ch); if ((lazy && thisChannel.length>=getSampleCount()) || (!lazy && thisChannel.length==getSampleCount())) { // we found a matching channel. Use it ! newChannel=thisChannel; channels.remove(ch); break; } } } if (newChannel==null) { newChannel=new float[getSampleCount()]; } channels.add(index, newChannel); this.channelCount++; if (silent) { makeSilence(index); } } /** performs a lazy remove of the channel */ public void removeChannel(int channel) { removeChannel(channel, LAZY_DEFAULT); } /** * Removes a channel. * If lazy is true, the channel is not physically removed, but only hidden. * These hidden channels are reused by subsequent calls to addChannel * or insertChannel. */ public void removeChannel(int channel, boolean lazy) { if (!lazy) { channels.remove(channel); } else if (channel<getChannelCount()-1) { // if not already, move this channel at the end channels.add(channels.remove(channel)); } channelCount--; } /** * both source and target channel have to exist. targetChannel * will be overwritten */ public void copyChannel(int sourceChannel, int targetChannel) { float[] source=getChannel(sourceChannel); float[] target=getChannel(targetChannel); System.arraycopy(source, 0, target, 0, getSampleCount()); } //////////////////////////////// properties ///////////////////////////////// public int getChannelCount() { return channelCount; } public int getSampleCount() { return sampleCount; } public float getSampleRate() { return sampleRate; } /** * Sets the sample rate of this buffer. * NOTE: no conversion is done. The samples are only re-interpreted. */ public void setSampleRate(float sampleRate) { if (sampleRate<=0) { throw new IllegalArgumentException ("Invalid samplerate for FloatSampleBuffer."); } this.sampleRate=sampleRate; } /** * NOTE: the returned array may be larger than sampleCount. So in any case, * sampleCount is to be respected. */ public float[] getChannel(int channel) { if (channel<0 || channel>=getChannelCount()) { throw new IllegalArgumentException( "FloatSampleBuffer: invalid channel number."); } return (float[]) channels.get(channel); } public Object[] getAllChannels() { Object[] res=new Object[getChannelCount()]; for (int ch=0; ch<getChannelCount(); ch++) { res[ch]=getChannel(ch); } return res; } /** * Set the number of bits for dithering. * Typically, a value between 0.2 and 0.9 gives best results. * <p>Note: this value is only used, when dithering is actually performed. */ public void setDitherBits(float ditherBits) { if (ditherBits<=0) { throw new IllegalArgumentException("DitherBits must be greater than 0"); } this.ditherBits=ditherBits; } public float getDitherBits() { return ditherBits; } /** * Sets the mode for dithering. * This can be one of: * <ul><li>DITHER_MODE_AUTOMATIC: it is decided automatically, * whether dithering is necessary - in general when sample size is * decreased. * <li>DITHER_MODE_ON: dithering will be forced * <li>DITHER_MODE_OFF: dithering will not be done. * </ul> */ public void setDitherMode(int mode) { if (mode!=DITHER_MODE_AUTOMATIC && mode!=DITHER_MODE_ON && mode!=DITHER_MODE_OFF) { throw new IllegalArgumentException("Illegal DitherMode"); } this.ditherMode=mode; } public int getDitherMode() { return ditherMode; } /////////////////////////////// "low level" conversion functions //////////////////////////////// public int getFormatType(int ssib, boolean signed, boolean bigEndian) { int bytesPerSample=ssib/8; int res=0; if (ssib==8) { res=F_8; } else if (ssib==16) { res=F_16; } else if (ssib==24) { res=F_24; } else if (ssib==32) { res=F_32; } if (res==0) { throw new IllegalArgumentException ("FloatSampleBuffer: unsupported sample size of " +ssib+" bits per sample."); } if (!signed && bytesPerSample>1) { throw new IllegalArgumentException ("FloatSampleBuffer: unsigned samples larger than " +"8 bit are not supported"); } if (signed) { res|=F_SIGNED; } if (bigEndian && (ssib!=8)) { res|=F_BIGENDIAN; } return res; } private static final float twoPower7=128.0f; private static final float twoPower15=32768.0f; private static final float twoPower23=8388608.0f; private static final float twoPower31=2147483648.0f; private static final float invTwoPower7=1/twoPower7; private static final float invTwoPower15=1/twoPower15; private static final float invTwoPower23=1/twoPower23; private static final float invTwoPower31=1/twoPower31; /*public*/ private static void convertByteToFloat(byte[] input, int offset, int sampleCount, float[] output, int bytesPerFrame, int formatType) { //if (TDebug.TraceAudioConverter) { // TDebug.out("FloatSampleBuffer.convertByteToFloat, formatType=" // +formatType2Str(formatType)); //} int sample; for (sample=0; sample<sampleCount; sample++) { // do conversion switch (formatType) { case CT_8S: output[sample]= ((float) input[offset])*invTwoPower7; break; case CT_8U: output[sample]= ((float) ((input[offset] & 0xFF)-128))*invTwoPower7; break; case CT_16SB: output[sample]= ((float) ((input[offset]<<8) | (input[offset+1] & 0xFF)))*invTwoPower15; break; case CT_16SL: output[sample]= ((float) ((input[offset+1]<<8) | (input[offset] & 0xFF)))*invTwoPower15; break; case CT_24SB: output[sample]= ((float) ((input[offset]<<16) | ((input[offset+1] & 0xFF)<<8) | (input[offset+2] & 0xFF)))*invTwoPower23; break; case CT_24SL: output[sample]= ((float) ((input[offset+2]<<16) | ((input[offset+1] & 0xFF)<<8) | (input[offset] & 0xFF)))*invTwoPower23; break; case CT_32SB: output[sample]= ((float) ((input[offset]<<24) | ((input[offset+1] & 0xFF)<<16) | ((input[offset+2] & 0xFF)<<8) | (input[offset+3] & 0xFF)))*invTwoPower31; break; case CT_32SL: output[sample]= ((float) ((input[offset+3]<<24) | ((input[offset+2] & 0xFF)<<16) | ((input[offset+1] & 0xFF)<<8) | (input[offset] & 0xFF)))*invTwoPower31; break; default: throw new IllegalArgumentException ("Unsupported formatType="+formatType); } offset+=bytesPerFrame; } } protected byte quantize8(float sample) { if (doDither) { sample+=random.nextFloat()*ditherBits; } if (sample>=127.0f) { return (byte) 127; } else if (sample<=-128) { return (byte) -128; } else { return (byte) (sample<0?(sample-0.5f):(sample+0.5f)); } } protected int quantize16(float sample) { if (doDither) { sample+=random.nextFloat()*ditherBits; } if (sample>=32767.0f) { return 32767; } else if (sample<=-32768.0f) { return -32768; } else { return (int) (sample<0?(sample-0.5f):(sample+0.5f)); } } protected int quantize24(float sample) { if (doDither) { sample+=random.nextFloat()*ditherBits; } if (sample>=8388607.0f) { return 8388607; } else if (sample<=-8388608.0f) { return -8388608; } else { return (int) (sample<0?(sample-0.5f):(sample+0.5f)); } } protected int quantize32(float sample) { if (doDither) { sample+=random.nextFloat()*ditherBits; } if (sample>=2147483647.0f) { return 2147483647; } else if (sample<=-2147483648.0f) { return -2147483648; } else { return (int) (sample<0?(sample-0.5f):(sample+0.5f)); } } // should be static and public, but dithering needs class members private void convertFloatToByte(float[] input, int sampleCount, byte[] output, int offset, int bytesPerFrame, int formatType) { //if (TDebug.TraceAudioConverter) { // TDebug.out("FloatSampleBuffer.convertFloatToByte, formatType=" // +"formatType2Str(formatType)); //} // let's see whether dithering is necessary switch (ditherMode) { case DITHER_MODE_AUTOMATIC: doDither=(originalFormatType & F_SAMPLE_WIDTH_MASK)> (formatType & F_SAMPLE_WIDTH_MASK); break; case DITHER_MODE_ON: doDither=true; break; case DITHER_MODE_OFF: doDither=false; break; } if (doDither && random==null) { // create the random number generator for dithering random=new Random(); } int inIndex; int iSample; for (inIndex=0; inIndex<sampleCount; inIndex++) { // do conversion switch (formatType) { case CT_8S: output[offset]=quantize8(input[inIndex]*twoPower7); break; case CT_8U: output[offset]=(byte) (quantize8(input[inIndex]*twoPower7)+128); break; case CT_16SB: iSample=quantize16(input[inIndex]*twoPower15); output[offset]=(byte) (iSample >> 8); output[offset+1]=(byte) (iSample & 0xFF); break; case CT_16SL: iSample=quantize16(input[inIndex]*twoPower15); output[offset+1]=(byte) (iSample >> 8); output[offset]=(byte) (iSample & 0xFF); break; case CT_24SB: iSample=quantize24(input[inIndex]*twoPower23); output[offset]=(byte) (iSample >> 16); output[offset+1]=(byte) ((iSample >>> 8) & 0xFF); output[offset+2]=(byte) (iSample & 0xFF); break; case CT_24SL: iSample=quantize24(input[inIndex]*twoPower23); output[offset+2]=(byte) (iSample >> 16); output[offset+1]=(byte) ((iSample >>> 8) & 0xFF); output[offset]=(byte) (iSample & 0xFF); break; case CT_32SB: iSample=quantize32(input[inIndex]*twoPower31); output[offset]=(byte) (iSample >> 24); output[offset+1]=(byte) ((iSample >>> 16) & 0xFF); output[offset+2]=(byte) ((iSample >>> 8) & 0xFF); output[offset+3]=(byte) (iSample & 0xFF); break; case CT_32SL: iSample=quantize32(input[inIndex]*twoPower31); output[offset+3]=(byte) (iSample >> 24); output[offset+2]=(byte) ((iSample >>> 16) & 0xFF); output[offset+1]=(byte) ((iSample >>> 8) & 0xFF); output[offset]=(byte) (iSample & 0xFF); break; default: throw new IllegalArgumentException ("Unsupported formatType="+formatType); } offset+=bytesPerFrame; } } /** * Debugging function */ private static String formatType2Str(int formatType) { String res=""+formatType+": "; switch (formatType & F_SAMPLE_WIDTH_MASK) { case F_8: res+="8bit"; break; case F_16: res+="16bit"; break; case F_24: res+="24bit"; break; case F_32: res+="32bit"; break; } res+=((formatType & F_SIGNED)==F_SIGNED)?" signed":" unsigned"; if ((formatType & F_SAMPLE_WIDTH_MASK)!=F_8) { res+=((formatType & F_BIGENDIAN)==F_BIGENDIAN)? " big endian":" little endian"; } return res; }}/*** FloatSampleBuffer.java ***/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -