plectrum

Plectrum: instrument tuner for Android
Log | Files | Refs | README | LICENSE

TarsosDSPAudioFloatConverter.java (43494B)


      1 /*
      2 *      _______                       _____   _____ _____  
      3 *     |__   __|                     |  __ \ / ____|  __ \ 
      4 *        | | __ _ _ __ ___  ___  ___| |  | | (___ | |__) |
      5 *        | |/ _` | '__/ __|/ _ \/ __| |  | |\___ \|  ___/ 
      6 *        | | (_| | |  \__ \ (_) \__ \ |__| |____) | |     
      7 *        |_|\__,_|_|  |___/\___/|___/_____/|_____/|_|     
      8 *                                                         
      9 * -------------------------------------------------------------
     10 *
     11 * TarsosDSP is developed by Joren Six at IPEM, University Ghent
     12 *  
     13 * -------------------------------------------------------------
     14 *
     15 *  Info: http://0110.be/tag/TarsosDSP
     16 *  Github: https://github.com/JorenSix/TarsosDSP
     17 *  Releases: http://0110.be/releases/TarsosDSP/
     18 *  
     19 *  TarsosDSP includes modified source code by various authors,
     20 *  for credits and info, see README.
     21 * 
     22 */
     23 
     24 
     25 /*
     26  * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
     27  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     28  *
     29  * This code is free software; you can redistribute it and/or modify it
     30  * under the terms of the GNU General Public License version 2 only, as
     31  * published by the Free Software Foundation.  Sun designates this
     32  * particular file as subject to the "Classpath" exception as provided
     33  * by Sun in the LICENSE file that accompanied this code.
     34  *
     35  * This code is distributed in the hope that it will be useful, but WITHOUT
     36  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     37  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     38  * version 2 for more details (a copy is included in the LICENSE file that
     39  * accompanied this code).
     40  *
     41  * You should have received a copy of the GNU General Public License version
     42  * 2 along with this work; if not, write to the Free Software Foundation,
     43  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
     44  *
     45  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
     46  * CA 95054 USA or visit www.sun.com if you need additional information or
     47  * have any questions.
     48  */
     49 package be.tarsos.dsp.io;
     50 
     51 import java.nio.ByteBuffer;
     52 import java.nio.ByteOrder;
     53 import java.nio.DoubleBuffer;
     54 import java.nio.FloatBuffer;
     55 
     56 import be.tarsos.dsp.io.TarsosDSPAudioFormat.Encoding;
     57 
     58 
     59 /**
     60  * This class is used to convert between 8,16,24,32,32+ bit signed/unsigned
     61  * big/litle endian fixed/floating point byte buffers and float buffers.
     62  * 
     63  * @author Karl Helgason
     64  */
     65 public abstract class TarsosDSPAudioFloatConverter {
     66 
     67     public static final Encoding PCM_FLOAT = new Encoding("PCM_FLOAT");
     68 
     69     /***************************************************************************
     70      * 
     71      * LSB Filter, used filter least significant byte in samples arrays.
     72      * 
     73      * Is used filter out data in lsb byte when SampleSizeInBits is not
     74      * dividable by 8.
     75      * 
     76      **************************************************************************/
     77 
     78     private static class AudioFloatLSBFilter extends TarsosDSPAudioFloatConverter {
     79 
     80         private TarsosDSPAudioFloatConverter converter;
     81 
     82         final private int offset;
     83 
     84         final private int stepsize;
     85 
     86         final private byte mask;
     87 
     88         private byte[] mask_buffer;
     89 
     90         public AudioFloatLSBFilter(TarsosDSPAudioFloatConverter converter,
     91         		TarsosDSPAudioFormat format) {
     92             int bits = format.getSampleSizeInBits();
     93             boolean bigEndian = format.isBigEndian();
     94             this.converter = converter;
     95             stepsize = (bits + 7) / 8;
     96             offset = bigEndian ? (stepsize - 1) : 0;
     97             int lsb_bits = bits % 8;
     98             if (lsb_bits == 0)
     99                 mask = (byte) 0x00;
    100             else if (lsb_bits == 1)
    101                 mask = (byte) 0x80;
    102             else if (lsb_bits == 2)
    103                 mask = (byte) 0xC0;
    104             else if (lsb_bits == 3)
    105                 mask = (byte) 0xE0;
    106             else if (lsb_bits == 4)
    107                 mask = (byte) 0xF0;
    108             else if (lsb_bits == 5)
    109                 mask = (byte) 0xF8;
    110             else if (lsb_bits == 6)
    111                 mask = (byte) 0xFC;
    112             else if (lsb_bits == 7)
    113                 mask = (byte) 0xFE;
    114             else
    115                 mask = (byte) 0xFF;
    116         }
    117 
    118         public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
    119                 byte[] out_buff, int out_offset) {
    120             byte[] ret = converter.toByteArray(in_buff, in_offset, in_len,
    121                     out_buff, out_offset);
    122 
    123             int out_offset_end = in_len * stepsize;
    124             for (int i = out_offset + offset; i < out_offset_end; i += stepsize) {
    125                 out_buff[i] = (byte) (out_buff[i] & mask);
    126             }
    127 
    128             return ret;
    129         }
    130 
    131         public float[] toFloatArray(byte[] in_buff, int in_offset,
    132                 float[] out_buff, int out_offset, int out_len) {
    133             if (mask_buffer == null || mask_buffer.length < in_buff.length)
    134                 mask_buffer = new byte[in_buff.length];
    135             System.arraycopy(in_buff, 0, mask_buffer, 0, in_buff.length);
    136             int in_offset_end = out_len * stepsize;
    137             for (int i = in_offset + offset; i < in_offset_end; i += stepsize) {
    138                 mask_buffer[i] = (byte) (mask_buffer[i] & mask);
    139             }
    140             float[] ret = converter.toFloatArray(mask_buffer, in_offset,
    141                     out_buff, out_offset, out_len);
    142             return ret;
    143         }
    144 
    145     }
    146 
    147     /***************************************************************************
    148      * 
    149      * 64 bit float, little/big-endian
    150      * 
    151      **************************************************************************/
    152 
    153     // PCM 64 bit float, little-endian
    154     private static class AudioFloatConversion64L extends TarsosDSPAudioFloatConverter {
    155         ByteBuffer bytebuffer = null;
    156 
    157         DoubleBuffer floatbuffer = null;
    158 
    159         double[] double_buff = null;
    160 
    161         public float[] toFloatArray(byte[] in_buff, int in_offset,
    162                 float[] out_buff, int out_offset, int out_len) {
    163             int in_len = out_len * 8;
    164             if (bytebuffer == null || bytebuffer.capacity() < in_len) {
    165                 bytebuffer = ByteBuffer.allocate(in_len).order(
    166                         ByteOrder.LITTLE_ENDIAN);
    167                 floatbuffer = bytebuffer.asDoubleBuffer();
    168             }
    169             bytebuffer.position(0);
    170             floatbuffer.position(0);
    171             bytebuffer.put(in_buff, in_offset, in_len);
    172             if (double_buff == null
    173                     || double_buff.length < out_len + out_offset)
    174                 double_buff = new double[out_len + out_offset];
    175             floatbuffer.get(double_buff, out_offset, out_len);
    176             int out_offset_end = out_offset + out_len;
    177             for (int i = out_offset; i < out_offset_end; i++) {
    178                 out_buff[i] = (float) double_buff[i];
    179             }
    180             return out_buff;
    181         }
    182 
    183         public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
    184                 byte[] out_buff, int out_offset) {
    185             int out_len = in_len * 8;
    186             if (bytebuffer == null || bytebuffer.capacity() < out_len) {
    187                 bytebuffer = ByteBuffer.allocate(out_len).order(
    188                         ByteOrder.LITTLE_ENDIAN);
    189                 floatbuffer = bytebuffer.asDoubleBuffer();
    190             }
    191             floatbuffer.position(0);
    192             bytebuffer.position(0);
    193             if (double_buff == null || double_buff.length < in_offset + in_len)
    194                 double_buff = new double[in_offset + in_len];
    195             int in_offset_end = in_offset + in_len;
    196             for (int i = in_offset; i < in_offset_end; i++) {
    197                 double_buff[i] = in_buff[i];
    198             }
    199             floatbuffer.put(double_buff, in_offset, in_len);
    200             bytebuffer.get(out_buff, out_offset, out_len);
    201             return out_buff;
    202         }
    203     }
    204 
    205     // PCM 64 bit float, big-endian
    206     private static class AudioFloatConversion64B extends TarsosDSPAudioFloatConverter {
    207         ByteBuffer bytebuffer = null;
    208 
    209         DoubleBuffer floatbuffer = null;
    210 
    211         double[] double_buff = null;
    212 
    213         public float[] toFloatArray(byte[] in_buff, int in_offset,
    214                 float[] out_buff, int out_offset, int out_len) {
    215             int in_len = out_len * 8;
    216             if (bytebuffer == null || bytebuffer.capacity() < in_len) {
    217                 bytebuffer = ByteBuffer.allocate(in_len).order(
    218                         ByteOrder.BIG_ENDIAN);
    219                 floatbuffer = bytebuffer.asDoubleBuffer();
    220             }
    221             bytebuffer.position(0);
    222             floatbuffer.position(0);
    223             bytebuffer.put(in_buff, in_offset, in_len);
    224             if (double_buff == null
    225                     || double_buff.length < out_len + out_offset)
    226                 double_buff = new double[out_len + out_offset];
    227             floatbuffer.get(double_buff, out_offset, out_len);
    228             int out_offset_end = out_offset + out_len;
    229             for (int i = out_offset; i < out_offset_end; i++) {
    230                 out_buff[i] = (float) double_buff[i];
    231             }
    232             return out_buff;
    233         }
    234 
    235         public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
    236                 byte[] out_buff, int out_offset) {
    237             int out_len = in_len * 8;
    238             if (bytebuffer == null || bytebuffer.capacity() < out_len) {
    239                 bytebuffer = ByteBuffer.allocate(out_len).order(
    240                         ByteOrder.BIG_ENDIAN);
    241                 floatbuffer = bytebuffer.asDoubleBuffer();
    242             }
    243             floatbuffer.position(0);
    244             bytebuffer.position(0);
    245             if (double_buff == null || double_buff.length < in_offset + in_len)
    246                 double_buff = new double[in_offset + in_len];
    247             int in_offset_end = in_offset + in_len;
    248             for (int i = in_offset; i < in_offset_end; i++) {
    249                 double_buff[i] = in_buff[i];
    250             }
    251             floatbuffer.put(double_buff, in_offset, in_len);
    252             bytebuffer.get(out_buff, out_offset, out_len);
    253             return out_buff;
    254         }
    255     }
    256 
    257     /***************************************************************************
    258      * 
    259      * 32 bit float, little/big-endian
    260      * 
    261      **************************************************************************/
    262 
    263     // PCM 32 bit float, little-endian
    264     private static class AudioFloatConversion32L extends TarsosDSPAudioFloatConverter {
    265         ByteBuffer bytebuffer = null;
    266 
    267         FloatBuffer floatbuffer = null;
    268 
    269         public float[] toFloatArray(byte[] in_buff, int in_offset,
    270                 float[] out_buff, int out_offset, int out_len) {
    271             int in_len = out_len * 4;
    272             if (bytebuffer == null || bytebuffer.capacity() < in_len) {
    273                 bytebuffer = ByteBuffer.allocate(in_len).order(
    274                         ByteOrder.LITTLE_ENDIAN);
    275                 floatbuffer = bytebuffer.asFloatBuffer();
    276             }
    277             bytebuffer.position(0);
    278             floatbuffer.position(0);
    279             bytebuffer.put(in_buff, in_offset, in_len);
    280             floatbuffer.get(out_buff, out_offset, out_len);
    281             return out_buff;
    282         }
    283 
    284         public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
    285                 byte[] out_buff, int out_offset) {
    286             int out_len = in_len * 4;
    287             if (bytebuffer == null || bytebuffer.capacity() < out_len) {
    288                 bytebuffer = ByteBuffer.allocate(out_len).order(
    289                         ByteOrder.LITTLE_ENDIAN);
    290                 floatbuffer = bytebuffer.asFloatBuffer();
    291             }
    292             floatbuffer.position(0);
    293             bytebuffer.position(0);
    294             floatbuffer.put(in_buff, in_offset, in_len);
    295             bytebuffer.get(out_buff, out_offset, out_len);
    296             return out_buff;
    297         }
    298     }
    299 
    300     // PCM 32 bit float, big-endian
    301     private static class AudioFloatConversion32B extends TarsosDSPAudioFloatConverter {
    302         ByteBuffer bytebuffer = null;
    303 
    304         FloatBuffer floatbuffer = null;
    305 
    306         public float[] toFloatArray(byte[] in_buff, int in_offset,
    307                 float[] out_buff, int out_offset, int out_len) {
    308             int in_len = out_len * 4;
    309             if (bytebuffer == null || bytebuffer.capacity() < in_len) {
    310                 bytebuffer = ByteBuffer.allocate(in_len).order(
    311                         ByteOrder.BIG_ENDIAN);
    312                 floatbuffer = bytebuffer.asFloatBuffer();
    313             }
    314             bytebuffer.position(0);
    315             floatbuffer.position(0);
    316             bytebuffer.put(in_buff, in_offset, in_len);
    317             floatbuffer.get(out_buff, out_offset, out_len);
    318             return out_buff;
    319         }
    320 
    321         public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
    322                 byte[] out_buff, int out_offset) {
    323             int out_len = in_len * 4;
    324             if (bytebuffer == null || bytebuffer.capacity() < out_len) {
    325                 bytebuffer = ByteBuffer.allocate(out_len).order(
    326                         ByteOrder.BIG_ENDIAN);
    327                 floatbuffer = bytebuffer.asFloatBuffer();
    328             }
    329             floatbuffer.position(0);
    330             bytebuffer.position(0);
    331             floatbuffer.put(in_buff, in_offset, in_len);
    332             bytebuffer.get(out_buff, out_offset, out_len);
    333             return out_buff;
    334         }
    335     }
    336 
    337     /***************************************************************************
    338      * 
    339      * 8 bit signed/unsigned
    340      * 
    341      **************************************************************************/
    342 
    343     // PCM 8 bit, signed
    344     private static class AudioFloatConversion8S extends TarsosDSPAudioFloatConverter {
    345         public float[] toFloatArray(byte[] in_buff, int in_offset,
    346                 float[] out_buff, int out_offset, int out_len) {
    347             int ix = in_offset;
    348             int ox = out_offset;
    349             for (int i = 0; i < out_len; i++)
    350                 out_buff[ox++] = in_buff[ix++] * (1.0f / 127.0f);
    351             return out_buff;
    352         }
    353 
    354         public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
    355                 byte[] out_buff, int out_offset) {
    356             int ix = in_offset;
    357             int ox = out_offset;
    358             for (int i = 0; i < in_len; i++)
    359                 out_buff[ox++] = (byte) (in_buff[ix++] * 127.0f);
    360             return out_buff;
    361         }
    362     }
    363 
    364     // PCM 8 bit, unsigned
    365     private static class AudioFloatConversion8U extends TarsosDSPAudioFloatConverter {
    366         public float[] toFloatArray(byte[] in_buff, int in_offset,
    367                 float[] out_buff, int out_offset, int out_len) {
    368             int ix = in_offset;
    369             int ox = out_offset;
    370             for (int i = 0; i < out_len; i++)
    371                 out_buff[ox++] = ((in_buff[ix++] & 0xFF) - 127)
    372                         * (1.0f / 127.0f);
    373             return out_buff;
    374         }
    375 
    376         public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
    377                 byte[] out_buff, int out_offset) {
    378             int ix = in_offset;
    379             int ox = out_offset;
    380             for (int i = 0; i < in_len; i++)
    381                 out_buff[ox++] = (byte) (127 + in_buff[ix++] * 127.0f);
    382             return out_buff;
    383         }
    384     }
    385 
    386     /***************************************************************************
    387      * 
    388      * 16 bit signed/unsigned, little/big-endian
    389      * 
    390      **************************************************************************/
    391 
    392     // PCM 16 bit, signed, little-endian
    393     private static class AudioFloatConversion16SL extends TarsosDSPAudioFloatConverter {
    394         public float[] toFloatArray(byte[] in_buff, int in_offset,
    395                 float[] out_buff, int out_offset, int out_len) {
    396             int ix = in_offset;
    397             int len = out_offset + out_len;
    398             for (int ox = out_offset; ox < len; ox++) {
    399                 out_buff[ox] = ((short) ((in_buff[ix++] & 0xFF) | 
    400                            (in_buff[ix++] << 8))) * (1.0f / 32767.0f);
    401             }
    402 
    403             return out_buff;
    404         }
    405 
    406         public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
    407                 byte[] out_buff, int out_offset) {
    408             int ox = out_offset;
    409             int len = in_offset + in_len;
    410             for (int ix = in_offset; ix < len; ix++) {
    411                 int x = (int) (in_buff[ix] * 32767.0);
    412                 out_buff[ox++] = (byte) x;
    413                 out_buff[ox++] = (byte) (x >>> 8);
    414             }
    415             return out_buff;
    416         }
    417     }
    418 
    419     // PCM 16 bit, signed, big-endian
    420     private static class AudioFloatConversion16SB extends TarsosDSPAudioFloatConverter {
    421         public float[] toFloatArray(byte[] in_buff, int in_offset,
    422                 float[] out_buff, int out_offset, int out_len) {
    423             int ix = in_offset;
    424             int ox = out_offset;
    425             for (int i = 0; i < out_len; i++) {
    426                 out_buff[ox++] = ((short) ((in_buff[ix++] << 8) | 
    427                         (in_buff[ix++] & 0xFF))) * (1.0f / 32767.0f);
    428             }
    429             return out_buff;
    430         }
    431 
    432         public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
    433                 byte[] out_buff, int out_offset) {
    434             int ix = in_offset;
    435             int ox = out_offset;
    436             for (int i = 0; i < in_len; i++) {
    437                 int x = (int) (in_buff[ix++] * 32767.0);
    438                 out_buff[ox++] = (byte) (x >>> 8);
    439                 out_buff[ox++] = (byte) x;
    440             }
    441             return out_buff;
    442         }
    443     }
    444 
    445     // PCM 16 bit, unsigned, little-endian
    446     private static class AudioFloatConversion16UL extends TarsosDSPAudioFloatConverter {
    447         public float[] toFloatArray(byte[] in_buff, int in_offset,
    448                 float[] out_buff, int out_offset, int out_len) {
    449             int ix = in_offset;
    450             int ox = out_offset;
    451             for (int i = 0; i < out_len; i++) {
    452                 int x = (in_buff[ix++] & 0xFF) | ((in_buff[ix++] & 0xFF) << 8);
    453                 out_buff[ox++] = (x - 32767) * (1.0f / 32767.0f);
    454             }
    455             return out_buff;
    456         }
    457 
    458         public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
    459                 byte[] out_buff, int out_offset) {
    460             int ix = in_offset;
    461             int ox = out_offset;
    462             for (int i = 0; i < in_len; i++) {
    463                 int x = 32767 + (int) (in_buff[ix++] * 32767.0);
    464                 out_buff[ox++] = (byte) x;
    465                 out_buff[ox++] = (byte) (x >>> 8);
    466             }
    467             return out_buff;
    468         }
    469     }
    470 
    471     // PCM 16 bit, unsigned, big-endian
    472     private static class AudioFloatConversion16UB extends TarsosDSPAudioFloatConverter {
    473         public float[] toFloatArray(byte[] in_buff, int in_offset,
    474                 float[] out_buff, int out_offset, int out_len) {
    475             int ix = in_offset;
    476             int ox = out_offset;
    477             for (int i = 0; i < out_len; i++) {
    478                 int x = ((in_buff[ix++] & 0xFF) << 8) | (in_buff[ix++] & 0xFF);
    479                 out_buff[ox++] = (x - 32767) * (1.0f / 32767.0f);
    480             }
    481             return out_buff;
    482         }
    483 
    484         public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
    485                 byte[] out_buff, int out_offset) {
    486             int ix = in_offset;
    487             int ox = out_offset;
    488             for (int i = 0; i < in_len; i++) {
    489                 int x = 32767 + (int) (in_buff[ix++] * 32767.0);
    490                 out_buff[ox++] = (byte) (x >>> 8);
    491                 out_buff[ox++] = (byte) x;
    492             }
    493             return out_buff;
    494         }
    495     }
    496 
    497     /***************************************************************************
    498      * 
    499      * 24 bit signed/unsigned, little/big-endian
    500      * 
    501      **************************************************************************/
    502 
    503     // PCM 24 bit, signed, little-endian
    504     private static class AudioFloatConversion24SL extends TarsosDSPAudioFloatConverter {
    505         public float[] toFloatArray(byte[] in_buff, int in_offset,
    506                 float[] out_buff, int out_offset, int out_len) {
    507             int ix = in_offset;
    508             int ox = out_offset;
    509             for (int i = 0; i < out_len; i++) {
    510                 int x = (in_buff[ix++] & 0xFF) | ((in_buff[ix++] & 0xFF) << 8)
    511                         | ((in_buff[ix++] & 0xFF) << 16);
    512                 if (x > 0x7FFFFF)
    513                     x -= 0x1000000;
    514                 out_buff[ox++] = x * (1.0f / (float)0x7FFFFF);
    515             }
    516             return out_buff;
    517         }
    518 
    519         public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
    520                 byte[] out_buff, int out_offset) {
    521             int ix = in_offset;
    522             int ox = out_offset;
    523             for (int i = 0; i < in_len; i++) {
    524                 int x = (int) (in_buff[ix++] * (float)0x7FFFFF);
    525                 if (x < 0)
    526                     x += 0x1000000;
    527                 out_buff[ox++] = (byte) x;
    528                 out_buff[ox++] = (byte) (x >>> 8);
    529                 out_buff[ox++] = (byte) (x >>> 16);
    530             }
    531             return out_buff;
    532         }
    533     }
    534 
    535     // PCM 24 bit, signed, big-endian
    536     private static class AudioFloatConversion24SB extends TarsosDSPAudioFloatConverter {
    537         public float[] toFloatArray(byte[] in_buff, int in_offset,
    538                 float[] out_buff, int out_offset, int out_len) {
    539             int ix = in_offset;
    540             int ox = out_offset;
    541             for (int i = 0; i < out_len; i++) {
    542                 int x = ((in_buff[ix++] & 0xFF) << 16)
    543                         | ((in_buff[ix++] & 0xFF) << 8) | (in_buff[ix++] & 0xFF);
    544                 if (x > 0x7FFFFF)
    545                     x -= 0x1000000;
    546                 out_buff[ox++] = x * (1.0f / (float)0x7FFFFF);
    547             }
    548             return out_buff;
    549         }
    550 
    551         public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
    552                 byte[] out_buff, int out_offset) {
    553             int ix = in_offset;
    554             int ox = out_offset;
    555             for (int i = 0; i < in_len; i++) {
    556                 int x = (int) (in_buff[ix++] * (float)0x7FFFFF);
    557                 if (x < 0)
    558                     x += 0x1000000;
    559                 out_buff[ox++] = (byte) (x >>> 16);
    560                 out_buff[ox++] = (byte) (x >>> 8);
    561                 out_buff[ox++] = (byte) x;
    562             }
    563             return out_buff;
    564         }
    565     }
    566 
    567     // PCM 24 bit, unsigned, little-endian
    568     private static class AudioFloatConversion24UL extends TarsosDSPAudioFloatConverter {
    569         public float[] toFloatArray(byte[] in_buff, int in_offset,
    570                 float[] out_buff, int out_offset, int out_len) {
    571             int ix = in_offset;
    572             int ox = out_offset;
    573             for (int i = 0; i < out_len; i++) {
    574                 int x = (in_buff[ix++] & 0xFF) | ((in_buff[ix++] & 0xFF) << 8)
    575                         | ((in_buff[ix++] & 0xFF) << 16);
    576                 x -= 0x7FFFFF;
    577                 out_buff[ox++] = x * (1.0f / (float)0x7FFFFF);
    578             }
    579             return out_buff;
    580         }
    581 
    582         public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
    583                 byte[] out_buff, int out_offset) {
    584             int ix = in_offset;
    585             int ox = out_offset;
    586             for (int i = 0; i < in_len; i++) {
    587                 int x = (int) (in_buff[ix++] * (float)0x7FFFFF);
    588                 x += 0x7FFFFF;
    589                 out_buff[ox++] = (byte) x;
    590                 out_buff[ox++] = (byte) (x >>> 8);
    591                 out_buff[ox++] = (byte) (x >>> 16);
    592             }
    593             return out_buff;
    594         }
    595     }
    596 
    597     // PCM 24 bit, unsigned, big-endian
    598     private static class AudioFloatConversion24UB extends TarsosDSPAudioFloatConverter {
    599         public float[] toFloatArray(byte[] in_buff, int in_offset,
    600                 float[] out_buff, int out_offset, int out_len) {
    601             int ix = in_offset;
    602             int ox = out_offset;
    603             for (int i = 0; i < out_len; i++) {
    604                 int x = ((in_buff[ix++] & 0xFF) << 16)
    605                         | ((in_buff[ix++] & 0xFF) << 8) | (in_buff[ix++] & 0xFF);
    606                 x -= 0x7FFFFF;
    607                 out_buff[ox++] = x * (1.0f / (float)0x7FFFFF);
    608             }
    609             return out_buff;
    610         }
    611 
    612         public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
    613                 byte[] out_buff, int out_offset) {
    614             int ix = in_offset;
    615             int ox = out_offset;
    616             for (int i = 0; i < in_len; i++) {
    617                 int x = (int) (in_buff[ix++] * (float)0x7FFFFF);
    618                 x += 0x7FFFFF;
    619                 out_buff[ox++] = (byte) (x >>> 16);
    620                 out_buff[ox++] = (byte) (x >>> 8);
    621                 out_buff[ox++] = (byte) x;
    622             }
    623             return out_buff;
    624         }
    625     }
    626 
    627     /***************************************************************************
    628      * 
    629      * 32 bit signed/unsigned, little/big-endian
    630      * 
    631      **************************************************************************/
    632 
    633     // PCM 32 bit, signed, little-endian
    634     private static class AudioFloatConversion32SL extends TarsosDSPAudioFloatConverter {
    635         public float[] toFloatArray(byte[] in_buff, int in_offset,
    636                 float[] out_buff, int out_offset, int out_len) {
    637             int ix = in_offset;
    638             int ox = out_offset;
    639             for (int i = 0; i < out_len; i++) {
    640                 int x = (in_buff[ix++] & 0xFF) | ((in_buff[ix++] & 0xFF) << 8) |
    641                         ((in_buff[ix++] & 0xFF) << 16) |
    642                         ((in_buff[ix++] & 0xFF) << 24);
    643                 out_buff[ox++] = x * (1.0f / (float)0x7FFFFFFF);
    644             }
    645             return out_buff;
    646         }
    647 
    648         public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
    649                 byte[] out_buff, int out_offset) {
    650             int ix = in_offset;
    651             int ox = out_offset;
    652             for (int i = 0; i < in_len; i++) {
    653                 int x = (int) (in_buff[ix++] * (float)0x7FFFFFFF);
    654                 out_buff[ox++] = (byte) x;
    655                 out_buff[ox++] = (byte) (x >>> 8);
    656                 out_buff[ox++] = (byte) (x >>> 16);
    657                 out_buff[ox++] = (byte) (x >>> 24);
    658             }
    659             return out_buff;
    660         }
    661     }
    662 
    663     // PCM 32 bit, signed, big-endian
    664     private static class AudioFloatConversion32SB extends TarsosDSPAudioFloatConverter {
    665         public float[] toFloatArray(byte[] in_buff, int in_offset,
    666                 float[] out_buff, int out_offset, int out_len) {
    667             int ix = in_offset;
    668             int ox = out_offset;
    669             for (int i = 0; i < out_len; i++) {
    670                 int x = ((in_buff[ix++] & 0xFF) << 24) |
    671                         ((in_buff[ix++] & 0xFF) << 16) |
    672                         ((in_buff[ix++] & 0xFF) << 8) | (in_buff[ix++] & 0xFF);
    673                 out_buff[ox++] = x * (1.0f / (float)0x7FFFFFFF);
    674             }
    675             return out_buff;
    676         }
    677 
    678         public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
    679                 byte[] out_buff, int out_offset) {
    680             int ix = in_offset;
    681             int ox = out_offset;
    682             for (int i = 0; i < in_len; i++) {
    683                 int x = (int) (in_buff[ix++] * (float)0x7FFFFFFF);
    684                 out_buff[ox++] = (byte) (x >>> 24);
    685                 out_buff[ox++] = (byte) (x >>> 16);
    686                 out_buff[ox++] = (byte) (x >>> 8);
    687                 out_buff[ox++] = (byte) x;
    688             }
    689             return out_buff;
    690         }
    691     }
    692 
    693     // PCM 32 bit, unsigned, little-endian
    694     private static class AudioFloatConversion32UL extends TarsosDSPAudioFloatConverter {
    695         public float[] toFloatArray(byte[] in_buff, int in_offset,
    696                 float[] out_buff, int out_offset, int out_len) {
    697             int ix = in_offset;
    698             int ox = out_offset;
    699             for (int i = 0; i < out_len; i++) {
    700                 int x = (in_buff[ix++] & 0xFF) | ((in_buff[ix++] & 0xFF) << 8) |
    701                         ((in_buff[ix++] & 0xFF) << 16) | 
    702                         ((in_buff[ix++] & 0xFF) << 24);
    703                 x -= 0x7FFFFFFF;
    704                 out_buff[ox++] = x * (1.0f / (float)0x7FFFFFFF);
    705             }
    706             return out_buff;
    707         }
    708 
    709         public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
    710                 byte[] out_buff, int out_offset) {
    711             int ix = in_offset;
    712             int ox = out_offset;
    713             for (int i = 0; i < in_len; i++) {
    714                 int x = (int) (in_buff[ix++] * (float)0x7FFFFFFF);
    715                 x += 0x7FFFFFFF;
    716                 out_buff[ox++] = (byte) x;
    717                 out_buff[ox++] = (byte) (x >>> 8);
    718                 out_buff[ox++] = (byte) (x >>> 16);
    719                 out_buff[ox++] = (byte) (x >>> 24);
    720             }
    721             return out_buff;
    722         }
    723     }
    724 
    725     // PCM 32 bit, unsigned, big-endian
    726     private static class AudioFloatConversion32UB extends TarsosDSPAudioFloatConverter {
    727 
    728         public float[] toFloatArray(byte[] in_buff, int in_offset,
    729                 float[] out_buff, int out_offset, int out_len) {
    730             int ix = in_offset;
    731             int ox = out_offset;
    732             for (int i = 0; i < out_len; i++) {
    733                 int x = ((in_buff[ix++] & 0xFF) << 24) |
    734                         ((in_buff[ix++] & 0xFF) << 16) |
    735                         ((in_buff[ix++] & 0xFF) << 8) | (in_buff[ix++] & 0xFF);
    736                 x -= 0x7FFFFFFF;
    737                 out_buff[ox++] = x * (1.0f / (float)0x7FFFFFFF);
    738             }
    739             return out_buff;
    740         }
    741 
    742         public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
    743                 byte[] out_buff, int out_offset) {
    744             int ix = in_offset;
    745             int ox = out_offset;
    746             for (int i = 0; i < in_len; i++) {
    747                 int x = (int) (in_buff[ix++] * (float)0x7FFFFFFF);
    748                 x += 0x7FFFFFFF;
    749                 out_buff[ox++] = (byte) (x >>> 24);
    750                 out_buff[ox++] = (byte) (x >>> 16);
    751                 out_buff[ox++] = (byte) (x >>> 8);
    752                 out_buff[ox++] = (byte) x;
    753             }
    754             return out_buff;
    755         }
    756     }
    757 
    758     /***************************************************************************
    759      * 
    760      * 32+ bit signed/unsigned, little/big-endian
    761      * 
    762      **************************************************************************/
    763 
    764     // PCM 32+ bit, signed, little-endian
    765     private static class AudioFloatConversion32xSL extends TarsosDSPAudioFloatConverter {
    766 
    767         final int xbytes;
    768 
    769         public AudioFloatConversion32xSL(int xbytes) {
    770             this.xbytes = xbytes;
    771         }
    772 
    773         public float[] toFloatArray(byte[] in_buff, int in_offset,
    774                 float[] out_buff, int out_offset, int out_len) {
    775             int ix = in_offset;
    776             int ox = out_offset;
    777             for (int i = 0; i < out_len; i++) {
    778                 ix += xbytes;
    779                 int x = (in_buff[ix++] & 0xFF) | ((in_buff[ix++] & 0xFF) << 8)
    780                         | ((in_buff[ix++] & 0xFF) << 16)
    781                         | ((in_buff[ix++] & 0xFF) << 24);
    782                 out_buff[ox++] = x * (1.0f / (float)0x7FFFFFFF);
    783             }
    784             return out_buff;
    785         }
    786 
    787         public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
    788                 byte[] out_buff, int out_offset) {
    789             int ix = in_offset;
    790             int ox = out_offset;
    791             for (int i = 0; i < in_len; i++) {
    792                 int x = (int) (in_buff[ix++] * (float)0x7FFFFFFF);
    793                 for (int j = 0; j < xbytes; j++) {
    794                     out_buff[ox++] = 0;
    795                 }
    796                 out_buff[ox++] = (byte) x;
    797                 out_buff[ox++] = (byte) (x >>> 8);
    798                 out_buff[ox++] = (byte) (x >>> 16);
    799                 out_buff[ox++] = (byte) (x >>> 24);
    800             }
    801             return out_buff;
    802         }
    803     }
    804 
    805     // PCM 32+ bit, signed, big-endian
    806     private static class AudioFloatConversion32xSB extends TarsosDSPAudioFloatConverter {
    807 
    808         final int xbytes;
    809 
    810         public AudioFloatConversion32xSB(int xbytes) {
    811             this.xbytes = xbytes;
    812         }
    813 
    814         public float[] toFloatArray(byte[] in_buff, int in_offset,
    815                 float[] out_buff, int out_offset, int out_len) {
    816             int ix = in_offset;
    817             int ox = out_offset;
    818             for (int i = 0; i < out_len; i++) {
    819                 int x = ((in_buff[ix++] & 0xFF) << 24)
    820                         | ((in_buff[ix++] & 0xFF) << 16)
    821                         | ((in_buff[ix++] & 0xFF) << 8)
    822                         | (in_buff[ix++] & 0xFF);
    823                 ix += xbytes;
    824                 out_buff[ox++] = x * (1.0f / (float)0x7FFFFFFF);
    825             }
    826             return out_buff;
    827         }
    828 
    829         public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
    830                 byte[] out_buff, int out_offset) {
    831             int ix = in_offset;
    832             int ox = out_offset;
    833             for (int i = 0; i < in_len; i++) {
    834                 int x = (int) (in_buff[ix++] * (float)0x7FFFFFFF);
    835                 out_buff[ox++] = (byte) (x >>> 24);
    836                 out_buff[ox++] = (byte) (x >>> 16);
    837                 out_buff[ox++] = (byte) (x >>> 8);
    838                 out_buff[ox++] = (byte) x;
    839                 for (int j = 0; j < xbytes; j++) {
    840                     out_buff[ox++] = 0;
    841                 }
    842             }
    843             return out_buff;
    844         }
    845     }
    846 
    847     // PCM 32+ bit, unsigned, little-endian
    848     private static class AudioFloatConversion32xUL extends TarsosDSPAudioFloatConverter {
    849 
    850         final int xbytes;
    851 
    852         public AudioFloatConversion32xUL(int xbytes) {
    853             this.xbytes = xbytes;
    854         }
    855 
    856         public float[] toFloatArray(byte[] in_buff, int in_offset,
    857                 float[] out_buff, int out_offset, int out_len) {
    858             int ix = in_offset;
    859             int ox = out_offset;
    860             for (int i = 0; i < out_len; i++) {
    861                 ix += xbytes;
    862                 int x = (in_buff[ix++] & 0xFF) | ((in_buff[ix++] & 0xFF) << 8)
    863                         | ((in_buff[ix++] & 0xFF) << 16)
    864                         | ((in_buff[ix++] & 0xFF) << 24);
    865                 x -= 0x7FFFFFFF;
    866                 out_buff[ox++] = x * (1.0f / (float)0x7FFFFFFF);
    867             }
    868             return out_buff;
    869         }
    870 
    871         public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
    872                 byte[] out_buff, int out_offset) {
    873             int ix = in_offset;
    874             int ox = out_offset;
    875             for (int i = 0; i < in_len; i++) {
    876                 int x = (int) (in_buff[ix++] * (float)0x7FFFFFFF);
    877                 x += 0x7FFFFFFF;
    878                 for (int j = 0; j < xbytes; j++) {
    879                     out_buff[ox++] = 0;
    880                 }
    881                 out_buff[ox++] = (byte) x;
    882                 out_buff[ox++] = (byte) (x >>> 8);
    883                 out_buff[ox++] = (byte) (x >>> 16);
    884                 out_buff[ox++] = (byte) (x >>> 24);
    885             }
    886             return out_buff;
    887         }
    888     }
    889 
    890     // PCM 32+ bit, unsigned, big-endian
    891     private static class AudioFloatConversion32xUB extends TarsosDSPAudioFloatConverter {
    892 
    893         final int xbytes;
    894 
    895         public AudioFloatConversion32xUB(int xbytes) {
    896             this.xbytes = xbytes;
    897         }
    898 
    899         public float[] toFloatArray(byte[] in_buff, int in_offset,
    900                 float[] out_buff, int out_offset, int out_len) {
    901             int ix = in_offset;
    902             int ox = out_offset;
    903             for (int i = 0; i < out_len; i++) {
    904                 int x = ((in_buff[ix++] & 0xFF) << 24) |
    905                         ((in_buff[ix++] & 0xFF) << 16) |
    906                         ((in_buff[ix++] & 0xFF) << 8) | (in_buff[ix++] & 0xFF);
    907                 ix += xbytes;
    908                 x -= 2147483647;
    909                 out_buff[ox++] = x * (1.0f / 2147483647.0f);
    910             }
    911             return out_buff;
    912         }
    913 
    914         public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
    915                 byte[] out_buff, int out_offset) {
    916             int ix = in_offset;
    917             int ox = out_offset;
    918             for (int i = 0; i < in_len; i++) {
    919                 int x = (int) (in_buff[ix++] * 2147483647.0);
    920                 x += 2147483647;
    921                 out_buff[ox++] = (byte) (x >>> 24);
    922                 out_buff[ox++] = (byte) (x >>> 16);
    923                 out_buff[ox++] = (byte) (x >>> 8);
    924                 out_buff[ox++] = (byte) x;
    925                 for (int j = 0; j < xbytes; j++) {
    926                     out_buff[ox++] = 0;
    927                 }
    928             }
    929             return out_buff;
    930         }
    931     }
    932 
    933     public static TarsosDSPAudioFloatConverter getConverter(TarsosDSPAudioFormat format) {
    934         TarsosDSPAudioFloatConverter conv = null;
    935         if (format.getFrameSize() == 0)
    936             return null;
    937         if (format.getFrameSize() != 
    938                 ((format.getSampleSizeInBits() + 7) / 8) * format.getChannels()) {
    939             return null;
    940         }
    941         if (format.getEncoding().equals(Encoding.PCM_SIGNED)) {
    942             if (format.isBigEndian()) {
    943                 if (format.getSampleSizeInBits() <= 8) {
    944                     conv = new AudioFloatConversion8S();
    945                 } else if (format.getSampleSizeInBits() > 8 &&
    946                       format.getSampleSizeInBits() <= 16) {
    947                     conv = new AudioFloatConversion16SB();
    948                 } else if (format.getSampleSizeInBits() > 16 &&
    949                       format.getSampleSizeInBits() <= 24) {
    950                     conv = new AudioFloatConversion24SB();
    951                 } else if (format.getSampleSizeInBits() > 24 &&
    952                       format.getSampleSizeInBits() <= 32) {
    953                     conv = new AudioFloatConversion32SB();
    954                 } else if (format.getSampleSizeInBits() > 32) {
    955                     conv = new AudioFloatConversion32xSB(((format
    956                             .getSampleSizeInBits() + 7) / 8) - 4);
    957                 } 
    958             } else {
    959                 if (format.getSampleSizeInBits() <= 8) {
    960                     conv = new AudioFloatConversion8S();
    961                 } else if (format.getSampleSizeInBits() > 8 &&
    962                          format.getSampleSizeInBits() <= 16) {
    963                     conv = new AudioFloatConversion16SL();
    964                 } else if (format.getSampleSizeInBits() > 16 &&
    965                          format.getSampleSizeInBits() <= 24) {
    966                     conv = new AudioFloatConversion24SL();
    967                 } else if (format.getSampleSizeInBits() > 24 &&
    968                          format.getSampleSizeInBits() <= 32) {
    969                     conv = new AudioFloatConversion32SL();
    970                 } else if (format.getSampleSizeInBits() > 32) {
    971                     conv = new AudioFloatConversion32xSL(((format
    972                             .getSampleSizeInBits() + 7) / 8) - 4);
    973                 }
    974             }
    975         } else if (format.getEncoding().equals(Encoding.PCM_UNSIGNED)) {
    976             if (format.isBigEndian()) {
    977                 if (format.getSampleSizeInBits() <= 8) {
    978                     conv = new AudioFloatConversion8U();
    979                 } else if (format.getSampleSizeInBits() > 8 &&
    980                         format.getSampleSizeInBits() <= 16) {
    981                     conv = new AudioFloatConversion16UB();
    982                 } else if (format.getSampleSizeInBits() > 16 &&
    983                         format.getSampleSizeInBits() <= 24) {
    984                     conv = new AudioFloatConversion24UB();
    985                 } else if (format.getSampleSizeInBits() > 24 &&
    986                         format.getSampleSizeInBits() <= 32) {
    987                     conv = new AudioFloatConversion32UB();
    988                 } else if (format.getSampleSizeInBits() > 32) {
    989                     conv = new AudioFloatConversion32xUB(((
    990                             format.getSampleSizeInBits() + 7) / 8) - 4);
    991                 }
    992             } else {
    993                 if (format.getSampleSizeInBits() <= 8) {
    994                     conv = new AudioFloatConversion8U();
    995                 } else if (format.getSampleSizeInBits() > 8 &&
    996                         format.getSampleSizeInBits() <= 16) {
    997                     conv = new AudioFloatConversion16UL();
    998                 } else if (format.getSampleSizeInBits() > 16 &&
    999                         format.getSampleSizeInBits() <= 24) {
   1000                     conv = new AudioFloatConversion24UL();
   1001                 } else if (format.getSampleSizeInBits() > 24 &&
   1002                         format.getSampleSizeInBits() <= 32) {
   1003                     conv = new AudioFloatConversion32UL();
   1004                 } else if (format.getSampleSizeInBits() > 32) {
   1005                     conv = new AudioFloatConversion32xUL(((
   1006                             format.getSampleSizeInBits() + 7) / 8) - 4);
   1007                 }
   1008             }
   1009         } else if (format.getEncoding().equals(PCM_FLOAT)) {
   1010             if (format.getSampleSizeInBits() == 32) {
   1011                 if (format.isBigEndian())
   1012                     conv = new AudioFloatConversion32B();
   1013                 else
   1014                     conv = new AudioFloatConversion32L();
   1015             } else if (format.getSampleSizeInBits() == 64) {
   1016                 if (format.isBigEndian()) 
   1017                     conv = new AudioFloatConversion64B();
   1018                 else 
   1019                     conv = new AudioFloatConversion64L();                
   1020             }
   1021 
   1022         }
   1023 
   1024         if ((format.getEncoding().equals(Encoding.PCM_SIGNED) || 
   1025                 format.getEncoding().equals(Encoding.PCM_UNSIGNED)) && 
   1026                 (format.getSampleSizeInBits() % 8 != 0)) {
   1027             conv = new AudioFloatLSBFilter(conv, format);
   1028         }
   1029 
   1030         if (conv != null)
   1031             conv.format = format;
   1032         return conv;
   1033     }
   1034 
   1035     private TarsosDSPAudioFormat format;
   1036 
   1037     public TarsosDSPAudioFormat getFormat() {
   1038         return format;
   1039     }
   1040 
   1041     public abstract float[] toFloatArray(byte[] in_buff, int in_offset,
   1042             float[] out_buff, int out_offset, int out_len);
   1043 
   1044     public float[] toFloatArray(byte[] in_buff, float[] out_buff,
   1045             int out_offset, int out_len) {
   1046         return toFloatArray(in_buff, 0, out_buff, out_offset, out_len);
   1047     }
   1048 
   1049     public float[] toFloatArray(byte[] in_buff, int in_offset,
   1050             float[] out_buff, int out_len) {
   1051         return toFloatArray(in_buff, in_offset, out_buff, 0, out_len);
   1052     }
   1053 
   1054     public float[] toFloatArray(byte[] in_buff, float[] out_buff, int out_len) {
   1055         return toFloatArray(in_buff, 0, out_buff, 0, out_len);
   1056     }
   1057 
   1058     public float[] toFloatArray(byte[] in_buff, float[] out_buff) {
   1059         return toFloatArray(in_buff, 0, out_buff, 0, out_buff.length);
   1060     }
   1061 
   1062     public abstract byte[] toByteArray(float[] in_buff, int in_offset,
   1063             int in_len, byte[] out_buff, int out_offset);
   1064 
   1065     public byte[] toByteArray(float[] in_buff, int in_len, byte[] out_buff,
   1066             int out_offset) {
   1067         return toByteArray(in_buff, 0, in_len, out_buff, out_offset);
   1068     }
   1069 
   1070     public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
   1071             byte[] out_buff) {
   1072         return toByteArray(in_buff, in_offset, in_len, out_buff, 0);
   1073     }
   1074 
   1075     public byte[] toByteArray(float[] in_buff, int in_len, byte[] out_buff) {
   1076         return toByteArray(in_buff, 0, in_len, out_buff, 0);
   1077     }
   1078 
   1079     public byte[] toByteArray(float[] in_buff, byte[] out_buff) {
   1080         return toByteArray(in_buff, 0, in_buff.length, out_buff, 0);
   1081     }
   1082 }