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