1056 lines · 41.3 KB · Java
RawDownload
/* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.  Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */package com.sun.media.sound; import java.nio.ByteBuffer;import java.nio.ByteOrder;import java.nio.DoubleBuffer;import java.nio.FloatBuffer; import javax.sound.sampled.AudioFormat;import javax.sound.sampled.AudioFormat.Encoding; /** * This class is used to convert between 8,16,24,32,32+ bit signed/unsigned * big/litle endian fixed/floating point byte buffers and float buffers. * * @author Karl Helgason */public abstract class AudioFloatConverter {     /***************************************************************************     *     * LSB Filter, used filter least significant byte in samples arrays.     *     * Is used filter out data in lsb byte when SampleSizeInBits is not     * dividable by 8.     *     **************************************************************************/     private static class AudioFloatLSBFilter extends AudioFloatConverter {         private AudioFloatConverter converter;         final private int offset;         final private int stepsize;         final private byte mask;         private byte[] mask_buffer;         public AudioFloatLSBFilter(AudioFloatConverter converter,                AudioFormat format) {            int bits = format.getSampleSizeInBits();            boolean bigEndian = format.isBigEndian();            this.converter = converter;            stepsize = (bits + 7) / 8;            offset = bigEndian ? (stepsize - 1) : 0;            int lsb_bits = bits % 8;            if (lsb_bits == 0)                mask = (byte) 0x00;            else if (lsb_bits == 1)                mask = (byte) 0x80;            else if (lsb_bits == 2)                mask = (byte) 0xC0;            else if (lsb_bits == 3)                mask = (byte) 0xE0;            else if (lsb_bits == 4)                mask = (byte) 0xF0;            else if (lsb_bits == 5)                mask = (byte) 0xF8;            else if (lsb_bits == 6)                mask = (byte) 0xFC;            else if (lsb_bits == 7)                mask = (byte) 0xFE;            else                mask = (byte) 0xFF;        }         public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,                byte[] out_buff, int out_offset) {            byte[] ret = converter.toByteArray(in_buff, in_offset, in_len,                    out_buff, out_offset);             int out_offset_end = in_len * stepsize;            for (int i = out_offset + offset; i < out_offset_end; i += stepsize) {                out_buff[i] = (byte) (out_buff[i] & mask);            }             return ret;        }         public float[] toFloatArray(byte[] in_buff, int in_offset,                float[] out_buff, int out_offset, int out_len) {            if (mask_buffer == null || mask_buffer.length < in_buff.length)                mask_buffer = new byte[in_buff.length];            System.arraycopy(in_buff, 0, mask_buffer, 0, in_buff.length);            int in_offset_end = out_len * stepsize;            for (int i = in_offset + offset; i < in_offset_end; i += stepsize) {                mask_buffer[i] = (byte) (mask_buffer[i] & mask);            }            float[] ret = converter.toFloatArray(mask_buffer, in_offset,                    out_buff, out_offset, out_len);            return ret;        }     }     /***************************************************************************     *     * 64 bit float, little/big-endian     *     **************************************************************************/     // PCM 64 bit float, little-endian    private static class AudioFloatConversion64L extends AudioFloatConverter {        ByteBuffer bytebuffer = null;         DoubleBuffer floatbuffer = null;         double[] double_buff = null;         public float[] toFloatArray(byte[] in_buff, int in_offset,                float[] out_buff, int out_offset, int out_len) {            int in_len = out_len * 8;            if (bytebuffer == null || bytebuffer.capacity() < in_len) {                bytebuffer = ByteBuffer.allocate(in_len).order(                        ByteOrder.LITTLE_ENDIAN);                floatbuffer = bytebuffer.asDoubleBuffer();            }            bytebuffer.position(0);            floatbuffer.position(0);            bytebuffer.put(in_buff, in_offset, in_len);            if (double_buff == null                    || double_buff.length < out_len + out_offset)                double_buff = new double[out_len + out_offset];            floatbuffer.get(double_buff, out_offset, out_len);            int out_offset_end = out_offset + out_len;            for (int i = out_offset; i < out_offset_end; i++) {                out_buff[i] = (float) double_buff[i];            }            return out_buff;        }         public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,                byte[] out_buff, int out_offset) {            int out_len = in_len * 8;            if (bytebuffer == null || bytebuffer.capacity() < out_len) {                bytebuffer = ByteBuffer.allocate(out_len).order(                        ByteOrder.LITTLE_ENDIAN);                floatbuffer = bytebuffer.asDoubleBuffer();            }            floatbuffer.position(0);            bytebuffer.position(0);            if (double_buff == null || double_buff.length < in_offset + in_len)                double_buff = new double[in_offset + in_len];            int in_offset_end = in_offset + in_len;            for (int i = in_offset; i < in_offset_end; i++) {                double_buff[i] = in_buff[i];            }            floatbuffer.put(double_buff, in_offset, in_len);            bytebuffer.get(out_buff, out_offset, out_len);            return out_buff;        }    }     // PCM 64 bit float, big-endian    private static class AudioFloatConversion64B extends AudioFloatConverter {        ByteBuffer bytebuffer = null;         DoubleBuffer floatbuffer = null;         double[] double_buff = null;         public float[] toFloatArray(byte[] in_buff, int in_offset,                float[] out_buff, int out_offset, int out_len) {            int in_len = out_len * 8;            if (bytebuffer == null || bytebuffer.capacity() < in_len) {                bytebuffer = ByteBuffer.allocate(in_len).order(                        ByteOrder.BIG_ENDIAN);                floatbuffer = bytebuffer.asDoubleBuffer();            }            bytebuffer.position(0);            floatbuffer.position(0);            bytebuffer.put(in_buff, in_offset, in_len);            if (double_buff == null                    || double_buff.length < out_len + out_offset)                double_buff = new double[out_len + out_offset];            floatbuffer.get(double_buff, out_offset, out_len);            int out_offset_end = out_offset + out_len;            for (int i = out_offset; i < out_offset_end; i++) {                out_buff[i] = (float) double_buff[i];            }            return out_buff;        }         public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,                byte[] out_buff, int out_offset) {            int out_len = in_len * 8;            if (bytebuffer == null || bytebuffer.capacity() < out_len) {                bytebuffer = ByteBuffer.allocate(out_len).order(                        ByteOrder.BIG_ENDIAN);                floatbuffer = bytebuffer.asDoubleBuffer();            }            floatbuffer.position(0);            bytebuffer.position(0);            if (double_buff == null || double_buff.length < in_offset + in_len)                double_buff = new double[in_offset + in_len];            int in_offset_end = in_offset + in_len;            for (int i = in_offset; i < in_offset_end; i++) {                double_buff[i] = in_buff[i];            }            floatbuffer.put(double_buff, in_offset, in_len);            bytebuffer.get(out_buff, out_offset, out_len);            return out_buff;        }    }     /***************************************************************************     *     * 32 bit float, little/big-endian     *     **************************************************************************/     // PCM 32 bit float, little-endian    private static class AudioFloatConversion32L extends AudioFloatConverter {        ByteBuffer bytebuffer = null;         FloatBuffer floatbuffer = null;         public float[] toFloatArray(byte[] in_buff, int in_offset,                float[] out_buff, int out_offset, int out_len) {            int in_len = out_len * 4;            if (bytebuffer == null || bytebuffer.capacity() < in_len) {                bytebuffer = ByteBuffer.allocate(in_len).order(                        ByteOrder.LITTLE_ENDIAN);                floatbuffer = bytebuffer.asFloatBuffer();            }            bytebuffer.position(0);            floatbuffer.position(0);            bytebuffer.put(in_buff, in_offset, in_len);            floatbuffer.get(out_buff, out_offset, out_len);            return out_buff;        }         public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,                byte[] out_buff, int out_offset) {            int out_len = in_len * 4;            if (bytebuffer == null || bytebuffer.capacity() < out_len) {                bytebuffer = ByteBuffer.allocate(out_len).order(                        ByteOrder.LITTLE_ENDIAN);                floatbuffer = bytebuffer.asFloatBuffer();            }            floatbuffer.position(0);            bytebuffer.position(0);            floatbuffer.put(in_buff, in_offset, in_len);            bytebuffer.get(out_buff, out_offset, out_len);            return out_buff;        }    }     // PCM 32 bit float, big-endian    private static class AudioFloatConversion32B extends AudioFloatConverter {        ByteBuffer bytebuffer = null;         FloatBuffer floatbuffer = null;         public float[] toFloatArray(byte[] in_buff, int in_offset,                float[] out_buff, int out_offset, int out_len) {            int in_len = out_len * 4;            if (bytebuffer == null || bytebuffer.capacity() < in_len) {                bytebuffer = ByteBuffer.allocate(in_len).order(                        ByteOrder.BIG_ENDIAN);                floatbuffer = bytebuffer.asFloatBuffer();            }            bytebuffer.position(0);            floatbuffer.position(0);            bytebuffer.put(in_buff, in_offset, in_len);            floatbuffer.get(out_buff, out_offset, out_len);            return out_buff;        }         public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,                byte[] out_buff, int out_offset) {            int out_len = in_len * 4;            if (bytebuffer == null || bytebuffer.capacity() < out_len) {                bytebuffer = ByteBuffer.allocate(out_len).order(                        ByteOrder.BIG_ENDIAN);                floatbuffer = bytebuffer.asFloatBuffer();            }            floatbuffer.position(0);            bytebuffer.position(0);            floatbuffer.put(in_buff, in_offset, in_len);            bytebuffer.get(out_buff, out_offset, out_len);            return out_buff;        }    }     /***************************************************************************     *     * 8 bit signed/unsigned     *     **************************************************************************/     // PCM 8 bit, signed    private static class AudioFloatConversion8S extends AudioFloatConverter {        public float[] toFloatArray(byte[] in_buff, int in_offset,                float[] out_buff, int out_offset, int out_len) {            int ix = in_offset;            int ox = out_offset;            for (int i = 0; i < out_len; i++)                out_buff[ox++] = in_buff[ix++] * (1.0f / 127.0f);            return out_buff;        }         public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,                byte[] out_buff, int out_offset) {            int ix = in_offset;            int ox = out_offset;            for (int i = 0; i < in_len; i++)                out_buff[ox++] = (byte) (in_buff[ix++] * 127.0f);            return out_buff;        }    }     // PCM 8 bit, unsigned    private static class AudioFloatConversion8U extends AudioFloatConverter {        public float[] toFloatArray(byte[] in_buff, int in_offset,                float[] out_buff, int out_offset, int out_len) {            int ix = in_offset;            int ox = out_offset;            for (int i = 0; i < out_len; i++)                out_buff[ox++] = ((in_buff[ix++] & 0xFF) - 127)                        * (1.0f / 127.0f);            return out_buff;        }         public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,                byte[] out_buff, int out_offset) {            int ix = in_offset;            int ox = out_offset;            for (int i = 0; i < in_len; i++)                out_buff[ox++] = (byte) (127 + in_buff[ix++] * 127.0f);            return out_buff;        }    }     /***************************************************************************     *     * 16 bit signed/unsigned, little/big-endian     *     **************************************************************************/     // PCM 16 bit, signed, little-endian    private static class AudioFloatConversion16SL extends AudioFloatConverter {        public float[] toFloatArray(byte[] in_buff, int in_offset,                float[] out_buff, int out_offset, int out_len) {            int ix = in_offset;            int len = out_offset + out_len;            for (int ox = out_offset; ox < len; ox++) {                out_buff[ox] = ((short) ((in_buff[ix++] & 0xFF) |                           (in_buff[ix++] << 8))) * (1.0f / 32767.0f);            }             return out_buff;        }         public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,                byte[] out_buff, int out_offset) {            int ox = out_offset;            int len = in_offset + in_len;            for (int ix = in_offset; ix < len; ix++) {                int x = (int) (in_buff[ix] * 32767.0);                out_buff[ox++] = (byte) x;                out_buff[ox++] = (byte) (x >>> 8);            }            return out_buff;        }    }     // PCM 16 bit, signed, big-endian    private static class AudioFloatConversion16SB extends AudioFloatConverter {        public float[] toFloatArray(byte[] in_buff, int in_offset,                float[] out_buff, int out_offset, int out_len) {            int ix = in_offset;            int ox = out_offset;            for (int i = 0; i < out_len; i++) {                out_buff[ox++] = ((short) ((in_buff[ix++] << 8) |                        (in_buff[ix++] & 0xFF))) * (1.0f / 32767.0f);            }            return out_buff;        }         public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,                byte[] out_buff, int out_offset) {            int ix = in_offset;            int ox = out_offset;            for (int i = 0; i < in_len; i++) {                int x = (int) (in_buff[ix++] * 32767.0);                out_buff[ox++] = (byte) (x >>> 8);                out_buff[ox++] = (byte) x;            }            return out_buff;        }    }     // PCM 16 bit, unsigned, little-endian    private static class AudioFloatConversion16UL extends AudioFloatConverter {        public float[] toFloatArray(byte[] in_buff, int in_offset,                float[] out_buff, int out_offset, int out_len) {            int ix = in_offset;            int ox = out_offset;            for (int i = 0; i < out_len; i++) {                int x = (in_buff[ix++] & 0xFF) | ((in_buff[ix++] & 0xFF) << 8);                out_buff[ox++] = (x - 32767) * (1.0f / 32767.0f);            }            return out_buff;        }         public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,                byte[] out_buff, int out_offset) {            int ix = in_offset;            int ox = out_offset;            for (int i = 0; i < in_len; i++) {                int x = 32767 + (int) (in_buff[ix++] * 32767.0);                out_buff[ox++] = (byte) x;                out_buff[ox++] = (byte) (x >>> 8);            }            return out_buff;        }    }     // PCM 16 bit, unsigned, big-endian    private static class AudioFloatConversion16UB extends AudioFloatConverter {        public float[] toFloatArray(byte[] in_buff, int in_offset,                float[] out_buff, int out_offset, int out_len) {            int ix = in_offset;            int ox = out_offset;            for (int i = 0; i < out_len; i++) {                int x = ((in_buff[ix++] & 0xFF) << 8) | (in_buff[ix++] & 0xFF);                out_buff[ox++] = (x - 32767) * (1.0f / 32767.0f);            }            return out_buff;        }         public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,                byte[] out_buff, int out_offset) {            int ix = in_offset;            int ox = out_offset;            for (int i = 0; i < in_len; i++) {                int x = 32767 + (int) (in_buff[ix++] * 32767.0);                out_buff[ox++] = (byte) (x >>> 8);                out_buff[ox++] = (byte) x;            }            return out_buff;        }    }     /***************************************************************************     *     * 24 bit signed/unsigned, little/big-endian     *     **************************************************************************/     // PCM 24 bit, signed, little-endian    private static class AudioFloatConversion24SL extends AudioFloatConverter {        public float[] toFloatArray(byte[] in_buff, int in_offset,                float[] out_buff, int out_offset, int out_len) {            int ix = in_offset;            int ox = out_offset;            for (int i = 0; i < out_len; i++) {                int x = (in_buff[ix++] & 0xFF) | ((in_buff[ix++] & 0xFF) << 8)                        | ((in_buff[ix++] & 0xFF) << 16);                if (x > 0x7FFFFF)                    x -= 0x1000000;                out_buff[ox++] = x * (1.0f / (float)0x7FFFFF);            }            return out_buff;        }         public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,                byte[] out_buff, int out_offset) {            int ix = in_offset;            int ox = out_offset;            for (int i = 0; i < in_len; i++) {                int x = (int) (in_buff[ix++] * (float)0x7FFFFF);                if (x < 0)                    x += 0x1000000;

Lines 1–500 of 1056.