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 
AudioFloatLSBFilter(AudioFloatConverter converter, AudioFormat format)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
toByteArray(float[] in_buff, int in_offset, int in_len, byte[] out_buff, int out_offset)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
toFloatArray(byte[] in_buff, int in_offset, float[] out_buff, int out_offset, int out_len)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
toFloatArray(byte[] in_buff, int in_offset, float[] out_buff, int out_offset, int out_len)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
toByteArray(float[] in_buff, int in_offset, int in_len, byte[] out_buff, int out_offset)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
toFloatArray(byte[] in_buff, int in_offset, float[] out_buff, int out_offset, int out_len)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
toByteArray(float[] in_buff, int in_offset, int in_len, byte[] out_buff, int out_offset)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
toFloatArray(byte[] in_buff, int in_offset, float[] out_buff, int out_offset, int out_len)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
toByteArray(float[] in_buff, int in_offset, int in_len, byte[] out_buff, int out_offset)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
toFloatArray(byte[] in_buff, int in_offset, float[] out_buff, int out_offset, int out_len)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
toByteArray(float[] in_buff, int in_offset, int in_len, byte[] out_buff, int out_offset)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
toFloatArray(byte[] in_buff, int in_offset, float[] out_buff, int out_offset, int out_len)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
toByteArray(float[] in_buff, int in_offset, int in_len, byte[] out_buff, int out_offset)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
toFloatArray(byte[] in_buff, int in_offset, float[] out_buff, int out_offset, int out_len)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
toByteArray(float[] in_buff, int in_offset, int in_len, byte[] out_buff, int out_offset)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
toFloatArray(byte[] in_buff, int in_offset, float[] out_buff, int out_offset, int out_len)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
toByteArray(float[] in_buff, int in_offset, int in_len, byte[] out_buff, int out_offset)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
toFloatArray(byte[] in_buff, int in_offset, float[] out_buff, int out_offset, int out_len)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
toByteArray(float[] in_buff, int in_offset, int in_len, byte[] out_buff, int out_offset)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
toFloatArray(byte[] in_buff, int in_offset, float[] out_buff, int out_offset, int out_len)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
toByteArray(float[] in_buff, int in_offset, int in_len, byte[] out_buff, int out_offset)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
toFloatArray(byte[] in_buff, int in_offset, float[] out_buff, int out_offset, int out_len)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
toByteArray(float[] in_buff, int in_offset, int in_len, byte[] out_buff, int out_offset)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
toFloatArray(byte[] in_buff, int in_offset, float[] out_buff, int out_offset, int out_len)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
toByteArray(float[] in_buff, int in_offset, int in_len, byte[] out_buff, int out_offset)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
toFloatArray(byte[] in_buff, int in_offset, float[] out_buff, int out_offset, int out_len)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
toByteArray(float[] in_buff, int in_offset, int in_len, byte[] out_buff, int out_offset)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
toFloatArray(byte[] in_buff, int in_offset, float[] out_buff, int out_offset, int out_len)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
toByteArray(float[] in_buff, int in_offset, int in_len, byte[] out_buff, int out_offset)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
toFloatArray(byte[] in_buff, int in_offset, float[] out_buff, int out_offset, int out_len)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
toByteArray(float[] in_buff, int in_offset, int in_len, byte[] out_buff, int out_offset)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
toFloatArray(byte[] in_buff, int in_offset, float[] out_buff, int out_offset, int out_len)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
toByteArray(float[] in_buff, int in_offset, int in_len, byte[] out_buff, int out_offset)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
toFloatArray(byte[] in_buff, int in_offset, float[] out_buff, int out_offset, int out_len)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
toByteArray(float[] in_buff, int in_offset, int in_len, byte[] out_buff, int out_offset)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
toFloatArray(byte[] in_buff, int in_offset, float[] out_buff, int out_offset, int out_len)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
toByteArray(float[] in_buff, int in_offset, int in_len, byte[] out_buff, int out_offset)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
toFloatArray(byte[] in_buff, int in_offset, float[] out_buff, int out_offset, int out_len)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
toByteArray(float[] in_buff, int in_offset, int in_len, byte[] out_buff, int out_offset)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 
AudioFloatConversion32xSL(int xbytes)797         AudioFloatConversion32xSL(int xbytes) {
798             this.xbytes = xbytes;
799         }
800 
801         @Override
toFloatArray(byte[] in_buff, int in_offset, float[] out_buff, int out_offset, int out_len)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
toByteArray(float[] in_buff, int in_offset, int in_len, byte[] out_buff, int out_offset)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 
AudioFloatConversion32xSB(int xbytes)840         AudioFloatConversion32xSB(int xbytes) {
841             this.xbytes = xbytes;
842         }
843 
844         @Override
toFloatArray(byte[] in_buff, int in_offset, float[] out_buff, int out_offset, int out_len)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
toByteArray(float[] in_buff, int in_offset, int in_len, byte[] out_buff, int out_offset)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 
AudioFloatConversion32xUL(int xbytes)884         AudioFloatConversion32xUL(int xbytes) {
885             this.xbytes = xbytes;
886         }
887 
888         @Override
toFloatArray(byte[] in_buff, int in_offset, float[] out_buff, int out_offset, int out_len)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
toByteArray(float[] in_buff, int in_offset, int in_len, byte[] out_buff, int out_offset)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 
AudioFloatConversion32xUB(int xbytes)929         AudioFloatConversion32xUB(int xbytes) {
930             this.xbytes = xbytes;
931         }
932 
933         @Override
toFloatArray(byte[] in_buff, int in_offset, float[] out_buff, int out_offset, int out_len)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
toByteArray(float[] in_buff, int in_offset, int in_len, byte[] out_buff, int out_offset)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 
getConverter(AudioFormat format)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 
getFormat()1073     public final AudioFormat getFormat() {
1074         return format;
1075     }
1076 
toFloatArray(byte[] in_buff, int in_offset, float[] out_buff, int out_offset, int out_len)1077     public abstract float[] toFloatArray(byte[] in_buff, int in_offset,
1078             float[] out_buff, int out_offset, int out_len);
1079 
toFloatArray(byte[] in_buff, float[] out_buff, int out_offset, int out_len)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 
toFloatArray(byte[] in_buff, int in_offset, float[] out_buff, int out_len)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 
toFloatArray(byte[] in_buff, float[] out_buff, int out_len)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 
toFloatArray(byte[] in_buff, float[] out_buff)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 
toByteArray(float[] in_buff, int in_offset, int in_len, byte[] out_buff, int out_offset)1099     public abstract byte[] toByteArray(float[] in_buff, int in_offset,
1100             int in_len, byte[] out_buff, int out_offset);
1101 
toByteArray(float[] in_buff, int in_len, byte[] out_buff, int out_offset)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 
toByteArray(float[] in_buff, int in_offset, int in_len, byte[] out_buff)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 
toByteArray(float[] in_buff, int in_len, byte[] out_buff)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 
toByteArray(float[] in_buff, byte[] out_buff)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