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
26package com.sun.media.sound;
27
28import java.nio.ByteBuffer;
29import java.nio.ByteOrder;
30import java.nio.DoubleBuffer;
31import java.nio.FloatBuffer;
32
33import javax.sound.sampled.AudioFormat;
34import 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 */
42public 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}
1121