|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
package com.sun.media.sound; |
|
|
|
import java.nio.ByteBuffer; |
|
import java.nio.ByteOrder; |
|
import java.nio.DoubleBuffer; |
|
import java.nio.FloatBuffer; |
|
|
|
import javax.sound.sampled.AudioFormat; |
|
import javax.sound.sampled.AudioFormat.Encoding; |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public abstract class AudioFloatConverter { |
|
|
|
/*************************************************************************** |
|
* |
|
* LSB Filter, used filter least significant byte in samples arrays. |
|
* |
|
* Is used filter out data in lsb byte when SampleSizeInBits is not |
|
* dividable by 8. |
|
* |
|
**************************************************************************/ |
|
|
|
private static class AudioFloatLSBFilter extends AudioFloatConverter { |
|
|
|
private final AudioFloatConverter converter; |
|
|
|
final private int offset; |
|
|
|
final private int stepsize; |
|
|
|
final private byte mask; |
|
|
|
private byte[] mask_buffer; |
|
|
|
AudioFloatLSBFilter(AudioFloatConverter converter, AudioFormat format) { |
|
int bits = format.getSampleSizeInBits(); |
|
boolean bigEndian = format.isBigEndian(); |
|
this.converter = converter; |
|
stepsize = (bits + 7) / 8; |
|
offset = bigEndian ? (stepsize - 1) : 0; |
|
int lsb_bits = bits % 8; |
|
if (lsb_bits == 0) |
|
mask = (byte) 0x00; |
|
else if (lsb_bits == 1) |
|
mask = (byte) 0x80; |
|
else if (lsb_bits == 2) |
|
mask = (byte) 0xC0; |
|
else if (lsb_bits == 3) |
|
mask = (byte) 0xE0; |
|
else if (lsb_bits == 4) |
|
mask = (byte) 0xF0; |
|
else if (lsb_bits == 5) |
|
mask = (byte) 0xF8; |
|
else if (lsb_bits == 6) |
|
mask = (byte) 0xFC; |
|
else if (lsb_bits == 7) |
|
mask = (byte) 0xFE; |
|
else |
|
mask = (byte) 0xFF; |
|
} |
|
|
|
public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, |
|
byte[] out_buff, int out_offset) { |
|
byte[] ret = converter.toByteArray(in_buff, in_offset, in_len, |
|
out_buff, out_offset); |
|
|
|
int out_offset_end = in_len * stepsize; |
|
for (int i = out_offset + offset; i < out_offset_end; i += stepsize) { |
|
out_buff[i] = (byte) (out_buff[i] & mask); |
|
} |
|
|
|
return ret; |
|
} |
|
|
|
public float[] toFloatArray(byte[] in_buff, int in_offset, |
|
float[] out_buff, int out_offset, int out_len) { |
|
if (mask_buffer == null || mask_buffer.length < in_buff.length) |
|
mask_buffer = new byte[in_buff.length]; |
|
System.arraycopy(in_buff, 0, mask_buffer, 0, in_buff.length); |
|
int in_offset_end = out_len * stepsize; |
|
for (int i = in_offset + offset; i < in_offset_end; i += stepsize) { |
|
mask_buffer[i] = (byte) (mask_buffer[i] & mask); |
|
} |
|
float[] ret = converter.toFloatArray(mask_buffer, in_offset, |
|
out_buff, out_offset, out_len); |
|
return ret; |
|
} |
|
|
|
} |
|
|
|
/*************************************************************************** |
|
* |
|
* 64 bit float, little/big-endian |
|
* |
|
**************************************************************************/ |
|
|
|
|
|
private static class AudioFloatConversion64L extends AudioFloatConverter { |
|
ByteBuffer bytebuffer = null; |
|
|
|
DoubleBuffer floatbuffer = null; |
|
|
|
double[] double_buff = null; |
|
|
|
public float[] toFloatArray(byte[] in_buff, int in_offset, |
|
float[] out_buff, int out_offset, int out_len) { |
|
int in_len = out_len * 8; |
|
if (bytebuffer == null || bytebuffer.capacity() < in_len) { |
|
bytebuffer = ByteBuffer.allocate(in_len).order( |
|
ByteOrder.LITTLE_ENDIAN); |
|
floatbuffer = bytebuffer.asDoubleBuffer(); |
|
} |
|
bytebuffer.position(0); |
|
floatbuffer.position(0); |
|
bytebuffer.put(in_buff, in_offset, in_len); |
|
if (double_buff == null |
|
|| double_buff.length < out_len + out_offset) |
|
double_buff = new double[out_len + out_offset]; |
|
floatbuffer.get(double_buff, out_offset, out_len); |
|
int out_offset_end = out_offset + out_len; |
|
for (int i = out_offset; i < out_offset_end; i++) { |
|
out_buff[i] = (float) double_buff[i]; |
|
} |
|
return out_buff; |
|
} |
|
|
|
public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, |
|
byte[] out_buff, int out_offset) { |
|
int out_len = in_len * 8; |
|
if (bytebuffer == null || bytebuffer.capacity() < out_len) { |
|
bytebuffer = ByteBuffer.allocate(out_len).order( |
|
ByteOrder.LITTLE_ENDIAN); |
|
floatbuffer = bytebuffer.asDoubleBuffer(); |
|
} |
|
floatbuffer.position(0); |
|
bytebuffer.position(0); |
|
if (double_buff == null || double_buff.length < in_offset + in_len) |
|
double_buff = new double[in_offset + in_len]; |
|
int in_offset_end = in_offset + in_len; |
|
for (int i = in_offset; i < in_offset_end; i++) { |
|
double_buff[i] = in_buff[i]; |
|
} |
|
floatbuffer.put(double_buff, in_offset, in_len); |
|
bytebuffer.get(out_buff, out_offset, out_len); |
|
return out_buff; |
|
} |
|
} |
|
|
|
|
|
private static class AudioFloatConversion64B extends AudioFloatConverter { |
|
ByteBuffer bytebuffer = null; |
|
|
|
DoubleBuffer floatbuffer = null; |
|
|
|
double[] double_buff = null; |
|
|
|
public float[] toFloatArray(byte[] in_buff, int in_offset, |
|
float[] out_buff, int out_offset, int out_len) { |
|
int in_len = out_len * 8; |
|
if (bytebuffer == null || bytebuffer.capacity() < in_len) { |
|
bytebuffer = ByteBuffer.allocate(in_len).order( |
|
ByteOrder.BIG_ENDIAN); |
|
floatbuffer = bytebuffer.asDoubleBuffer(); |
|
} |
|
bytebuffer.position(0); |
|
floatbuffer.position(0); |
|
bytebuffer.put(in_buff, in_offset, in_len); |
|
if (double_buff == null |
|
|| double_buff.length < out_len + out_offset) |
|
double_buff = new double[out_len + out_offset]; |
|
floatbuffer.get(double_buff, out_offset, out_len); |
|
int out_offset_end = out_offset + out_len; |
|
for (int i = out_offset; i < out_offset_end; i++) { |
|
out_buff[i] = (float) double_buff[i]; |
|
} |
|
return out_buff; |
|
} |
|
|
|
public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, |
|
byte[] out_buff, int out_offset) { |
|
int out_len = in_len * 8; |
|
if (bytebuffer == null || bytebuffer.capacity() < out_len) { |
|
bytebuffer = ByteBuffer.allocate(out_len).order( |
|
ByteOrder.BIG_ENDIAN); |
|
floatbuffer = bytebuffer.asDoubleBuffer(); |
|
} |
|
floatbuffer.position(0); |
|
bytebuffer.position(0); |
|
if (double_buff == null || double_buff.length < in_offset + in_len) |
|
double_buff = new double[in_offset + in_len]; |
|
int in_offset_end = in_offset + in_len; |
|
for (int i = in_offset; i < in_offset_end; i++) { |
|
double_buff[i] = in_buff[i]; |
|
} |
|
floatbuffer.put(double_buff, in_offset, in_len); |
|
bytebuffer.get(out_buff, out_offset, out_len); |
|
return out_buff; |
|
} |
|
} |
|
|
|
/*************************************************************************** |
|
* |
|
* 32 bit float, little/big-endian |
|
* |
|
**************************************************************************/ |
|
|
|
|
|
private static class AudioFloatConversion32L extends AudioFloatConverter { |
|
ByteBuffer bytebuffer = null; |
|
|
|
FloatBuffer floatbuffer = null; |
|
|
|
public float[] toFloatArray(byte[] in_buff, int in_offset, |
|
float[] out_buff, int out_offset, int out_len) { |
|
int in_len = out_len * 4; |
|
if (bytebuffer == null || bytebuffer.capacity() < in_len) { |
|
bytebuffer = ByteBuffer.allocate(in_len).order( |
|
ByteOrder.LITTLE_ENDIAN); |
|
floatbuffer = bytebuffer.asFloatBuffer(); |
|
} |
|
bytebuffer.position(0); |
|
floatbuffer.position(0); |
|
bytebuffer.put(in_buff, in_offset, in_len); |
|
floatbuffer.get(out_buff, out_offset, out_len); |
|
return out_buff; |
|
} |
|
|
|
public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, |
|
byte[] out_buff, int out_offset) { |
|
int out_len = in_len * 4; |
|
if (bytebuffer == null || bytebuffer.capacity() < out_len) { |
|
bytebuffer = ByteBuffer.allocate(out_len).order( |
|
ByteOrder.LITTLE_ENDIAN); |
|
floatbuffer = bytebuffer.asFloatBuffer(); |
|
} |
|
floatbuffer.position(0); |
|
bytebuffer.position(0); |
|
floatbuffer.put(in_buff, in_offset, in_len); |
|
bytebuffer.get(out_buff, out_offset, out_len); |
|
return out_buff; |
|
} |
|
} |
|
|
|
|
|
private static class AudioFloatConversion32B extends AudioFloatConverter { |
|
ByteBuffer bytebuffer = null; |
|
|
|
FloatBuffer floatbuffer = null; |
|
|
|
public float[] toFloatArray(byte[] in_buff, int in_offset, |
|
float[] out_buff, int out_offset, int out_len) { |
|
int in_len = out_len * 4; |
|
if (bytebuffer == null || bytebuffer.capacity() < in_len) { |
|
bytebuffer = ByteBuffer.allocate(in_len).order( |
|
ByteOrder.BIG_ENDIAN); |
|
floatbuffer = bytebuffer.asFloatBuffer(); |
|
} |
|
bytebuffer.position(0); |
|
floatbuffer.position(0); |
|
bytebuffer.put(in_buff, in_offset, in_len); |
|
floatbuffer.get(out_buff, out_offset, out_len); |
|
return out_buff; |
|
} |
|
|
|
public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, |
|
byte[] out_buff, int out_offset) { |
|
int out_len = in_len * 4; |
|
if (bytebuffer == null || bytebuffer.capacity() < out_len) { |
|
bytebuffer = ByteBuffer.allocate(out_len).order( |
|
ByteOrder.BIG_ENDIAN); |
|
floatbuffer = bytebuffer.asFloatBuffer(); |
|
} |
|
floatbuffer.position(0); |
|
bytebuffer.position(0); |
|
floatbuffer.put(in_buff, in_offset, in_len); |
|
bytebuffer.get(out_buff, out_offset, out_len); |
|
return out_buff; |
|
} |
|
} |
|
|
|
/*************************************************************************** |
|
* |
|
* 8 bit signed/unsigned |
|
* |
|
**************************************************************************/ |
|
|
|
|
|
private static class AudioFloatConversion8S extends AudioFloatConverter { |
|
public float[] toFloatArray(byte[] in_buff, int in_offset, |
|
float[] out_buff, int out_offset, int out_len) { |
|
int ix = in_offset; |
|
int ox = out_offset; |
|
for (int i = 0; i < out_len; i++) |
|
out_buff[ox++] = in_buff[ix++] * (1.0f / 127.0f); |
|
return out_buff; |
|
} |
|
|
|
public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, |
|
byte[] out_buff, int out_offset) { |
|
int ix = in_offset; |
|
int ox = out_offset; |
|
for (int i = 0; i < in_len; i++) |
|
out_buff[ox++] = (byte) (in_buff[ix++] * 127.0f); |
|
return out_buff; |
|
} |
|
} |
|
|
|
|
|
private static class AudioFloatConversion8U extends AudioFloatConverter { |
|
public float[] toFloatArray(byte[] in_buff, int in_offset, |
|
float[] out_buff, int out_offset, int out_len) { |
|
int ix = in_offset; |
|
int ox = out_offset; |
|
for (int i = 0; i < out_len; i++) |
|
out_buff[ox++] = ((in_buff[ix++] & 0xFF) - 127) |
|
* (1.0f / 127.0f); |
|
return out_buff; |
|
} |
|
|
|
public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, |
|
byte[] out_buff, int out_offset) { |
|
int ix = in_offset; |
|
int ox = out_offset; |
|
for (int i = 0; i < in_len; i++) |
|
out_buff[ox++] = (byte) (127 + in_buff[ix++] * 127.0f); |
|
return out_buff; |
|
} |
|
} |
|
|
|
/*************************************************************************** |
|
* |
|
* 16 bit signed/unsigned, little/big-endian |
|
* |
|
**************************************************************************/ |
|
|
|
|
|
private static class AudioFloatConversion16SL extends AudioFloatConverter { |
|
public float[] toFloatArray(byte[] in_buff, int in_offset, |
|
float[] out_buff, int out_offset, int out_len) { |
|
int ix = in_offset; |
|
int len = out_offset + out_len; |
|
for (int ox = out_offset; ox < len; ox++) { |
|
out_buff[ox] = ((short) ((in_buff[ix++] & 0xFF) | |
|
(in_buff[ix++] << 8))) * (1.0f / 32767.0f); |
|
} |
|
|
|
return out_buff; |
|
} |
|
|
|
public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, |
|
byte[] out_buff, int out_offset) { |
|
int ox = out_offset; |
|
int len = in_offset + in_len; |
|
for (int ix = in_offset; ix < len; ix++) { |
|
int x = (int) (in_buff[ix] * 32767.0); |
|
out_buff[ox++] = (byte) x; |
|
out_buff[ox++] = (byte) (x >>> 8); |
|
} |
|
return out_buff; |
|
} |
|
} |
|
|
|
|
|
private static class AudioFloatConversion16SB extends AudioFloatConverter { |
|
public float[] toFloatArray(byte[] in_buff, int in_offset, |
|
float[] out_buff, int out_offset, int out_len) { |
|
int ix = in_offset; |
|
int ox = out_offset; |
|
for (int i = 0; i < out_len; i++) { |
|
out_buff[ox++] = ((short) ((in_buff[ix++] << 8) | |
|
(in_buff[ix++] & 0xFF))) * (1.0f / 32767.0f); |
|
} |
|
return out_buff; |
|
} |
|
|
|
public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, |
|
byte[] out_buff, int out_offset) { |
|
int ix = in_offset; |
|
int ox = out_offset; |
|
for (int i = 0; i < in_len; i++) { |
|
int x = (int) (in_buff[ix++] * 32767.0); |
|
out_buff[ox++] = (byte) (x >>> 8); |
|
out_buff[ox++] = (byte) x; |
|
} |
|
return out_buff; |
|
} |
|
} |
|
|
|
|
|
private static class AudioFloatConversion16UL extends AudioFloatConverter { |
|
public float[] toFloatArray(byte[] in_buff, int in_offset, |
|
float[] out_buff, int out_offset, int out_len) { |
|
int ix = in_offset; |
|
int ox = out_offset; |
|
for (int i = 0; i < out_len; i++) { |
|
int x = (in_buff[ix++] & 0xFF) | ((in_buff[ix++] & 0xFF) << 8); |
|
out_buff[ox++] = (x - 32767) * (1.0f / 32767.0f); |
|
} |
|
return out_buff; |
|
} |
|
|
|
public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, |
|
byte[] out_buff, int out_offset) { |
|
int ix = in_offset; |
|
int ox = out_offset; |
|
for (int i = 0; i < in_len; i++) { |
|
int x = 32767 + (int) (in_buff[ix++] * 32767.0); |
|
out_buff[ox++] = (byte) x; |
|
out_buff[ox++] = (byte) (x >>> 8); |
|
} |
|
return out_buff; |
|
} |
|
} |
|
|
|
|
|
private static class AudioFloatConversion16UB extends AudioFloatConverter { |
|
public float[] toFloatArray(byte[] in_buff, int in_offset, |
|
float[] out_buff, int out_offset, int out_len) { |
|
int ix = in_offset; |
|
int ox = out_offset; |
|
for (int i = 0; i < out_len; i++) { |
|
int x = ((in_buff[ix++] & 0xFF) << 8) | (in_buff[ix++] & 0xFF); |
|
out_buff[ox++] = (x - 32767) * (1.0f / 32767.0f); |
|
} |
|
return out_buff; |
|
} |
|
|
|
public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, |
|
byte[] out_buff, int out_offset) { |
|
int ix = in_offset; |
|
int ox = out_offset; |
|
for (int i = 0; i < in_len; i++) { |
|
int x = 32767 + (int) (in_buff[ix++] * 32767.0); |
|
out_buff[ox++] = (byte) (x >>> 8); |
|
out_buff[ox++] = (byte) x; |
|
} |
|
return out_buff; |
|
} |
|
} |
|
|
|
/*************************************************************************** |
|
* |
|
* 24 bit signed/unsigned, little/big-endian |
|
* |
|
**************************************************************************/ |
|
|
|
|
|
private static class AudioFloatConversion24SL extends AudioFloatConverter { |
|
public float[] toFloatArray(byte[] in_buff, int in_offset, |
|
float[] out_buff, int out_offset, int out_len) { |
|
int ix = in_offset; |
|
int ox = out_offset; |
|
for (int i = 0; i < out_len; i++) { |
|
int x = (in_buff[ix++] & 0xFF) | ((in_buff[ix++] & 0xFF) << 8) |
|
| ((in_buff[ix++] & 0xFF) << 16); |
|
if (x > 0x7FFFFF) |
|
x -= 0x1000000; |
|
out_buff[ox++] = x * (1.0f / (float)0x7FFFFF); |
|
} |
|
return out_buff; |
|
} |
|
|
|
public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, |
|
byte[] out_buff, int out_offset) { |
|
int ix = in_offset; |
|
int ox = out_offset; |
|
for (int i = 0; i < in_len; i++) { |
|
int x = (int) (in_buff[ix++] * (float)0x7FFFFF); |
|
if (x < 0) |
|
x += 0x1000000; |
|
out_buff[ox++] = (byte) x; |
|
out_buff[ox++] = (byte) (x >>> 8); |
|
out_buff[ox++] = (byte) (x >>> 16); |
|
} |
|
return out_buff; |
|
} |
|
} |
|
|
|
|
|
private static class AudioFloatConversion24SB extends AudioFloatConverter { |
|
public float[] toFloatArray(byte[] in_buff, int in_offset, |
|
float[] out_buff, int out_offset, int out_len) { |
|
int ix = in_offset; |
|
int ox = out_offset; |
|
for (int i = 0; i < out_len; i++) { |
|
int x = ((in_buff[ix++] & 0xFF) << 16) |
|
| ((in_buff[ix++] & 0xFF) << 8) | (in_buff[ix++] & 0xFF); |
|
if (x > 0x7FFFFF) |
|
x -= 0x1000000; |
|
out_buff[ox++] = x * (1.0f / (float)0x7FFFFF); |
|
} |
|
return out_buff; |
|
} |
|
|
|
public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, |
|
byte[] out_buff, int out_offset) { |
|
int ix = in_offset; |
|
int ox = out_offset; |
|
for (int i = 0; i < in_len; i++) { |
|
int x = (int) (in_buff[ix++] * (float)0x7FFFFF); |
|
if (x < 0) |
|
x += 0x1000000; |
|
out_buff[ox++] = (byte) (x >>> 16); |
|
out_buff[ox++] = (byte) (x >>> 8); |
|
out_buff[ox++] = (byte) x; |
|
} |
|
return out_buff; |
|
} |
|
} |
|
|
|
|
|
private static class AudioFloatConversion24UL extends AudioFloatConverter { |
|
public float[] toFloatArray(byte[] in_buff, int in_offset, |
|
float[] out_buff, int out_offset, int out_len) { |
|
int ix = in_offset; |
|
int ox = out_offset; |
|
for (int i = 0; i < out_len; i++) { |
|
int x = (in_buff[ix++] & 0xFF) | ((in_buff[ix++] & 0xFF) << 8) |
|
| ((in_buff[ix++] & 0xFF) << 16); |
|
x -= 0x7FFFFF; |
|
out_buff[ox++] = x * (1.0f / (float)0x7FFFFF); |
|
} |
|
return out_buff; |
|
} |
|
|
|
public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, |
|
byte[] out_buff, int out_offset) { |
|
int ix = in_offset; |
|
int ox = out_offset; |
|
for (int i = 0; i < in_len; i++) { |
|
int x = (int) (in_buff[ix++] * (float)0x7FFFFF); |
|
x += 0x7FFFFF; |
|
out_buff[ox++] = (byte) x; |
|
out_buff[ox++] = (byte) (x >>> 8); |
|
out_buff[ox++] = (byte) (x >>> 16); |
|
} |
|
return out_buff; |
|
} |
|
} |
|
|
|
|
|
private static class AudioFloatConversion24UB extends AudioFloatConverter { |
|
public float[] toFloatArray(byte[] in_buff, int in_offset, |
|
float[] out_buff, int out_offset, int out_len) { |
|
int ix = in_offset; |
|
int ox = out_offset; |
|
for (int i = 0; i < out_len; i++) { |
|
int x = ((in_buff[ix++] & 0xFF) << 16) |
|
| ((in_buff[ix++] & 0xFF) << 8) | (in_buff[ix++] & 0xFF); |
|
x -= 0x7FFFFF; |
|
out_buff[ox++] = x * (1.0f / (float)0x7FFFFF); |
|
} |
|
return out_buff; |
|
} |
|
|
|
public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, |
|
byte[] out_buff, int out_offset) { |
|
int ix = in_offset; |
|
int ox = out_offset; |
|
for (int i = 0; i < in_len; i++) { |
|
int x = (int) (in_buff[ix++] * (float)0x7FFFFF); |
|
x += 0x7FFFFF; |
|
out_buff[ox++] = (byte) (x >>> 16); |
|
out_buff[ox++] = (byte) (x >>> 8); |
|
out_buff[ox++] = (byte) x; |
|
} |
|
return out_buff; |
|
} |
|
} |
|
|
|
/*************************************************************************** |
|
* |
|
* 32 bit signed/unsigned, little/big-endian |
|
* |
|
**************************************************************************/ |
|
|
|
|
|
private static class AudioFloatConversion32SL extends AudioFloatConverter { |
|
public float[] toFloatArray(byte[] in_buff, int in_offset, |
|
float[] out_buff, int out_offset, int out_len) { |
|
int ix = in_offset; |
|
int ox = out_offset; |
|
for (int i = 0; i < out_len; i++) { |
|
int x = (in_buff[ix++] & 0xFF) | ((in_buff[ix++] & 0xFF) << 8) | |
|
((in_buff[ix++] & 0xFF) << 16) | |
|
((in_buff[ix++] & 0xFF) << 24); |
|
out_buff[ox++] = x * (1.0f / (float)0x7FFFFFFF); |
|
} |
|
return out_buff; |
|
} |
|
|
|
public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, |
|
byte[] out_buff, int out_offset) { |
|
int ix = in_offset; |
|
int ox = out_offset; |
|
for (int i = 0; i < in_len; i++) { |
|
int x = (int) (in_buff[ix++] * (float)0x7FFFFFFF); |
|
out_buff[ox++] = (byte) x; |
|
out_buff[ox++] = (byte) (x >>> 8); |
|
out_buff[ox++] = (byte) (x >>> 16); |
|
out_buff[ox++] = (byte) (x >>> 24); |
|
} |
|
return out_buff; |
|
} |
|
} |
|
|
|
|
|
private static class AudioFloatConversion32SB extends AudioFloatConverter { |
|
public float[] toFloatArray(byte[] in_buff, int in_offset, |
|
float[] out_buff, int out_offset, int out_len) { |
|
int ix = in_offset; |
|
int ox = out_offset; |
|
for (int i = 0; i < out_len; i++) { |
|
int x = ((in_buff[ix++] & 0xFF) << 24) | |
|
((in_buff[ix++] & 0xFF) << 16) | |
|
((in_buff[ix++] & 0xFF) << 8) | (in_buff[ix++] & 0xFF); |
|
out_buff[ox++] = x * (1.0f / (float)0x7FFFFFFF); |
|
} |
|
return out_buff; |
|
} |
|
|
|
public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, |
|
byte[] out_buff, int out_offset) { |
|
int ix = in_offset; |
|
int ox = out_offset; |
|
for (int i = 0; i < in_len; i++) { |
|
int x = (int) (in_buff[ix++] * (float)0x7FFFFFFF); |
|
out_buff[ox++] = (byte) (x >>> 24); |
|
out_buff[ox++] = (byte) (x >>> 16); |
|
out_buff[ox++] = (byte) (x >>> 8); |
|
out_buff[ox++] = (byte) x; |
|
} |
|
return out_buff; |
|
} |
|
} |
|
|
|
|
|
private static class AudioFloatConversion32UL extends AudioFloatConverter { |
|
public float[] toFloatArray(byte[] in_buff, int in_offset, |
|
float[] out_buff, int out_offset, int out_len) { |
|
int ix = in_offset; |
|
int ox = out_offset; |
|
for (int i = 0; i < out_len; i++) { |
|
int x = (in_buff[ix++] & 0xFF) | ((in_buff[ix++] & 0xFF) << 8) | |
|
((in_buff[ix++] & 0xFF) << 16) | |
|
((in_buff[ix++] & 0xFF) << 24); |
|
x -= 0x7FFFFFFF; |
|
out_buff[ox++] = x * (1.0f / (float)0x7FFFFFFF); |
|
} |
|
return out_buff; |
|
} |
|
|
|
public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, |
|
byte[] out_buff, int out_offset) { |
|
int ix = in_offset; |
|
int ox = out_offset; |
|
for (int i = 0; i < in_len; i++) { |
|
int x = (int) (in_buff[ix++] * (float)0x7FFFFFFF); |
|
x += 0x7FFFFFFF; |
|
out_buff[ox++] = (byte) x; |
|
out_buff[ox++] = (byte) (x >>> 8); |
|
out_buff[ox++] = (byte) (x >>> 16); |
|
out_buff[ox++] = (byte) (x >>> 24); |
|
} |
|
return out_buff; |
|
} |
|
} |
|
|
|
|
|
private static class AudioFloatConversion32UB extends AudioFloatConverter { |
|
|
|
public float[] toFloatArray(byte[] in_buff, int in_offset, |
|
float[] out_buff, int out_offset, int out_len) { |
|
int ix = in_offset; |
|
int ox = out_offset; |
|
for (int i = 0; i < out_len; i++) { |
|
int x = ((in_buff[ix++] & 0xFF) << 24) | |
|
((in_buff[ix++] & 0xFF) << 16) | |
|
((in_buff[ix++] & 0xFF) << 8) | (in_buff[ix++] & 0xFF); |
|
x -= 0x7FFFFFFF; |
|
out_buff[ox++] = x * (1.0f / (float)0x7FFFFFFF); |
|
} |
|
return out_buff; |
|
} |
|
|
|
public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, |
|
byte[] out_buff, int out_offset) { |
|
int ix = in_offset; |
|
int ox = out_offset; |
|
for (int i = 0; i < in_len; i++) { |
|
int x = (int) (in_buff[ix++] * (float)0x7FFFFFFF); |
|
x += 0x7FFFFFFF; |
|
out_buff[ox++] = (byte) (x >>> 24); |
|
out_buff[ox++] = (byte) (x >>> 16); |
|
out_buff[ox++] = (byte) (x >>> 8); |
|
out_buff[ox++] = (byte) x; |
|
} |
|
return out_buff; |
|
} |
|
} |
|
|
|
/*************************************************************************** |
|
* |
|
* 32+ bit signed/unsigned, little/big-endian |
|
* |
|
**************************************************************************/ |
|
|
|
|
|
private static class AudioFloatConversion32xSL extends AudioFloatConverter { |
|
|
|
final int xbytes; |
|
|
|
AudioFloatConversion32xSL(int xbytes) { |
|
this.xbytes = xbytes; |
|
} |
|
|
|
public float[] toFloatArray(byte[] in_buff, int in_offset, |
|
float[] out_buff, int out_offset, int out_len) { |
|
int ix = in_offset; |
|
int ox = out_offset; |
|
for (int i = 0; i < out_len; i++) { |
|
ix += xbytes; |
|
int x = (in_buff[ix++] & 0xFF) | ((in_buff[ix++] & 0xFF) << 8) |
|
| ((in_buff[ix++] & 0xFF) << 16) |
|
| ((in_buff[ix++] & 0xFF) << 24); |
|
out_buff[ox++] = x * (1.0f / (float)0x7FFFFFFF); |
|
} |
|
return out_buff; |
|
} |
|
|
|
public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, |
|
byte[] out_buff, int out_offset) { |
|
int ix = in_offset; |
|
int ox = out_offset; |
|
for (int i = 0; i < in_len; i++) { |
|
int x = (int) (in_buff[ix++] * (float)0x7FFFFFFF); |
|
for (int j = 0; j < xbytes; j++) { |
|
out_buff[ox++] = 0; |
|
} |
|
out_buff[ox++] = (byte) x; |
|
out_buff[ox++] = (byte) (x >>> 8); |
|
out_buff[ox++] = (byte) (x >>> 16); |
|
out_buff[ox++] = (byte) (x >>> 24); |
|
} |
|
return out_buff; |
|
} |
|
} |
|
|
|
|
|
private static class AudioFloatConversion32xSB extends AudioFloatConverter { |
|
|
|
final int xbytes; |
|
|
|
AudioFloatConversion32xSB(int xbytes) { |
|
this.xbytes = xbytes; |
|
} |
|
|
|
public float[] toFloatArray(byte[] in_buff, int in_offset, |
|
float[] out_buff, int out_offset, int out_len) { |
|
int ix = in_offset; |
|
int ox = out_offset; |
|
for (int i = 0; i < out_len; i++) { |
|
int x = ((in_buff[ix++] & 0xFF) << 24) |
|
| ((in_buff[ix++] & 0xFF) << 16) |
|
| ((in_buff[ix++] & 0xFF) << 8) |
|
| (in_buff[ix++] & 0xFF); |
|
ix += xbytes; |
|
out_buff[ox++] = x * (1.0f / (float)0x7FFFFFFF); |
|
} |
|
return out_buff; |
|
} |
|
|
|
public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, |
|
byte[] out_buff, int out_offset) { |
|
int ix = in_offset; |
|
int ox = out_offset; |
|
for (int i = 0; i < in_len; i++) { |
|
int x = (int) (in_buff[ix++] * (float)0x7FFFFFFF); |
|
out_buff[ox++] = (byte) (x >>> 24); |
|
out_buff[ox++] = (byte) (x >>> 16); |
|
out_buff[ox++] = (byte) (x >>> 8); |
|
out_buff[ox++] = (byte) x; |
|
for (int j = 0; j < xbytes; j++) { |
|
out_buff[ox++] = 0; |
|
} |
|
} |
|
return out_buff; |
|
} |
|
} |
|
|
|
|
|
private static class AudioFloatConversion32xUL extends AudioFloatConverter { |
|
|
|
final int xbytes; |
|
|
|
AudioFloatConversion32xUL(int xbytes) { |
|
this.xbytes = xbytes; |
|
} |
|
|
|
public float[] toFloatArray(byte[] in_buff, int in_offset, |
|
float[] out_buff, int out_offset, int out_len) { |
|
int ix = in_offset; |
|
int ox = out_offset; |
|
for (int i = 0; i < out_len; i++) { |
|
ix += xbytes; |
|
int x = (in_buff[ix++] & 0xFF) | ((in_buff[ix++] & 0xFF) << 8) |
|
| ((in_buff[ix++] & 0xFF) << 16) |
|
| ((in_buff[ix++] & 0xFF) << 24); |
|
x -= 0x7FFFFFFF; |
|
out_buff[ox++] = x * (1.0f / (float)0x7FFFFFFF); |
|
} |
|
return out_buff; |
|
} |
|
|
|
public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, |
|
byte[] out_buff, int out_offset) { |
|
int ix = in_offset; |
|
int ox = out_offset; |
|
for (int i = 0; i < in_len; i++) { |
|
int x = (int) (in_buff[ix++] * (float)0x7FFFFFFF); |
|
x += 0x7FFFFFFF; |
|
for (int j = 0; j < xbytes; j++) { |
|
out_buff[ox++] = 0; |
|
} |
|
out_buff[ox++] = (byte) x; |
|
out_buff[ox++] = (byte) (x >>> 8); |
|
out_buff[ox++] = (byte) (x >>> 16); |
|
out_buff[ox++] = (byte) (x >>> 24); |
|
} |
|
return out_buff; |
|
} |
|
} |
|
|
|
|
|
private static class AudioFloatConversion32xUB extends AudioFloatConverter { |
|
|
|
final int xbytes; |
|
|
|
AudioFloatConversion32xUB(int xbytes) { |
|
this.xbytes = xbytes; |
|
} |
|
|
|
public float[] toFloatArray(byte[] in_buff, int in_offset, |
|
float[] out_buff, int out_offset, int out_len) { |
|
int ix = in_offset; |
|
int ox = out_offset; |
|
for (int i = 0; i < out_len; i++) { |
|
int x = ((in_buff[ix++] & 0xFF) << 24) | |
|
((in_buff[ix++] & 0xFF) << 16) | |
|
((in_buff[ix++] & 0xFF) << 8) | (in_buff[ix++] & 0xFF); |
|
ix += xbytes; |
|
x -= 2147483647; |
|
out_buff[ox++] = x * (1.0f / 2147483647.0f); |
|
} |
|
return out_buff; |
|
} |
|
|
|
public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, |
|
byte[] out_buff, int out_offset) { |
|
int ix = in_offset; |
|
int ox = out_offset; |
|
for (int i = 0; i < in_len; i++) { |
|
int x = (int) (in_buff[ix++] * 2147483647.0); |
|
x += 2147483647; |
|
out_buff[ox++] = (byte) (x >>> 24); |
|
out_buff[ox++] = (byte) (x >>> 16); |
|
out_buff[ox++] = (byte) (x >>> 8); |
|
out_buff[ox++] = (byte) x; |
|
for (int j = 0; j < xbytes; j++) { |
|
out_buff[ox++] = 0; |
|
} |
|
} |
|
return out_buff; |
|
} |
|
} |
|
|
|
public static AudioFloatConverter getConverter(AudioFormat format) { |
|
AudioFloatConverter conv = null; |
|
if (format.getFrameSize() == 0) |
|
return null; |
|
if (format.getFrameSize() != |
|
((format.getSampleSizeInBits() + 7) / 8) * format.getChannels()) { |
|
return null; |
|
} |
|
if (format.getEncoding().equals(Encoding.PCM_SIGNED)) { |
|
if (format.isBigEndian()) { |
|
if (format.getSampleSizeInBits() <= 8) { |
|
conv = new AudioFloatConversion8S(); |
|
} else if (format.getSampleSizeInBits() > 8 && |
|
format.getSampleSizeInBits() <= 16) { |
|
conv = new AudioFloatConversion16SB(); |
|
} else if (format.getSampleSizeInBits() > 16 && |
|
format.getSampleSizeInBits() <= 24) { |
|
conv = new AudioFloatConversion24SB(); |
|
} else if (format.getSampleSizeInBits() > 24 && |
|
format.getSampleSizeInBits() <= 32) { |
|
conv = new AudioFloatConversion32SB(); |
|
} else if (format.getSampleSizeInBits() > 32) { |
|
conv = new AudioFloatConversion32xSB(((format |
|
.getSampleSizeInBits() + 7) / 8) - 4); |
|
} |
|
} else { |
|
if (format.getSampleSizeInBits() <= 8) { |
|
conv = new AudioFloatConversion8S(); |
|
} else if (format.getSampleSizeInBits() > 8 && |
|
format.getSampleSizeInBits() <= 16) { |
|
conv = new AudioFloatConversion16SL(); |
|
} else if (format.getSampleSizeInBits() > 16 && |
|
format.getSampleSizeInBits() <= 24) { |
|
conv = new AudioFloatConversion24SL(); |
|
} else if (format.getSampleSizeInBits() > 24 && |
|
format.getSampleSizeInBits() <= 32) { |
|
conv = new AudioFloatConversion32SL(); |
|
} else if (format.getSampleSizeInBits() > 32) { |
|
conv = new AudioFloatConversion32xSL(((format |
|
.getSampleSizeInBits() + 7) / 8) - 4); |
|
} |
|
} |
|
} else if (format.getEncoding().equals(Encoding.PCM_UNSIGNED)) { |
|
if (format.isBigEndian()) { |
|
if (format.getSampleSizeInBits() <= 8) { |
|
conv = new AudioFloatConversion8U(); |
|
} else if (format.getSampleSizeInBits() > 8 && |
|
format.getSampleSizeInBits() <= 16) { |
|
conv = new AudioFloatConversion16UB(); |
|
} else if (format.getSampleSizeInBits() > 16 && |
|
format.getSampleSizeInBits() <= 24) { |
|
conv = new AudioFloatConversion24UB(); |
|
} else if (format.getSampleSizeInBits() > 24 && |
|
format.getSampleSizeInBits() <= 32) { |
|
conv = new AudioFloatConversion32UB(); |
|
} else if (format.getSampleSizeInBits() > 32) { |
|
conv = new AudioFloatConversion32xUB((( |
|
format.getSampleSizeInBits() + 7) / 8) - 4); |
|
} |
|
} else { |
|
if (format.getSampleSizeInBits() <= 8) { |
|
conv = new AudioFloatConversion8U(); |
|
} else if (format.getSampleSizeInBits() > 8 && |
|
format.getSampleSizeInBits() <= 16) { |
|
conv = new AudioFloatConversion16UL(); |
|
} else if (format.getSampleSizeInBits() > 16 && |
|
format.getSampleSizeInBits() <= 24) { |
|
conv = new AudioFloatConversion24UL(); |
|
} else if (format.getSampleSizeInBits() > 24 && |
|
format.getSampleSizeInBits() <= 32) { |
|
conv = new AudioFloatConversion32UL(); |
|
} else if (format.getSampleSizeInBits() > 32) { |
|
conv = new AudioFloatConversion32xUL((( |
|
format.getSampleSizeInBits() + 7) / 8) - 4); |
|
} |
|
} |
|
} else if (format.getEncoding().equals(Encoding.PCM_FLOAT)) { |
|
if (format.getSampleSizeInBits() == 32) { |
|
if (format.isBigEndian()) |
|
conv = new AudioFloatConversion32B(); |
|
else |
|
conv = new AudioFloatConversion32L(); |
|
} else if (format.getSampleSizeInBits() == 64) { |
|
if (format.isBigEndian()) |
|
conv = new AudioFloatConversion64B(); |
|
else |
|
conv = new AudioFloatConversion64L(); |
|
} |
|
|
|
} |
|
|
|
if ((format.getEncoding().equals(Encoding.PCM_SIGNED) || |
|
format.getEncoding().equals(Encoding.PCM_UNSIGNED)) && |
|
(format.getSampleSizeInBits() % 8 != 0)) { |
|
conv = new AudioFloatLSBFilter(conv, format); |
|
} |
|
|
|
if (conv != null) |
|
conv.format = format; |
|
return conv; |
|
} |
|
|
|
private AudioFormat format; |
|
|
|
public final AudioFormat getFormat() { |
|
return format; |
|
} |
|
|
|
public abstract float[] toFloatArray(byte[] in_buff, int in_offset, |
|
float[] out_buff, int out_offset, int out_len); |
|
|
|
public final float[] toFloatArray(byte[] in_buff, float[] out_buff, |
|
int out_offset, int out_len) { |
|
return toFloatArray(in_buff, 0, out_buff, out_offset, out_len); |
|
} |
|
|
|
public final float[] toFloatArray(byte[] in_buff, int in_offset, |
|
float[] out_buff, int out_len) { |
|
return toFloatArray(in_buff, in_offset, out_buff, 0, out_len); |
|
} |
|
|
|
public final float[] toFloatArray(byte[] in_buff, float[] out_buff, |
|
int out_len) { |
|
return toFloatArray(in_buff, 0, out_buff, 0, out_len); |
|
} |
|
|
|
public final float[] toFloatArray(byte[] in_buff, float[] out_buff) { |
|
return toFloatArray(in_buff, 0, out_buff, 0, out_buff.length); |
|
} |
|
|
|
public abstract byte[] toByteArray(float[] in_buff, int in_offset, |
|
int in_len, byte[] out_buff, int out_offset); |
|
|
|
public final byte[] toByteArray(float[] in_buff, int in_len, |
|
byte[] out_buff, int out_offset) { |
|
return toByteArray(in_buff, 0, in_len, out_buff, out_offset); |
|
} |
|
|
|
public final byte[] toByteArray(float[] in_buff, int in_offset, int in_len, |
|
byte[] out_buff) { |
|
return toByteArray(in_buff, in_offset, in_len, out_buff, 0); |
|
} |
|
|
|
public final byte[] toByteArray(float[] in_buff, int in_len, |
|
byte[] out_buff) { |
|
return toByteArray(in_buff, 0, in_len, out_buff, 0); |
|
} |
|
|
|
public final byte[] toByteArray(float[] in_buff, byte[] out_buff) { |
|
return toByteArray(in_buff, 0, in_buff.length, out_buff, 0); |
|
} |
|
} |