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