I am trying to read data of a .wav file both in java and matlab and save as an array of bytes.
In java the code looks as follows:
public byte[] readWav2(File file) throws UnsupportedAudioFileException, IOException {
AudioFormat audioFormat;
AudioInputStream inputAIS = AudioSystem.getAudioInputStream(file);
audioFormat = inputAIS.getFormat();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
// Read the audio data into a memory buffer.
int nBufferSize = BUFFER_LENGTH * audioFormat.getFrameSize();
byte[] abBuffer = new byte[nBufferSize];
while (true) {
int nBytesRead = inputAIS.read(abBuffer);
if (nBytesRead == -1) {
break;
}
baos.write(abBuffer, 0, nBytesRead);
}
byte[] abAudioData = baos.toByteArray();
return abAudioData;
}
In matlab I am using the wavread function:
[Y, FS] = wavread('sound.wav', 'native');
But the results I am getting are different.
In java the first 20 bytes:
53, 0, 19, 0, -71, -1, -80, -1, -99, -1, 10, 0, 87, 0, -69, -1, 123, -1, -77, -1
In matlab:
53, 19, -71, -80, -99, 10, 87, -69, -133, -77, 38, 143, 13, -100, 39, 45, -52, -83, -82, 56
Why every second byte in java is 0 or -1 where in matlab there isn't? Even though I skip the 0's and -1's where in java there is 123 for matlab there is -133? Why is it different?
Java is returning you 16-bit signed PCM data. Since each sample is 16 bits and a byte holds 8 bits, each sample spans two bytes in Java. What Matlab returns you is an array of the 16-bit samples directly.
Basically, the data is the same. It's just laid out differently in memory.
To access the samples in an easier way from Java you could do some bitwise arithmetic, like this:
int firstSample = (abAudioData[0]&0xFF) | (abAudioData[1]<<8);
Another way to read the samples is with the java.nio buffers:
ByteBuffer bb = ByteBuffer.wrap(abAudioData);
bb.order(ByteOrder.LITTLE_ENDIAN);
ShortBuffer sb = bb.asShortBuffer();
int firstSample = sb.get();
Related
So, I am trying to store 3 longs to a file, but it will a lot of data so I convert them to byte arrays and save them. My current method for saving them:
try (FileOutputStream output = new FileOutputStream(path, true)) {
//Put the data into my format
byte[] data = new byte[24];
main.getLogger().log(Level.INFO, "Saving most sig bits");
System.arraycopy(ByteUtils.longToBytes(uuid.getMostSignificantBits()), 0, data, 0, 8);
System.arraycopy(ByteUtils.longToBytes(uuid.getLeastSignificantBits()), 0, data, 8, 8);
System.arraycopy(ByteUtils.longToBytes(player.getTokens()), 0, data, 16, 8);
//Write data in the format
output.write(data);
}
longToBytes method:
private static ByteBuffer buffer = ByteBuffer.allocate(8);
public static byte[] longToBytes(long x) {
System.out.println(x);
buffer.putLong(0, x);
return buffer.array();
}
The byte array gets saved to the file, but the first byte gets truncated. the print statement in longToByes prints 8 three times.
The original longs are:
-9089798603852198353, -5339652910133477779, 5992
If I print the byte array I get:
-127, -38, -116, 84, 97, -116, 78, 47, -75, -27, -67, -8, 11, -100, -2, 109, 0, 0, 0, 0, 0, 0, 23, 104 (24 bytes)
But in the file I see:
ÚŒTaŒN/µå½ø(VT symbol)œþm(nul)(nul)(nul)(nul)(nul)(nul)(etb)h
which is 23 bytes (the first box doesn't show in notepad++)
but if I read it using
bytes = IOUtils.toByteArray(new FileReader(file));
I see:
64, -38, -116, 84, 97, -116, 78, 47, -75, -27, -67, -8, 11, -100, -2, 109, 0, 0, 0, 0, 0, 0, 23, 104 (24 bytes)
-127 is replaced with 64 somehow.
I concat the byte with "" to print it btw.
Do not use FileReader to read raw bytes from file. Use FileInputStream instead.
The problem with FileReader is that it reads chars, not bytes, from the file, by trying to decode the bytes using some character encoding (the default one if none was given).
bytes = IOUtils.toByteArray(new FileInputStream(file));
Alternatively you can use DataOutputStream to write long directly to an output stream and use DataInputStream to read from an input stream.
try (DataOutputStream out = new DataOutputStream(new FileOutputStream(file))) {
out.writeLong(uuid.getMostSignificantBits());
out.writeLong(uuid.getLeastSignificantBits());
out.writeLong(player.getTokens());
}
try (DataInputStream in = new DataInputStream(new FileInputStream(file))) {
long uuidMSB = in.readLong();
long uuidLSB = in.readLong();
long tokens = in.readLong();
}
I am working on an application that reads data from a database. There are already encrypted entries in the DB. I have the key as a byte array and want to load it from a yaml file.
Is there a way i can populate an array like this
private static final byte[] iv = { 13, -11, -88, 20, -110, 113, -2, -8, -15, -99, -23, -10, -10, -74, 1, 11 }
Directly from a yaml file?
yaml file:
iv: 13,-11,-88
Since I cannot autowire the class where I need to use the key, i cannot use #value annotation (from my understanding). So I was looking to use a util class like so:
public static byte[] getKeyFor(Class type) {
return context.getEnvironment().getProperty("iv");
}
Below should work:
application.yml:
iv: 12,32,12,32
In the class where you want the values, bind it like below:
#Value("${iv}") byte[] iv;
You got some string with your byte data in String format.
String iv = someCall(); //"13, -11, -88, 20, -110, 113, -2, -8, -15, -99, -23"
String[] byteStrings = iv.split(",");
byte[] byteData = new byte[byteStrings.length];
for (int i = 0; i < byteData.length; i++){
byteData[i] = Byte.parseByte(byteStrings[i], 8);
}
I have a double(float/Decimal) value and I want to get the same byte array as produced by Java ByteBuffer in C#.
However the byte array produced by using ByteBuffer.PutDouble in Java and BinaryWriter in C# is different. Can someone please explain the implementation detail difference between the two.
Java:
ByteBuffer bytes = ByteBuffer.allocate(8).putDouble(0,1.12346);
bytes[] = {63, -15, -7, -83, -45, 115, -106, 54};
C#:
double value = 1.12346;
byte[] arr;
using (MemoryStream stream = new MemoryStream())
{
using (BinaryWriter writer = new BinaryWriter(stream))
{
writer.Write(value);
arr = stream.ToArray();
}
}
arr[] = {153, 211, 101, 49, 177, 249, 241, 63};
ByteBuffer is big endian by default and bytes are signed.
In C#, it's little endian by default and bytes are unsigned.
You have the same data in the opposite order, from a serialization point of view, the sign of the bytes is not important except it is a little confusing.
In C# you can use the EndianBinaryWriter BinaryWriter Endian issue
I've created the following procedure in the run() method of the ConnectedThread taken from the BluetoothChat sample.
// Read from the InputStream
byte[] buffer = new byte[16];
int offset = 0;
while(buffer.length-offset != 0)
{
int bytesRead += mmInStream.read(buffer, offset, buffer.length-offset);
offset += bytesRead;
}
// Do stuff with the contents of the buffer
The buffer is loaded in with 16 bytes gradually as expected but for some reason at the 10th byte in the array a 0 is inserted and shifts the remaining part of the package(and as such corrupting the entire package)
Here is an example of what is happening
The following is sent from the other client :
[-11, 126, -16, -30, -92, 110, -26, 13, 22, 91, -31, 32, 54, -125, -112, 45]
This is what I receive :
[-11, 126, -16, -30, -92, 110, -26, 13, 22, 91, 0, -31, 32, 54, -125, -112]
As you can see, an extra 0 is pushed in as the 10th byte and the rest of the package is shifted to the right(cutting off the last byte)
As part of the debugging process we tried having a breakpoint at bytesRead += mmInStream.read(buffer, offset, buffer.length-offset) and to our surprise the entire original message was received. What gives?
How does the "break" in reads correct this issue? What am I doing wrong or not understanding?
Probably you meant
bytesRead = mmInStream.read(buffer, offset, buffer.length-offset);
offset += bytesRead;
instead of
bytesRead += ...
Throw it all away and use DataInputStream.readFully().
As input I'm getting a short array like {20, 250, 12, 255}.
I need to convert it to byte[] {20,-6,12,-1}
I tried to use ByteBuffer:
short[] data = {20, 250, 12, 255};
ByteBuffer dbuf = ByteBuffer.allocate(data.length*2);
dbuf.asShortBuffer().put(data);
byte[] array = dbuf.array();
But the output formatted as:
{0,20,0,-6,0,12,0,-1}
How to get signed byte array like {20,-6,12,-1}?
Just simply use byte[] which is signed because byte in java is singed. There is no need to convert to short if you want output like that.
Below is just conversion mechanism if you cant.
Loop over the array and do a down cast.
short[] data = { 20, 250, 12, 255 };
byte[] bytes = new byte[data.length];
int count = 0;
for (short i : data) {
bytes[count++] = (byte)i;
}
System.out.println(Arrays.toString(bytes));
Output:
[20, -6, 12, -1]